Android 7.0+ APK包下载安装流程

废话:bugly这些也挺好用的,偶尔需要自己写...

1.请求安装未知应用来源的权限

//配置权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
btnInstall.setOnClickListener(v -> {
          if (Build.VERSION.SDK_INT >= 26) {
              boolean b = getPackageManager().canRequestPackageInstalls();
              if (b) {
                  //存储权限申请
                  requestWriteExternalStorage();
              } else {
                  //请求安装未知应用来源的权限
                  showDialogRequestInstall();
              }
          } else {
              requestWriteExternalStorage();
          }
      });
//跳转让用户手动开启权限
private void showDialogRequestInstall() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("权限管理")
                .setMessage("请开启允许应用安装权限")
                .setPositiveButton("确定", (dialog, which) -> {
                    dialog.dismiss();
                    Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                    startActivityForResult(intent, Constant.REQUECT_INSTALL_PERMISSION);
                });
        builder.show();
    }

2.权限请求

//随便搜一下 有很多框架可以使用 这里使用
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
//配置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
private void requestWriteExternalStorage() {
        PermissionManager.newBuilder(this)
                .setPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .callBack(new PermissionManager.PermissionRequestCallBack() {
                    @Override
                    public void successCallBack() {
                        //请求成功回调
                        downloadApk();
                    }

                    @Override
                    public void failureCallBack() {
                        //请求失败回调
                        //提示用户自己去权限管理处开启权限
                        showGetPermissionDialog();
                    }
                });
    }
public static void showGetPermissionDialog(Context context) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("权限管理")
                .setMessage("请前往权限管理开启相应权限")
                .setPositiveButton("前往", (dialogInterface, i) -> {
                    dialogInterface.dismiss();
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    intent.setData(Uri.parse(ConstantObject.PACKAGE_URL_SCHEME + context.getPackageName()));
                    context.startActivity(intent);
                })
                .setNegativeButton("取消", (dialogInterface, i) -> dialogInterface.dismiss());
        builder.setCancelable(false);
        builder.show();
    }
//权限请求的工具类 可能有未知问题的 emmmm

public class PermissionManager {

    private static PermissionManager mPermissionManager;
    private static RxPermissions rxPermissions;
    private String permission;

    private PermissionManager() {

    }

    public static PermissionManager newBuilder(Activity activity) {
        mPermissionManager = new PermissionManager();
        rxPermissions = new RxPermissions(activity);
        return  mPermissionManager;
    }

    public PermissionManager setPermission(String permission){
        this.permission =  permission;
        return this;
    }

    public void callBack(final PermissionRequestCallBack callBack) {
        rxPermissions.request(permission)
                .filter(it -> callBack!=null)
                .subscribe(aBoolean -> {
                    if (aBoolean) {
                        callBack.successCallBack();
                    } else {
                        callBack.failureCallBack();
                    }
                }, t-> t.printStackTrace());

    }

    public interface PermissionRequestCallBack {

        void successCallBack();

        void failureCallBack();
    }
}

3.下载

//一般网络请求框架都能下载文件的 这里使用:
implementation 'com.liulishuo.filedownloader:library:1.7.4'
//配置权限
<uses-permission android:name="android.permission.INTERNET" />
    //在Application里初始化  FileDownloader.init(this);
    //下载链接
    private String apkUrl ="";
    //下载存储路径 根目录下的apk文件夹
    private String apkPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath() + "/apk/"+"yingyongming.apk";

    private void downloadApk() {
        AlertDialog alertDialog = new AlertDialog.Builder(this).create();
        alertDialog.setMessage("下载中0%...");
        alertDialog.setCancelable(false);
        alertDialog.show();
        FileDownloader.getImpl().create(apkUrl)
                .setPath(apkPath)
                .setListener(new FileDownloadListener() {
                    @Override
                    protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                    }

                    @Override
                    protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
                    }

                    @Override
                    protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                        alertDialog.setMessage("下载中"+(int)((double) soFarBytes / (double) totalBytes * 100)+"%...");
                    }

                    @Override
                    protected void blockComplete(BaseDownloadTask task) {
                    }

                    @Override
                    protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {
                    }

                    @Override
                    protected void completed(BaseDownloadTask task) {
                        alertDialog.setMessage("下载中100%...");
                        alertDialog.dismiss();
                        installApp(context, "包名", apkPath);
                    }

                    @Override
                    protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                    }

                    @Override
                    protected void error(BaseDownloadTask task, Throwable e) {
                        alertDialog.dismiss();
                        e.printStackTrace();
                    }

                    @Override
                    protected void warn(BaseDownloadTask task) {
                    }
                }).start();
    }

4.安装 需要注意7.0之后文件的访问是通过FileProvider

在res文件下创建xml文件夹 创建共享的目录文件 xxx.xml
其中
<files-path>:内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径;
<cache-path>:内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;
<external-path>:外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径;
<external-files-path>:外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径;
<external-cache-path>:外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir();

//在AndroidManifest.xml 中配置 FileProvider
<application>

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.yourname"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>

</application>
public static void installApp(Context context,String packageName,String mUrl) {
        File appFile = new File(mUrl);
        if (!appFile.getParentFile().exists()) {
            appFile.getParentFile().mkdir();
        }
        //判断版本是否在7.0以上
        //跳转到新版本应用安装页面
        if (Build.VERSION.SDK_INT >= 24) {
            //yourname 是定义在xxxx.xml中的值
            Uri apkUri = FileProvider.getUriForFile(context, packageName+".yourname", appFile);//在AndroidManifest中的android:authorities值
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            install.setDataAndType(apkUri, "application/vnd.android.package-archive");
            context.startActivity(install);
        } else {
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.fromFile(appFile), "application/vnd.android.package-archive");
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(install);
        }
        System.exit(0);
    }

5.效果图

6.告辞

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章