• 应用中对APK进行安装


    权限

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>   //允许安装未知来源的app
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    说明:REQUEST_INSTALL_PACKAGES该权限是8.0及以后得版本产生的,低于此版本不需要动态申请权限(当你动态申请权限的时候,会得到该权限没有授权的回调,但是你去申请权限是弹不出选择窗口,而是直接进了未授权的回调)。

    清单文件
    <application>
      ................

      <!--适配7.0以上安装app-->
      <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/filepaths" /> //说明:这里的
    filepaths是res下面新建的xml名称的文件夹下的文件
      </provider>
    </application>

    res资源文件
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <paths>
    <external-path path="." name="download" />
    </paths>
    </resources>

      该文件 <paths>标签下的标签有如下几种类型:

    1、<files-path path="" name="camera_photos" />

      该方式提供在应用的内部存储区的文件/子目录的文件。它对应Context.getFilesDir返回的路径:    eg:"/data/data/com.jph.simple/files"。

    2、<cache-path name="name" path="path" />

      该方式提供在应用的内部存储区的缓存子目录的文件。它对应getCacheDir返回的路径:eg:“/data/data/com.jph.simple/cache”;

    3、<external-path name="name" path="path" />

      该方式提供在外部存储区域根目录下的文件。它对应Environment.getExternalStorageDirectory返回的路径:eg:"/storage/emulated/0";

    4、<external-files-path name="name" path="path" />

      该方式提供在应用的外部存储区根目录的下的文件。它对应Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/files"。

    5、<external-cache-path name="name" path="path" />

      该方式提供在应用的外部缓存区根目录的文件。它对应Context.getExternalCacheDir()返回的路径。eg:"/storage/emulated/0/Android/data/com.jph.simple/cache"。

    6、<root-path path="" name="camera_photos" />

      root-path代表/也就是Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录。

    综上:对filepaths,xml文件的编写,需要根据你的apk包所在文件路径来选择paths的相对应类型,

        从而保障调用FileProvider.getUriForFile()时不会报“Failed to find configured root that contains”异常。

    下载    
    private void loadFromServer() {
    DialogUtil.getInstance().showDialogText(this,"0%");
    OkGo.<File>get(appurl)
    .tag(this)
    .execute(new FileCallback() {
    @Override
    public void onSuccess(Response<File> response) {
    dialogDismiss();
    installApp(response.body());
    }

    @Override
    public void onError(Response<File> response) {
    super.onError(response);
    if (newVersionBean!=null&&newVersionBean.getData()!=null&&"1".equals(newVersionBean.getData().getIs_force_update())){
    android.os.Process.killProcess(android.os.Process.myPid()); //获取PID
    System.exit(0);
    }else{
    dialogDismiss();
    displayMessage(getResources().getString(R.string.prompt_downloadfauil));
    }
    }

    @Override
    public void downloadProgress(Progress progress) {
    super.downloadProgress(progress);
    DialogUtil.getInstance().showContent((int)((progress.currentSize/(float)progress.totalSize)*100)+"%");
    }
    });
    }

    安装app
    private void installApp(File file){
    // setPermission(file.getPath());
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.putExtra("name", "");
    intent.addCategory("android.intent.category.DEFAULT");
    String packageName = getPackageName();
    Uri data;
    if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ //8.0以上需要在清单文件中写上权限:REQUEST_INSTALL_PACKAGES。小米的时候并不需要getPackageManager().canRequestPackageInstalls()的结果为true才做安装操作,会自动弹出允许安装未知来源的App的系统弹窗
    //            boolean b = getPackageManager().canRequestPackageInstalls();
    // 临时允许
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    data = FileProvider.getUriForFile(this, packageName + ".fileprovider", file);
    }else if (Build.VERSION.SDK_INT >= 24){
    // 临时允许
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    data = FileProvider.getUriForFile(this, packageName + ".fileprovider", file);
    }else {
    data = Uri.fromFile(file);
    }
    intent.setDataAndType(data, "application/vnd.android.package-archive");
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    }
    /**
    * 提升读写权限
    *
    * @param filePath 文件路径
    */
    private static void setPermission(String filePath) {
    String command = "chmod " + "777" + " " + filePath;
    Runtime runtime = Runtime.getRuntime();
    try {
    runtime.exec(command);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    // 获取当前App版本
    private String getLocalVersion() {
    // 获取包管理者对象
    PackageManager pm = getPackageManager();
    try {
    // 获取包的详细信息
    PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
    // 获取版本号和版本名称
    return info.versionName;
    } catch (Exception e) {
    return "";
    }
    }
    鸣谢:

    https://www.jianshu.com/p/121bbb07cb07



     
  • 相关阅读:
    ORM中介模型 + auth模块(用户登录校验)
    ModelForm
    Form组件------注册
    信贷相关业务
    pymongo
    开发者工具使用
    kindeditor文字编辑器 文章点赞评论操作
    VS Code:设置多行注释快捷键
    Nodejs:npm run build之后,distindex.html页面在火狐中可以正常显示登录页面并登录成功,在Chrome中可以正常显示登录页面,登录失败
    Maven:项目结构
  • 原文地址:https://www.cnblogs.com/qynprime/p/10197482.html
Copyright © 2020-2023  润新知