From 50b516760af7755f178d32861e2aaafb0c2bfda1 Mon Sep 17 00:00:00 2001 From: Suchi Amalapurapu Date: Fri, 8 May 2009 15:01:06 -0700 Subject: [PATCH] Add version number to Installed_App_Details Change uninstall string value to Factory reset for updated system apps present a new confirmation dialog when factory resetting a system app. refresh size, app properties and button's text(to clear, uninstall or factory reset) in onStart Add new version attribute in layout. Add new layout attributes for app snippets instead of using the one from ManageApps Use managed dialogs to avoid leaks --- res/layout/installed_app_details.xml | 48 ++- res/values/strings.xml | 12 + .../android/settings/InstalledAppDetails.java | 279 +++++++++++------- 3 files changed, 234 insertions(+), 105 deletions(-) diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml index 7c8a672608f..13d3b1006d5 100644 --- a/res/layout/installed_app_details.xml +++ b/res/layout/installed_app_details.xml @@ -28,9 +28,51 @@ android:paddingTop="5dip" android:paddingBottom="5dip" android:orientation="vertical"> - + + + + + + + + + + + + + + + Uninstall Clear data + + Factory reset You have selected to launch this application by default for some actions. @@ -1319,12 +1321,22 @@ found in the list of installed applications. Unable to clear application data. + + Factory reset system app + + Do you want to fallback to factory version of system application? + + Clear data + + Failed clearing data for application This application can access the following on your phone: Computing\u2026 Unable to compute package size You do not have any third-party apps installed. + + version %1$s diff --git a/src/com/android/settings/InstalledAppDetails.java b/src/com/android/settings/InstalledAppDetails.java index 692fc8eba45..5a4e672b9d5 100644 --- a/src/com/android/settings/InstalledAppDetails.java +++ b/src/com/android/settings/InstalledAppDetails.java @@ -22,13 +22,16 @@ import com.android.settings.R; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; +import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; +import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageStatsObserver; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageStats; import android.content.pm.PackageManager.NameNotFoundException; @@ -36,6 +39,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.RemoteException; import android.text.format.Formatter; import android.util.Config; import android.util.Log; @@ -64,9 +68,8 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene private ApplicationInfo mAppInfo; private Button mAppButton; private Button mActivitiesButton; - private boolean mCanUninstall; - private boolean localLOGV=Config.LOGV || false; - private TextView mAppSnippetSize; + private boolean localLOGV = false; + private TextView mAppVersion; private TextView mTotalSize; private TextView mAppSize; private TextView mDataSize; @@ -100,10 +103,18 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene private CharSequence mComputingStr; private CharSequence mAppButtonText; + // Dialog identifiers used in showDialog + private static final int DLG_BASE = 0; + private static final int DLG_CLEAR_DATA = DLG_BASE + 1; + private static final int DLG_FACTORY_RESET = DLG_BASE + 2; + private static final int DLG_APP_NOT_FOUND = DLG_BASE + 3; + private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 4; + // Possible btn states private enum AppButtonStates { CLEAR_DATA, UNINSTALL, + FACTORY_RESET, NONE } private AppButtonStates mAppButtonState; @@ -127,14 +138,6 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene } }; - private boolean isUninstallable() { - if (((mAppInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) && - ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0)) { - return false; - } - return true; - } - class ClearUserDataObserver extends IPackageDataObserver.Stub { public void onRemoveCompleted(final String packageName, final boolean succeeded) { final Message msg = mHandler.obtainMessage(CLEAR_USER_DATA); @@ -154,7 +157,7 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene } } - + class ClearCacheObserver extends IPackageDataObserver.Stub { public void onRemoveCompleted(final String packageName, final boolean succeeded) { final Message msg = mHandler.obtainMessage(CLEAR_CACHE); @@ -170,40 +173,13 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene return Formatter.formatFileSize(this, size); } - private void setAppBtnState() { - boolean visible = false; - if(mCanUninstall) { - //app can clear user data - if((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) - == ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) { - mAppButtonText = getText(R.string.clear_user_data_text); - mAppButtonState = AppButtonStates.CLEAR_DATA; - visible = true; - } else { - //hide button if diableClearUserData is set - visible = false; - mAppButtonState = AppButtonStates.NONE; - } - } else { - visible = true; - mAppButtonState = AppButtonStates.UNINSTALL; - mAppButtonText = getText(R.string.uninstall_text); - } - if(visible) { - mAppButton.setText(mAppButtonText); - mAppButton.setVisibility(View.VISIBLE); - } else { - mAppButton.setVisibility(View.GONE); - } - } - /** Called when the activity is first created. */ @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); - //get package manager + // Get package manager mPm = getPackageManager(); - //get application's name from intent + // Get application's name from intent Intent intent = getIntent(); final String packageName = intent.getStringExtra(ManageApplications.APP_PKG_NAME); mComputingStr = getText(R.string.computing_size); @@ -217,38 +193,26 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene PackageManager.GET_UNINSTALLED_PACKAGES); } catch (NameNotFoundException e) { Log.e(TAG, "Exception when retrieving package:"+packageName, e); - displayErrorDialog(R.string.app_not_found_dlg_text, true, true); + showDialogInner(DLG_APP_NOT_FOUND); + return; } - setContentView(R.layout.installed_app_details); - ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm)); - //set application name TODO version - CharSequence appName = mAppInfo.loadLabel(mPm); - if(appName == null) { - appName = getString(_UNKNOWN_APP); - } - ((TextView)findViewById(R.id.app_name)).setText(appName); - mAppSnippetSize = ((TextView)findViewById(R.id.app_size)); - mAppSnippetSize.setText(totalSizeStr); + setContentView(R.layout.installed_app_details); //TODO download str and download url - //set values on views + // Set default values on sizes mTotalSize = (TextView)findViewById(R.id.total_size_text); mTotalSize.setText(totalSizeStr); mAppSize = (TextView)findViewById(R.id.application_size_text); mAppSize.setText(appSizeStr); mDataSize = (TextView)findViewById(R.id.data_size_text); mDataSize.setText(dataSizeStr); - + // Get AppButton mAppButton = ((Button)findViewById(R.id.uninstall_button)); - //determine if app is a system app - mCanUninstall = !isUninstallable(); - if(localLOGV) Log.i(TAG, "Is systemPackage "+mCanUninstall); - setAppBtnState(); + // Get ManageSpaceButton mManageSpaceButton = (Button)findViewById(R.id.manage_space_button); if(mAppInfo.manageSpaceActivityName != null) { mManageSpaceButton.setVisibility(View.VISIBLE); mManageSpaceButton.setOnClickListener(this); } - // Cache section mCachePanel = findViewById(R.id.cache_panel); mCacheSize = (TextView) findViewById(R.id.cache_size_text); @@ -256,17 +220,16 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene mClearCacheButton = (Button) findViewById(R.id.clear_cache_button); mForceStopButton = (Button) findViewById(R.id.force_stop_button); mForceStopButton.setOnClickListener(this); - - //clear activities + // Get list of preferred activities mActivitiesButton = (Button)findViewById(R.id.clear_activities_button); List prefActList = new ArrayList(); - //intent list cannot be null. so pass empty list + // Intent list cannot be null. so pass empty list List intentList = new ArrayList(); mPm.getPreferredActivities(intentList, prefActList, packageName); if(localLOGV) Log.i(TAG, "Have "+prefActList.size()+" number of activities in prefered list"); TextView autoLaunchView = (TextView)findViewById(R.id.auto_launch); if(prefActList.size() <= 0) { - //disable clear activities button + // Disable clear activities button autoLaunchView.setText(R.string.auto_launch_disable_text); mActivitiesButton.setEnabled(false); } else { @@ -274,7 +237,7 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene mActivitiesButton.setOnClickListener(this); } - // security permissions section + // Security permissions section LinearLayout permsView = (LinearLayout) findViewById(R.id.permissions_section); AppSecurityPermissions asp = new AppSecurityPermissions(this, packageName); if(asp.getPermissionCount() > 0) { @@ -288,29 +251,85 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene } } - @Override - public void onStart() { - super.onStart(); + private void refreshAppAttributes(PackageInfo pkgInfo) { + setAppLabelAndIcon(); + // Version number of application + setAppVersion(pkgInfo); + setAppBtnState(); + // Refresh size info if (mAppInfo != null && mAppInfo.packageName != null) { mPm.getPackageSizeInfo(mAppInfo.packageName, mSizeObserver); } } - private void displayErrorDialog(int msgId, final boolean finish, final boolean changed) { - //display confirmation dialog - new AlertDialog.Builder(this) - .setTitle(getString(R.string.app_not_found_dlg_title)) - .setIcon(android.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 - setIntentAndFinish(finish, changed); - } + // Utility method to set applicaiton label and icon. + private void setAppLabelAndIcon() { + ((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mAppInfo.loadIcon(mPm)); + //set application name TODO version + CharSequence appName = mAppInfo.loadLabel(mPm); + if(appName == null) { + appName = getString(_UNKNOWN_APP); + } + ((TextView)findViewById(R.id.app_name)).setText(appName); + } + + // Utility method to set application version + private void setAppVersion(PackageInfo pkgInfo) { + // Version number of application + mAppVersion = ((TextView)findViewById(R.id.app_version)); + if (pkgInfo != null) { + mAppVersion.setVisibility(View.VISIBLE); + mAppVersion.setText(getString(R.string.version_text, + String.valueOf(pkgInfo.versionCode))); + } else { + mAppVersion.setVisibility(View.GONE); + } + } + + // Utility method to set button state + private void setAppBtnState() { + boolean visible = true; + if ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + if ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { + mAppButtonState = AppButtonStates.FACTORY_RESET; + mAppButtonText = getText(R.string.app_factory_reset); + } else { + if ((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) { + // Hide button if diableClearUserData is set + mAppButtonState = AppButtonStates.NONE; + visible = false; + } else { + mAppButtonState = AppButtonStates.CLEAR_DATA; + mAppButtonText = getText(R.string.clear_user_data_text); } - ) - .show(); + } + } else { + mAppButtonState = AppButtonStates.UNINSTALL; + mAppButtonText = getText(R.string.uninstall_text); + } + if(visible) { + mAppButton.setText(mAppButtonText); + mAppButton.setVisibility(View.VISIBLE); + } else { + mAppButton.setVisibility(View.GONE); + } + } + + @Override + public void onStart() { + super.onStart(); + PackageInfo pkgInfo; + // Get application info again to refresh changed properties of application + try { + mAppInfo = mPm.getApplicationInfo(mAppInfo.packageName, + PackageManager.GET_UNINSTALLED_PACKAGES); + pkgInfo = mPm.getPackageInfo(mAppInfo.packageName, 0); + } catch (NameNotFoundException e) { + Log.e(TAG, "Exception when retrieving package:" + mAppInfo.packageName, e); + showDialogInner(DLG_APP_NOT_FOUND); + return; + } + refreshAppAttributes(pkgInfo); } private void setIntentAndFinish(boolean finish, boolean appChanged) { @@ -337,7 +356,6 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene mSizeInfo = newPs; String str = getSizeStr(newTot); mTotalSize.setText(str); - mAppSnippetSize.setText(str); mAppSize.setText(getSizeStr(newPs.codeSize)); mDataSize.setText(getSizeStr(newPs.dataSize)); mCacheSize.setText(getSizeStr(newPs.cacheSize)); @@ -346,7 +364,6 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene if(newTot != oldTot) { String str = getSizeStr(newTot); mTotalSize.setText(str); - mAppSnippetSize.setText(str); changed = true; } if(newPs.codeSize != mSizeInfo.codeSize) { @@ -421,14 +438,76 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); boolean res = am.clearApplicationUserData(packageName, mClearDataObserver); if(!res) { - //doesnt initiate clear. some error. should not happen but just log error for now + // Clearing data failed for some obscure reason. Just log error for now Log.i(TAG, "Couldnt clear application user data for package:"+packageName); - displayErrorDialog(R.string.clear_data_failed, false, false); + showDialogInner(DLG_CANNOT_CLEAR_DATA); } else { mAppButton.setText(R.string.recompute_size); } } + private void showDialogInner(int id) { + //removeDialog(id); + showDialog(id); + } + + @Override + public Dialog onCreateDialog(int id) { + switch (id) { + case DLG_CLEAR_DATA: + return new AlertDialog.Builder(this) + .setTitle(getString(R.string.clear_data_dlg_title)) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(getString(R.string.clear_data_dlg_text)) + .setPositiveButton(R.string.dlg_ok, this) + .setNegativeButton(R.string.dlg_cancel, this) + .create(); + case DLG_FACTORY_RESET: + return new AlertDialog.Builder(this) + .setTitle(getString(R.string.app_factory_reset_dlg_title)) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(getString(R.string.app_factory_reset_dlg_text)) + .setPositiveButton(R.string.dlg_ok, this) + .setNegativeButton(R.string.dlg_cancel, this) + .create(); + case DLG_APP_NOT_FOUND: + return new AlertDialog.Builder(this) + .setTitle(getString(R.string.app_not_found_dlg_title)) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(getString(R.string.app_not_found_dlg_title)) + .setNeutralButton(getString(R.string.dlg_ok), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + //force to recompute changed value + setIntentAndFinish(true, true); + } + }) + .create(); + case DLG_CANNOT_CLEAR_DATA: + return new AlertDialog.Builder(this) + .setTitle(getString(R.string.clear_failed_dlg_title)) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(getString(R.string.clear_failed_dlg_text)) + .setNeutralButton(R.string.dlg_ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + //force to recompute changed value + setIntentAndFinish(false, false); + } + }) + .create(); + } + return null; + } + + private void uninstallPkg(String packageName) { + // Create new intent to launch Uninstaller activity + Uri packageURI = Uri.parse("package:"+packageName); + Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI); + startActivity(uninstallIntent); + setIntentAndFinish(true, true); + } + /* * Method implementing functionality of buttons clicked * @see android.view.View.OnClickListener#onClick(android.view.View) @@ -436,21 +515,12 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene public void onClick(View v) { String packageName = mAppInfo.packageName; if(v == mAppButton) { - if(mCanUninstall) { - //display confirmation dialog - new AlertDialog.Builder(this) - .setTitle(getString(R.string.clear_data_dlg_title)) - .setIcon(android.R.drawable.ic_dialog_alert) - .setMessage(getString(R.string.clear_data_dlg_text)) - .setPositiveButton(R.string.dlg_ok, this) - .setNegativeButton(R.string.dlg_cancel, this) - .show(); - } else { - //create new intent to launch Uninstaller activity - Uri packageURI = Uri.parse("package:"+packageName); - Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI); - startActivity(uninstallIntent); - setIntentAndFinish(true, true); + if (mAppButtonState == AppButtonStates.CLEAR_DATA) { + showDialogInner(DLG_CLEAR_DATA); + } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) { + showDialogInner(DLG_FACTORY_RESET); + } else if (mAppButtonState == AppButtonStates.UNINSTALL) { + uninstallPkg(packageName); } } else if(v == mActivitiesButton) { mPm.clearPackagePreferredActivities(packageName); @@ -474,8 +544,13 @@ public class InstalledAppDetails extends Activity implements View.OnClickListene public void onClick(DialogInterface dialog, int which) { if(which == AlertDialog.BUTTON_POSITIVE) { - //invoke uninstall or clear user data based on sysPackage - initiateClearUserDataForSysPkg(); + if (mAppButtonState == AppButtonStates.CLEAR_DATA) { + // Invoke uninstall or clear user data based on sysPackage + initiateClearUserDataForSysPkg(); + } else if (mAppButtonState == AppButtonStates.FACTORY_RESET) { + // Initiate package installer to delete package + uninstallPkg(mAppInfo.packageName); + } } else { //cancel do nothing just retain existing screen }