privatevoidonDocumentPicked(DocumentInfo doc, @ViewTypeint type, @ViewTypeint fallback) { //…… // For APKs, even if the type is preview, we send an ACTION_VIEW intent to allow // PackageManager to install it. This allows users to install APKs from any root. // The Downloads special case is handled above in #manageDocument. if (MimeTypes.isApkType(doc.mimeType)) { viewDocument(doc); return; } //…… }
// Downloads has traditionally added the WRITE permission // in the TrampolineActivity. Since this behavior is long // established, we set the same permission for non-managed files // This ensures consistent behavior between the Downloads root // and other roots. intflags= Intent.FLAG_GRANT_READ_URI_PERMISSION; if (doc.isWriteSupported()) { flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; } intent.setFlags(flags);
// The the installation source as the nextActivity thinks this activity is the source, hence // set the originating UID and sourceInfo explicitly nextActivity.putExtra(PackageInstallerActivity.EXTRA_CALLING_PACKAGE, callingPackage); nextActivity.putExtra(PackageInstallerActivity.EXTRA_ORIGINAL_SOURCE_INFO, sourceInfo); nextActivity.putExtra(Intent.EXTRA_ORIGINATING_UID, originatingUid); //PackageInstallerSession已存在,此时Activity是从PackageInstallerSession的commitLocked方法中启动的 if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) { nextActivity.setClass(this, PackageInstallerActivity.class); } else { UripackageUri= intent.getData(); //从Android 7开始不能把file://类型的url传递给其他应用了 if (packageUri != null && (packageUri.getScheme().equals(ContentResolver.SCHEME_FILE) || packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))) { // Copy file to prevent it from being changed underneath this process nextActivity.setClass(this, InstallStaging.class); } elseif (packageUri != null && packageUri.getScheme().equals( PackageInstallerActivity.SCHEME_PACKAGE)) { nextActivity.setClass(this, PackageInstallerActivity.class); } else { //…… } }
if (nextActivity != null) { startActivity(nextActivity); }
// load dummy layout with OK button disabled until we override this layout in // startInstallConfirm bindUi(R.layout.install_confirm, false); checkIfAllowedAndInitiateInstall(); }
privatevoidinitiateInstall() { StringpkgName= 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(newString[] { 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.MATCH_UNINSTALLED_PACKAGES); if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { mAppInfo = null; } } catch (NameNotFoundException e) { mAppInfo = null; }
privatevoidstartInstallConfirm() { // We might need to show permissions, load layout with permissions if (mAppInfo != null) { bindUi(R.layout.install_confirm_perm_update, true); } else { bindUi(R.layout.install_confirm_perm, true); } //…… 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(newRunnable() { @Override publicvoidrun() { mOk.setText(R.string.install); mOkCanInstall = true; } }); } }
// This is the first onResume in a single life of the activity if (mInstallingTask == null) { PackageInstallerinstaller= getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfosessionInfo= installer.getSessionInfo(mSessionId);
if (sessionInfo != null && !sessionInfo.isActive()) { mInstallingTask = newInstallingAsyncTask(); mInstallingTask.execute(); } else { // we will receive a broadcast when the install is finished mCancelButton.setEnabled(false); setFinishOnTouchOutside(false); } } }