summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:32:31 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:32:31 -0800
commit91ec61c3dca241befdf4a3803c45b051a3e3124f (patch)
tree59fc988de9bdfbca4bcf0b946d29bceda657fa7c /src
parent8106e501baad76e7192c7ddbb9f5e179c7ff6f9b (diff)
downloadandroid_packages_apps_PackageInstaller-91ec61c3dca241befdf4a3803c45b051a3e3124f.tar.gz
android_packages_apps_PackageInstaller-91ec61c3dca241befdf4a3803c45b051a3e3124f.tar.bz2
android_packages_apps_PackageInstaller-91ec61c3dca241befdf4a3803c45b051a3e3124f.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src')
-rwxr-xr-xsrc/com/android/packageinstaller/InstallAppConfirmation.java126
-rwxr-xr-xsrc/com/android/packageinstaller/InstallAppDone.java109
-rwxr-xr-xsrc/com/android/packageinstaller/InstallAppProgress.java114
-rw-r--r--src/com/android/packageinstaller/PackageInstallerActivity.java420
-rw-r--r--src/com/android/packageinstaller/PackageUtil.java121
-rwxr-xr-xsrc/com/android/packageinstaller/UninstallAppDone.java72
-rwxr-xr-xsrc/com/android/packageinstaller/UninstallAppProgress.java91
-rwxr-xr-xsrc/com/android/packageinstaller/UninstallerActivity.java189
8 files changed, 1242 insertions, 0 deletions
diff --git a/src/com/android/packageinstaller/InstallAppConfirmation.java b/src/com/android/packageinstaller/InstallAppConfirmation.java
new file mode 100755
index 00000000..fe7126b9
--- /dev/null
+++ b/src/com/android/packageinstaller/InstallAppConfirmation.java
@@ -0,0 +1,126 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import com.android.packageinstaller.R;
+import java.util.ArrayList;
+import android.widget.AppSecurityPermissions;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PermissionInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * This activity corresponds to a confirmation screen that is displayed when the user tries
+ * to install an application bundled as an apk file.
+ * The intent that launches this activity should include the application information object
+ * of the application(to be installed) and a list of permission strings associated
+ * with the application. This information is displayed on the screen and installation is either
+ * continued or canceled based on the user response(click ok or cancel).
+ */
+public class InstallAppConfirmation extends Activity implements View.OnClickListener {
+ private final String TAG="InstallAppConfirmation";
+ private boolean localLOGV = false;
+ private Button mOk;
+ private Button mCancel;
+ private ApplicationInfo mAppInfo;
+ private Uri mPkgURI;
+ private View mContentView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ if(localLOGV) Log.i(TAG, "intent="+intent);
+ mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+ mPkgURI = intent.getData();
+ if(localLOGV) Log.i(TAG, "mAppInfo = "+mAppInfo);
+ initView();
+ }
+
+ public void initView() {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ String unknown = getString(R.string.unknown);
+ //set description
+ String desc = getString(R.string.security_settings_desc);
+ if(desc == null) {
+ desc = unknown;
+ }
+ LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mContentView = inflater.inflate(R.layout.install_confirm, null);
+ setContentView(mContentView);
+ //initialize views
+ PackageUtil.initAppSnippet(this, mAppInfo, R.id.app_snippet);
+ if(desc != null) {
+ ((TextView)findViewById(R.id.security_settings_desc)).setText(desc);
+ }
+
+
+ LinearLayout permsView = (LinearLayout) mContentView.findViewById(
+ R.id.permissions_section);
+ boolean permVisible = false;
+ PackageParser.Package pkg = PackageUtil.getPackageInfo(mPkgURI);
+ if(pkg != null) {
+ AppSecurityPermissions asp = new AppSecurityPermissions(this, pkg);
+ if(asp.getPermissionCount() > 0) {
+ permVisible = true;
+ permsView.setVisibility(View.VISIBLE);
+ LinearLayout securityList = (LinearLayout) permsView.findViewById(
+ R.id.security_settings_list);
+ securityList.addView(asp.getPermissionsView());
+ }
+ }
+ if(!permVisible){
+ permsView.setVisibility(View.GONE);
+ }
+ mOk = (Button)findViewById(R.id.ok_button);
+ mCancel = (Button)findViewById(R.id.cancel_button);
+ mOk.setOnClickListener(this);
+ mCancel.setOnClickListener(this);
+ }
+
+ public void setResultAndReturn(int result) {
+ if(result == RESULT_CANCELED) Log.i(TAG, "Result has been canceled");
+ if(result == RESULT_OK) Log.i(TAG, "result ok");
+ setResult(result);
+ finish();
+ }
+
+ public void onClick(View v) {
+ int result = RESULT_CANCELED;
+ if(v == mOk) {
+ result = RESULT_OK;
+ setResultAndReturn(result);
+ } else if(v == mCancel) {
+ result = RESULT_CANCELED;
+ setResultAndReturn(result);
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/InstallAppDone.java b/src/com/android/packageinstaller/InstallAppDone.java
new file mode 100755
index 00000000..5a3f7d65
--- /dev/null
+++ b/src/com/android/packageinstaller/InstallAppDone.java
@@ -0,0 +1,109 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+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;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * This activity corresponds to a install status screen that is displayed
+ * when the user tries
+ * to install an application bundled as an apk file. The screen
+ * has two buttons to either launch the newly installed application
+ * or close the screen. The installation result and the package uri are passed through the
+ * intent that launches the activity.
+ */
+public class InstallAppDone extends Activity implements View.OnClickListener {
+ private final String TAG="InstallAppDone";
+ private boolean localLOGV = false;
+ private ApplicationInfo mAppInfo;
+ private Button mDoneButton;
+ private Button mLaunchButton;
+ private boolean installFlag;
+ private Intent mLaunchIntent;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+ installFlag = intent.getBooleanExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true);
+ if(localLOGV) Log.i(TAG, "installFlag="+installFlag);
+ initView();
+ }
+
+ public void initView() {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ String unknown = getString(R.string.unknown);
+ setContentView(R.layout.install_done);
+ // Initialize views
+ PackageUtil.initAppSnippet(this, mAppInfo, R.id.app_snippet);
+ TextView centerText = (TextView)findViewById(R.id.center_text);
+ mDoneButton = (Button)findViewById(R.id.done_button);
+ mLaunchButton = (Button)findViewById(R.id.launch_button);
+ int centerTextDrawableId;
+ int centerTextLabel;
+ if(installFlag) {
+ mLaunchButton.setVisibility(View.VISIBLE);
+ centerTextDrawableId = R.drawable.button_indicator_finish;
+ centerTextLabel = R.string.install_done;
+ // Enable or disable launch button
+ try {
+ mLaunchIntent = getPackageManager().getLaunchIntentForPackage(
+ mAppInfo.packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ if(mLaunchIntent != null) {
+ mLaunchButton.setOnClickListener(this);
+ } else {
+ mLaunchButton.setEnabled(false);
+ }
+ } else {
+ centerTextDrawableId = com.android.internal.R.drawable.ic_bullet_key_permission;
+ centerTextLabel = R.string.install_failed;
+ mLaunchButton.setVisibility(View.INVISIBLE);
+ }
+ Drawable centerTextDrawable = getResources().getDrawable(centerTextDrawableId);
+ centerTextDrawable.setBounds(0, 0,
+ centerTextDrawable.getIntrinsicWidth(),
+ centerTextDrawable.getIntrinsicHeight());
+ centerText.setCompoundDrawables(centerTextDrawable, null, null, null);
+ centerText.setText(getString(centerTextLabel));
+ mDoneButton.setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ if(v == mDoneButton) {
+ Log.i(TAG, "Finished installing "+mAppInfo);
+ finish();
+ } else if(v == mLaunchButton) {
+ startActivity(mLaunchIntent);
+ finish();
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/InstallAppProgress.java b/src/com/android/packageinstaller/InstallAppProgress.java
new file mode 100755
index 00000000..da1044c9
--- /dev/null
+++ b/src/com/android/packageinstaller/InstallAppProgress.java
@@ -0,0 +1,114 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import com.android.packageinstaller.R;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageInstallObserver;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Window;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+/**
+ * This activity corresponds to a download progress screen that is displayed
+ * when the user tries
+ * to install an application bundled as an apk file. The result of the application install
+ * is indicated in the result code that gets set to the corresponding installation status
+ * codes defined in PackageManager. If the package being installed already exists,
+ * the existing package is replaced with the new one.
+ */
+public class InstallAppProgress extends Activity {
+ private final String TAG="InstallAppProgress";
+ private boolean localLOGV = false;
+ private ApplicationInfo mAppInfo;
+ private Uri mPackageURI;
+ private ProgressBar mProgressBar;
+ private final int INSTALL_COMPLETE = 1;
+ private Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case INSTALL_COMPLETE:
+ //finish the activity posting result
+ setResultAndFinish(msg.arg1);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+ mPackageURI = intent.getData();
+ initView();
+ }
+
+ class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ public void packageInstalled(String packageName, int returnCode) {
+ Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
+ msg.arg1 = returnCode;
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ void setResultAndFinish(int retCode) {
+ Intent data = new Intent();
+ setResult(retCode);
+ finish();
+ }
+
+ public void initView() {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ String unknown = getString(R.string.unknown);
+ setContentView(R.layout.op_progress);
+ //initialize views
+ PackageUtil.initAppSnippet(this, mAppInfo, R.id.app_snippet);
+ TextView installTextView = (TextView)findViewById(R.id.center_text);
+ installTextView.setText(R.string.installing);
+ mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ mProgressBar.setIndeterminate(true);
+ // Set flag to replace package if already existing
+ int installFlags = 0;
+ PackageManager pm = getPackageManager();
+ try {
+ PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ if(pi != null) {
+ installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE;
+ }
+ } catch (NameNotFoundException e) {
+ }
+ if((installFlags & PackageManager.REPLACE_EXISTING_PACKAGE )!= 0) {
+ Log.w(TAG, "Replacing package:"+mAppInfo.packageName);
+ }
+ PackageInstallObserver observer = new PackageInstallObserver();
+ pm.installPackage(mPackageURI, observer, installFlags);
+ }
+}
diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java
new file mode 100644
index 00000000..29f05b43
--- /dev/null
+++ b/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -0,0 +1,420 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import com.android.packageinstaller.R;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+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;
+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;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Window;
+
+/*
+ * This activity is launched when a new application is installed via side loading
+ * The package is first parsed and the user is notified of parse errors via a dialog.
+ * If the package is successfully parsed, the user is notified to turn on the install unknown
+ * applications setting. A memory check is made at this point and the user is notified of out
+ * of memory conditions if any. If the package is already existing on the device,
+ * a confirmation dialog (to replace the existing package) is presented to the user.
+ * Based on the user response the package is then installed by launching InstallAppConfirm
+ * 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 String TAG = "PackageInstaller";
+ private Uri mPackageURI;
+ private boolean localLOGV = false;
+ private int mCurrentState = INSTALL_INITIAL;
+ PackageManager mPm;
+ private PackageParser.Package mPkgInfo;
+ private File mTmpFile;
+ 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;
+
+ // 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) {
+ case FREE_SPACE:
+ unregisterReceiver(mClearCacheReceiver);
+ if(msg.arg1 == SUCCEEDED) {
+ makeTempCopyAndInstall();
+ } else {
+ showDialogInner(DLG_OUT_OF_SPACE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ private void startInstallActivityClass(int requestCode, Class<?> cls) {
+ 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);
+ newIntent.setData(mPackageURI);
+ newIntent.setClass(this, cls);
+ 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,
+ mPkgInfo.applicationInfo);
+ newIntent.setData(mPackageURI);
+ newIntent.setClass(this, InstallAppConfirmation.class);
+ startActivityForResult(newIntent, INSTALL_CONFIRM);
+ }
+
+ private void startInstallProgress() {
+ startInstallActivityClass(INSTALL_PROGRESS, InstallAppProgress.class);
+ }
+
+ private void startInstallDone() {
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true);
+ startInstallActivityClass(newIntent, INSTALL_DONE, InstallAppDone.class);
+ }
+
+ private void showDialogInner(int id) {
+ // TODO better fix for this? Remove dialog so that it gets created again
+ removeDialog(id);
+ showDialog(id);
+ }
+
+ @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";
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Message msg = mHandler.obtainMessage(FREE_SPACE);
+ msg.arg1 = (getResultCode() ==1) ? SUCCEEDED : FAILED;
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ private void checkOutOfSpace(long size) {
+ if(localLOGV) Log.i(TAG, "Checking for "+size+" number of bytes");
+ if (mClearCacheReceiver == null) {
+ mClearCacheReceiver = new ClearCacheReceiver();
+ }
+ registerReceiver(mClearCacheReceiver,
+ new IntentFilter(ClearCacheReceiver.INTENT_CLEAR_CACHE));
+ PendingIntent pi = PendingIntent.getBroadcast(this,
+ 0, new Intent(ClearCacheReceiver.INTENT_CLEAR_CACHE), 0);
+ mPm.freeStorage(size, pi);
+ }
+
+ private void launchSettingsAppAndFinish() {
+ //Create an intent to launch SettingsTwo activity
+ Intent launchSettingsIntent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
+ startActivity(launchSettingsIntent);
+ finish();
+ }
+
+ private boolean isInstallingUnknownAppsAllowed() {
+ return Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.INSTALL_NON_MARKET_APPS, 0) > 0;
+ }
+
+ private File createTempPackageFile(String filePath) {
+ File tmpPackageFile;
+ int i = filePath.lastIndexOf("/");
+ String tmpFileName;
+ if(i != -1) {
+ tmpFileName = filePath.substring(i+1);
+ } else {
+ tmpFileName = filePath;
+ }
+ FileOutputStream fos;
+ try {
+ fos=openFileOutput(tmpFileName, MODE_WORLD_READABLE);
+ } catch (FileNotFoundException e1) {
+ Log.e(TAG, "Error opening file "+tmpFileName);
+ return null;
+ }
+ try {
+ fos.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Error opening file "+tmpFileName);
+ return null;
+ }
+ tmpPackageFile=getFileStreamPath(tmpFileName);
+ File srcPackageFile = new File(filePath);
+ if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
+ return null;
+ }
+ return tmpPackageFile;
+ }
+
+ private void makeTempCopyAndInstall() {
+ //copy file to tmp dir
+ mTmpFile = createTempPackageFile(mPackageURI.getPath());
+ if(mTmpFile == null) {
+ //display a dialog
+ Log.e(TAG, "Error copying file locally. Failed Installation");
+ showDialogInner(DLG_OUT_OF_SPACE);
+ return;
+ }
+ mPackageURI = Uri.parse("file://"+mTmpFile.getPath());
+ // Check if package is already installed. display confirmation dialog if replacing pkg
+ 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);
+ showDialogInner(DLG_REPLACE_APP);
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ //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");
+ showDialogInner(DLG_PACKAGE_ERROR);
+ return;
+ }
+
+ //set view
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.install_start);
+ PackageUtil.initAppSnippet(this, mPkgInfo.applicationInfo, R.id.app_snippet);
+ //check setting
+ if(!isInstallingUnknownAppsAllowed()) {
+ //ask user to enable setting first
+ showDialogInner(DLG_UNKNOWN_APPS);
+ return;
+ }
+ //compute the size of the application. just an estimate
+ long size;
+ String apkPath = mPackageURI.getPath();
+ File apkFile = new File(apkPath);
+ //TODO? DEVISE BETTER HEAURISTIC
+ size = 4*apkFile.length();
+ checkOutOfSpace(size);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ // Delete the temporary file if it still exists
+ if (mTmpFile != null) {
+ deleteFile(mTmpFile.getName());
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ boolean finish = true;
+ boolean removeTmpFile = false;
+ switch(requestCode) {
+ case INSTALL_CONFIRM:
+ if (resultCode == RESULT_OK) {
+ finish = false;
+ mCurrentState = INSTALL_PROGRESS;
+ startInstallProgress();
+ } else {
+ removeTmpFile = true;
+ }
+ break;
+ case INSTALL_PROGRESS:
+ finish = false;
+ mCurrentState = INSTALL_DONE;
+ if (resultCode == PackageManager.INSTALL_SUCCEEDED) {
+ //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;
+ break;
+ case INSTALL_DONE:
+ //neednt check for result code here
+ break;
+ default:
+ break;
+ }
+ if ((removeTmpFile) && (mTmpFile != null)) {
+ deleteFile(mTmpFile.getName());
+ }
+ if (finish) {
+ //finish off this activity to return to the previous activity that launched it
+ if (localLOGV) Log.i(TAG, "Finishing off activity");
+ finish();
+ }
+ }
+
+ // Generic handling when pressing back key
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+}
diff --git a/src/com/android/packageinstaller/PackageUtil.java b/src/com/android/packageinstaller/PackageUtil.java
new file mode 100644
index 00000000..b36bcf2b
--- /dev/null
+++ b/src/com/android/packageinstaller/PackageUtil.java
@@ -0,0 +1,121 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import java.io.File;
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * This is a utility class for defining some utility methods and constants
+ * used in the package installer application.
+ */
+public class PackageUtil {
+ public static final String PREFIX="com.android.packageinstaller.";
+ public static final String INTENT_ATTR_INSTALL_STATUS = PREFIX+"installStatus";
+ public static final String INTENT_ATTR_APPLICATION_INFO=PREFIX+"applicationInfo";
+ public static final String INTENT_ATTR_PERMISSIONS_LIST=PREFIX+"PermissionsList";
+ //intent attribute strings related to uninstall
+ public static final String INTENT_ATTR_PACKAGE_NAME=PREFIX+"PackageName";
+
+ /*
+ * Utility method to get application information for a given packageURI
+ */
+ public static ApplicationInfo getApplicationInfo(Uri packageURI) {
+ final String archiveFilePath = packageURI.getPath();
+ PackageParser packageParser = new PackageParser(archiveFilePath);
+ File sourceFile = new File(archiveFilePath);
+ DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+ PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+ if (pkg == null) {
+ return null;
+ }
+ return pkg.applicationInfo;
+ }
+
+ /*
+ * Utility method to get package information for a given packageURI
+ */
+ public static PackageParser.Package getPackageInfo(Uri packageURI) {
+ final String archiveFilePath = packageURI.getPath();
+ PackageParser packageParser = new PackageParser(archiveFilePath);
+ File sourceFile = new File(archiveFilePath);
+ DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+ return packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+ }
+
+ /*
+ * Utility method to get application label from package manager for a given context
+ */
+ public static CharSequence getApplicationLabel(Context context, ApplicationInfo appInfo) {
+ CharSequence appName = appInfo.loadLabel(context.getPackageManager());
+ if(appName == null) {
+ appName = context.getString(R.string.unknown);
+ }
+ return appName;
+ }
+
+ /*
+ * Utility method to getApplicationIcon from package manager for a given context
+ */
+ public static Drawable getApplicationIcon(Context context, ApplicationInfo appInfo) {
+ return appInfo.loadIcon(context.getPackageManager());
+ }
+
+ /*
+ * Utility method to display application snippet. make sure to setContentView on context
+ * before invoking this method
+ */
+ public static View initAppSnippet(Activity context, ApplicationInfo appInfo, int snippetId) {
+ View appSnippet = context.findViewById(snippetId);
+ ((ImageView)appSnippet.findViewById(R.id.app_icon)).setImageDrawable(
+ getApplicationIcon(context, appInfo));
+ ((TextView)appSnippet.findViewById(R.id.app_name)).setText(
+ getApplicationLabel(context, appInfo));
+ return appSnippet;
+ }
+
+ public static boolean isPackageAlreadyInstalled(Activity context, String pkgName) {
+ List<PackageInfo> installedList = context.getPackageManager().getInstalledPackages(
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ int installedListSize = installedList.size();
+ for(int i = 0; i < installedListSize; i++) {
+ PackageInfo tmp = installedList.get(i);
+ if(pkgName.equalsIgnoreCase(tmp.packageName)) {
+ return true;
+ }
+
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/packageinstaller/UninstallAppDone.java b/src/com/android/packageinstaller/UninstallAppDone.java
new file mode 100755
index 00000000..73dffe3d
--- /dev/null
+++ b/src/com/android/packageinstaller/UninstallAppDone.java
@@ -0,0 +1,72 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import com.android.packageinstaller.R;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * This activity corresponds to a uninstall status screen that is displayed
+ * when an application gets uninstalled. The screen contains a single ok button at the
+ * bottom.
+ */
+public class UninstallAppDone extends Activity implements View.OnClickListener {
+ private final String TAG="UninstallAppDone";
+ private boolean localLOGV = false;
+ private ApplicationInfo mAppInfo;
+ private Button mOkButton;
+ private boolean uninstallFlag;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+ //TODO set installFlag
+ uninstallFlag = intent.getBooleanExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true);
+ initView();
+ }
+
+ public void initView() {
+ String unknown = getString(R.string.unknown);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.uninstall_done);
+ TextView centerText = (TextView)findViewById(R.id.center_text);
+ if(uninstallFlag) {
+ centerText.setText(getString(R.string.uninstall_done));
+ } else {
+ centerText.setText(R.string.uninstall_failed);
+ }
+ mOkButton = (Button)findViewById(R.id.ok_button);
+ mOkButton.setOnClickListener(this);
+ }
+
+ public void onClick(View v) {
+ if(v == mOkButton) {
+ Log.i(TAG, "Finished installing "+mAppInfo);
+ finish();
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/UninstallAppProgress.java b/src/com/android/packageinstaller/UninstallAppProgress.java
new file mode 100755
index 00000000..6b30118b
--- /dev/null
+++ b/src/com/android/packageinstaller/UninstallAppProgress.java
@@ -0,0 +1,91 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package com.android.packageinstaller;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Window;
+import android.view.ViewDebug;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+/**
+ * This activity corresponds to a download progress screen that is displayed
+ * when an application is uninstalled. The result of the application uninstall
+ * is indicated in the result code that gets set to 0 or 1. The application gets launched
+ * by an intent with the intent's class name explicitly set to UninstallAppProgress and expects
+ * the application object of the application to uninstall.
+ */
+public class UninstallAppProgress extends Activity {
+ private final String TAG="UninstallAppProgress";
+ private boolean localLOGV = false;
+ private ApplicationInfo mAppInfo;
+ private final int UNINSTALL_COMPLETE = 1;
+ public final static int SUCCEEDED=1;
+ public final static int FAILED=0;
+ private Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case UNINSTALL_COMPLETE:
+ //finish the activity posting result
+ setResultAndFinish(msg.arg1);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Intent intent = getIntent();
+ mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
+ initView();
+ }
+
+ class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
+ public void packageDeleted(boolean succeeded) {
+ Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE);
+ msg.arg1 = succeeded?SUCCEEDED:FAILED;
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ void setResultAndFinish(int retCode) {
+ setResult(retCode);
+ finish();
+ }
+
+ public void initView() {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.op_progress);
+ //initialize views
+ PackageUtil.initAppSnippet(this, mAppInfo, R.id.app_snippet);
+ TextView installTextView = (TextView)findViewById(R.id.center_text);
+ installTextView.setText(R.string.uninstalling);
+ final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ progressBar.setIndeterminate(true);
+ PackageDeleteObserver observer = new PackageDeleteObserver();
+ getPackageManager().deletePackage(mAppInfo.packageName, observer, 0);
+ }
+}
diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java
new file mode 100755
index 00000000..f22cc28a
--- /dev/null
+++ b/src/com/android/packageinstaller/UninstallerActivity.java
@@ -0,0 +1,189 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+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;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+/*
+ * This activity presents UI to uninstall an application. Usually launched with intent
+ * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute
+ * com.android.packageinstaller.PackageName set to the application package name
+ */
+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;
+ 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,
+ mAppInfo);
+ newIntent.setClass(this, UninstallAppProgress.class);
+ startActivityForResult(newIntent, UNINSTALL_PROGRESS);
+ }
+
+ 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, true);
+ newIntent.setClass(this, UninstallAppDone.class);
+ startActivityForResult(newIntent, UNINSTALL_DONE);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ //get intent information
+ final Intent intent = getIntent();
+ Uri packageURI = intent.getData();
+ String packageName = packageURI.getEncodedSchemeSpecificPart();
+ if(packageName == null) {
+ Log.e(TAG, "Invalid package name:"+packageName);
+ showDialog(DLG_APP_NOT_FOUND);
+ return;
+ }
+ //initialize package manager
+ mPm = getPackageManager();
+ boolean errFlag = false;
+ try {
+ mAppInfo = mPm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (NameNotFoundException e) {
+ errFlag = true;
+ }
+ if(mAppInfo == null || errFlag) {
+ Log.e(TAG, "Invalid application:"+packageName);
+ showDialog(DLG_APP_NOT_FOUND);
+ } else {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ //set view
+ setContentView(R.layout.uninstall_confirm);
+ PackageUtil.initAppSnippet(this, mAppInfo, R.id.app_snippet);
+ //initialize ui elements
+ mOk = (Button)findViewById(R.id.ok_button);
+ mCancel = (Button)findViewById(R.id.cancel_button);
+ mOk.setOnClickListener(this);
+ mCancel.setOnClickListener(this);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ boolean finish = true;
+ switch(requestCode) {
+ case UNINSTALL_PROGRESS:
+ finish = false;
+ mCurrentState = UNINSTALL_DONE;
+ //start the next screen to show final status of installation
+ if (resultCode==UninstallAppProgress.SUCCEEDED) {
+ startUninstallDone();
+ } else {
+ showDialogInner(DLG_UNINSTALL_FAILED);
+ }
+ break;
+ case UNINSTALL_DONE:
+ //neednt check for result code here
+ break;
+ default:
+ break;
+ }
+ if(finish) {
+ //finish off this activity to return to the previous activity that launched it
+ Log.i(TAG, "Finishing off activity");
+ finish();
+ }
+ }
+
+ private void finishAndReturn() {
+ finish();
+ }
+
+ public void onClick(View v) {
+ if(v == mOk) {
+ //initiate next screen
+ startUninstallProgress();
+ } else if(v == mCancel) {
+ finishAndReturn();
+ }
+ }
+}