Android 7.1 PackageInstaller(应用安装器)增加自动点击安装

平台

RK3288 + Android 7.1

需求

修改系统源码, 通过Intent附带参数, 支持自动点击安装下一步, 调用代码

Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
File apkFile = new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk";
install.putExtra("confirm", true);
install.setDataAndType(Uri.fromFile(apkFile)), "application/vnd.android.package-archive");
startActivity(install)

补丁

diff --git a/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index e600dd8..f6cf2c7 100644
--- a/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -564,6 +564,12 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
         } else {
             initiateInstall();
         }
+		// add confirm extra for install package.
+        boolean confirm = intent.getBooleanExtra("confirm", true);
+        if(!confirm){
+			mOkCanInstall = true;
+			onClick(mOk);
+		}
     }
 
     /** Get the ApplicationInfo for the calling package, if available */

修改后源码文件

/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package com.android.packageinstaller;

import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.ManifestDigest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.ResolveInfo;
import android.content.pm.VerificationParams;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AppSecurityPermissions;
import android.widget.Button;
import android.widget.TabHost;
import android.widget.TextView;

import java.io.File;
import java.util.List;

/*
 * This activity is launched when a new application is installed via side loading
 * The package is first parsed and the user is notified of parse errors via a dialog.
 * If the package is successfully parsed, the user is notified to turn on the install unknown
 * applications setting. A memory check is made at this point and the user is notified of out
 * of memory conditions if any. If the package is already existing on the device,
 * a confirmation dialog (to replace the existing package) is presented to the user.
 * Based on the user response the package is then installed by launching InstallAppConfirm
 * sub activity. All state transitions are handled in this activity
 */
public class PackageInstallerActivity extends Activity implements OnCancelListener, OnClickListener {
    private static final String TAG = "PackageInstaller";

    private int mSessionId = -1;
    private Uri mPackageURI;
    private Uri mOriginatingURI;
    private Uri mReferrerURI;
    private int mOriginatingUid = VerificationParams.NO_UID;
    private ManifestDigest mPkgDigest;

    private boolean localLOGV = false;
    PackageManager mPm;
    UserManager mUserManager;
    PackageInstaller mInstaller;
    PackageInfo mPkgInfo;
    ApplicationInfo mSourceInfo;

    // ApplicationInfo object primarily used for already existing applications
    private ApplicationInfo mAppInfo = null;

    private InstallFlowAnalytics mInstallFlowAnalytics;

    // View for install progress
    View mInstallConfirm;
    // Buttons to indicate user acceptance
    private Button mOk;
    private Button mCancel;
    CaffeinatedScrollView mScrollView = null;
    private boolean mOkCanInstall = false;

    static final String PREFS_ALLOWED_SOURCES = "allowed_sources";

    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";

    private static final String TAB_ID_ALL = "all";
    private static final String TAB_ID_NEW = "new";

    // Dialog identifiers used in showDialog
    private static final int DLG_BASE = 0;
    private static final int DLG_UNKNOWN_SOURCES = DLG_BASE + 1;
    private static final int DLG_PACKAGE_ERROR = DLG_BASE + 2;
    private static final int DLG_OUT_OF_SPACE = DLG_BASE + 3;
    private static final int DLG_INSTALL_ERROR = DLG_BASE + 4;
    private static final int DLG_ALLOW_SOURCE = DLG_BASE + 5;
    private static final int DLG_ADMIN_RESTRICTS_UNKNOWN_SOURCES = DLG_BASE + 6;

