zoukankan      html  css  js  c++  java
  • Android关于版本更新下载安装之踩坑记录(针对7.0以上)

    最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了)。那么升级后一些问题开始出现。

    Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用。在应用权限设置的“特殊访问权限”中,加入了“安装其他应用”的设置,默认是关闭的。所以安装时需要授权用户去开启。

    实现

    1.清单文件权限声明

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

      

    2.点击安装判断是否有权限

     1    if (Build.VERSION.SDK_INT >= 26) {  
     2         //来判断应用是否有权限安装apk
     3         boolean installAllowed= getPackageManager().canRequestPackageInstalls();  
     4         //有权限
     5         if (installAllowed) {  
     6             //安装apk
     7             install(apkPath);
     8         } else {  
     9             //无权限 申请权限
    10             ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_APK_REQUESTCODE);  
    11         }  
    12     } else {  
    13         install(apkPath);  
    14     } 

    权限申请回调

     1 @Override  
     2 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
     3     super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
     4     switch (requestCode) {  
     5         case INSTALL_APK_REQUESTCODE:  
     6             //有注册权限且用户允许安装
     7             if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
     8                 install(apkPath);  
     9             } else {  
    10                 //将用户引导至安装未知应用界面。
    11                 Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);  
    12                 startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);  
    13             }  
    14             break;  
    15     }  
    16 }  

    安装APK

     1    private void install(String apkPath) {
     2         //7.0以上通过FileProvider
     3         if (Environment.SYSTEM_VERSION_CODE >= 24) {
     4             Uri uri = FileProvider.getUriForFile(context, Environment.FILE_PROVIDER_AUTHORITY, new File(apkPath));
     5             Intent intent = new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "application/vnd.android.package-archive");
     6             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     7             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
     8             context.startActivity(intent);
     9         } else {
    10             Intent intent = new Intent(Intent.ACTION_VIEW);
    11             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    12             intent.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive");
    13             context.startActivity(intent);
    14         }
    15     }

    这里需要注意的是7.0引入了“私有目录被限制访问”,“StrictMode API 政策”。” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。

    上面用到的代码中的Uri.fromFile 其实就是生成一个file://URL。一旦我们通过这种办法打开其它程序(这里打开系统包安装器)就认为file:// URI类型的 Intent 离开你的应用。这样程序就会发生异常。

    解决办法:

    FileProvider来解决这一问题,首先在清单文件中添加:

     1         <!-- FileProvider配置访问路径,适配7.0及其以上-->
     2         <provider
     3             android:name="android.support.v4.content.FileProvider"
     4             android:authorities="${applicationId}.provider"
     5             android:exported="false"
     6             android:grantUriPermissions="true">
     7             <meta-data
     8                 android:name="android.support.FILE_PROVIDER_PATHS"
     9                 android:resource="@xml/provider_paths" />
    10         </provider>

    authorities:app的包名;fileProvider grantUriPermissions:true;表示授予 URI 临时访问权限 exported:false ; resource:下一步添加的文件。

    然后在res下新建一个名为xml的文件家,再新建文件provider_paths:

    1 <?xml version="1.0" encoding="utf-8"?>
    2 <paths>
    3     <external-path
    4         name="files_root"
    5         path="Android/data/com.example.downloadapk/"/>
    6     <external-path
    7         name="external_storage_root"
    8         path="."/>
    9 </paths>

    path:需要临时授权访问的路径(.代表所有路径) name:给访问路径命名。

    这样就可以完美解决7.0和8.0的问题啦!

    BY LiYing

  • 相关阅读:
    启动hbase时出现HMaster Aborted错误
    kylin的安装与配置
    【转】HBase原理和设计
    ts项目报错:Import sources within a group must be alphabetized
    TypeScript 之 tsconfig.json
    TypeScript 之 声明文件的结构
    TypeScript 之 声明文件的使用
    TypeScript 之 声明文件的发布
    TypeScript 之 NPM包的类型
    create-react-app-typescript 知识点
  • 原文地址:https://www.cnblogs.com/widgetbox/p/10096816.html
Copyright © 2011-2022 走看看