Thursday, December 20, 2012

WinJS Data Storage and Protection in Windows 8 Store Apps

In my previous post I discussed about how to protect JavaScript source in Windows Store apps. Today I will discuss how to store and secure WinJS app data inside the client machine.

Data Storage and Access


The first question is how and where to save the data. This MSDN documentation is a good reference. There're a lot of options out there but you may end up using one of following methods to store configurations or settings in a Windows 8 machine:

1. WinJS.Application.local.writeText and WinJS.Application.local.readText. Both methods return Promise and they are used to write/read the specified text to/from the specified file. The saved content will be plain text and the content is physically stored in C:\Users\{UserName}\AppData\Local\Packages\{AppID}\LocalState folder. Code example:
    var appLocal = WinJS.Application.local;
    var mySettings = [ {Locale : "EN-CA"}, { Theme : "Classic" }, { LastAccessDate: "2012-12-12" }]; 
    appLocal.writeText("app.config", JSON.stringify(mySettings)).then(function () {
        appLocal.readText("app.config").then(function (data) {
            try {
                var retrievedSettings = JSON.parse(data);
                // do stuff
            }
            catch (ex) {
                // Exception handling 
            }
        });
    });
2. Windows.Storage.ApplicationData.current.localFolder. Same as using "ms-appdata:///Local/" protocol. The data storage location of this localFolder is actually the same as above but the API is different:
    var localFolder = Windows.Storage.ApplicationData.current.localFolder;
    var saveOption = Windows.Storage.CreationCollisionOption;
    var mySettings = {Locale : "EN-CA", Theme : "Classic", LastAccessDate: "2012-12-12"}; 
    localFolder.createFileAsync("myapp.config", saveOption.replaceExisting).then(
        function (file) {
            return Windows.Storage.FileIO.writeTextAsync(file, JSON.stringify(mySettings));
        }).done(function () { 
            localFolder.getFileAsync("myapp.config").then(function (file) {
                return Windows.Storage.FileIO.readTextAsync(file);
            }).done(function (data) {
                var retrievedSettings = JSON.parse(data);
                // do stuff
            });
        });
    }
3. Windows.Storage.ApplicationData.current.localSettings. This localSettings, a key/value pair container, is a bit easier to use because it's not implemented by Prmoise like above two methods. You can set and get values directly in a traditional JavaScript way. The data is stored in C:\Users\{UserName}\AppData\Local\Packages\{AppID}\Settings folder. As name suggested localSettings is ideal for saving settings or small amount of data but not good for big size of content:
    var localSettings = Windows.Storage.ApplicationData.current.localSettings;
    var mySettings = { Locale: "EN-CA", Theme: "Classic", LastAccessDate: "2012-12-12" };
    localSettings.values["myAppSetting"] = JSON.stringify(mySettings); // Assign value
    var data = localSettings.values["myAppSetting"]; // Retrieve value
    if (data) {
        try {
            var retrievedSettings = JSON.parse(data);
            // do stuff
        }
        catch (ex) {
            localSettings.values.remove("myAppSetting");
        }
    }
4. Windows.Storage.ApplicationData.current.roamingSettings/roamingFolder.. The roamingSettings API is pretty much the same as localSettings, and roamingFolder just like localFolder. The difference are:
  • Roaming store would automatically sync the local data to the user's profile in the cloud when the user login as a Microsoft account.
  • Roaming store's physical location is C:\Users\{UserName}\AppData\Local\Packages\{AppID}\RoamingState.
  • Roaming store's URI is "ms-appdata:///Roaming/"
  • Roaming store can only save maximum of 100K data.

Data Encryption and Decryption


In all above methods the saved data are not secure and they can be easily retrieved in other place. So how to protect sensitive data stored in the client machine? Encryption is straightforward answer. Encrypt your data if you don't want to expose them directly to the end user.

The asymmetric encryption is hard and not applicable for distributed single alone application due to the complexity of PKI system. Symmetric encryption such as AES is used in most cases. But client side symmetric encryption is not safe in general because the same encryption key is used in the client machine. The encrypted data can be decrypted in any other machine running the same app, and it's not hard to get the decrypted value. It would be more secure if the encryption key is associated with login user's identity such as SID in Windows machine. In that case the encrypted data can't be decrypted easily in other machine or different user in the same machine.

The problem is that the user SID is not achievable in JavaScript or Runtime component. Fortunately Windows Runtime environment provides Windows.Security.Cryptography library which includes mechanism to encrypt/decrypt data using a key associated with the current user, and the library is accessible from WinJS:
    var localSettings = Windows.Storage.ApplicationData.current.localSettings;
    var cryptography = Windows.Security.Cryptography;
    var cryptoBuffer = cryptography.CryptographicBuffer;
    var cryptoProvider = new cryptography.DataProtection.DataProtectionProvider("LOCAL=user");
            
    var mySettings = { Locale: "EN-CA", Theme: "Classic", LastAccessDate: "2012-12-12" };
    var bufferData = cryptoBuffer.convertStringToBinary(JSON.stringify(mySettings), cryptography.BinaryStringEncoding.utf8);

    cryptoProvider.protectAsync(bufferData).then(function (encryptedData) {
        var dataToBeSaved = cryptoBuffer.encodeToHexString(encryptedData);
        localSettings.values["appSecuredSetting"] = dataToBeSaved;
    }).then(function () {
        var encryptedHexData = localSettings.values["appSecuredSetting"];
        if (encryptedHexData) {
            try {
                var bufferData = cryptoBuffer.decodeFromHexString(encryptedHexData);
                cryptoProvider.unprotectAsync(bufferData).then(
                    function (decryptedBuffer) {
                        var decryptedData =
                            cryptoBuffer.convertBinaryToString(cryptography.BinaryStringEncoding.utf8, decryptedBuffer);
                        var retrievedSettings = JSON.parse(decryptedData);
                        // do stuff
                    },
                    function (err) {
                        // Decryption error handling
                    });
            } catch (ex) {
                // DecodeFromHexString error handling
            }
        }
    });;
The descriptor parameter of "LOCAL=user" passed to DataProtectionProvider is important. I tested other available parameters and this "LOCAL=user" parameter is the only one that would prevent other user from decrypting the data. When data is encrypted with this parameter, they can't be decrypted by any other user in the same machine or other machine. I also tried to decrypt the data in another machine by the same user name but it failed.

