精华内容
下载资源
问答
  • 未知来源应用权限   Android8.0的诸多新...Android8.0的变化是,未知应用安装权限的开关被除掉,取而代之的是未知来源应用的管理列表,需要在里面打开每个应用的未知来源的安装权限。Google这么做是为了防止一...

    未知来源应用权限

     

    Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限

    以前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知来源的应用都可以被安装。

    Android8.0的变化是,未知应用安装权限的开关被除掉,取而代之的是未知来源应用的管理列表,需要在里面打开每个应用的未知来源的安装权限。Google这么做是为了防止一开始正经的应用后来开始通过升级来做一些不合法的事情,侵犯用户权益。 
    当你的应用直接适配到Android8之后,内部启动应用安装是会被阻塞的,如果不处理好这个未知来源的权限,会导致应用根本无法更新,只能去应用市场重新下载。 

    适配android 8.0:

    1.需要在manifast.xml中ti添加一个权限:

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    2.由于这个quan权限不是运行权限,所以不能通过请求权限获取权限;要通过下面一行代码获取是否有权限,返回一个boolean类型,true有权限,falsewuqu无权限;

    getPackageManager().canRequestPackageInstalls();

    3.跳到设置页面进行设置,通过startActivityForResult的方法,返回设置结果;

        public void checkPermission(){
            boolean haveInstallPermission;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                haveInstallPermission = getPackageManager().canRequestPackageInstalls();
                if(!haveInstallPermission){
                    //没有权限让调到设置页面进行开启权限;
                    Uri packageURI = Uri.parse("package:" + getPackageName());
                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
                    startActivityForResult(intent, 10086);
                }else{
    
                    //有权限,执行自己的逻辑;
                   
                }
            }else{
                //其他android版本,可以直接执行安装逻辑;
               
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            if (resultCode == RESULT_OK && requestCode == 10086) {
                //返回权限后,执行自己的逻辑;
                
            }
        }

     

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

    之前 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

    展开全文
  • Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限(危险权限) android6.0到android8.0之前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知...

    Android8.0未知来源应用安装权限

    Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限(危险权限)
    android6.0到android8.0之前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知来源的应用都可以被安装。

    Android8.0的变化是,未知应用安装权限的开关被除掉,取而代之的是未知来源应用的管理列表,需要在里面打开每个应用的未知来源的安装权限。Google这么做是为了防止一开始正经的应用后来开始通过升级来做一些不合法的事情,侵犯用户权益。
    当你的应用直接适配到Android8之后,内部启动应用安装是会被阻塞的,如果不处理好这个未知来源的权限,会导致应用根本无法更新,只能去应用市场重新下载
    Activity类下getPackageManager().canRequestPackageInstalls();获取是否有未知来源应用安装权限
    源码如下

    AndroidManifest文件中配置
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    
    //权限检查
    private void CheckUnknowInstallPermssion(){
        boolean haveInstallPermission;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            //获取是否有安装未知应用程序权限
            haveInstallPermission = getActivity().getPackageManager().canRequestPackageInstalls();
         if(!haveInstallPermission)
            {   //无权限,开启未知应用安装程序权限
                toInstallPermissionSettingIntent();
            };
            }
        }
    }
     //开启安装未知来源权限
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void toInstallPermissionSettingIntent() {
        Uri packageURI = Uri.parse("package:"+getActivity().getPackageName());
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,packageURI);
       //系统将打开是未知来源应用的管理列表,需要用户手动设置未知来源应用安装权限
        startActivityForResult(intent, 1);
    }
    //权限开启后的回调函数
      @Override
        public  void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK && requestCode == 1) {
              //权限开启成功,编写用户服务函数 
          // Toast.makeText(getActivity(),"ShadeScan安装权限已打开",Toast.LENGTH_SHORT).show();
            }
        }
        ```
    
    展开全文
  • 完美的适配Android8.0未知来源应用安装权限方案

    万次阅读 多人点赞 2017-12-26 21:41:22
    第二完美的适配Android8.0未知来源应用安装权限方案Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限以前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,...

    完美的适配Android8.0未知来源应用安装权限方案

    大家的要求 提供源码,我自己写了一个demo,在虚拟机上可以运行,请查看源码:

    源码传送

    2018年5月纠正:
    @this蜗牛 提供的需要设置包名,去打开权限设置界面才能在onActivityResult中接收到【resultCode 等于 RESULT_OK 】

    所以修改方法:

        @RequiresApi(api = Build.VERSION_CODES.O)
        private void startInstallPermissionSettingActivity() {
            //注意这个是8.0新API
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
            startActivityForResult(intent, 10086);
        }

    为如下:

        @RequiresApi(api = Build.VERSION_CODES.O)
        private void startInstallPermissionSettingActivity() {
            Uri packageURI = Uri.parse("package:" + getPackageName());
            //注意这个是8.0新API
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            startActivityForResult(intent, 10086);
        }

    感谢 @this蜗牛 提出的意见


    Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限

    以前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知来源的应用都可以被安装。

    Android8.0的变化是,未知应用安装权限的开关被除掉,取而代之的是未知来源应用的管理列表,需要在里面打开每个应用的未知来源的安装权限。Google这么做是为了防止一开始正经的应用后来开始通过升级来做一些不合法的事情,侵犯用户权益。
    当你的应用直接适配到Android8之后,内部启动应用安装是会被阻塞的,如果不处理好这个未知来源的权限,会导致应用根本无法更新,只能去应用市场重新下载。
    那么如何来适配8.0这一个新变化呢?

    1、在清单文件中增加请求安装权限

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    2、我们还需要在代码里面对权限进行处理
    首先用canRequestPackageInstalls()方法判断你的应用是否有这个权限

    haveInstallPermission = getPackageManager().canRequestPackageInstalls();

    如果haveInstallPermission 为 true,则说明你的应用有安装未知来源应用的权限,你直接执行安装应用的操作即可。

    如果haveInstallPermission 为 false,则说明你的应用没有安装未知来源应用的权限,则无法安装应用。由于这个权限不是运行时权限,所以无法再代码中请求权限,还是需要用户跳转到设置界面中自己去打开权限。

    具体的操作是:

    弹出dialog,告知用户

    “安装应用需要打开未知来源权限,请去设置中开启权限”

    然后用户点击确定之后跳转到未知来源应用权限管理列表:

    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
    startActivityForResult(intent, 10086);

    然后在onActivityResult中去接收结果:

    if (resultCode == RESULT_OK && requestCode == 10086) {
                installProcess();//再次执行安装流程,包含权限判等
     }
    完整的流程如下:
        //安装应用的流程
        private void installProcess() {
            boolean haveInstallPermission;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                //先获取是否有安装未知来源应用的权限
                haveInstallPermission = getPackageManager().canRequestPackageInstalls();
                if (!haveInstallPermission) {//没有权限
                    DialogUtils.showDialog(this, "安装应用需要打开未知来源权限,请去设置中开启权限", 
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                startInstallPermissionSettingActivity();
                            }
                        }
                    }, null);
                    return;
                }
            }
            //有权限,开始安装应用程序
            installApk(apk);
        }
    
    
        @RequiresApi(api = Build.VERSION_CODES.O)
        private void startInstallPermissionSettingActivity() {
            Uri packageURI = Uri.parse("package:" + getPackageName());
            //注意这个是8.0新API
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            startActivityForResult(intent, 10086);
        }
    
        //安装应用
        private void installApk(File apk) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                intent.setDataAndType(Uri.fromFile(apk), "application/vnd.android.package-archive");
            } else {//Android7.0之后获取uri要用contentProvider
                Uri uri = AppCommonUtils.getUriFromFile(getBaseContext(), apk);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
    
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            getBaseContext().startActivity(intent);
        }

    以上,Android8.0的未知来源应用安装权限适配基本结束,希望对大家能有帮助

    转载请注明出处

    展开全文
  • 根据翻译,猜测这个常量就是用来控制是否允许安装未知来源应用的。 /** * 允许安装未知来源的应用 */ public static void allowUnKnowSrc (Context context){ try { android.provider.Settings....
  • Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限 以前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知来源的应用都可以被安装。 ...
  •   得知在 Android 8.0 中未知应用安装权限的开关默认是被关闭的 ,需要用户手动打开允许 【未知来源应用权限】才能够安装。Google 对于Android 的安全可谓是越来越严格了。 下面介绍如何处理 1、在清单文件中...
  • Android 8.0 允许安装未知来源权限

    千次阅读 2018-12-29 13:07:00
    在Android8.0之前的系统中,用户要从除官方应用商店之外的来源安装App时,需要打开系统设置当中的”允许未知来源”安装应用程序的选项,在最新的Android O当中谷歌已经删除了该永久授权的选项,从系统设置当中已经找...
  • 由于大陆相关部门出台的新规定指出,应用在未经用户允许的前提下,系统不能授予其使用联网、获取定位的功能。Apple 在 iOS 10 操作系统中加入了关于应用使用数据的授权弹窗提示,用户在 iOS 10 系统中第一次打开应用...
  • 当你的应用适配到8.0后,会检测是否允许未知来源系统,没有打开的话会弹框提示去打开
  • Android8.0 允许安装未知来源权限(一)

    万次阅读 热门讨论 2018-04-26 14:27:43
    在Android8.0之前的系统中,用户要从除官方应用商店之外的来源安装App时,需要打开系统设置当中的”允许未知来源”安装应用程序的选项,在最新的Android O当中谷歌已经删除了该永久授权的选项,从系统设置当中已经...
  • 第一次安装 iOS 应用获取网络权限

    千次阅读 2017-06-22 10:17:49
    在iOS 10下 ,首次进入应用时,会有询问是否允许网络连接权限的的弹窗,为更好进行用户交互,需要在打开应用时获取应用禁用网络权限状态(状态分为:未知、限制网络、未限制网络),客户端根据不同的权限状态定制...
  • 国行 iOS10 系统的 iPhone,具体原因和解决方案参照 iOS 10 不提示「是否允许应用访问数据」,导致应用无法使用的解决方案 和 具透 | 你可能不知道,iOS 10 有一个中国「特供」的联网权限功能 引导页或启动页使用...
  • 安装mysql,自定义->修改路径3.配置mysql,选择自定义->server模式->500访问量->勾选控制台->设置gbk->设置密码和允许root用户远程登录等等。以管理员权限,在控制台输入:net start MySQL, 启动...
  • 1、ColorOS 5.0及以上版本,进入设置--其他设置--设备与隐私--未知来源安装应用,打开对应应用开关,即可安装从该应用内下载的软件;2、ColorOS 3.1版本,进入设置--其他设置--安全与隐私--允许安装未知来源应用,...
  • 以下的代码需要平台的签名或者作为系统应用来运行才行(adb push <your apk files> /system/app/<your apk files>) ---当然 需要先运行 adb root 1.需要添加的权限 <uses-permission an...
  • 对于应用程序请求的“permissions”可以有几种处理方式:如自动允许权限,通过用户提示或者证书来允许或禁止该权限应用程序需要的“permissions”在程序中静态声明,在程序安装时被系统知晓,并不会再改变。  ...
  • 由于大陆相关部门出台的新规定指出,应用在未经用户允许的前提下,系统不能授予其使用联网、获取定位的功能。Apple 在 iOS 10 操作系统中加入了关于应用使用数据的授权弹窗提示,用户在 iOS 10 系统中第一次打开应用...
  • 我最好的猜测是,我登录的用户没有运行make命令的权限,但希望它是不允许安装的其他东西.为什么我得到权限被拒绝,我应该检查或配置为了尝试授予许可?编辑错误信息:gcc -I. -O3 -o pp-inspector pp-inspecto...
  • Android-真机应用安装失败原因

    万次阅读 2017-07-24 19:21:19
    那些年的安装失败:1.INSTALL_FAILED_USER_RESTRICTED原因:这个问题,我是在魅族手机上碰到的,原因是 APP 初次安装时,会弹出一个是否允许安装的对话框,我手一抖点击了禁止安装。解决方法:手机管家-&gt;权限...
  • 原因:Android系统会给targetSdk版本为“4”以下的应用自动分配WRITE_EXTERNAL_STORAGE 和 READ_PHONE_STATE 权限。 解放办法:在manifest.xml中添加<uses-sdk android:minSdkVersion="4" android:targetSdk...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,020
精华内容 408
关键字:

允许应用安装应用权限