> 文档中心 > 国科微平台android 9.0跳过“未知来源”进行安装应用

国科微平台android 9.0跳过“未知来源”进行安装应用

需求:点击更新应用进行安装的过程中弹出“未知来源”设置提示,需要跳过该步骤直接安装。

 

 分析:

1.首先9.0 app安装是通过packages/apps/PackageInstaller里面的应用进行安装的。

2.其次定位到安装界面是/src/com/android/packageinstaller/PackageInstallerActivity.java

3.查看handleUnknownSources里面进行了代码控制,至此问题已解决(或者直接通过appOpMode和包名进行判断调用initiateInstall()函数也行,不建议),但是我们还得深入看下弹框做了什么动作。。。

 private void handleUnknownSources() { if (mOriginatingPackage == null) {     Log.i(TAG, "No source found for package " + mPkgInfo.packageName);     showDialogInner(DLG_ANONYMOUS_SOURCE);     return; } Log.e(TAG, "wgd==No source found for package " + mPkgInfo.packageName); // Shouldn't use static constant directly, see b/65534401. //提前设置允许该应用获取未知来源权限 if("com.ctg.itrdc.clouddesk".equals(mPkgInfo.packageName)){     mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, mOriginatingUid,     mPkgInfo.packageName, AppOpsManager.MODE_ALLOWED); } final int appOpCode =  AppOpsManager.permissionToOpCode(Manifest.permission.REQUEST_INSTALL_PACKAGES); final int appOpMode = mAppOpsManager.noteOpNoThrow(appOpCode,  mOriginatingUid, mOriginatingPackage);//根据appOpMode判断是否已获得未知来源安装权限   MODE_ERRORED没获取  MODE_ALLOWED已获取   switch (appOpMode) {     case AppOpsManager.MODE_DEFAULT:  mAppOpsManager.setMode(appOpCode, mOriginatingUid,   mOriginatingPackage, AppOpsManager.MODE_ERRORED);  // fall through     case AppOpsManager.MODE_ERRORED:  showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED);  break;     case AppOpsManager.MODE_ALLOWED:  initiateInstall();  break;     default:  Log.e(TAG, "Invalid app op mode " + appOpMode   + " for OP_REQUEST_INSTALL_PACKAGES found for uid " + mOriginatingUid);  finish();  break; }    }

4.showDialogInner(DLG_EXTERNAL_SOURCE_BLOCKED)弹框做了什么工作呢? 接下来调用了创建窗口函数createDialog()

 /     * Replace any dialog shown by the dialog with the one for the given {@link #createDialog id}.     *     * @param id The dialog type to add     */    private void showDialogInner(int id) { DialogFragment currentDialog =  (DialogFragment) getFragmentManager().findFragmentByTag("dialog"); if (currentDialog != null) {     currentDialog.dismissAllowingStateLoss(); } DialogFragment newDialog = createDialog(id); if (newDialog != null) {     newDialog.showAllowingStateLoss(getFragmentManager(), "dialog"); }    }
 /     * Create a new dialog.     *     * @param id The id of the dialog (determines dialog type)     *     * @return The dialog     */    private DialogFragment createDialog(int id) { switch (id) {     case DLG_PACKAGE_ERROR:  return SimpleErrorDialog.newInstance(R.string.Parse_error_dlg_text);     case DLG_OUT_OF_SPACE:  return OutOfSpaceDialog.newInstance(   mPm.getApplicationLabel(mPkgInfo.applicationInfo));     case DLG_INSTALL_ERROR:  return InstallErrorDialog.newInstance(   mPm.getApplicationLabel(mPkgInfo.applicationInfo));     case DLG_NOT_SUPPORTED_ON_WEAR:  return NotSupportedOnWearDialog.newInstance();     case DLG_INSTALL_APPS_RESTRICTED_FOR_USER:  return SimpleErrorDialog.newInstance(   R.string.install_apps_user_restriction_dlg_text);     case DLG_UNKNOWN_SOURCES_RESTRICTED_FOR_USER:  return SimpleErrorDialog.newInstance(   R.string.unknown_apps_user_restriction_dlg_text);     case DLG_EXTERNAL_SOURCE_BLOCKED:  //未知来源  return ExternalSourcesBlockedDialog.newInstance(mOriginatingPackage);     case DLG_ANONYMOUS_SOURCE:  return AnonymousSourceDialog.newInstance(); } return null;    }
 /     * An error dialog shown when external sources are not allowed     */    public static class ExternalSourcesBlockedDialog extends AppErrorDialog { static AppErrorDialog newInstance(@NonNull String originationPkg) {     ExternalSourcesBlockedDialog dialog = new ExternalSourcesBlockedDialog();     dialog.setArgument(originationPkg);     return dialog; } @Override protected Dialog createDialog(@NonNull CharSequence argument) {     try {  PackageManager pm = getActivity().getPackageManager();  ApplicationInfo sourceInfo = pm.getApplicationInfo(argument.toString(), 0);  return new AlertDialog.Builder(getActivity())   .setTitle(pm.getApplicationLabel(sourceInfo))   .setIcon(pm.getApplicationIcon(sourceInfo))   .setMessage(R.string.untrusted_external_source_warning)   .setPositiveButton(R.string.external_sources_settings,    (dialog, which) -> { Intent settingsIntent = new Intent(); settingsIntent.setAction(  Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); final Uri packageUri = Uri.parse("package:" + argument); settingsIntent.setData(packageUri); try {     getActivity().startActivityForResult(settingsIntent,      REQUEST_TRUST_EXTERNAL_SOURCE); } catch (ActivityNotFoundException exc) {     Log.e(TAG, "Settings activity not found for action: "      + Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); }    })   .setNegativeButton(R.string.cancel,    (dialog, which) -> getActivity().finish())   .create();     } catch (NameNotFoundException e) {  Log.e(TAG, "Did not find app info for " + argument);  getActivity().finish();  return null;     } }    }

 Intent settingsIntent = new Intent();

 settingsIntent.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);

 接下来主要看看是跳转到哪了,这其实调用到设置apk里面了。通过界面文字搜索最终定位到

/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java类

 最终发现设置打开应用“未知来源”权限执行了以下代码,至此得出第3步修改方案。

我们也可以按照下面进行初始化实现 

    private void openAppInstallUnknownSource(Context context){ try {     String packageName = SystemProperties.get("persist.sys.app_install_unknown_source");     if(!android.text.TextUtils.isEmpty(packageName)){  AppOpsManager mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);  PackageManager mPm = context.getPackageManager();  PackageInfo mPackageInfo = mPm.getPackageInfo(packageName,      PackageManager.MATCH_DISABLED_COMPONENTS |      PackageManager.MATCH_ANY_USER |      PackageManager.GET_SIGNATURES |      PackageManager.GET_PERMISSIONS);  mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,  mPackageInfo.applicationInfo.uid, packageName,AppOpsManager.MODE_ALLOWED);     } }catch (Exception e) {     Log.e(TAG, "Exception" + e); }    }