The real encryption key used by DataProtectionProvider is invisible to end user or developer. That's great because it makes super hard for attackers to reproduce that key. Conclusion is that by using Windows.Security.Cryptography library and passing "LOCAL=user" to DataProtectionProvider we could secure the data saved to a Windows 8 box.

Tuesday, December 18, 2012

Secure JavaScript Source for Windows 8 Store Apps

I demonstrated how to import an installed Windows JavaScript/HTML application in my previous post. JavaScript is an interpreted language and theoretically you can't prevent it from being reverse engineering. But Windows 8 store apps' architecture makes super easy for a user with administration right to see apps' source file by simply a few clicks. This is not acceptable and I agree with Justin Angel's opinion: that's a fundamental design flaw.

Originally JavaScript is designed to run inside browser. It's mainly for presentation layer and the application flow is driven by the web server. This has been evolved a bit recently due to the popularity of JavaScript, for instance the node.js framework developed for server environment. Now JavaScript becomes one of the main stream languages for developing Windows 8 store apps and the JavaScript code plays more important role there. Those apps' source is so easy to get from physical file system that it would attract people to do so. No need to jailbreak or root the Windows 8 devices, now even casual attackers can have an easy starting point simply by a few clicks. The worst thing is that most developers may not aware of that potential security hole. They simply trust Microsoft and do little or nothing to protect their application. That's why Justin was so easy to break various popular games built by C++, C#/XAML and HTML/JavaScript.

As time goes by I believe more and more measures will be introduced to address the security issues of Windows 8 store apps. For developers, what we can do is to secure our code and data. Following three methods can be used to improve the code security for Window 8 applications:

1. Move critical logic and data back to server side. This is kind of hybrid approach. The Windows 8 app runs locally but some pages or sometimes it would just act like an embedded browser.

2. Split some code into Windows Runtime Component using C#/C++/VB. The Runtime Component is compiled as a dll and can be called directly from JavaScript. For further protection we can obfuscate the code in Runtime Component.

3. Minimize/obfuscate JavaScript code. That's an easy but effective way to protect your code and your logic. Scott Hanselman has a great post going through a couple of tools to do this job. For example following batch file will go through all JavaScript in a solution folder and make a minimized version of it with .min.js extension (original js file unchanged) using AjaxMin:

dir /s /b *.js | find /v ".min.js" | find /v "\bin\" > jsminlist.txt
for /f "usebackq delims=" %%x in (`findstr /V min.js jsminlist.txt`) do (AjaxMinifier.exe "%%x" -o "%%~dpx/%%~nx.min.js" -clobber)
Note that the AjaxMin's executable AjaxMinifier.exe needs to be copied to the solution's root folder before running above script. After run the batch command, we simply exclude the original javascripts not ending with *.min.js, and include those minimized version of JavaScript ending with *.min.js, then update all html files to reference the new JavaScript.

Another topic is secure the data we stored in client machine. I will discuss that in my next post.

Update 2013-01:
1. when publishing the app if you get app validation error of "xxx.js is not properly UTF-8 encoded. Re-save the file as UTF-8 (including Byte Order Mark).", you simple the open the JavaScript file in Visual Studio and click File => Save xxxx.js As... from the menu, select "Save with Encoding" (default is "Save") from the popup window, and select "Unicode (UTF-8 without signature) - Codepage 65001" encoding format then click OK to save the file with proper format for publishing.

2. if get the "Optimized Binding References" error during app validation, something like "WinJS.Binding.optimizeBindingReferences = true is not set and data-win-bind was found in xxxx.html on line number xxx.", to resolve the problem you have to add "WinJS.Binding.optimizeBindingReferences = true;" right on top of your JavaScript if you have data binding in your page. If you get this error only after JavaScript minification, that means the Windows app certification kit doesn't recognize the obfuscated JavaScript and you need to try another tool to do the job. Using JSMin from Douglas Crockford would work for sure since it only removes the space and comments without any other code scrambling.

Sunday, December 16, 2012

An Exercise of Reverse Engineering Windows 8 JavaScript/HTML App

What's the buzz this week? Quite a lot of attention was drawn from a Nokia engineer Justin Angel, a former Microsoft developer who posted online how to hack various popular Windows 8 games in detail. Justin Angel's blog is offline now and even its Google cached page is not available any more. This once more raises people's concern about the Windows 8 application security. Actually Justin had wrote a blog post talking about reverse engineering Windows 8 app more than a year ago. I believe Justin has notified Microsoft about security concerns in the past year but Microsoft just didn't paid enough attention on it. Justin looked frustrated and he wrote: "If Microsoft doesn’t take it upon itself to fix these security attack vectors it’s not because it couldn’t, it’s because it chooses not to."

Justin then hacked some Windows 8 games and rang alarm bells once again. Hope Microsoft won't ignore the security issues this time. As a follow-up on Justin's work I am going to do some testing to reverse engineering a WinJS app. The goal is to run and debug the app using Visual Studio 2010 locally. I am doing this only for study purpose by no means any other.

