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.告辭

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