GoogleAccountLogin.java revision 081caaa34ab5af0694087c3203e39be25797455a
1539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott/* 2539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Copyright (C) 2010 The Android Open Source Project 3539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 4539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Licensed under the Apache License, Version 2.0 (the "License"); 5539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * you may not use this file except in compliance with the License. 6539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * You may obtain a copy of the License at 7539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 8539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * http://www.apache.org/licenses/LICENSE-2.0 9539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 10539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Unless required by applicable law or agreed to in writing, software 11539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * distributed under the License is distributed on an "AS IS" BASIS, 12539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * See the License for the specific language governing permissions and 14539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * limitations under the License. 15539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott */ 16539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 17539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottpackage com.android.browser; 18539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 19539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.Header; 20539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HeaderIterator; 21539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpEntity; 22539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpResponse; 23539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpStatus; 24539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.client.methods.HttpPost; 25539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.util.EntityUtils; 26539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 27539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.Account; 28539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManager; 29539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerCallback; 30539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerFuture; 31539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.app.Activity; 32539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.Context; 33539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface; 34539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface.OnCancelListener; 35539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.net.http.AndroidHttpClient; 36539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.net.Uri; 37539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.os.Bundle; 3897efb1e650b356d3fc81ff531544383362759d77Patrick Scottimport android.webkit.CookieManager; 39539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebView; 40539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebViewClient; 41539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 4297efb1e650b356d3fc81ff531544383362759d77Patrick Scottimport java.util.StringTokenizer; 43539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 44539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottpublic class GoogleAccountLogin extends Thread implements 45539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManagerCallback<Bundle>, OnCancelListener { 46539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 47539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for issuing the uber token. 48539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Uri ISSUE_AUTH_TOKEN_URL = Uri.parse( 49539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/IssueAuthToken?service=gaia&Session=false"); 50539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for signing into a particular service. 51539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final static Uri TOKEN_AUTH_URL = Uri.parse( 52539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/TokenAuth"); 53539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Google account type 54539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final static String GOOGLE = "com.google"; 55539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 56539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Activity mActivity; 57539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Account mAccount; 58539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final WebView mWebView; 59539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Runnable mRunnable; 60539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 61539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // SID and LSID retrieval process. 62539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mSid; 63539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mLsid; 64539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private int mState; // {NONE(0), SID(1), LSID(2)} 65539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 66539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott GoogleAccountLogin(Activity activity, String name) { 67539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity = activity; 68539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount = new Account(name, GOOGLE); 69539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView = new WebView(mActivity); 70539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView.setWebViewClient(new WebViewClient() { 71539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 72539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public boolean shouldOverrideUrlLoading(WebView view, String url) { 73539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return false; 74539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 75539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 76539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onPageFinished(WebView view, String url) { 77539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 78539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 79539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 80539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 81539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 82539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Thread 83539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 84539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run() { 85539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String url = ISSUE_AUTH_TOKEN_URL.buildUpon() 86539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("SID", mSid) 87539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("LSID", mLsid) 88539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 89081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // Check mRunnable to see if the request has been canceled. Otherwise 90081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // we might access a destroyed WebView. 91081caaa34ab5af0694087c3203e39be25797455aPatrick Scott String ua = null; 92081caaa34ab5af0694087c3203e39be25797455aPatrick Scott synchronized (this) { 93081caaa34ab5af0694087c3203e39be25797455aPatrick Scott if (mRunnable == null) { 94081caaa34ab5af0694087c3203e39be25797455aPatrick Scott return; 95081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 96081caaa34ab5af0694087c3203e39be25797455aPatrick Scott ua = mWebView.getSettings().getUserAgentString(); 97081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 98539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Intentionally not using Proxy. 99081caaa34ab5af0694087c3203e39be25797455aPatrick Scott AndroidHttpClient client = AndroidHttpClient.newInstance(ua); 100539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpPost request = new HttpPost(url); 101539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 102539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String result = null; 103539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 104539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpResponse response = client.execute(request); 105539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { 106539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 107539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 108539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 109539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpEntity entity = response.getEntity(); 110539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (entity == null) { 111539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 112539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 113539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 114539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott result = EntityUtils.toString(entity, "UTF-8"); 115539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 116539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott request.abort(); 117539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 118539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 119539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } finally { 120539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott client.close(); 121539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 122539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott final String newUrl = TOKEN_AUTH_URL.buildUpon() 123539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("source", "android-browser") 124539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("auth", result) 125539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("continue", 126539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott BrowserSettings.getFactoryResetHomeUrl(mActivity)) 127539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 128539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(new Runnable() { 129539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override public void run() { 130081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // Check mRunnable in case the request has been canceled. This 131081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // is most likely not necessary as run() is the only non-UI 132081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // thread that calls done() but I am paranoid. 133081caaa34ab5af0694087c3203e39be25797455aPatrick Scott synchronized (GoogleAccountLogin.this) { 134081caaa34ab5af0694087c3203e39be25797455aPatrick Scott if (mRunnable == null) { 135081caaa34ab5af0694087c3203e39be25797455aPatrick Scott return; 136081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 137081caaa34ab5af0694087c3203e39be25797455aPatrick Scott mWebView.loadUrl(newUrl); 138081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 139539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 140539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 141539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 142539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 143539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // AccountManager callbacks. 144539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 145539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run(AccountManagerFuture<Bundle> value) { 146539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 147539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String id = value.getResult().getString( 148539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.KEY_AUTHTOKEN); 149539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott switch (mState) { 150539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott default: 151539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 0: 152539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott throw new IllegalStateException( 153539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "Impossible to get into this state"); 154539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 1: 155539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mSid = id; 156539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 2; // LSID 157539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 158539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "LSID", null, mActivity, this, null); 159539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 160539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 2: 161539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mLsid = id; 162539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott this.start(); 163539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 164539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 165539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 166539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // For all exceptions load the original signin page. 167539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // TODO: toast login failed? 168539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 169539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 170539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 171539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 172539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void startLogin(Runnable runnable) { 173539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mRunnable = runnable; 174539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 1; // SID 175539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 176539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "SID", null, mActivity, this, null); 177539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 178539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 179539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Returns the account name passed in if the account exists, otherwise 180539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // returns the default account. 181539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public static String validateAccount(Context ctx, String name) { 182539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott Account[] accounts = getAccounts(ctx); 183539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (accounts.length == 0) { 184539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return null; 185539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 186539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (name != null) { 187539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Make sure the account still exists. 188539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott for (Account a : accounts) { 189539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (a.name.equals(name)) { 190539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return name; 191539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 192539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 193539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 194539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Return the first entry. 195539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return accounts[0].name; 196539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 197539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 198539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public static Account[] getAccounts(Context ctx) { 199539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return AccountManager.get(ctx).getAccountsByType(GOOGLE); 200539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 201539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 20297efb1e650b356d3fc81ff531544383362759d77Patrick Scott // Checks for the presence of the SID cookie on google.com. 20397efb1e650b356d3fc81ff531544383362759d77Patrick Scott public static boolean isLoggedIn() { 20497efb1e650b356d3fc81ff531544383362759d77Patrick Scott String cookies = CookieManager.getInstance().getCookie( 20597efb1e650b356d3fc81ff531544383362759d77Patrick Scott "http://www.google.com"); 20697efb1e650b356d3fc81ff531544383362759d77Patrick Scott if (cookies != null) { 20797efb1e650b356d3fc81ff531544383362759d77Patrick Scott StringTokenizer tokenizer = new StringTokenizer(cookies, ";"); 20897efb1e650b356d3fc81ff531544383362759d77Patrick Scott while (tokenizer.hasMoreTokens()) { 20997efb1e650b356d3fc81ff531544383362759d77Patrick Scott String cookie = tokenizer.nextToken().trim(); 21097efb1e650b356d3fc81ff531544383362759d77Patrick Scott if (cookie.startsWith("SID=")) { 21197efb1e650b356d3fc81ff531544383362759d77Patrick Scott return true; 21297efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 21397efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 21497efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 21597efb1e650b356d3fc81ff531544383362759d77Patrick Scott return false; 21697efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 21797efb1e650b356d3fc81ff531544383362759d77Patrick Scott 218539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Used to indicate that the Browser should continue loading the main page. 219539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // This can happen on success, error, or timeout. 220539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private synchronized void done() { 221539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (mRunnable != null) { 222539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(mRunnable); 223539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mRunnable = null; 224539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView.destroy(); 225539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 226539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 227539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 228539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Called by the progress dialog on startup. 229539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onCancel(DialogInterface unused) { 230539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 231539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 232539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott} 233