1/* 2** 3** Copyright 2007, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17package com.android.packageinstaller; 18 19import android.app.Activity; 20import android.app.AlertDialog; 21import android.app.Dialog; 22import android.content.ComponentName; 23import android.content.DialogInterface; 24import android.content.Intent; 25import android.content.pm.ActivityInfo; 26import android.content.pm.ApplicationInfo; 27import android.content.pm.PackageManager; 28import android.content.pm.PackageManager.NameNotFoundException; 29import android.content.pm.ResolveInfo; 30import android.graphics.drawable.Drawable; 31import android.net.Uri; 32import android.os.Bundle; 33import android.util.Log; 34import android.view.LayoutInflater; 35import android.view.View; 36import android.view.View.OnClickListener; 37import android.view.ViewGroup; 38import android.view.Window; 39import android.widget.Button; 40import android.widget.TextView; 41 42import java.util.List; 43 44/* 45 * This activity presents UI to uninstall an application. Usually launched with intent 46 * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute 47 * com.android.packageinstaller.PackageName set to the application package name 48 */ 49public class UninstallerActivity extends Activity implements OnClickListener, 50 DialogInterface.OnCancelListener { 51 private static final String TAG = "UninstallerActivity"; 52 private boolean localLOGV = false; 53 PackageManager mPm; 54 private ApplicationInfo mAppInfo; 55 private Button mOk; 56 private Button mCancel; 57 58 // Dialog identifiers used in showDialog 59 private static final int DLG_BASE = 0; 60 private static final int DLG_APP_NOT_FOUND = DLG_BASE + 1; 61 private static final int DLG_UNINSTALL_FAILED = DLG_BASE + 2; 62 63 @Override 64 public Dialog onCreateDialog(int id) { 65 switch (id) { 66 case DLG_APP_NOT_FOUND : 67 return new AlertDialog.Builder(this) 68 .setTitle(R.string.app_not_found_dlg_title) 69 .setIcon(com.android.internal.R.drawable.ic_dialog_alert) 70 .setMessage(R.string.app_not_found_dlg_text) 71 .setNeutralButton(getString(R.string.dlg_ok), 72 new DialogInterface.OnClickListener() { 73 public void onClick(DialogInterface dialog, int which) { 74 setResult(Activity.RESULT_FIRST_USER); 75 finish(); 76 }}) 77 .create(); 78 case DLG_UNINSTALL_FAILED : 79 // Guaranteed not to be null. will default to package name if not set by app 80 CharSequence appTitle = mPm.getApplicationLabel(mAppInfo); 81 String dlgText = getString(R.string.uninstall_failed_msg, 82 appTitle.toString()); 83 // Display uninstall failed dialog 84 return new AlertDialog.Builder(this) 85 .setTitle(R.string.uninstall_failed) 86 .setIcon(com.android.internal.R.drawable.ic_dialog_alert) 87 .setMessage(dlgText) 88 .setNeutralButton(getString(R.string.dlg_ok), 89 new DialogInterface.OnClickListener() { 90 public void onClick(DialogInterface dialog, int which) { 91 setResult(Activity.RESULT_FIRST_USER); 92 finish(); 93 }}) 94 .create(); 95 } 96 return null; 97 } 98 99 private void startUninstallProgress() { 100 Intent newIntent = new Intent(Intent.ACTION_VIEW); 101 newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, 102 mAppInfo); 103 if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { 104 newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); 105 newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 106 } 107 newIntent.setClass(this, UninstallAppProgress.class); 108 startActivity(newIntent); 109 finish(); 110 } 111 112 @Override 113 public void onCreate(Bundle icicle) { 114 super.onCreate(icicle); 115 // Get intent information. 116 // We expect an intent with URI of the form package://<packageName>#<className> 117 // className is optional; if specified, it is the activity the user chose to uninstall 118 final Intent intent = getIntent(); 119 Uri packageURI = intent.getData(); 120 String packageName = packageURI.getEncodedSchemeSpecificPart(); 121 if(packageName == null) { 122 Log.e(TAG, "Invalid package name:" + packageName); 123 showDialog(DLG_APP_NOT_FOUND); 124 return; 125 } 126 127 mPm = getPackageManager(); 128 boolean errFlag = false; 129 try { 130 mAppInfo = mPm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); 131 } catch (NameNotFoundException e) { 132 errFlag = true; 133 } 134 135 // The class name may have been specified (e.g. when deleting an app from all apps) 136 String className = packageURI.getFragment(); 137 ActivityInfo activityInfo = null; 138 if (className != null) { 139 try { 140 activityInfo = mPm.getActivityInfo(new ComponentName(packageName, className), 0); 141 } catch (NameNotFoundException e) { 142 errFlag = true; 143 } 144 } 145 146 if(mAppInfo == null || errFlag) { 147 Log.e(TAG, "Invalid packageName or componentName in " + packageURI.toString()); 148 showDialog(DLG_APP_NOT_FOUND); 149 } else { 150 boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); 151 152 setContentView(R.layout.uninstall_confirm); 153 154 TextView confirm = (TextView) findViewById(R.id.uninstall_confirm); 155 if (isUpdate) { 156 setTitle(R.string.uninstall_update_title); 157 confirm.setText(R.string.uninstall_update_text); 158 } else { 159 setTitle(R.string.uninstall_application_title); 160 confirm.setText(R.string.uninstall_application_text); 161 } 162 163 // If an activity was specified (e.g. when dragging from All Apps to trash can), 164 // give a bit more info if the activity label isn't the same as the package label. 165 if (activityInfo != null) { 166 CharSequence activityLabel = activityInfo.loadLabel(mPm); 167 if (!activityLabel.equals(mAppInfo.loadLabel(mPm))) { 168 TextView activityText = (TextView) findViewById(R.id.activity_text); 169 CharSequence text = getString(R.string.uninstall_activity_text, activityLabel); 170 activityText.setText(text); 171 activityText.setVisibility(View.VISIBLE); 172 } 173 } 174 175 View snippetView = findViewById(R.id.uninstall_activity_snippet); 176 PackageUtil.initSnippetForInstalledApp(this, mAppInfo, snippetView); 177 178 //initialize ui elements 179 mOk = (Button)findViewById(R.id.ok_button); 180 mCancel = (Button)findViewById(R.id.cancel_button); 181 mOk.setOnClickListener(this); 182 mCancel.setOnClickListener(this); 183 } 184 } 185 186 public void onClick(View v) { 187 if(v == mOk) { 188 //initiate next screen 189 startUninstallProgress(); 190 } else if(v == mCancel) { 191 finish(); 192 } 193 } 194 195 public void onCancel(DialogInterface dialog) { 196 finish(); 197 } 198} 199