FileDocCategorySizeDatePackage
PackageInstallerActivity.javaAPI DocAndroid 1.5 API17198Wed May 06 22:42:46 BST 2009com.android.packageinstaller

PackageInstallerActivity

public class PackageInstallerActivity extends android.app.Activity implements android.content.DialogInterface.OnCancelListener

Fields Summary
private static final int
INSTALL_INITIAL
private static final int
INSTALL_CONFIRM
private static final int
INSTALL_PROGRESS
private static final int
INSTALL_DONE
private static final String
TAG
private android.net.Uri
mPackageURI
private boolean
localLOGV
private int
mCurrentState
android.content.pm.PackageManager
mPm
private PackageParser.Package
mPkgInfo
private File
mTmpFile
private static final int
SUCCEEDED
private static final int
FAILED
ClearCacheReceiver
mClearCacheReceiver
private static final int
HANDLER_BASE_MSG_IDX
private static final int
FREE_SPACE
private android.content.pm.ApplicationInfo
mAppInfo
private static final int
DLG_BASE
private static final int
DLG_REPLACE_APP
private static final int
DLG_UNKNOWN_APPS
private static final int
DLG_PACKAGE_ERROR
private static final int
DLG_OUT_OF_SPACE
private static final int
DLG_INSTALL_ERROR
private android.os.Handler
mHandler
Constructors Summary
Methods Summary
private voidcheckOutOfSpace(long size)

        if(localLOGV) Log.i(TAG, "Checking for "+size+" number of bytes");
        if (mClearCacheReceiver == null) {
            mClearCacheReceiver = new ClearCacheReceiver();
        }
        registerReceiver(mClearCacheReceiver,
                new IntentFilter(ClearCacheReceiver.INTENT_CLEAR_CACHE));
        PendingIntent pi = PendingIntent.getBroadcast(this,
                0,  new Intent(ClearCacheReceiver.INTENT_CLEAR_CACHE), 0);
        mPm.freeStorage(size, pi);
    
private java.io.FilecreateTempPackageFile(java.lang.String filePath)

        File tmpPackageFile;
        int i = filePath.lastIndexOf("/");
        String tmpFileName;
        if(i != -1) {
            tmpFileName = filePath.substring(i+1);
        } else {
            tmpFileName = filePath;
        }
        FileOutputStream fos;
        try {
            fos=openFileOutput(tmpFileName, MODE_WORLD_READABLE);
        } catch (FileNotFoundException e1) {
            Log.e(TAG, "Error opening file "+tmpFileName);
            return null;
        }
        try {
            fos.close();
        } catch (IOException e) {
            Log.e(TAG, "Error opening file "+tmpFileName);
            return null;
        }
        tmpPackageFile=getFileStreamPath(tmpFileName);
        File srcPackageFile = new File(filePath);
        if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
            return null;
        }
        return tmpPackageFile;
    
private booleanisInstallingUnknownAppsAllowed()

        return Settings.Secure.getInt(getContentResolver(), 
            Settings.Secure.INSTALL_NON_MARKET_APPS, 0) > 0;
    
private voidlaunchSettingsAppAndFinish()

        //Create an intent to launch SettingsTwo activity
        Intent launchSettingsIntent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
        startActivity(launchSettingsIntent);
        finish();
    
private voidmakeTempCopyAndInstall()

        //copy file to tmp dir
        mTmpFile = createTempPackageFile(mPackageURI.getPath());
        if(mTmpFile == null) {
            //display a dialog
            Log.e(TAG, "Error copying file locally. Failed Installation");
            showDialogInner(DLG_OUT_OF_SPACE);
            return;
        }
        mPackageURI = Uri.parse("file://"+mTmpFile.getPath());
        // Check if package is already installed. display confirmation dialog if replacing pkg
        try {
            mAppInfo = mPm.getApplicationInfo(mPkgInfo.packageName,
                    PackageManager.GET_UNINSTALLED_PACKAGES);
        } catch (NameNotFoundException e) {
            mAppInfo = null;
        }
        if (mAppInfo == null) {
            startInstallConfirm();
        } else {
            if(localLOGV) Log.i(TAG, "Replacing existing package:"+
                    mPkgInfo.applicationInfo.packageName);
            showDialogInner(DLG_REPLACE_APP);
        }
    
protected voidonActivityResult(int requestCode, int resultCode, android.content.Intent data)

        boolean finish = true;
        boolean removeTmpFile = false;
        switch(requestCode) {
        case INSTALL_CONFIRM:
            if (resultCode == RESULT_OK) {
                finish = false;
                mCurrentState = INSTALL_PROGRESS;
                startInstallProgress();
            } else {
                removeTmpFile = true;
            }
            break;
        case INSTALL_PROGRESS:
            finish = false;
            mCurrentState = INSTALL_DONE;
            if (resultCode == PackageManager.INSTALL_SUCCEEDED) {
                //start the next screen to show final status of installation
                startInstallDone();
            } else {
                showDialogInner(DLG_INSTALL_ERROR);
            }
            // Now that the package is installed just delete the temp file
            removeTmpFile = true;
            break;
        case INSTALL_DONE:
            //neednt check for result code here
            break;
        default:
            break;
        }
        if ((removeTmpFile) && (mTmpFile != null)) {
            deleteFile(mTmpFile.getName());
        }
        if (finish) {
            //finish off this activity to return to the previous activity that launched it
            if (localLOGV) Log.i(TAG, "Finishing off activity");
            finish();
        }
    