The test environment I have is a Windows 8 64-bit virtual machine with Visual Studio 2012 and BingMap SDK installed. The app to be reversely engineered is called USAToday, one of my favorite apps also one of the top free apps under News category in Windows store. After installed the app you can see the physical HTML, JavaScript and CSS files under C:\Program Files\WindowsApps\USATODAY.USATODAY_1.2.0.0_neutral__wy7mw3214mat8 folder (google it if you can't see or open this folder). Following are steps I did to import USAToday files into VS2012.

Step 1. Open up VS2012 and create a JavaScript Windows Store project named "USATodayMock" using Navigation App template. The VS2012 solution looks like:



Step 2. Copy highlighted files and folders in C:\Program Files\WindowsApps\USATODAY.USATODAY_1.2.0.0_neutral__wy7mw3214mat8 as below to the VS2012 project:



After files copied to the VS2010 solution:



Step 3. Add project references: Windows Library for JavaScript 1.0, BingMap for JavaScript, and two dlls from USAToday source files:



Now the VS2012 solution can be compiled. When you run it in debug mode in VS2012 it will prompt you a warning, just click yes to override the existing app:



Then you will get an exception thrown by getResourceString method inside Microsoft.PlayerFramework.Js/js/PlayerFramework.js:



It shows missing resource string for "Microsoft.PlayerFramework.Js/resources/TimeFormatterTemplate". Apparently the original USAToday solution includes Microsoft Player Framework which requires some resource strings. To make it simple I just reverse engineer the compiled PRI resource file (resources.pri) come with Windows 8 app package, and directly add those resource strings to the solution. See next step for detail.


Step 4. Open Developer Command Prompt, go to app installation folder C:\Program Files\WindowsApps\USATODAY.USATODAY_1.2.0.0_neutral__wy7mw3214mat8, run "makepri dump" to build the resources.pri.xml file:



The exported resources.pri.xml looks something like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PriInfo>
  <ResourceMap name="USATODAY.USATODAY" version="1.0" primary="true">
    <Qualifiers></Qualifiers>
    <ResourceMapSubtree name="Bing.Maps.Javascript"></ResourceMapSubtree>
    <ResourceMapSubtree name="Files">
    <ResourceMapSubtree name="Microsoft.PlayerFramework.Js">
      <ResourceMapSubtree name="resources">
         <NamedResource name="TimeElapsedTitle" 
          uri="ms-resource://USATODAY.USATODAY/Microsoft.PlayerFramework.Js/resources/TimeElapsedTitle">
            <Candidate qualifiers="Language-EN-US" isDefault="true" type="String">
              <Value>{hour.integer}:{minute.integer(2)}:{second.integer(2)}</Value>
            </Candidate>
         </NamedResource>
       </ResourceMapSubtree>
     </ResourceMapSubtree>
   </ResourceMap>
</PriInfo>
Copying those resource strings is tedious. I created a simple console app that convert those player framework resource strings in resources.pri.xml to WinJS recognizable JSON format:
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> resources = new Dictionary<string, string>();
            XDocument xdoc = XDocument.Load("c:\\temp\\resources.pri.xml");
            var frameworkResources = xdoc.Descendants("ResourceMapSubtree")
                    .Where(e => (string)e.Attribute("name") == "Microsoft.PlayerFramework.Js")
                    .Elements("ResourceMapSubtree")
                    .Where(e => (string)e.Attribute("name") == "resources")
                    .Elements();
            foreach (var item in frameworkResources)
            {
                var key = item.Attribute("name").Value;
                var value = item.Descendants("Value").First().Value;
                resources.Add(key, value);
            }
            using (TextWriter tw = new StreamWriter("C:\\temp\\resources.resjson"))
            {
                tw.WriteLine("{");
                int resourceCount = resources.Count, counter = 1;
                foreach (var item in resources)
                {
                    if (counter++ < resourceCount)
                        tw.WriteLine(string.Format("\"{0}\" : \"{1}\",", item.Key, item.Value));
                    else
                        tw.WriteLine(string.Format("\"{0}\" : \"{1}\"", item.Key, item.Value));
                }
                tw.WriteLine("}");
            }
        }
    }
}
Above console app will create a resources.resjson file in C:\temp folder. Copy it to USATodayMock solution.

Step 5. Modify getResourceString method in Microsoft.PlayerFramework.Js/js/PlayerFramework.js, remove the prefix of "Microsoft.PlayerFramework.Js/resources/" for the resource keys since they are included in the project directly:
    function getResourceString(id) {
        /// <summary>Returns the resource string with the specified ID.</summary>
        /// <param name="id" type="String">The resource identifier.</param>
        /// <returns type="String">The resource string.</returns>

        if (id.indexOf("resources/") > 0)
            id = id.substring(id.lastIndexOf("/") + 1);

        var string = WinJS.Resources.getString(id);

        if (string.empty) {
            throw invalidResourceId;
        }

        return string.value;
    }
Click F5 and bang the USATodayMock app can be run and debug now!

Step 6. This step is to do a little more of test by modifying the default page. USAToday Win8 app shows weather in the right top corner:



Let's just change weather text to red and show some dummy text when you click it. Search following text inside default.html page under the root of the USATodayMock solution:
    <div class="banner">
        <div class="snapped-back"></div>
        <div class="app-logo"></div>

        <div class="weather">
            <div class="location"></div>
            <div class="icon-wrapper hidden"><img class="icon" /></div>
            <div class="temp"></div>
        </div>
    </div>
Then replace it with following HTML:
    <div class="weather">
        <div class="location" style="color:red;" onclick="showAlert();"></div>
        <div class="icon-wrapper hidden"><img class="icon" /></div>
        <div class="temp"></div>
    </div>

    <div id="divAlert" style="display:none; position:fixed; margin-top: 200px; margin-left: 150px;">
            <h1>App has been modified!</h1> 
    </div>
    <script type="text/javascript">
        function showAlert() {
            event.cancelBubble = true;
            WinJS.Utilities.query("#divAlert").setStyle("display", "block");
            WinJS.Utilities.query("#app-body").setStyle("display", "none");
        }
    </script>
Run the application again you will see the red location text:



When you click that red text (New York) the page will show the custom content instead of going to the location setting page:



So we see how easy it's to import an installed Windows 8 application into Visual Studio and run it directly. In my next post I will discuss some methods to secure the code and make it harder to be reversely engineered.

Saturday, December 08, 2012

