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
This commit is contained in:
Suchi Amalapurapu
2009-05-08 15:01:06 -07:00
parent e3744c8c8a
commit 50b516760a
3 changed files with 234 additions and 105 deletions

View File

@@ -28,9 +28,51 @@
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:orientation="vertical">
<include
layout="@layout/manage_applications_item"
android:id="@+id/app_snippet"/>
<!-- App snippet -->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<LinearLayout
android:orientation="vertical"
android:layout_alignParentLeft="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingRight="6dip"
android:paddingLeft="6dip" >
<!-- application name -->
<TextView android:id="@+id/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="marquee"
android:layout_marginBottom="2dip" />
<!-- application version -->
<TextView android:id="@+id/app_version"
android:layout_marginTop="-4dip"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<!-- application icon -->
<ImageView android:id="@+id/app_icon"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_alignParentRight="true"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingRight="6dip"
android:scaleType="fitCenter" />
</RelativeLayout>
<TextView
style="?android:attr/listSeparatorTextViewStyle"

View File

@@ -1274,6 +1274,8 @@
<string name="uninstall_text">Uninstall</string>
<!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for exampel, remove all cached emails for an Email app) -->
<string name="clear_user_data_text">Clear data</string>
<!-- Manage applications, restore updated system application to factory version -->
<string name="app_factory_reset">Factory reset</string>
<!-- Manage applications, individual application info screen, screen, message text under Launch by default heading. This is present if the app is set as a default for some actions. -->
<string name="auto_launch_enable_text">You have selected to launch this application by default for some actions.</string>
<!-- Manage applications, individual application screen, text under Launch by default heading if the app is NOT a default for actions -->
@@ -1319,12 +1321,22 @@
found in the list of installed applications.</string>
<!-- Manage applications, individual application dialog box message. Shown when there was an error trying to clear the data. -->
<string name="clear_data_failed">Unable to clear application data.</string>
<!-- Manage applications, factory reset dialog title for system applications. -->
<string name="app_factory_reset_dlg_title">Factory reset system app</string>
<!-- Manage applications, factory reset option dialog text for system applications. -->
<string name="app_factory_reset_dlg_text">Do you want to fallback to factory version of system application?</string>
<!-- Manage applications, title for dialog if clear data fails-->
<string name="clear_failed_dlg_title">Clear data</string>
<!-- Manage applications, text for dialog if clear data fails-->
<string name="clear_failed_dlg_text">Failed clearing data for application</string>
<!-- Manage applications, individual application info screen, text that appears under the "Permissions" heading. This describes the permissions that the application has. -->
<string name="security_settings_desc">This application can access the following on your phone:</string>
<string name="computing_size">Computing\u2026</string>
<string name="invalid_size_value">Unable to compute package size</string>
<!-- String displayed when list is empty -->
<string name="empty_list_msg">You do not have any third-party apps installed.</string>
<!-- Manage applications, version string displayed in app snippet -->
<string name="version_text">version <xliff:g id="version_num">%1$s</xliff:g></string>
<!-- Language Settings --> <skip />
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings realted to locale and text -->

View File

@@ -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<ComponentName> prefActList = new ArrayList<ComponentName>();
//intent list cannot be null. so pass empty list
// Intent list cannot be null. so pass empty list
List<IntentFilter> intentList = new ArrayList<IntentFilter>();
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
}