Android 8.1 允许安装未知来源权限/允许来自此来源的应用

您所在的位置:网站首页 怎么样修改安装未知应用 Android 8.1 允许安装未知来源权限/允许来自此来源的应用

Android 8.1 允许安装未知来源权限/允许来自此来源的应用

2024-07-10 04:05:30| 来源: 网络整理| 查看: 265

之前 6.0 的未知来源权限是一个总的权限,现在单独分开了具体到 app 对应的权限了。具体可见截图

在这里插入图片描述

安装未知来源权限其实就是这货 Manifest.permission.REQUEST_INSTALL_PACKAGES,具体的修改代码方案已经在上篇 Android9.0/8.1/6.0 默认给系统 app 授予所有权限中提供了。这篇只是分析解题思路。

核心方法如下

if (checkInstallPackagesPermission(pkgName, mPackageInfo)) { Log.e(TAG, pkgName + " need grant INSTALL_PACKAGES permission"); mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, mPackageInfo.applicationInfo.uid, pkgName, AppOpsManager.MODE_ALLOWED); Log.e(TAG, "grant INSTALL_PACKAGES permission done"); } private static boolean checkInstallPackagesPermission(String packageName, PackageInfo mPackageInfo){ int uid = mPackageInfo.applicationInfo.uid; //boolean permissionGranted = hasPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES, uid); boolean permissionRequested = hasRequestedAppOpPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName); int appOpMode = getAppOpMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, uid, packageName); return appOpMode != AppOpsManager.MODE_DEFAULT || permissionRequested; } private static int getAppOpMode(int appOpCode, int uid, String packageName) { return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName); } private static boolean hasRequestedAppOpPermission(String permission, String packageName) { try { String[] packages = mIpm.getAppOpPermissionPackages(permission); return ArrayUtils.contains(packages, packageName); } catch (Exception exc) { Log.e(TAG, "PackageManager dead. Cannot get permission info"); return false; } }

从 Settings 说起,我们看见的设置界面中有允许未知来源的 Preference,经过搜索找到 InstalledAppDetails,允许未知来源是动态增加的 Preference ,看如下代码

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\applications\InstalledAppDetails.java

private void addDynamicPrefs() { if (UserManager.get(getContext()).isManagedProfile()) { return; } ... boolean isPotentialAppSource = isPotentialAppSource(); if (isPotentialAppSource) { Preference pref = new Preference(getPrefContext()); pref.setTitle(R.string.install_other_apps); pref.setKey("install_other_apps"); pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { startAppInfoFragment(ExternalSourcesDetails.class, getString(R.string.install_other_apps)); return true; } }); category.addPreference(pref); } } addAppInstallerInfoPref(screen); maybeAddInstantAppButtons(); } private boolean isPotentialAppSource() { AppStateInstallAppsBridge.InstallAppsState appState = new AppStateInstallAppsBridge(getContext(), null, null) .createInstallAppsStateFor(mPackageName, mPackageInfo.applicationInfo.uid); return appState.isPotentialAppSource(); }

isPotentialAppSource 值决定当前 app 详情页面是否需要显示允许来自此来源的应用,isPotentialAppSource() 中初始化了 AppStateInstallAppsBridge对象,并由该对象的isPotentialAppSource()返回。 vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\applications\AppStateInstallAppsBridge.java

InstallAppsState createInstallAppsStateFor(String packageName, int uid) { final InstallAppsState appState = new InstallAppsState(); appState.permissionRequested = hasRequestedAppOpPermission( Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName); appState.permissionGranted = hasPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES, uid); appState.appOpMode = getAppOpMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, uid, packageName); return appState; } public static class InstallAppsState { boolean permissionRequested; boolean permissionGranted; int appOpMode; public InstallAppsState() { this.appOpMode = AppOpsManager.MODE_DEFAULT; } .... public boolean isPotentialAppSource() { Log.e("ExternalSources","appOpMode="+(appOpMode != AppOpsManager.MODE_DEFAULT)); Log.e("ExternalSources","permissionRequested="+permissionRequested); return appOpMode != AppOpsManager.MODE_DEFAULT || permissionRequested; } .... }

InstallAppsState 构造函数初始化将赋值 appOpMode = AppOpsManager.MODE_DEFAULT,

appOpMode 的取值有

public static final int MODE_ALLOWED = 0; public static final int MODE_IGNORED = 1; public static final int MODE_ERRORED = 2; public static final int MODE_DEFAULT = 3;

isPotentialAppSource() 的返回值取决于 appOpMode 和 permissionRequested,这两值在 createInstallAppsStateFor() 被重新赋值,继续看对应的方法

public AppStateInstallAppsBridge(Context context, ApplicationsState appState, Callback callback) { super(appState, callback); mIpm = AppGlobals.getPackageManager(); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); } private boolean hasRequestedAppOpPermission(String permission, String packageName) { try { Log.e(TAG, "packageName "+packageName); String[] packages = mIpm.getAppOpPermissionPackages(permission); for (String pck : packages) { Log.e(TAG, "PackageManager "+pck); } return ArrayUtils.contains(packages, packageName); } catch (RemoteException exc) { Log.e(TAG, "PackageManager dead. Cannot get permission info"); return false; } } private int getAppOpMode(int appOpCode, int uid, String packageName) { return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName); }

通过 AppOpsManager 获取当前 app 的模式

通过 IPackageManager 获取包含 REQUEST_INSTALL_PACKAGES 权限的包名数组,判断当前包名是否在其中

好了,是否需要显示此权限的逻辑搞清楚了,接下来再看如何授权?

InstalledAppDetails 中 Preference 点击事件对应

startAppInfoFragment(ExternalSourcesDetails.class, getString(R.string.install_other_apps));

对应的页面为 ExternalSourcesDetails

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\applications\ExternalSourcesDetails.java

@Override public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean checked = (Boolean) newValue; if (preference == mSwitchPref) { if (mInstallAppsState != null && checked != mInstallAppsState.canInstallApps()) { if (Settings.ManageAppExternalSourcesActivity.class.getName().equals( getIntent().getComponent().getClassName())) { setResult(checked ? RESULT_OK : RESULT_CANCELED); } setCanInstallApps(checked); refreshUi(); } return true; } return false; } private void setCanInstallApps(boolean newState) { mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, mPackageInfo.applicationInfo.uid, mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED); }

点击 RestrictedSwitchPreference 时通过 AppOpsManager 修改 mode 为 AppOpsManager.MODE_ALLOWED



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