Notes About Android Threading

  • Main thread, or UI thread, starts Android application, processes UI rendering and handles user interactions. Do NOT execute any long-running or heavy tasks inside main thread otherwise the UI would appear lagging and not responsive.
  • A Looper holds a message queue and implements infinite loop. It takes tasks one by one from the queue and executes them in sequence. When message queue is empty, the Looper is blocking and waiting for processing next queued task. A thread can associate with a Looper (only one to one relationship), then it becomes a Looper thread being able to process messages and tasks continuously, vs. regular thread that will die when completes its job in the run() method.
  • Handler is a bridge between Looper message queue and thread(s). Current thread or other threads can push runnable jobs to a Looper message queue by method handler.post() and its scheduled variance (postDelayed, postAtTime, etc.), or send a message to the queue by handler.sendMessage() method and its scheduled variance (sendMessageDelayed, sendMessageAtTime, etc.). Handler can also process the message by the Handler's handleMessage(Message) callback.
  • You can setup a thread with a Looper manually. Androdi also provides a handy class called HandlerThread for starting a new thread that already has a Looper attached. Not sure why it's not called LooperThread. It's a bit confusing as there's no Handler in a HandlerThread object. You always need to create Handler for a HandlerThread:
        HandlerThread  handlerThread = new HandlerThread("Thread name");
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());
    
  • Main thread is a Looper thread. All UI interactions are pushed to main thread's Looper message queue and then are processed one by one. Configuration change request, such as orientation rotation, is just a special type of message sent to main thread's message queue.
  • Only main thread can update UI elements safely. Worker thread or background thread can use following means to work on UI elements:
    • Implement main thread Handler, then you can update UI inside handler.handleMessage() callback, and post UI-related task to handler.Post() method or their variance.
    • Use View.Post(Runnable). Android View objects have tied to a default Handler inside UI thread so you can post UI-related runnable jobs to it directly.
    • Use Activity.runOnUiThread(Runnable) method. Android Activity class has this runOnUiThread helper method to update the UI.
    • Use AsyncTask. The AsyncTask implementation takes the advantage of Thread pooling concept and provides a simple, understandable interface. Simply run background task inside the doInbackground() method, and run UI-related work inside the onPreExecute(), onProgressUpdate() and onPostExcute() methods. But be aware of the performance penalty of using it, see next.
  • AsyncTask thread has low priority of Process.THREAD_PRIORITY_BACKGROUND. With such low priority the total CPU consumption of all AysncTasks together is less than 10 percent of overall CPU power. This may cause some performance issue. You can change this behavior by changing its priority:
        new AsyncTaskClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
        //...
        class AsyncTaskClass extends AsyncTask<...> {
            //...
            protected Void doInBackground() {
                Thread.currentThread().setPriority(Process.THREAD_PRIORITY_DEFAULT);
                //...
            }
        }
    
  • On the other hand the HandlerThread uses Process.THREAD_PRIORITY_DEFAULT priority by default, but you can specify HandlerThread's priority from its constructor, e.g. setting a low priority background:
    HandlerThread bgThread = new HandlerThread("Background thread", Process.THREAD_PRIORITY_BACKGROUND);
    
  • The ExecutorService is more powerful and can manage a pool of threads. Go for it if you want to have full control of your threads.
  • Usually worker thread is created from Activity. But it can also run in Service context (thread object created inside Service) without UI connection. Note that Service still runs in main UI thread by default if it starts from the Activity, but Service is not bound to Activity's life-cycle. IntentService simply extends Service and implements an internal HandlerThread object, so you can guarantee the job passed to IntentService's onHandleIntent callback runs in a separate worker thread.
  • There're a few ways to deal with recurring or repeating tasks. One common approach is keep posting to Activity's handler by using Handler.postDelayed() inside the runnable task:
        int recurInSeconds = 5;
        Handler handler = new Handler();
        handler.postDelayed(runnable, 0); // start the task
        Runnable runnable = new Runnable() {
           @Override
           public void run() {
              doTask(); 
              handler.postDelayed(this, recurInSeconds * 1000); // repeat the task
           }
        };
    Without Activity context we can use following methods to achieve the goal:
    • AlarmManager.setRepeating()/setInexactRepeating() to repeatedly start a Broadcast/Service in which the job is handled. For longer sleep intervals this is the preferred mechanism. It's handled by system and is only triggered at the time arrives thus consuming less power.
    • ScheduledThreadPoolExecutor.scheduleWithFixedDelay()/scheduleWithFixedDelay() to repeatedly run a task.
      ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
      executor.scheduleAtFixedRate(runnable, 0, recurInSeconds, TimeUnit.SECONDS);
    • Use Timer.scheduleAtFixedRate() to do the recurring TimerTask. This is not the recommended way described from Android development guild.
  • Anders Göransson's Efficient Android Threading slides for DroidCon are very informative. It's the best reference on the topic of Android threading I have found so far.

Wednesday, November 28, 2012

Disable Eamil Notification When Adding Colleague in SharePoint 2010

By default SharePoint 2010 an email notification will be sent out when a user has added the other user as a colleague. This may not be a good idea for a big company. Consider the case that thousands of employees may add the CEO as colleague so they could follow what CEO's news feed. That would be a huge spam for the CEO. Of course anyone can go to his/her mysite and change that email notification option:



IT forks have no problem to figure out all that, but most business people in a company are not technical guys, they are busy for other stuff, and have no time or no willing to explore tons of options available in SharePoint settings. Then you may get a request to disable the email notification for all employees.

The easiest way to do that is use Powershell script to update each user's profile. Create a script called "CreateMysites.ps1":
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
#[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")

$site = Get-SPSite "http://mysites.company.com";
$ServerContext = Get-SPServiceContext $site;
$ProfileManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($ServerContext);
$ProfileEnumerators = $ProfileManager.GetEnumerator();

#Go through each user profile and update its setting
foreach ($profile in $ProfileEnumerators)
{
    try {
        $AccountName = $profile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::AccountName].Value
        if ($AccountName.ToLower().StartsWith("mydomain\")) 
        {
            #Three values map to three options shown in above screen-shot: 0 is ON and 1 is OFF
            $profile["SPS-EmailOptin"].Value = 010;
            $profile.Commit();
        }
    }
    catch [Exception] {
      write-host $_.Exception.Message;
    }
} 
$site.Dispose();
The script can be executed in SharePoint 2010 Management Shell directly. The powershell script can also be run by Windows Scheduled task. You just need to create a batch file "CreateMysites.bat" to start the powershell:
PowerShell.exe -command C:\Schedule\CreateMysites.ps1
To setup a schedule to run the script in Windows, go to SharePoint server => Administrative Tools => Task Scheduler, click Create Task action from the right-hand side panel, give a task name, set the schedule as daily, weekly or whatever you need in the Triggers tab, and then add a new Action in the Actions tab:

Sunday, November 18, 2012

Toggle Android Toast Message Manually

Android Toast shows a popup notification message for a short time then automatically fades out. Following code example will show a Toast when you touch the phone scree:

public class MainActivity extends Activity implements OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.mainLayout).setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
        Toast.makeText(this, "Toast Message", Toast.LENGTH_LONG).show();
    }
}