    private void startInstallConfirm() {
        TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
        tabHost.setup();
        ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
        TabsAdapter adapter = new TabsAdapter(this, tabHost, viewPager);
        adapter.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
            @Override
            public void onTabChanged(String tabId) {
                if (TAB_ID_ALL.equals(tabId)) {
                    mInstallFlowAnalytics.setAllPermissionsDisplayed(true);
                } else if (TAB_ID_NEW.equals(tabId)) {
                    mInstallFlowAnalytics.setNewPermissionsDisplayed(true);
                }
            }
        });

        boolean permVisible = false;
        mScrollView = null;
        mOkCanInstall = false;
        int msg = 0;
        if (mPkgInfo != null) {
            AppSecurityPermissions perms = new AppSecurityPermissions(this, mPkgInfo);
            final int NP = perms.getPermissionCount(AppSecurityPermissions.WHICH_PERSONAL);
            final int ND = perms.getPermissionCount(AppSecurityPermissions.WHICH_DEVICE);
            if (mAppInfo != null) {
                msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
                        ? R.string.install_confirm_question_update_system
                        : R.string.install_confirm_question_update;
                mScrollView = new CaffeinatedScrollView(this);
                mScrollView.setFillViewport(true);
                boolean newPermissionsFound =
                        (perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW) > 0);
                mInstallFlowAnalytics.setNewPermissionsFound(newPermissionsFound);
                if (newPermissionsFound) {
                    permVisible = true;
                    mScrollView.addView(perms.getPermissionsView(
                            AppSecurityPermissions.WHICH_NEW));
                } else {
                    LayoutInflater inflater = (LayoutInflater)getSystemService(
                            Context.LAYOUT_INFLATER_SERVICE);
                    TextView label = (TextView)inflater.inflate(R.layout.label, null);
                    label.setText(R.string.no_new_perms);
                    mScrollView.addView(label);
                }
                adapter.addTab(tabHost.newTabSpec(TAB_ID_NEW).setIndicator(
                        getText(R.string.newPerms)), mScrollView);
            } else  {
                findViewById(R.id.tabscontainer).setVisibility(View.GONE);
                findViewById(R.id.divider).setVisibility(View.VISIBLE);
            }
            if (NP > 0 || ND > 0) {
                permVisible = true;
                LayoutInflater inflater = (LayoutInflater)getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE);
                View root = inflater.inflate(R.layout.permissions_list, null);
                if (mScrollView == null) {
                    mScrollView = (CaffeinatedScrollView)root.findViewById(R.id.scrollview);
                }
                if (NP > 0) {
                    ((ViewGroup)root.findViewById(R.id.privacylist)).addView(
                            perms.getPermissionsView(AppSecurityPermissions.WHICH_PERSONAL));
                } else {
                    root.findViewById(R.id.privacylist).setVisibility(View.GONE);
                }
                if (ND > 0) {
                    ((ViewGroup)root.findViewById(R.id.devicelist)).addView(
                            perms.getPermissionsView(AppSecurityPermissions.WHICH_DEVICE));
                } else {
                    root.findViewById(R.id.devicelist).setVisibility(View.GONE);
                }
                adapter.addTab(tabHost.newTabSpec(TAB_ID_ALL).setIndicator(
                        getText(R.string.allPerms)), root);
            }
        }
        mInstallFlowAnalytics.setPermissionsDisplayed(permVisible);
        if (!permVisible) {
            if (mAppInfo != null) {
                // This is an update to an application, but there are no
                // permissions at all.
                msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
                        ? R.string.install_confirm_question_update_system_no_perms
                        : R.string.install_confirm_question_update_no_perms;
            } else {
                // This is a new application with no permissions.
                msg = R.string.install_confirm_question_no_perms;
            }
            tabHost.setVisibility(View.GONE);
            mInstallFlowAnalytics.setAllPermissionsDisplayed(false);
            mInstallFlowAnalytics.setNewPermissionsDisplayed(false);
            findViewById(R.id.filler).setVisibility(View.VISIBLE);
            findViewById(R.id.divider).setVisibility(View.GONE);
            mScrollView = null;
        }
        if (msg != 0) {
            ((TextView)findViewById(R.id.install_confirm_question)).setText(msg);
        }
        mInstallConfirm.setVisibility(View.VISIBLE);
        mOk = (Button)findViewById(R.id.ok_button);
        mCancel = (Button)findViewById(R.id.cancel_button);
        mOk.setOnClickListener(this);
        mCancel.setOnClickListener(this);
        if (mScrollView == null) {
            // There is nothing to scroll view, so the ok button is immediately
            // set to install.
            mOk.setText(R.string.install);
            mOkCanInstall = true;
        } else {
            mScrollView.setFullScrollAction(new Runnable() {
                @Override
                public void run() {
                    mOk.setText(R.string.install);
                    mOkCanInstall = true;
                }
            });
        }
    }

    private void showDialogInner(int id) {
        // TODO better fix for this? Remove dialog so that it gets created again
        removeDialog(id);
        showDialog(id);
    }

    @Override
    public Dialog onCreateDialog(int id, Bundle bundle) {
        switch (id) {
        case DLG_UNKNOWN_SOURCES:
            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_ADMIN_RESTRICTS_UNKNOWN_SOURCES:
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.unknown_apps_dlg_title)
                    .setMessage(R.string.unknown_apps_admin_dlg_text)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .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");
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            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();
        case DLG_ALLOW_SOURCE:
            CharSequence appTitle2 = mPm.getApplicationLabel(mSourceInfo);
            String dlgText2 = getString(R.string.allow_source_dlg_text,
                    appTitle2.toString());
            return new AlertDialog.Builder(this)
                    .setTitle(R.string.allow_source_dlg_title)
                    .setMessage(dlgText2)
                    .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            setResult(RESULT_CANCELED);
                            finish();
                        }})
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            SharedPreferences prefs = getSharedPreferences(PREFS_ALLOWED_SOURCES,
                                    Context.MODE_PRIVATE);
                            prefs.edit().putBoolean(mSourceInfo.packageName, true).apply();
                            startInstallConfirm();
                        }
                    })
                    .setOnCancelListener(this)
                    .create();
       }
       return null;
   }

    private void launchSettingsAppAndFinish() {
        // Create an intent to launch SettingsTwo activity
        Intent launchSettingsIntent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
        launchSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(launchSettingsIntent);
        finish();
    }

    private boolean isInstallRequestFromUnknownSource(Intent intent) {
        String callerPackage = getCallingPackage();
        if (callerPackage != null && intent.getBooleanExtra(
                Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)) {
            try {
                mSourceInfo = mPm.getApplicationInfo(callerPackage, 0);
                if (mSourceInfo != null) {
                    if ((mSourceInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
                        // Privileged apps are not considered an unknown source.
                        return false;
                    }
                }
            } catch (NameNotFoundException e) {
            }
        }

        return true;
    }

    private boolean isVerifyAppsEnabled() {
        if (mUserManager.hasUserRestriction(UserManager.ENSURE_VERIFY_APPS)) {
            return true;
        }
        return Settings.Global.getInt(getContentResolver(),
                Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0;
    }

    private boolean isAppVerifierInstalled() {
        final PackageManager pm = getPackageManager();
        final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
        verification.setType(PACKAGE_MIME_TYPE);
        verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
        return (receivers.size() > 0) ? true : false;
    }

    /**
     * @return whether unknown sources is enabled by user in Settings
     */
    private boolean isUnknownSourcesEnabled() {
        return Settings.Secure.getInt(getContentResolver(),
                Settings.Secure.INSTALL_NON_MARKET_APPS, 0) > 0;
    }

    /**
     * @return whether the device admin restricts installation from unknown sources
     */
    private boolean isUnknownSourcesAllowedByAdmin() {
        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
    }

    private void initiateInstall() {
        String pkgName = mPkgInfo.packageName;
        // Check if there is already a package on the device with this name
        // but it has been renamed to something else.
        String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
        if (oldName != null && oldName.length > 0 && oldName[0] != null) {
            pkgName = oldName[0];
            mPkgInfo.packageName = pkgName;
            mPkgInfo.applicationInfo.packageName = pkgName;
        }
        // Check if package is already installed. display confirmation dialog if replacing pkg
        try {
            // This is a little convoluted because we want to get all uninstalled
            // apps, but this may include apps with just data, and if it is just
            // data we still want to count it as "installed".
            mAppInfo = mPm.getApplicationInfo(pkgName,
                    PackageManager.GET_UNINSTALLED_PACKAGES);
            if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
                mAppInfo = null;
            }
        } catch (NameNotFoundException e) {
            mAppInfo = null;
        }

        mInstallFlowAnalytics.setReplace(mAppInfo != null);
        mInstallFlowAnalytics.setSystemApp(
                (mAppInfo != null) && ((mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0));

        startInstallConfirm();
    }

    void setPmResult(int pmResult) {
        Intent result = new Intent();
        result.putExtra(Intent.EXTRA_INSTALL_RESULT, pmResult);
        setResult(pmResult == PackageManager.INSTALL_SUCCEEDED
                ? RESULT_OK : RESULT_FIRST_USER, result);
    }

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mPm = getPackageManager();
        mInstaller = mPm.getPackageInstaller();
        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);

        final Intent intent = getIntent();
        if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) {
            final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
            final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
            if (info == null || !info.sealed || info.resolvedBaseCodePath == null) {
                Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
                finish();
                return;
            }

            mSessionId = sessionId;
            mPackageURI = Uri.fromFile(new File(info.resolvedBaseCodePath));
            mOriginatingURI = null;
            mReferrerURI = null;
        } else {
            mSessionId = -1;
            mPackageURI = intent.getData();
            mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
            mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
        }

        final boolean unknownSourcesAllowedByAdmin = isUnknownSourcesAllowedByAdmin();
        final boolean unknownSourcesAllowedByUser = isUnknownSourcesEnabled();

        boolean requestFromUnknownSource = isInstallRequestFromUnknownSource(intent);
        mInstallFlowAnalytics = new InstallFlowAnalytics();
        mInstallFlowAnalytics.setContext(this);
        mInstallFlowAnalytics.setStartTimestampMillis(SystemClock.elapsedRealtime());
        mInstallFlowAnalytics.setInstallsFromUnknownSourcesPermitted(unknownSourcesAllowedByAdmin
                && unknownSourcesAllowedByUser);
        mInstallFlowAnalytics.setInstallRequestFromUnknownSource(requestFromUnknownSource);
        mInstallFlowAnalytics.setVerifyAppsEnabled(isVerifyAppsEnabled());
        mInstallFlowAnalytics.setAppVerifierInstalled(isAppVerifierInstalled());
        mInstallFlowAnalytics.setPackageUri(mPackageURI.toString());

        final String scheme = mPackageURI.getScheme();
        if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) {
            Log.w(TAG, "Unsupported scheme " + scheme);
            setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
            mInstallFlowAnalytics.setFlowFinished(
                    InstallFlowAnalytics.RESULT_FAILED_UNSUPPORTED_SCHEME);
            finish();
            return;
        }

        final PackageUtil.AppSnippet as;
        if ("package".equals(mPackageURI.getScheme())) {
            mInstallFlowAnalytics.setFileUri(false);
            try {
                mPkgInfo = mPm.getPackageInfo(mPackageURI.getSchemeSpecificPart(),
                        PackageManager.GET_PERMISSIONS | PackageManager.GET_UNINSTALLED_PACKAGES);
            } catch (NameNotFoundException e) {
            }
            if (mPkgInfo == null) {
                Log.w(TAG, "Requested package " + mPackageURI.getScheme()
                        + " not available. Discontinuing installation");
                showDialogInner(DLG_PACKAGE_ERROR);
                setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
                mInstallFlowAnalytics.setPackageInfoObtained();
                mInstallFlowAnalytics.setFlowFinished(
                        InstallFlowAnalytics.RESULT_FAILED_PACKAGE_MISSING);
                return;
            }
            as = new PackageUtil.AppSnippet(mPm.getApplicationLabel(mPkgInfo.applicationInfo),
                    mPm.getApplicationIcon(mPkgInfo.applicationInfo));
        } else {
            mInstallFlowAnalytics.setFileUri(true);
            final File sourceFile = new File(mPackageURI.getPath());
            PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);

            // Check for parse errors
            if (parsed == null) {
                Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
                showDialogInner(DLG_PACKAGE_ERROR);
                setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
                mInstallFlowAnalytics.setPackageInfoObtained();
                mInstallFlowAnalytics.setFlowFinished(
                        InstallFlowAnalytics.RESULT_FAILED_TO_GET_PACKAGE_INFO);
                return;
            }
            mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
                    PackageManager.GET_PERMISSIONS, 0, 0, null,
                    new PackageUserState());
            mPkgDigest = parsed.manifestDigest;
            as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
        }
        mInstallFlowAnalytics.setPackageInfoObtained();

        //set view
        setContentView(R.layout.install_start);
        mInstallConfirm = findViewById(R.id.install_confirm_panel);
        mInstallConfirm.setVisibility(View.INVISIBLE);
        PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);

        mOriginatingUid = getOriginatingUid(intent);

        // Block the install attempt on the Unknown Sources setting if necessary.
        if (!requestFromUnknownSource) {
            initiateInstall();
            return;
        }

        // If the admin prohibits it, or we're running in a managed profile, just show error
        // and exit. Otherwise show an option to take the user to Settings to change the setting.
        final boolean isManagedProfile = mUserManager.isManagedProfile();
        if (!unknownSourcesAllowedByAdmin
                || (!unknownSourcesAllowedByUser && isManagedProfile)) {
            showDialogInner(DLG_ADMIN_RESTRICTS_UNKNOWN_SOURCES);
            mInstallFlowAnalytics.setFlowFinished(
                    InstallFlowAnalytics.RESULT_BLOCKED_BY_UNKNOWN_SOURCES_SETTING);
        } else if (!unknownSourcesAllowedByUser) {
            // Ask user to enable setting first
            showDialogInner(DLG_UNKNOWN_SOURCES);
            mInstallFlowAnalytics.setFlowFinished(
                    InstallFlowAnalytics.RESULT_BLOCKED_BY_UNKNOWN_SOURCES_SETTING);
        } else {
            initiateInstall();
        }
		//add confirm extra for install package.
        boolean confirm = intent.getBooleanExtra("confirm", true);
        if(!confirm){
			mOkCanInstall = true;
			onClick(mOk);
		}
    }

    /** Get the ApplicationInfo for the calling package, if available */
    private ApplicationInfo getSourceInfo() {
        String callingPackage = getCallingPackage();
        if (callingPackage != null) {
            try {
                return mPm.getApplicationInfo(callingPackage, 0);
            } catch (NameNotFoundException ex) {
                // ignore
            }
        }
        return null;
    }


    /** Get the originating uid if possible, or VerificationParams.NO_UID if not available */
    private int getOriginatingUid(Intent intent) {
        // The originating uid from the intent. We only trust/use this if it comes from a
        // system application
        int uidFromIntent = intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
                VerificationParams.NO_UID);

        // Get the source info from the calling package, if available. This will be the
        // definitive calling package, but it only works if the intent was started using
        // startActivityForResult,
        ApplicationInfo sourceInfo = getSourceInfo();
        if (sourceInfo != null) {
            if (uidFromIntent != VerificationParams.NO_UID &&
                    (mSourceInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
                return uidFromIntent;

            }
            // We either didn't get a uid in the intent, or we don't trust it. Use the
            // uid of the calling package instead.
            return sourceInfo.uid;
        }

        // We couldn't get the specific calling package. Let's get the uid instead
        int callingUid;
        try {
            callingUid = ActivityManagerNative.getDefault()
                    .getLaunchedFromUid(getActivityToken());
        } catch (android.os.RemoteException ex) {
            Log.w(TAG, "Could not determine the launching uid.");
            // nothing else we can do
            return VerificationParams.NO_UID;
        }

        // If we got a uid from the intent, we need to verify that the caller is a
        // privileged system package before we use it
        if (uidFromIntent != VerificationParams.NO_UID) {
            String[] callingPackages = mPm.getPackagesForUid(callingUid);
            if (callingPackages != null) {
                for (String packageName: callingPackages) {
                    try {
                        ApplicationInfo applicationInfo =
                                mPm.getApplicationInfo(packageName, 0);

                        if ((applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
                            return uidFromIntent;
                        }
                    } catch (NameNotFoundException ex) {
                        // ignore it, and try the next package
                    }
                }
            }
        }
        // We either didn't get a uid from the intent, or we don't trust it. Use the
        // calling uid instead.
        return callingUid;
    }

    @Override
    public void onBackPressed() {
        if (mSessionId != -1) {
            mInstaller.setPermissionsResult(mSessionId, false);
        }
        mInstallFlowAnalytics.setFlowFinished(
                InstallFlowAnalytics.RESULT_CANCELLED_BY_USER);
        super.onBackPressed();
    }

    // Generic handling when pressing back key
    public void onCancel(DialogInterface dialog) {
        finish();
    }

    public void onClick(View v) {
        if (v == mOk) {
            if (mOkCanInstall || mScrollView == null) {
                mInstallFlowAnalytics.setInstallButtonClicked();
                if (mSessionId != -1) {
                    mInstaller.setPermissionsResult(mSessionId, true);

                    // We're only confirming permissions, so we don't really know how the
                    // story ends; assume success.
                    mInstallFlowAnalytics.setFlowFinishedWithPackageManagerResult(
                            PackageManager.INSTALL_SUCCEEDED);
                } else {
                    // Start subactivity to actually install the application
                    Intent newIntent = new Intent();
                    newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
                            mPkgInfo.applicationInfo);
                    newIntent.setData(mPackageURI);
                    newIntent.setClass(this, InstallAppProgress.class);
                    newIntent.putExtra(InstallAppProgress.EXTRA_MANIFEST_DIGEST, mPkgDigest);
                    newIntent.putExtra(
                            InstallAppProgress.EXTRA_INSTALL_FLOW_ANALYTICS, mInstallFlowAnalytics);
                    String installerPackageName = getIntent().getStringExtra(
                            Intent.EXTRA_INSTALLER_PACKAGE_NAME);
                    if (mOriginatingURI != null) {
                        newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
                    }
                    if (mReferrerURI != null) {
                        newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
                    }
                    if (mOriginatingUid != VerificationParams.NO_UID) {
                        newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
                    }
                    if (installerPackageName != null) {
                        newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                                installerPackageName);
                    }
                    if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
                        newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
                        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
                    }
                    if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
                    startActivity(newIntent);
                }
                finish();
            } else {
                mScrollView.pageScroll(View.FOCUS_DOWN);
            }
        } else if(v == mCancel) {
            // Cancel and finish
            setResult(RESULT_CANCELED);
            if (mSessionId != -1) {
                mInstaller.setPermissionsResult(mSessionId, false);
            }
            mInstallFlowAnalytics.setFlowFinished(
                    InstallFlowAnalytics.RESULT_CANCELLED_BY_USER);
            finish();
        }
    }
}

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
packageinstaller 是一款用于安装 Android 应用程序的工具。它可以在 Android 设备上安装来自于各种来源的应用程序包(APK)。下面是 packageinstaller安装流程: 1. 准备安装:首先,用户需要下载所需的 APK 文件。这个文件可以来自于各种来源,如应用商店、网站或其他设备。 2. 打开 packageinstaller:用户可以通过点击 APK 文件,或者手动打开 packageinstaller 应用程序进入安装界面。 3. 安全性校验:Android 系统会对 APK 文件进行安全性校验,以确保其不包含病毒或恶意软件。 4. 安装设置:在安装界面中,用户可以选择是否允许安装未知来源的应用。如果用户未开启此选项,则只能安装来自于应用商店或其他受信任来源的应用。 5. 安装确认:用户需要仔细阅读权限授权列表,并确认是否同意这些权限。这些权限可能包括访问设备上的文件、使用摄像头、定位信息等。 6. 安装应用:一旦用户确认权限,packageinstaller 会开始安装应用程序。它会解析 APK 文件并将应用程序的文件和数据复制到设备上。 7. 安装完成:安装过程完成后,用户将收到一个提示,告诉他们应用程序已经成功安装。用户可以选择立即打开应用程序或者返回主屏幕。 总结来说,packageinstaller 安装流程包括准备安装、打开 packageinstaller、安全性校验、安装设置、安装确认、安装应用安装完成等步骤。通过这个流程,用户可以安全地安装他们所需的 Android 应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值