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 com.android.packageinstaller.R; 20 21import android.app.Activity; 22import android.app.AlertDialog; 23import android.app.Dialog; 24import android.content.DialogInterface; 25import android.content.Intent; 26import android.content.DialogInterface.OnCancelListener; 27import android.content.pm.ApplicationInfo; 28import android.content.pm.IPackageInstallObserver; 29import android.content.pm.PackageInfo; 30import android.content.pm.PackageManager; 31import android.content.pm.ResolveInfo; 32import android.content.pm.PackageManager.NameNotFoundException; 33import android.graphics.drawable.LevelListDrawable; 34import android.net.Uri; 35import android.os.Bundle; 36import android.os.Handler; 37import android.os.Message; 38import android.util.Log; 39import android.view.View; 40import android.widget.Button; 41import android.widget.ProgressBar; 42import android.widget.TextView; 43 44import java.util.List; 45 46/** 47 * This activity corresponds to a download progress screen that is displayed 48 * when the user tries 49 * to install an application bundled as an apk file. The result of the application install 50 * is indicated in the result code that gets set to the corresponding installation status 51 * codes defined in PackageManager. If the package being installed already exists, 52 * the existing package is replaced with the new one. 53 */ 54public class InstallAppProgress extends Activity implements View.OnClickListener, OnCancelListener { 55 private final String TAG="InstallAppProgress"; 56 private boolean localLOGV = false; 57 private ApplicationInfo mAppInfo; 58 private Uri mPackageURI; 59 private ProgressBar mProgressBar; 60 private View mOkPanel; 61 private TextView mStatusTextView; 62 private TextView mExplanationTextView; 63 private Button mDoneButton; 64 private Button mLaunchButton; 65 private final int INSTALL_COMPLETE = 1; 66 private Intent mLaunchIntent; 67 private static final int DLG_OUT_OF_SPACE = 1; 68 private CharSequence mLabel; 69 70 private Handler mHandler = new Handler() { 71 public void handleMessage(Message msg) { 72 switch (msg.what) { 73 case INSTALL_COMPLETE: 74 if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) { 75 Intent result = new Intent(); 76 result.putExtra(Intent.EXTRA_INSTALL_RESULT, msg.arg1); 77 setResult(msg.arg1 == PackageManager.INSTALL_SUCCEEDED 78 ? Activity.RESULT_OK : Activity.RESULT_FIRST_USER, 79 result); 80 finish(); 81 return; 82 } 83 // Update the status text 84 mProgressBar.setVisibility(View.INVISIBLE); 85 // Show the ok button 86 int centerTextLabel; 87 int centerExplanationLabel = -1; 88 LevelListDrawable centerTextDrawable = (LevelListDrawable) getResources() 89 .getDrawable(R.drawable.ic_result_status); 90 if (msg.arg1 == PackageManager.INSTALL_SUCCEEDED) { 91 mLaunchButton.setVisibility(View.VISIBLE); 92 centerTextDrawable.setLevel(0); 93 centerTextLabel = R.string.install_done; 94 // Enable or disable launch button 95 mLaunchIntent = getPackageManager().getLaunchIntentForPackage( 96 mAppInfo.packageName); 97 boolean enabled = false; 98 if(mLaunchIntent != null) { 99 List<ResolveInfo> list = getPackageManager(). 100 queryIntentActivities(mLaunchIntent, 0); 101 if (list != null && list.size() > 0) { 102 enabled = true; 103 } 104 } 105 if (enabled) { 106 mLaunchButton.setOnClickListener(InstallAppProgress.this); 107 } else { 108 mLaunchButton.setEnabled(false); 109 } 110 } else if (msg.arg1 == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){ 111 showDialogInner(DLG_OUT_OF_SPACE); 112 return; 113 } else { 114 // Generic error handling for all other error codes. 115 centerTextDrawable.setLevel(1); 116 centerExplanationLabel = getExplanationFromErrorCode(msg.arg1); 117 centerTextLabel = R.string.install_failed; 118 mLaunchButton.setVisibility(View.INVISIBLE); 119 } 120 if (centerTextDrawable != null) { 121 centerTextDrawable.setBounds(0, 0, 122 centerTextDrawable.getIntrinsicWidth(), 123 centerTextDrawable.getIntrinsicHeight()); 124 mStatusTextView.setCompoundDrawables(centerTextDrawable, null, null, null); 125 } 126 mStatusTextView.setText(centerTextLabel); 127 if (centerExplanationLabel != -1) { 128 mExplanationTextView.setText(centerExplanationLabel); 129 mExplanationTextView.setVisibility(View.VISIBLE); 130 } else { 131 mExplanationTextView.setVisibility(View.GONE); 132 } 133 mDoneButton.setOnClickListener(InstallAppProgress.this); 134 mOkPanel.setVisibility(View.VISIBLE); 135 break; 136 default: 137 break; 138 } 139 } 140 }; 141 142 private int getExplanationFromErrorCode(int errCode) { 143 Log.d(TAG, "Installation error code: " + errCode); 144 switch (errCode) { 145 case PackageManager.INSTALL_FAILED_INVALID_APK: 146 return R.string.install_failed_invalid_apk; 147 case PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES: 148 return R.string.install_failed_inconsistent_certificates; 149 case PackageManager.INSTALL_FAILED_OLDER_SDK: 150 return R.string.install_failed_older_sdk; 151 case PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE: 152 return R.string.install_failed_cpu_abi_incompatible; 153 default: 154 return -1; 155 } 156 } 157 158 @Override 159 public void onCreate(Bundle icicle) { 160 super.onCreate(icicle); 161 Intent intent = getIntent(); 162 mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); 163 mPackageURI = intent.getData(); 164 initView(); 165 } 166 167 @Override 168 public Dialog onCreateDialog(int id, Bundle bundle) { 169 switch (id) { 170 case DLG_OUT_OF_SPACE: 171 String dlgText = getString(R.string.out_of_space_dlg_text, mLabel); 172 return new AlertDialog.Builder(this) 173 .setTitle(R.string.out_of_space_dlg_title) 174 .setMessage(dlgText) 175 .setPositiveButton(R.string.manage_applications, new DialogInterface.OnClickListener() { 176 public void onClick(DialogInterface dialog, int which) { 177 //launch manage applications 178 Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE"); 179 startActivity(intent); 180 finish(); 181 } 182 }) 183 .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 184 public void onClick(DialogInterface dialog, int which) { 185 Log.i(TAG, "Canceling installation"); 186 finish(); 187 } 188 }) 189 .setOnCancelListener(this) 190 .create(); 191 } 192 return null; 193 } 194 195 private void showDialogInner(int id) { 196 removeDialog(id); 197 showDialog(id); 198 } 199 200 class PackageInstallObserver extends IPackageInstallObserver.Stub { 201 public void packageInstalled(String packageName, int returnCode) { 202 Message msg = mHandler.obtainMessage(INSTALL_COMPLETE); 203 msg.arg1 = returnCode; 204 mHandler.sendMessage(msg); 205 } 206 } 207 208 public void initView() { 209 setContentView(R.layout.op_progress); 210 int installFlags = 0; 211 PackageManager pm = getPackageManager(); 212 try { 213 PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName, 214 PackageManager.GET_UNINSTALLED_PACKAGES); 215 if(pi != null) { 216 installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 217 } 218 } catch (NameNotFoundException e) { 219 } 220 if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) { 221 Log.w(TAG, "Replacing package:" + mAppInfo.packageName); 222 } 223 PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo, 224 mPackageURI); 225 mLabel = as.label; 226 PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet); 227 mStatusTextView = (TextView)findViewById(R.id.center_text); 228 mStatusTextView.setText(R.string.installing); 229 mExplanationTextView = (TextView) findViewById(R.id.center_explanation); 230 mProgressBar = (ProgressBar) findViewById(R.id.progress_bar); 231 mProgressBar.setIndeterminate(true); 232 // Hide button till progress is being displayed 233 mOkPanel = (View)findViewById(R.id.buttons_panel); 234 mDoneButton = (Button)findViewById(R.id.done_button); 235 mLaunchButton = (Button)findViewById(R.id.launch_button); 236 mOkPanel.setVisibility(View.INVISIBLE); 237 238 String installerPackageName = getIntent().getStringExtra( 239 Intent.EXTRA_INSTALLER_PACKAGE_NAME); 240 PackageInstallObserver observer = new PackageInstallObserver(); 241 pm.installPackage(mPackageURI, observer, installFlags, installerPackageName); 242 } 243 244 @Override 245 protected void onDestroy() { 246 super.onDestroy(); 247 } 248 249 public void onClick(View v) { 250 if(v == mDoneButton) { 251 if (mAppInfo.packageName != null) { 252 Log.i(TAG, "Finished installing "+mAppInfo.packageName); 253 } 254 finish(); 255 } else if(v == mLaunchButton) { 256 startActivity(mLaunchIntent); 257 finish(); 258 } 259 } 260 261 public void onCancel(DialogInterface dialog) { 262 finish(); 263 } 264} 265