From the latest Toast implementation source code I noticed that the Toast message is controlled by INotificationManager:

    /**
     * Show the view for the specified duration.
     */
    public void show() {
        if (mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;

        try {
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
            // Empty
        }
    }
We can see the message text is set to a TN object. TN is an inner class that actually shows or hides the Toast message:
     private static class TN extends ITransientNotification.Stub {
          TN() {
            // XXX This should be changed to use a Dialog, with a Theme.Toast
            // defined that sets up the layout params appropriately.
            final WindowManager.LayoutParams params = mParams;
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
            params.format = PixelFormat.TRANSLUCENT;
            params.windowAnimations = com.android.internal.R.style.Animation_Toast;
            params.type = WindowManager.LayoutParams.TYPE_TOAST;
            params.setTitle("Toast");
        }

        /**
         * schedule handleShow into the right thread
         */
        public void show() {
            if (localLOGV) Log.v(TAG, "SHOW: " + this);
            mHandler.post(mShow);
        }

        /**
         * schedule handleHide into the right thread
         */
        public void hide() {
            if (localLOGV) Log.v(TAG, "HIDE: " + this);
            mHandler.post(mHide);
        }
Use reflection we can access the internal TN object, bypass the INotificationManager and show/hide the Toast message manually. Instead of fading out automatically, the result is a permanent Toast message on the screen.

Following code illustrates how to toggle Toast message manually where the Toast Message shows up when you touch the screen, and the message will stay on the screen unless you touch the screen again:

public class MainActivity extends Activity implements OnClickListener {
    private boolean isToastShowing = false;
    private Toast toast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.mainLayout).setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
        //Toast.makeText(this, "Toast Message", Toast.LENGTH_LONG).show();
        if (toast == null) {
            toast = Toast.makeText(this, "Toast Message", Toast.LENGTH_LONG);
        }
        Field mTNField;
        try {
            mTNField = toast.getClass().getDeclaredField("mTN");
            mTNField.setAccessible(true);
            Object obj = mTNField.get(toast);
            Method method;
            if (isToastShowing) {
                method = obj.getClass().getDeclaredMethod("hide", null);
                isToastShowing = false;
            } else {
                method = obj.getClass().getDeclaredMethod("show", null);
                isToastShowing = true;
            }
            method.invoke(obj, null);
        } catch (Exception e) {
            e.printStackTrace();
        }        
    }
}

Monday, November 12, 2012

Windows 8 JavaScript Access Denied Runtime Error

An exception "0x80070005 - JavaScript runtime error: Access is denied." is thrown from Windows.UI.Popups.MessageDialog.showAsync() method. It turns out that another layer of the app has already shown a MessageDialog. Windows 8 can not support multiple dialogs at one time. It simple throws this "Access is denied" error. A workaround is to chain the dialogs in sequence:

messageDialog1.showAsync().then(function () { messageDialog2.showAsync()...});

Monday, November 05, 2012

Android Service Life Cycle

Unlike Activity Android Service doesn't have a UI for user interaction, it runs in background to perform long-running actions. A Service can be initiated from Activity, AlarmManager, BroacastReceiver, or other Service. In addition, a Service can run in the same process of caller (local Service) or run in different process (remote Service). Started Services are started by startService(), and bound Services are started by bindSerivce() method, as described in Android Developer Guides. The Service life-cycle has two branches for the started Service and the bound Service:

In this post I will do some testing on how Android Service's created by Activities, and examine its clife-cycle. For simplicity the examples are the Local Service, and there's no logic to stop the Service specifically so we can see how a Service instance survives when the Activity that created it is killed. The tests are conducted in Geingerbread 2.3 and latest Jelly Bean 4.1 and they show the exact same results.

Test Service and UI

First we define a dummy TestService for our test where each callback invocation is logged:

public class TestService extends Service {
    private static final String TAG = TestService.class.getSimpleName();
    private final IBinder binder = new ServiceBinder();
    
    @Override
    public IBinder onBind(Intent arg0) {
        Log.d(TAG, "onBind()");
        return binder;
    }
    
    @Override
    public void onRebind(Intent intent) {
        Log.d(TAG, "onRebind()");
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind()");
        return super.onUnbind(intent);
    }
    
    public class ServiceBinder extends Binder {
        private final String TAGB = ServiceBinder.class.getSimpleName();
        public TestService getService() {
            Log.d(TAGB, "getService()");
            return TestService.this;
        }
    }

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate()");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy()");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }
}

We also have two Activities to do the test. The main Activity has two buttons that could start a TestService or navigate to SecondActivity. The SecondActivity only has one button to start the TestService.

Activity UI:

Activity XML definition:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/mainLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <Button
        android:id="@+id/btnGoActivty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Go to SecondActivity" 
        android:onClick="startSecondActivity" />  
     
    <Button
        android:id="@+id/btnStartService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start TestService"
        android:onClick="startTestService" /> 
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <Button
        android:id="@+id/btnStartService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start TestService" /> 
        
</LinearLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidtest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="11" />

    <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" 
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity"></activity>
        <service android:name=".TestService" ></service>
    </application>

</manifest>

Started Service

MainActivity code:

public class MainActivity extends Activity {
    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate()");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy()");
        super.onDestroy();
    }

    public void startSecondActivity(View v) {
        Log.d(TAG, "starting ServiceActivity");
        Intent activtyIntent = new Intent(MainActivity.this, SecondActivity.class);
        startActivity(activtyIntent);
    }

    public void startTestService(View v) {
        Log.d(TAG, "starting TestService");
        Intent serviceIntent = new Intent(MainActivity.this, TestService.class);
        startService(serviceIntent);
    }
}
SecondActivity:
public class SecondActivity extends Activity {
    private static final String TAG = SecondActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Button btnStartService = (Button) findViewById(R.id.btnStartService);
        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "starting TestService");
                Intent serviceIntent = new Intent(SecondActivity.this, TestService.class);
                startService(serviceIntent);
            }
        });
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy()");
        super.onDestroy();
    }
}

On the MainActivity I click "Go to SecondActivity" button, then click "Start TestService" to start the dummy service. The LogCat shows:

The TestService.onCreate() and TestService.onStartCommand() call backs are invoked when the service is started. Next click Android Back button to navigate back to MainActivity:

We can see the TestService instance remains when the SecondActivity is destroyed which initiated the Service. This is because the Service is running in background and is not tied to Activity's life-cycle.

Inside MainActivity click "Start TestService" button, the TestServcie.onStartCommand() is called but not the onCreate() callback:

If we click the Back button again the MainActivity is destroyed and the Android Home page shows up, as there's no other Activity instance in the Task stack:

Apparently the TestService is still running even though the MainActivity is gone. Unless the hosting process is killed the Service will remain running in background forever. The only exception is that Android runtime may terminate the service in low resources situations. Such runtime termination can happen in background Activities also.

By default the local Service is running in the same UI thread, and Service and Activity can communicate each other directly. A new thread is required to run the heavy long-running job inside Service to avoid blocking the main thread. Once the Service finishes its work, it can send the result back to Activity through main thread's handler. If Service is running in a different process, Broadcast mechanism could be used to do the cross-process communication.

To stop a started Service just call the stopService() method. It will stop the Service if it's running, otherwise nothing happens. Note that the number of calls to startService() is not counted, and stopService() will simply stop the Service no matter how many times the Service has been started.

Bound Service

Bound services are started by the bindService() method call. Activity or other component wishing to bind to a Service needs to have a ServiceConnection object containing onServiceConnected() and onServiceDisconnected() methods which will be called once the Service connection has been established or disconnected respectively:

    private TestService testService;
    ServiceConnection mConnection = new ServiceConnection() {  
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "Service disconnected");
            testService = null;
        }
          
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "Service connected");
            testService = ((ServiceBinder)service).getService();
            // TestService methods are reachable via testService instance
        }
    };

With the ServiceConnection created, MainActivity and SecondActivity can bind the TestService directly:

    public void startTestService(View v) {
        Log.d(TAG, "starting TestService");
        Intent serviceIntent = new Intent(MainActivity.this, TestService.class);
        bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
    }

Then we redo the experiment again: MainActivity => SecondActivity => Start Service (bindService) => Start Service (binService) => Back to MainActivity => Start Service (bindService) => click Back button to destroy MainActivity. The LogCat records:

We can see that the TestService.onCreate() is called, then the onBind() callback when TestService is bound, but subsequent bind requests do not trigger TestService.onBind(). Another significant difference comparing with started Service is that the TestService is terminated, and TestService.unbind() and TestService.onDestroy() are invoked when the bound Activity object is destroyed.

We change the action a little bit: MainActivity => Start Service (bindService) => SecondActivity => Start Service (bindService) => Start Service (bindService) => Back to MainActivity => Start Service (bindService) => Back button to destroy MainActivity:

This time the TestService is not stopped when SecondActivity is destroyed because the TestService object still has bound reference in MainActivity. Once the MainActivity is destroyed the TestService is also terminated as there's no bound reference for TestService anymore. However, if Service is already started using startService() before the bindService() call, then the Service will remain when all Activity instances are destroyed as we discussed above in started Service section. We change the MainActivity code to use startService and the result becomes:

Once the Service is bound, an IBinder object is returned to the requester, so the Activity would be able to access the Service data directly in local Service secnaros. In remote Service situations where the bound service is not running in the same process as the Activity, the recommended interaction would be the Messenger and Handler implementation.

To stop bound Services, we can invoke the unbindService() method call. As stopService(), the bound Service will be stopped on request of unbindService() invocation if started, no matter how many times bindService() are called, otherwise nothing will happen.

IntentService

IntentService is a special implementation of started Service. Internally IntentService implements a HandlerThread to process the long-running task. A simple IntentService test code:

public class TestIntentService extends IntentService {
    private static final String TAG = TestIntentService.class.getSimpleName();
    
    public TestIntentService() {
        super(TAG);
        Log.d(TAG, "Constructor()");
    }

    @Override
    protected void onHandleIntent(Intent arg0) {
        Log.d(TAG, "onHandleIntent() start...");
        try {
            Thread.sleep(5000); // pause 5 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "onHandleIntent() completed");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy()");
    }
}

We change the Service initialization code in MainActivity and SecondActivity:

    public void startTestService(View v) {
        Log.d(TAG, "starting TestIntentService");
        Intent serviceIntent = new Intent(MainActivity.this, TestIntentService.class);
        startService(serviceIntent);
    }

Run the application with following actions: MainActivity => Go to SecondActivity => Start TestIntentService (wait for more than 5 seconds) => Start TestIntentService (less than 5 seconds) => Back to MainActivity => Back button to destroy MainActivity. The logs:

Unlike started Service IntentService terminates when completes its work. Also the task in IntentService.onHandleIntent() remains running even the Activity started it is gone. This is because the task inside onHandleIntent() callback is running in a separate thread.

If we click "Start TestIntentService" a few times quickly in MainActivity:

It clearly shows that the tasks are processed in sequence, not running in parallel. This is because the tasks are pushed to IntentService's message queue, and its internal handler will execute the task one by one.

Conclusion.

  • The started Service is not bound to Activity life-cycle except the above case. Service could run in background and consuming resources even all Activity instances are closed
  • Service.onStartCommand() is guaranteed to be called for each startService() call, and Service.onCreate() is only called once for the first time the Service object is created.
  • Local bound Service could be related to Activity's life-cycle if it's not started when the bindService() is invoked, i.e. the bound Service instance will be destroyed when the Activity instance is gone.
  • Local bound Service will not be tied to Activity's life-cycle if the Service has started before the bindService() is invoked, i.e. the Service will continue to run in this case.
  • Both Service.onCreate() and Service.onBind() are invoked once for the first bindService() call, all subsequent bindService() calls won't result in any Service callback.
  • IntentService.onHandleIntent() runs in a separate thread, and processes tasks one by one in sequence. Once all tasks are completed the IntentService instance is destroyed. It's not tied to Activity life-cycle either.

Thursday, October 25, 2012

Promisable Windows Runtime Component

The async methods in Windows Runtime component can be consumed directly by C# apps, but not by JavaScript. In order to expose async method to JavaScript world, simply wrap it using AsAsyncOperation() method:
using System;
using System.Threading.Tasks;
using Windows.Foundation;

namespace WinRTComponent
{
    public sealed class Test
    {
        public IAsyncOperation<double> TestAsync(int a, int b)
        {
            return DivideAsync(a, b).AsAsyncOperation();
        }

