From 2fa4ad8141ed0cb686c7acab27f01e8c2bc2877a Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Mon, 2 Mar 2009 22:54:43 -0800 Subject: auto import from //depot/cupcake/@137055 --- .../android/packageinstaller/InstallAppDone.java | 8 +- .../packageinstaller/PackageInstallerActivity.java | 265 +++++++++++---------- src/com/android/packageinstaller/PackageUtil.java | 25 -- .../packageinstaller/UninstallerActivity.java | 85 ++++--- 4 files changed, 209 insertions(+), 174 deletions(-) (limited to 'src/com/android/packageinstaller') diff --git a/src/com/android/packageinstaller/InstallAppDone.java b/src/com/android/packageinstaller/InstallAppDone.java index 554ed2db..5a3f7d65 100755 --- a/src/com/android/packageinstaller/InstallAppDone.java +++ b/src/com/android/packageinstaller/InstallAppDone.java @@ -20,6 +20,7 @@ import com.android.packageinstaller.R; import android.app.Activity; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -72,8 +73,11 @@ public class InstallAppDone extends Activity implements View.OnClickListener { centerTextDrawableId = R.drawable.button_indicator_finish; centerTextLabel = R.string.install_done; // Enable or disable launch button - mLaunchIntent = PackageUtil.getLaunchIntentForPackage(this, - mAppInfo.packageName); + try { + mLaunchIntent = getPackageManager().getLaunchIntentForPackage( + mAppInfo.packageName); + } catch (PackageManager.NameNotFoundException e) { + } if(mLaunchIntent != null) { mLaunchButton.setOnClickListener(this); } else { diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java index deeb8f42..29f05b43 100644 --- a/src/com/android/packageinstaller/PackageInstallerActivity.java +++ b/src/com/android/packageinstaller/PackageInstallerActivity.java @@ -24,6 +24,7 @@ import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.app.AlertDialog; +import android.app.Dialog; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -31,9 +32,11 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.DialogInterface.OnCancelListener; +import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Bundle; import android.os.FileUtils; @@ -54,10 +57,10 @@ import android.view.Window; * sub activity. All state transitions are handled in this activity */ public class PackageInstallerActivity extends Activity implements OnCancelListener { - private static final int INSTALL_INITIAL=0; - private static final int INSTALL_CONFIRM=1; - private static final int INSTALL_PROGRESS=2; - private static final int INSTALL_DONE=3; + private static final int INSTALL_INITIAL = 0; + private static final int INSTALL_CONFIRM = 1; + private static final int INSTALL_PROGRESS = 2; + private static final int INSTALL_DONE = 3; private static final String TAG = "PackageInstaller"; private Uri mPackageURI; private boolean localLOGV = false; @@ -65,13 +68,24 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen PackageManager mPm; private PackageParser.Package mPkgInfo; private File mTmpFile; - private Uri mPackageUri; - private static final int SUCCEEDED=1; - private static final int FAILED=0; + private static final int SUCCEEDED = 1; + private static final int FAILED = 0; // Broadcast receiver for clearing cache ClearCacheReceiver mClearCacheReceiver; private static final int HANDLER_BASE_MSG_IDX = 0; - private static final int FREE_SPACE = HANDLER_BASE_MSG_IDX+1; + private static final int FREE_SPACE = HANDLER_BASE_MSG_IDX + 1; + + // ApplicationInfo object primarily used for already existing applications + private ApplicationInfo mAppInfo = null; + + // Dialog identifiers used in showDialog + private static final int DLG_BASE = 0; + private static final int DLG_REPLACE_APP = DLG_BASE + 1; + private static final int DLG_UNKNOWN_APPS = DLG_BASE + 2; + private static final int DLG_PACKAGE_ERROR = DLG_BASE + 3; + private static final int DLG_OUT_OF_SPACE = DLG_BASE + 4; + private static final int DLG_INSTALL_ERROR = DLG_BASE + 5; + private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { @@ -80,7 +94,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen if(msg.arg1 == SUCCEEDED) { makeTempCopyAndInstall(); } else { - displayOutOfSpaceDialog(); + showDialogInner(DLG_OUT_OF_SPACE); } break; default: @@ -93,6 +107,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen Intent newIntent = new Intent(); startInstallActivityClass(newIntent, requestCode, cls); } + private void startInstallActivityClass(Intent newIntent, int requestCode, Class cls) { newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo); @@ -101,8 +116,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI); startActivityForResult(newIntent, requestCode); } - - + private void startInstallConfirm() { Intent newIntent = new Intent(); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, @@ -116,107 +130,112 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen startInstallActivityClass(INSTALL_PROGRESS, InstallAppProgress.class); } - private void startInstallDone(boolean result) { + private void startInstallDone() { Intent newIntent = new Intent(Intent.ACTION_VIEW); - newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, result); + newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true); startInstallActivityClass(newIntent, INSTALL_DONE, InstallAppDone.class); } - private void displayReplaceAppDialog() { - new AlertDialog.Builder(this) - .setTitle(R.string.dlg_app_replacement_title) - .setMessage(R.string.dlg_app_replacement_statement) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - startInstallConfirm(); - }}) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "Canceling installation"); - finish(); - }}) - .setOnCancelListener(this) - .show(); - } - - - /* - * Utility method to display a dialog prompting the user to turn on settings property - * before installing application - */ - private void displayUnknowAppsDialog() { - new AlertDialog.Builder(this) - .setTitle(R.string.unknown_apps_dlg_title) - .setMessage(R.string.unknown_apps_dlg_text) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "Finishing off activity so that user can navigate to settings manually"); - finish(); - }}) - .setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "Launching settings"); - launchSettingsAppAndFinish(); - } - }) - .setOnCancelListener(this) - .show(); - } - - /* - * Utility method to display a dialog indicating a parse error when parsing the package - */ - private void displayPackageErrorDialog() { - new AlertDialog.Builder(this) - .setTitle(R.string.Parse_error_dlg_title) - .setMessage(R.string.Parse_error_dlg_text) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }) - .setOnCancelListener(this) - .show(); - } - - /* - * Utility method to display dialog indicating out of disk space - */ - private void displayOutOfSpaceDialog() { - //guaranteed not to be null. will default to package name if not set by app - CharSequence appTitle = mPm.getApplicationLabel(mPkgInfo.applicationInfo); - String dlgText = getString(R.string.out_of_space_dlg_text, - appTitle.toString()); - - new AlertDialog.Builder(this) - .setTitle(R.string.out_of_space_dlg_title) - .setMessage(dlgText) - .setPositiveButton(R.string.manage_applications, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - //launch manage applications - Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); - startActivity(intent); - finish(); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "Canceling installation"); - finish(); - } - }) - .setOnCancelListener(this) - .show(); + private void showDialogInner(int id) { + // TODO better fix for this? Remove dialog so that it gets created again + removeDialog(id); + showDialog(id); } - private class PkgDataObserver extends IPackageDataObserver.Stub { - public void onRemoveCompleted(String packageName, boolean succeeded) { - Message msg = mHandler.obtainMessage(FREE_SPACE); - msg.arg1 = succeeded?SUCCEEDED:FAILED; - mHandler.sendMessage(msg); - } - } - + @Override + public Dialog onCreateDialog(int id) { + switch (id) { + case DLG_REPLACE_APP: + int msgId = R.string.dlg_app_replacement_statement; + // Customized text for system apps + if ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + msgId = R.string.dlg_sys_app_replacement_statement; + } + return new AlertDialog.Builder(this) + .setTitle(R.string.dlg_app_replacement_title) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + startInstallConfirm(); + }}) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "Canceling installation"); + finish(); + }}) + .setMessage(msgId) + .setOnCancelListener(this) + .create(); + case DLG_UNKNOWN_APPS: + return new AlertDialog.Builder(this) + .setTitle(R.string.unknown_apps_dlg_title) + .setMessage(R.string.unknown_apps_dlg_text) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "Finishing off activity so that user can navigate to settings manually"); + finish(); + }}) + .setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "Launching settings"); + launchSettingsAppAndFinish(); + } + }) + .setOnCancelListener(this) + .create(); + case DLG_PACKAGE_ERROR : + return new AlertDialog.Builder(this) + .setTitle(R.string.Parse_error_dlg_title) + .setMessage(R.string.Parse_error_dlg_text) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }) + .setOnCancelListener(this) + .create(); + case DLG_OUT_OF_SPACE: + // Guaranteed not to be null. will default to package name if not set by app + CharSequence appTitle = mPm.getApplicationLabel(mPkgInfo.applicationInfo); + String dlgText = getString(R.string.out_of_space_dlg_text, + appTitle.toString()); + return new AlertDialog.Builder(this) + .setTitle(R.string.out_of_space_dlg_title) + .setMessage(dlgText) + .setPositiveButton(R.string.manage_applications, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + //launch manage applications + Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); + startActivity(intent); + finish(); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "Canceling installation"); + finish(); + } + }) + .setOnCancelListener(this) + .create(); + case DLG_INSTALL_ERROR : + // Guaranteed not to be null. will default to package name if not set by app + CharSequence appTitle1 = mPm.getApplicationLabel(mPkgInfo.applicationInfo); + String dlgText1 = getString(R.string.install_failed_msg, + appTitle1.toString()); + return new AlertDialog.Builder(this) + .setTitle(R.string.install_failed) + .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }) + .setMessage(dlgText1) + .setOnCancelListener(this) + .create(); + } + return null; + } + private class ClearCacheReceiver extends BroadcastReceiver { public static final String INTENT_CLEAR_CACHE = "com.android.packageinstaller.CLEAR_CACHE"; @@ -288,19 +307,23 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen if(mTmpFile == null) { //display a dialog Log.e(TAG, "Error copying file locally. Failed Installation"); - displayOutOfSpaceDialog(); + showDialogInner(DLG_OUT_OF_SPACE); return; } mPackageURI = Uri.parse("file://"+mTmpFile.getPath()); // Check if package is already installed. display confirmation dialog if replacing pkg - boolean alreadyInstalled = PackageUtil.isPackageAlreadyInstalled(this, - mPkgInfo.applicationInfo.packageName); - if(alreadyInstalled) { + try { + mAppInfo = mPm.getApplicationInfo(mPkgInfo.packageName, + PackageManager.GET_UNINSTALLED_PACKAGES); + } catch (NameNotFoundException e) { + mAppInfo = null; + } + if (mAppInfo == null) { + startInstallConfirm(); + } else { if(localLOGV) Log.i(TAG, "Replacing existing package:"+ mPkgInfo.applicationInfo.packageName); - displayReplaceAppDialog(); - } else { - startInstallConfirm(); + showDialogInner(DLG_REPLACE_APP); } } @@ -310,14 +333,16 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen //get intent information final Intent intent = getIntent(); mPackageURI = intent.getData(); + mPm = getPackageManager(); mPkgInfo = PackageUtil.getPackageInfo(mPackageURI); + // Check for parse errors if(mPkgInfo == null) { Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation"); - displayPackageErrorDialog(); + showDialogInner(DLG_PACKAGE_ERROR); return; } - mPm = getPackageManager(); + //set view requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.install_start); @@ -325,7 +350,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen //check setting if(!isInstallingUnknownAppsAllowed()) { //ask user to enable setting first - displayUnknowAppsDialog(); + showDialogInner(DLG_UNKNOWN_APPS); return; } //compute the size of the application. just an estimate @@ -361,16 +386,16 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen } break; case INSTALL_PROGRESS: - boolean ok = false; finish = false; mCurrentState = INSTALL_DONE; if (resultCode == PackageManager.INSTALL_SUCCEEDED) { - ok = true; + //start the next screen to show final status of installation + startInstallDone(); + } else { + showDialogInner(DLG_INSTALL_ERROR); } // Now that the package is installed just delete the temp file removeTmpFile = true; - //start the next screen to show final status of installation - startInstallDone(ok); break; case INSTALL_DONE: //neednt check for result code here diff --git a/src/com/android/packageinstaller/PackageUtil.java b/src/com/android/packageinstaller/PackageUtil.java index 6dc782de..b36bcf2b 100644 --- a/src/com/android/packageinstaller/PackageUtil.java +++ b/src/com/android/packageinstaller/PackageUtil.java @@ -118,29 +118,4 @@ public class PackageUtil { } return false; } - - /** - * Returns an intent that can be used to launch the main activity in the given package. - * - * @param ctx - * @param packageName - * @return an intent launching the main activity in the given package - */ - public static Intent getLaunchIntentForPackage(Context ctx, String packageName) { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - PackageManager manager = ctx.getPackageManager(); - Intent intentToResolve = new Intent(Intent.ACTION_MAIN, null); - intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); - final List apps = - manager.queryIntentActivities(intentToResolve, 0); - // TODO in future add a new tag to application for launchable main activity - for (ResolveInfo app : apps) { - if (app.activityInfo.packageName.equals(packageName)) { - intent.setClassName(packageName, app.activityInfo.name); - return intent; - } - } - return null; - } } diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java index b80f8ef1..f22cc28a 100755 --- a/src/com/android/packageinstaller/UninstallerActivity.java +++ b/src/com/android/packageinstaller/UninstallerActivity.java @@ -19,6 +19,7 @@ package com.android.packageinstaller; import com.android.packageinstaller.R; import android.app.Activity; import android.app.AlertDialog; +import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -40,16 +41,59 @@ import android.content.pm.PackageManager.NameNotFoundException; public class UninstallerActivity extends Activity implements OnClickListener { private static final String TAG = "UninstallerActivity"; private boolean localLOGV = false; - //states indicating status of ui display when uninstalling application - private static final int UNINSTALL_CONFIRM=1; - private static final int UNINSTALL_PROGRESS=2; - private static final int UNINSTALL_DONE=3; + // States indicating status of ui display when uninstalling application + private static final int UNINSTALL_CONFIRM = 1; + private static final int UNINSTALL_PROGRESS = 2; + private static final int UNINSTALL_DONE = 3; private int mCurrentState = UNINSTALL_CONFIRM; PackageManager mPm; private ApplicationInfo mAppInfo; private Button mOk; private Button mCancel; + + // Dialog identifiers used in showDialog + private static final int DLG_BASE = 0; + private static final int DLG_APP_NOT_FOUND = DLG_BASE + 1; + private static final int DLG_UNINSTALL_FAILED = DLG_BASE + 2; + + private void showDialogInner(int id) { + showDialog(id); + } + @Override + public Dialog onCreateDialog(int id) { + switch (id) { + case DLG_APP_NOT_FOUND : + return new AlertDialog.Builder(this) + .setTitle(R.string.app_not_found_dlg_title) + .setIcon(com.android.internal.R.drawable.ic_dialog_alert) + .setMessage(R.string.app_not_found_dlg_text) + .setNeutralButton(getString(R.string.dlg_ok), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + }}) + .create(); + case DLG_UNINSTALL_FAILED : + // Guaranteed not to be null. will default to package name if not set by app + CharSequence appTitle = mPm.getApplicationLabel(mAppInfo); + String dlgText = getString(R.string.uninstall_failed_msg, + appTitle.toString()); + // Display uninstall failed dialog + return new AlertDialog.Builder(this) + .setTitle(R.string.uninstall_failed) + .setIcon(com.android.internal.R.drawable.ic_dialog_alert) + .setMessage(dlgText) + .setNeutralButton(getString(R.string.dlg_ok), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + }}) + .create(); + } + return null; + } + private void startUninstallProgress() { Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, @@ -58,32 +102,15 @@ public class UninstallerActivity extends Activity implements OnClickListener { startActivityForResult(newIntent, UNINSTALL_PROGRESS); } - private void startUninstallDone(boolean result) { + private void startUninstallDone() { Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mAppInfo); - newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, result); + newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true); newIntent.setClass(this, UninstallAppDone.class); startActivityForResult(newIntent, UNINSTALL_DONE); } - - private void displayErrorDialog(int msgId) { - //display confirmation dialog - new AlertDialog.Builder(this) - .setTitle(getString(R.string.app_not_found_dlg_title)) - .setIcon(com.android.internal.R.drawable.ic_dialog_alert) - .setMessage(getString(msgId)) - .setNeutralButton(getString(R.string.dlg_ok), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - //force to recompute changed value - finish(); - } - } - ) - .show(); - } - + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -93,7 +120,7 @@ public class UninstallerActivity extends Activity implements OnClickListener { String packageName = packageURI.getEncodedSchemeSpecificPart(); if(packageName == null) { Log.e(TAG, "Invalid package name:"+packageName); - displayErrorDialog(R.string.app_not_found_dlg_text); + showDialog(DLG_APP_NOT_FOUND); return; } //initialize package manager @@ -106,7 +133,7 @@ public class UninstallerActivity extends Activity implements OnClickListener { } if(mAppInfo == null || errFlag) { Log.e(TAG, "Invalid application:"+packageName); - displayErrorDialog(R.string.app_not_found_dlg_text); + showDialog(DLG_APP_NOT_FOUND); } else { requestWindowFeature(Window.FEATURE_NO_TITLE); //set view @@ -128,7 +155,11 @@ public class UninstallerActivity extends Activity implements OnClickListener { finish = false; mCurrentState = UNINSTALL_DONE; //start the next screen to show final status of installation - startUninstallDone(resultCode==UninstallAppProgress.SUCCEEDED); + if (resultCode==UninstallAppProgress.SUCCEEDED) { + startUninstallDone(); + } else { + showDialogInner(DLG_UNINSTALL_FAILED); + } break; case UNINSTALL_DONE: //neednt check for result code here -- cgit v1.2.3