From 3e3e1126d588bb1fb1879c34a0f9963206ec8f22 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Fri, 29 Aug 2014 11:30:47 -0700 Subject: Use an AlertDialog for the Uninstall confirmation This allows us to get the correct theming for free moving forward. Bug:17045520 Change-Id: I173315b39816b0061c048459e1f14d81747f072b --- AndroidManifest.xml | 4 +- res/values-large/styles.xml | 21 -- res/values/styles.xml | 4 +- .../packageinstaller/UninstallerActivity.java | 278 +++++++++++---------- 4 files changed, 156 insertions(+), 151 deletions(-) delete mode 100755 res/values-large/styles.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 66d22542..ca8777d0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,7 +17,7 @@ + android:theme="@style/Theme.AlertDialogActivity"> diff --git a/res/values-large/styles.xml b/res/values-large/styles.xml deleted file mode 100755 index c7b2ec42..00000000 --- a/res/values-large/styles.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - diff --git a/res/values/styles.xml b/res/values/styles.xml index f935675f..b5d8d480 100755 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -19,6 +19,8 @@ 16dip 16dip - diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java index 531754e2..96bc9937 100755 --- a/src/com/android/packageinstaller/UninstallerActivity.java +++ b/src/com/android/packageinstaller/UninstallerActivity.java @@ -19,8 +19,10 @@ package com.android.packageinstaller; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentTransaction; import android.content.ComponentName; -import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -29,6 +31,7 @@ import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageManager; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; @@ -37,70 +40,109 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; /* * 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 { +public class UninstallerActivity extends Activity { private static final String TAG = "UninstallerActivity"; - private boolean localLOGV = false; - private PackageManager mPm; - private IPackageManager mIpm; + public static class UninstallAlertDialogFragment extends DialogFragment implements + DialogInterface.OnClickListener { + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final PackageManager pm = getActivity().getPackageManager(); + final DialogInfo dialogInfo = ((UninstallerActivity) getActivity()).mDialogInfo; + final CharSequence appLabel = dialogInfo.appInfo.loadLabel(pm); + + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); + StringBuilder messageBuilder = new StringBuilder(); + + // If the Activity label differs from the App label, then make sure the user + // knows the Activity belongs to the App being uninstalled. + if (dialogInfo.activityInfo != null) { + final CharSequence activityLabel = dialogInfo.activityInfo.loadLabel(pm); + if (!activityLabel.equals(appLabel)) { + messageBuilder.append( + getString(R.string.uninstall_activity_text, activityLabel)); + messageBuilder.append(" ").append(appLabel).append(".\n\n"); + } + } - private UserHandle mUserHandle; - private ApplicationInfo mAppInfo; - private boolean mAllUsers; - private IBinder mCallback; + final boolean isUpdate = + ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); + if (isUpdate) { + messageBuilder.append(getString(R.string.uninstall_update_text)); + } else { + UserManager userManager = UserManager.get(getActivity()); + if (dialogInfo.allUsers && userManager.getUserCount() >= 2) { + messageBuilder.append(getString(R.string.uninstall_application_text_all_users)); + } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) { + UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier()); + messageBuilder.append( + getString(R.string.uninstall_application_text_user, userInfo.name)); + } else { + messageBuilder.append(getString(R.string.uninstall_application_text)); + } + } - private Button mOk; - private Button mCancel; + dialogBuilder.setTitle(appLabel); + dialogBuilder.setIcon(dialogInfo.appInfo.loadIcon(pm)); + dialogBuilder.setPositiveButton(android.R.string.ok, this); + dialogBuilder.setNegativeButton(android.R.string.cancel, this); + dialogBuilder.setMessage(messageBuilder.toString()); + return dialogBuilder.create(); + } - // Dialog identifiers used in showDialog - private static final int DLG_BASE = 0; - private static final int DLG_APP_NOT_FOUND = DLG_BASE + 1; + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == Dialog.BUTTON_POSITIVE) { + ((UninstallerActivity) getActivity()).startUninstallProgress(); + } else { + ((UninstallerActivity) getActivity()).dispatchAborted(); + } + } - @Override - public Dialog onCreateDialog(int id) { - switch (id) { - case DLG_APP_NOT_FOUND : - return new AlertDialog.Builder(this) + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + getActivity().finish(); + } + } + + public static class AppNotFoundDialogFragment extends DialogFragment { + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) .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) { - dispatchAborted(); - setResult(Activity.RESULT_FIRST_USER); - finish(); - }}) + .setNeutralButton(android.R.string.ok, null) .create(); } - return null; - } - private void startUninstallProgress() { - Intent newIntent = new Intent(Intent.ACTION_VIEW); - newIntent.putExtra(Intent.EXTRA_USER, mUserHandle); - newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mAllUsers); - newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mCallback); - newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mAppInfo); - if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { - newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); - newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + ((UninstallerActivity) getActivity()).dispatchAborted(); + getActivity().setResult(Activity.RESULT_FIRST_USER); + getActivity().finish(); } - newIntent.setClass(this, UninstallAppProgress.class); - startActivity(newIntent); - finish(); } + static class DialogInfo { + ApplicationInfo appInfo; + ActivityInfo activityInfo; + boolean allUsers; + UserHandle user; + IBinder callback; + } + + private DialogInfo mDialogInfo; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -108,116 +150,98 @@ public class UninstallerActivity extends Activity implements OnClickListener { // We expect an intent with URI of the form package://# // className is optional; if specified, it is the activity the user chose to uninstall 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); + final Uri packageUri = intent.getData(); + if (packageUri == null) { + Log.e(TAG, "No package URI in intent"); + showAppNotFound(); + return; + } + final String packageName = packageUri.getEncodedSchemeSpecificPart(); + if (packageName == null) { + Log.e(TAG, "Invalid package name in URI: " + packageUri); + showAppNotFound(); return; } - mPm = getPackageManager(); - mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); + final IPackageManager pm = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); - mUserHandle = intent.getParcelableExtra(Intent.EXTRA_USER); - if (mUserHandle == null) { - mUserHandle = android.os.Process.myUserHandle(); + mDialogInfo = new DialogInfo(); + + mDialogInfo.user = intent.getParcelableExtra(Intent.EXTRA_USER); + if (mDialogInfo.user == null) { + mDialogInfo.user = android.os.Process.myUserHandle(); } - mAllUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false); - mCallback = intent.getIBinderExtra(PackageInstaller.EXTRA_CALLBACK); - boolean errFlag = false; + mDialogInfo.allUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false); + mDialogInfo.callback = intent.getIBinderExtra(PackageInstaller.EXTRA_CALLBACK); + try { - mAppInfo = mIpm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES, - mUserHandle.getIdentifier()); + mDialogInfo.appInfo = pm.getApplicationInfo(packageName, + PackageManager.GET_UNINSTALLED_PACKAGES, mDialogInfo.user.getIdentifier()); } catch (RemoteException e) { - errFlag = true; + Log.e(TAG, "Unable to get packageName. Package manager is dead?"); + } + + if (mDialogInfo.appInfo == null) { + Log.e(TAG, "Invalid packageName: " + packageName); + showAppNotFound(); + return; } // The class name may have been specified (e.g. when deleting an app from all apps) - String className = packageURI.getFragment(); - ActivityInfo activityInfo = null; + final String className = packageUri.getFragment(); if (className != null) { try { - activityInfo = mIpm.getActivityInfo(new ComponentName(packageName, className), 0, - mUserHandle.getIdentifier()); + mDialogInfo.activityInfo = pm.getActivityInfo( + new ComponentName(packageName, className), 0, + mDialogInfo.user.getIdentifier()); } catch (RemoteException e) { - errFlag = true; + Log.e(TAG, "Unable to get className. Package manager is dead?"); + // Continue as the ActivityInfo isn't critical. } } - if(mAppInfo == null || errFlag) { - Log.e(TAG, "Invalid packageName or componentName in " + packageURI.toString()); - showDialog(DLG_APP_NOT_FOUND); - } else { - boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); - - setContentView(R.layout.uninstall_confirm); - - TextView confirm = (TextView) findViewById(R.id.uninstall_confirm); - if (isUpdate) { - setTitle(R.string.uninstall_update_title); - confirm.setText(R.string.uninstall_update_text); - } else { - UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); - setTitle(R.string.uninstall_application_title); - if (mAllUsers && userManager.getUsers().size() >= 2) { - confirm.setText(R.string.uninstall_application_text_all_users); - } else if (!mUserHandle.equals(android.os.Process.myUserHandle())) { - String userName = userManager.getUserInfo(mUserHandle.getIdentifier()).name; - confirm.setText(String.format( - getString(R.string.uninstall_application_text_user), userName)); - } else { - confirm.setText(R.string.uninstall_application_text); - } - } - - // If an activity was specified (e.g. when dragging from All Apps to trash can), - // give a bit more info if the activity label isn't the same as the package label. - if (activityInfo != null) { - CharSequence activityLabel = activityInfo.loadLabel(mPm); - if (!activityLabel.equals(mAppInfo.loadLabel(mPm))) { - TextView activityText = (TextView) findViewById(R.id.activity_text); - CharSequence text = getString(R.string.uninstall_activity_text, activityLabel); - activityText.setText(text); - activityText.setVisibility(View.VISIBLE); - } - } + showConfirmationDialog(); + } - View snippetView = findViewById(R.id.uninstall_activity_snippet); - PackageUtil.initSnippetForInstalledApp(this, mAppInfo, snippetView, mUserHandle); + private void showConfirmationDialog() { + showDialogFragment(new UninstallAlertDialogFragment()); + } - //initialize ui elements - mOk = (Button)findViewById(R.id.ok_button); - mCancel = (Button)findViewById(R.id.cancel_button); - mOk.setOnClickListener(this); - mCancel.setOnClickListener(this); - } + private void showAppNotFound() { + showDialogFragment(new AppNotFoundDialogFragment()); } - @Override - public void onBackPressed() { - dispatchAborted(); - super.onBackPressed(); + private void showDialogFragment(DialogFragment fragment) { + FragmentTransaction ft = getFragmentManager().beginTransaction(); + Fragment prev = getFragmentManager().findFragmentByTag("dialog"); + if (prev != null) { + ft.remove(prev); + } + fragment.show(ft, "dialog"); } - @Override - public void onClick(View v) { - if(v == mOk) { - //initiate next screen - startUninstallProgress(); - } else if (v == mCancel) { - dispatchAborted(); - finish(); + void startUninstallProgress() { + Intent newIntent = new Intent(Intent.ACTION_VIEW); + newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user); + newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); + newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback); + newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo); + if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { + newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); + newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); } + newIntent.setClass(this, UninstallAppProgress.class); + startActivity(newIntent); } - private void dispatchAborted() { - if (mCallback != null) { + void dispatchAborted() { + if (mDialogInfo != null && mDialogInfo.callback != null) { final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub.asInterface( - mCallback); + mDialogInfo.callback); try { - observer.onPackageDeleted(mAppInfo.packageName, + observer.onPackageDeleted(mDialogInfo.appInfo.packageName, PackageManager.DELETE_FAILED_ABORTED, "Cancelled by user"); } catch (RemoteException ignored) { } -- cgit v1.2.3