        private static async Task<double> DivideAsync(int a, int b)
        {
            if ( b == 0 )
                throw new InvalidOperationException("Dividing by zero!");
            await Task.Delay(1000);
            return 1.0 * a / b;
        }
    }
}
Inside WinJS project you just add reference to the runtime component, and the async method will be availale (intelliSense works as well):
    WinJS.UI.Pages.define("/pages/home/home.html", {
        ready: function (element, options) {

            var tester = new WinRTComponent.Test();
            tester.testAsync(123, 2).then(function (result) {
                console.log(result);        // result = 61.5
            });
            tester.testAsync(123, 0).then(
                function (result) {
                    console.log(result);    // not reachable 
                },
                function (error) {
                    console.log(error);     // InvalidOperationException 
                });
        }
    }
Note that the async method name automatically becomes camel case (TestAsync => testAsync). Also the exception thrown by runtime component will fall to error function handler in WinJS promise then function. The exception type is visible but the original excetion string is invisible from JavaScript side:

Saturday, October 13, 2012

Android Activity Life Cycle

Android apps with UI interaction are composed of one or more Activity. It's crucial to understand Activity life cycle just as ASP.NET developers have to know how the Page object is constructed. Following image from Android developer guide shows the overall flow:

A few notes on events for different user actions:

  1. Hit home/power button: onPause() => onStop(). Stop state means in Activity in background, and it's no longer visible on the screen. From documentation Android OS could kill the activity process (onDestroy() will be called) when memory reaches a low point, but I can't effectively reproduce that in a physical device.
  2. From 1 back to activity: onRestart() => onStart() => onResume(). This is quite straightforward. If the low-memory-kill-background-process happened, a new Activity instance will be recreated from scratch.
  3. Hit back button: onPause() => onStop() => onDestroy(). The previous Activity will show up and current activity is destroyed and gone. The app will close if no previous activity exists in navigation history.
  4. Rotate the screen from landscape to portrait or vise verse: onPause() => onStop() => onDestroy() => onCreate() => onStart() => onResume(). The whole activity is destroyed and recreated. That's very different from Windows 8/Windows phone 8 implementation where that only triggers an event and the instance of the page or class remains. Android considers screen rotation, language change, storage plug/unplug, etc. as "runtime configuration change". The Activity will be reloaded by default when configuration is changed, so a new layout xml file as well as other related resources can be reconstructed properly. You can skip this behavior by overriding onConfigurationChanged method to handle the situation by your own, but such approach is not recommended from Android developer guide.

Another interesting thing is the state management, two scenarios in particular: 1. background Activity is destroyed due to low memory and then is back to active Activty; 2. foreground Activity is destroyed and rebuilt because of the screen rotation. Android provides onSaveInstanceState method for you to save your data, which is executed after the onPause(0 and before the onStop() callback handlers, then you can restore the data in onCreate() method:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // check if saved state data exists 
        if (savedInstanceState != null) {
            int prevSelectedNumber = savedInstanceState.getInt("SELECTEDNUMBER");
            // do UI logic based on prevSelectedNumber
        }
    }
 
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
 
        // save instance state data
        savedInstanceState.putInt("SELECTEDNUMBER", 123);
    }

Note that onSaveInstanceState() method is only called when the Activity is destroyed by Android OS internally like the orientation change discussed above, but it will not be called if the Activity is killed by the user action such as turning off the device or pressing the back button to go to previous Activity. In some cases, for example the address/contact input form, it would be great to keep unsaved and uncompleted data to avoid user retyping when the user is going back and forth to different screens, then the data should be saved during onPause() callback.

On top of Activities there're a set of rules defining how an Activity instance is created and behaves in one or multiple applications, e.g. a browser Activity declared as singleTask launch mode will result in only one instance running inside one Task cross the whole Android environment. The details are well described in this Android Developer Guide.

Friday, October 12, 2012

Eclipse Tips

I mainly use Visual Studio for development in the past 8 years. Recently I switch to Eclipse to do some Android work. Not like old days I had to spend a lot of time on memorizing a list of commands to run the vi editor, modern IDEs are quite easy to work with, but the right settings and handy short-cuts can still speed up your work. Below is some of my findings on Eclipse that helps me to do my work more efficiently.

Preference Settings:

1. Show code line number:

I am not sure why both Eclipse and Visual Studio are not showing line number by default. The line number is quite useful for me to pin point the source code, so I turn it on the first place.

2. Save before build but not automatically build.

Unlike Visual Studio Eclipse will not save your changes when you click build or run the application. On the other hand, Eclipse automatically build(compile) the source files in the background every time you make a change in source file. I don't like both default options and here is where you can change the behavior:

3. Enable auto insert:

This is a nice feature in Eclipse which is not available in Visual Studio or I am not aware of. Basically you can type ";" or "{" anywhere during coding and Eclipse will automatically put it to the right spot, the ending of the code line.

4. Enable step filters:

With “Step Filters” you will skip stepping into those types during debugging, so you could just focus on your own code.

Handy short-cuts

Ctrl+Space content assist just like intellisense in Visual Studio
Ctrl+Shift+F format code
Ctrl+/ comment/uncomment code with //
Ctrl+Shift+/ comment code with /**/
Ctrl+D delete line
F3 go to declaration
Ctrl+Shift+O auto import (when this available in Visual Studio?)
Ctrl+T show type hierarchy
Ctrl+Shift+T search for type
Ctrl+Shift+R search for resource
Ctrl+Shift+G find all references
Ctrl+H open advanced search window
Alt+Left/Right navigate source back and forward like Ctrl-/+ in Visual Studio

Saturday, October 06, 2012

WinJS Promise Any and Join

WinJS.Promise.any function will return another Promise object when any of the Promise objects defined in an array completes. The object passed to next Promise function from Promise.Any function has key and value properties. The key property is the array index (zero-based) of the first completed Promise, and the value property is another Promise object which wraps the return of first completed Promise, as demoed in following code snippet:
    function addAsync(number1, number2, delayInSeconds) {
        return new WinJS.Promise(function (c, m, p) {
            setTimeout(function () {
                c(number1 + number2);
            }, delayInSeconds * 1000); 
        });
    }

