UninstallerActivity.java revision 596ce64f71011e7600ee2be66d977dafb86b9da3
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.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
26import android.content.pm.ActivityInfo;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.IPackageManager;
29import android.content.pm.PackageManager;
30import android.net.Uri;
31import android.os.Bundle;
32import android.os.RemoteException;
33import android.os.ServiceManager;
34import android.os.UserHandle;
35import android.os.UserManager;
36import android.util.Log;
37import android.view.View;
38import android.view.View.OnClickListener;
39import android.widget.Button;
40import android.widget.TextView;
41
42/*
43 * This activity presents UI to uninstall an application. Usually launched with intent
44 * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute
45 * com.android.packageinstaller.PackageName set to the application package name
46 */
47public class UninstallerActivity extends Activity implements OnClickListener,
48        DialogInterface.OnCancelListener {
49    private static final String TAG = "UninstallerActivity";
50    private boolean localLOGV = false;
51    PackageManager mPm;
52    private IPackageManager mIpm;
53    private ApplicationInfo mAppInfo;
54    private boolean mAllUsers;
55    private Button mOk;
56    private Button mCancel;
57    private UserHandle mUserHandle;
58
59    // Dialog identifiers used in showDialog
60    private static final int DLG_BASE = 0;
61    private static final int DLG_APP_NOT_FOUND = DLG_BASE + 1;
62    private static final int DLG_UNINSTALL_FAILED = DLG_BASE + 2;
63
64    @Override
65    public Dialog onCreateDialog(int id) {
66        switch (id) {
67        case DLG_APP_NOT_FOUND :
68            return new AlertDialog.Builder(this)
69                    .setTitle(R.string.app_not_found_dlg_title)
70                    .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
71                    .setMessage(R.string.app_not_found_dlg_text)
72                    .setNeutralButton(getString(R.string.dlg_ok),
73                            new DialogInterface.OnClickListener() {
74                                public void onClick(DialogInterface dialog, int which) {
75                                    setResult(Activity.RESULT_FIRST_USER);
76                                    finish();
77                                }})
78                    .create();
79        case DLG_UNINSTALL_FAILED :
80            // Guaranteed not to be null. will default to package name if not set by app
81           CharSequence appTitle = mPm.getApplicationLabel(mAppInfo);
82           String dlgText = getString(R.string.uninstall_failed_msg,
83                    appTitle.toString());
84            // Display uninstall failed dialog
85            return new AlertDialog.Builder(this)
86                    .setTitle(R.string.uninstall_failed)
87                    .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
88                    .setMessage(dlgText)
89                    .setNeutralButton(getString(R.string.dlg_ok),
90                            new DialogInterface.OnClickListener() {
91                                public void onClick(DialogInterface dialog, int which) {
92                                    setResult(Activity.RESULT_FIRST_USER);
93                                    finish();
94                                }})
95                    .create();
96        }
97        return null;
98    }
99
100    private void startUninstallProgress() {
101        Intent newIntent = new Intent(Intent.ACTION_VIEW);
102        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
103                                                  mAppInfo);
104        newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mAllUsers);
105        newIntent.putExtra(Intent.EXTRA_USER, mUserHandle);
106        if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
107            newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
108            newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
109        }
110        newIntent.setClass(this, UninstallAppProgress.class);
111        startActivity(newIntent);
112        finish();
113    }
114
115    @Override
116    public void onCreate(Bundle icicle) {
117        super.onCreate(icicle);
118        // Get intent information.
119        // We expect an intent with URI of the form package://<packageName>#<className>
120        // className is optional; if specified, it is the activity the user chose to uninstall
121        final Intent intent = getIntent();
122        Uri packageURI = intent.getData();
123        String packageName = packageURI.getEncodedSchemeSpecificPart();
124        if(packageName == null) {
125            Log.e(TAG, "Invalid package name:" + packageName);
126            showDialog(DLG_APP_NOT_FOUND);
127            return;
128        }
129
130        mUserHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
131        if (mUserHandle == null) {
132            mUserHandle = android.os.Process.myUserHandle();
133        }
134
135        mPm = getPackageManager();
136        mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
137
138        boolean errFlag = false;
139        try {
140            mAppInfo = mIpm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES,
141                    mUserHandle.getIdentifier());
142        } catch (RemoteException e) {
143            errFlag = true;
144        }
145
146        mAllUsers = intent.getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
147
148        // The class name may have been specified (e.g. when deleting an app from all apps)
149        String className = packageURI.getFragment();
150        ActivityInfo activityInfo = null;
151        if (className != null) {
152            try {
153                activityInfo = mIpm.getActivityInfo(new ComponentName(packageName, className), 0,
154                        mUserHandle.getIdentifier());
155            } catch (RemoteException e) {
156                errFlag = true;
157            }
158        }
159
160        if(mAppInfo == null || errFlag) {
161            Log.e(TAG, "Invalid packageName or componentName in " + packageURI.toString());
162            showDialog(DLG_APP_NOT_FOUND);
163        } else {
164            boolean isUpdate = ((mAppInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
165
166            setContentView(R.layout.uninstall_confirm);
167
168            TextView confirm = (TextView) findViewById(R.id.uninstall_confirm);
169            if (isUpdate) {
170                setTitle(R.string.uninstall_update_title);
171                confirm.setText(R.string.uninstall_update_text);
172            } else {
173                UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
174                setTitle(R.string.uninstall_application_title);
175                if (mAllUsers && userManager.getUsers().size() >= 2) {
176                    confirm.setText(R.string.uninstall_application_text_all_users);
177                } else if (!mUserHandle.equals(android.os.Process.myUserHandle())) {
178                    String userName = userManager.getUserInfo(mUserHandle.getIdentifier()).name;
179                    confirm.setText(String.format(
180                            getString(R.string.uninstall_application_text_user), userName));
181                } else {
182                    confirm.setText(R.string.uninstall_application_text);
183                }
184            }
185
186            // If an activity was specified (e.g. when dragging from All Apps to trash can),
187            // give a bit more info if the activity label isn't the same as the package label.
188            if (activityInfo != null) {
189                CharSequence activityLabel = activityInfo.loadLabel(mPm);
190                if (!activityLabel.equals(mAppInfo.loadLabel(mPm))) {
191                    TextView activityText = (TextView) findViewById(R.id.activity_text);
192                    CharSequence text = getString(R.string.uninstall_activity_text, activityLabel);
193                    activityText.setText(text);
194                    activityText.setVisibility(View.VISIBLE);
195                }
196            }
197
198            View snippetView = findViewById(R.id.uninstall_activity_snippet);
199            PackageUtil.initSnippetForInstalledApp(this, mAppInfo, snippetView, mUserHandle);
200
201            //initialize ui elements
202            mOk = (Button)findViewById(R.id.ok_button);
203            mCancel = (Button)findViewById(R.id.cancel_button);
204            mOk.setOnClickListener(this);
205            mCancel.setOnClickListener(this);
206        }
207    }
208
209    public void onClick(View v) {
210        if(v == mOk) {
211            //initiate next screen
212            startUninstallProgress();
213        } else if(v == mCancel) {
214            finish();
215        }
216    }
217
218    public void onCancel(DialogInterface dialog) {
219        finish();
220    }
221}
222