android 9.0跳过“未知来源”进行安装应用
需求:点击更新应用进行安装的过程中弹出“未知来源”设置提示,需要跳过该步骤直接安装。分析:1.首先9.0 app安装是通过packages/apps/PackageInstaller里面的应用进行安装的。2.其次定位到安装界面是/src/com/android/packageinstaller/PackageInstallerActivity.java3.查看handleUnknownSource
需求:点击更新应用进行安装的过程中弹出“未知来源”设置提示,需要跳过该步骤直接安装。
方案1
分析:
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);
}
}
修改方案2:
frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
在private void grantDefaultSystemHandlerPermissions(int userId) 函数中添加如下代码:
PackageParser.Package feedBackPackage = getPackage("net.sunniwell.dss");
if (feedBackPackage != null
&& doesPackageSupportRuntimePermissions(feedBackPackage)) {
grantRuntimePermissions(feedBackPackage, STORAGE_PERMISSIONS, userId);
}
2.判断是否已获取未知来源权限
//getPackageManager()表示当前应用是否获得未知来源权限,一般用于自升级判断
boolean canRequestPackageInstalls = getPackageManager().canRequestPackageInstalls();
log.d("upgradech:canRequestPackageInstalls = " + canRequestPackageInstalls);
更多推荐
所有评论(0)