public voidonCancel(android.content.DialogInterface dialog)

        finish();
    
public voidonCreate(android.os.Bundle icicle)

        super.onCreate(icicle);
        //get intent information
        final Intent intent = getIntent();
        mPackageURI = intent.getData();
        mPm = getPackageManager();
        mPkgInfo = PackageUtil.getPackageInfo(mPackageURI);
        
        // Check for parse errors
        if(mPkgInfo == null) {
            Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
            showDialogInner(DLG_PACKAGE_ERROR);
            return;
        }
        
        //set view
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.install_start);
        PackageUtil.initAppSnippet(this, mPkgInfo.applicationInfo, R.id.app_snippet);
       //check setting
        if(!isInstallingUnknownAppsAllowed()) {
            //ask user to enable setting first
            showDialogInner(DLG_UNKNOWN_APPS);
            return;
        }
        //compute the size of the application. just an estimate
        long size;
        String apkPath = mPackageURI.getPath();
        File apkFile = new File(apkPath);
        //TODO? DEVISE BETTER HEAURISTIC
        size = 4*apkFile.length();
        checkOutOfSpace(size);
    
public android.app.DialogonCreateDialog(int id)

        switch (id) {
        case DLG_REPLACE_APP:
            int msgId = R.string.dlg_app_replacement_statement;
            // Customized text for system apps
            if ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                msgId = R.string.dlg_sys_app_replacement_statement;
            }
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.dlg_app_replacement_title)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            startInstallConfirm();
                        }})
                    .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.i(TAG, "Canceling installation");
                            finish();
                        }})
                    .setMessage(msgId)
                    .setOnCancelListener(this)
                    .create();
        case DLG_UNKNOWN_APPS:
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.unknown_apps_dlg_title)
                    .setMessage(R.string.unknown_apps_dlg_text)
                    .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.i(TAG, "Finishing off activity so that user can navigate to settings manually");
                            finish();
                        }})
                    .setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.i(TAG, "Launching settings");
                            launchSettingsAppAndFinish();
                        }
                    })
                    .setOnCancelListener(this)
                    .create(); 
        case DLG_PACKAGE_ERROR :
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.Parse_error_dlg_title)
                    .setMessage(R.string.Parse_error_dlg_text)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .setOnCancelListener(this)
                    .create();
        case DLG_OUT_OF_SPACE:
            // Guaranteed not to be null. will default to package name if not set by app
            CharSequence appTitle = mPm.getApplicationLabel(mPkgInfo.applicationInfo);
            String dlgText = getString(R.string.out_of_space_dlg_text, 
                    appTitle.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.out_of_space_dlg_title)
                    .setMessage(dlgText)
                    .setPositiveButton(R.string.manage_applications, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            //launch manage applications
                            Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
                            startActivity(intent);   
                            finish();
                        }
                    })
                    .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            Log.i(TAG, "Canceling installation");
                            finish();
                        }
                  })
                  .setOnCancelListener(this)
                  .create();
        case DLG_INSTALL_ERROR :
            // Guaranteed not to be null. will default to package name if not set by app
            CharSequence appTitle1 = mPm.getApplicationLabel(mPkgInfo.applicationInfo);
            String dlgText1 = getString(R.string.install_failed_msg,
                    appTitle1.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.install_failed)
                    .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .setMessage(dlgText1)
                    .setOnCancelListener(this)
                    .create();
       }
       return null;
   
public voidonDestroy()

        super.onDestroy();
        // Delete the temporary file if it still exists
        if (mTmpFile != null) {
            deleteFile(mTmpFile.getName());
        }
    
private voidshowDialogInner(int id)

        // TODO better fix for this? Remove dialog so that it gets created again
        removeDialog(id);
        showDialog(id);
    
private voidstartInstallActivityClass(int requestCode, java.lang.Class cls)

   
          
        Intent newIntent = new Intent();
        startInstallActivityClass(newIntent, requestCode, cls);
    
private voidstartInstallActivityClass(android.content.Intent newIntent, int requestCode, java.lang.Class cls)

        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, 
                                                  mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        newIntent.setClass(this, cls);
        if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
        startActivityForResult(newIntent, requestCode);
    
private voidstartInstallConfirm()

        Intent newIntent = new Intent();
        newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, 
                mPkgInfo.applicationInfo);
        newIntent.setData(mPackageURI);
        newIntent.setClass(this, InstallAppConfirmation.class);
        startActivityForResult(newIntent, INSTALL_CONFIRM);
    
private voidstartInstallDone()

        Intent newIntent = new Intent(Intent.ACTION_VIEW);
        newIntent.putExtra(PackageUtil.INTENT_ATTR_INSTALL_STATUS, true);
        startInstallActivityClass(newIntent, INSTALL_DONE, InstallAppDone.class);
    
private voidstartInstallProgress()

        startInstallActivityClass(INSTALL_PROGRESS, InstallAppProgress.class);