    function test() {
        var promise1 = addAsync(1, 1, 3);
        var promise2 = addAsync(2, 2, 2);
        var promise3 = addAsync(3, 3, 1);

        WinJS.Promise.any([promise1, promise2, promise3]).then(function (data) {
            var key = data.key;            // key = 2
            var value = data.value;        // value is a Promise
            var realValue = value._value;  // realValue = 6
        });
    }
On the other hand, Promise.join function will wait for all Promises in an array to complete before the then function starts. The same size of array holding each Promise's return will be passed to the then function:
    function addAsync(number1, number2, delayInSeconds) {
        return new WinJS.Promise(function (c, m, p) {
            setTimeout(function () {
                c(number1 + number2);
            }, delayInSeconds * 1000); 
        });
    }

    function test() {
        var promise1 = addAsync(1, 1, 3);
        var promise2 = addAsync(2, 2, 2);
        var promise3 = addAsync(3, 3, 1);

        WinJS.Promise.join([promise1, promise2, promise3]).then(function (data) {
            var promise1Return = data[0];    // promise1Return = 2
            var promise2Return = data[1];    // promise2Return = 4
            var promise3Return = data[2];    // promise3Return = 6
        });
    }
What happens if exception occurs inside the Promise? Let's change a little of the test code:
    function test() {
        var promise1 = addAsync(1, 1, 3);
        var promise2 = addAsync(2, 2, 2).then(function () { throw "promise2 error" });
        var promise3 = addAsync(3, 3, 1);

        WinJS.Promise.any([promise1, promise2, promise3]).done(function () {
            console.log("Promise.any completed");
        }, function (err) {
            console.log("Promise.any err: " + err);
        });

        WinJS.Promise.join([promise1, promise2, promise3]).done(function () {
            console.log("Promise.join completed");
        }, function (err) {
            console.log("Promise.join err: " + err);
        });
    }
The result is:
Promise.any completed
Promise.join err: ,promise2 error
We can see Promise.any function would complete successfully if any of the Promise object is completed without error. But Promise.join would fail and jump to error handler if any Promise object throws exception. There's a comma "," in error message because like the return data in okay case, the errors are wrapped to an array and mapped to the Promise index, in above case: err[0] is undefined and err[1] is "promise2 error" message.

Reference: the source of Promise.any and Promise.join is defined in base.js from WinJS library:
  any: function Promise_any(values) {
        /// <signature helpKeyword="WinJS.Promise.any">
        /// <summary locid="WinJS.Promise.any">
        /// Returns a promise that is fulfilled when one of the input promises
        /// has been fulfilled.
        /// </summary>
        /// <param name="values" type="Array" locid="WinJS.Promise.any_p:values">
        /// An array that contains promise objects or objects whose property
        /// values include promise objects.
        /// </param>
        /// <returns type="WinJS.Promise" locid="WinJS.Promise.any_returnValue">
        /// A promise that on fulfillment yields the value of the input (complete or error).
        /// </returns>
        /// </signature>
        return new Promise(
            function (complete, error, progress) {
                var keys = Object.keys(values);
                var errors = Array.isArray(values) ? [] : {};
                if (keys.length === 0) {
                    complete();
                }
                var canceled = 0;
                keys.forEach(function (key) {
                    Promise.as(values[key]).then(
                        function () { complete({ key: key, value: values[key] }); },
                        function (e) {
                            if (e instanceof Error && e.name === canceledName) {
                                if ((++canceled) === keys.length) {
                                    complete(WinJS.Promise.cancel);
                                }
                                return;
                            }
                            error({ key: key, value: values[key] });
                        }
                    );
                });
            },
            function () {
                var keys = Object.keys(values);
                keys.forEach(function (key) {
                    var promise = Promise.as(values[key]);
                    if (typeof promise.cancel === "function") {
                        promise.cancel();
                    }
                });
            }
        );
    },
  join: function Promise_join(values) {
        /// <signature helpKeyword="WinJS.Promise.join">
        /// <summary locid="WinJS.Promise.join">
        /// Creates a promise that is fulfilled when all the values are fulfilled.
        /// </summary>
        /// <param name="values" type="Object" locid="WinJS.Promise.join_p:values">
        /// An object whose fields contain values, some of which may be promises.
        /// </param>
        /// <returns type="WinJS.Promise" locid="WinJS.Promise.join_returnValue">
        /// A promise whose value is an object with the same field names as those of the object in the values parameter, where
        /// each field value is the fulfilled value of a promise.
        /// </returns>
        /// </signature>
        return new Promise(
            function (complete, error, progress) {
                var keys = Object.keys(values);
                var errors = Array.isArray(values) ? [] : {};
                var results = Array.isArray(values) ? [] : {};
                var undefineds = 0;
                var pending = keys.length;
                var argDone = function (key) {
                    if ((--pending) === 0) {
                        var errorCount = Object.keys(errors).length;
                        if (errorCount === 0) {
                            complete(results);
                        } else {
                            var canceledCount = 0;
                            keys.forEach(function (key) {
                                var e = errors[key];
                                if (e instanceof Error && e.name === canceledName) {
                                    canceledCount++;
                                }
                            });
                            if (canceledCount === errorCount) {
                                complete(WinJS.Promise.cancel);
                            } else {
                                error(errors);
                            }
                        }
                    } else {
                        progress({ Key: key, Done: true });
                    }
                };
                keys.forEach(function (key) {
                    var value = values[key];
                    if (value === undefined) {
                        undefineds++;
                    } else {
                        Promise.then(value,
                            function (value) { results[key] = value; argDone(key); },
                            function (value) { errors[key] = value; argDone(key); }
                        );
                    }
                });
                pending -= undefineds;
                if (pending === 0) {
                    complete(results);
                    return;
                }
            },
            function () {
                Object.keys(values).forEach(function (key) {
                    var promise = Promise.as(values[key]);
                    if (typeof promise.cancel === "function") {
                        promise.cancel();
                    }
                });
            }
        );
    }