android 软件版本更新

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/fzkf9225/article/details/80969439

       随着android 7.0的普及android 8.0的也逐渐流行起来,那么google对权限方面又有了新的修改。而且我发现在android8.0中除了一些bug,比如说:在小米6(Android 8.0系统)中无法自动安装的问题,那么之前做的更新系统就要稍微调整下。

        我们理下思路:

                1、接口调用是否有更新,返回数据如下大致如下:

                

{
    "status":true,
    "code":200,
    "data":{
        "VersionName":"1.1.8",
        "VersionCode":19,
        "AppUrl":"https://********/appfile/*****.apk",//更新地址
        "Content":"部分BUG修复",//提示内容
        "Status":1,
        "isMustUpdate":true//是否强制更新
    },
    "msg":"返回成功"
}

            2、创建更新提示dialog,同时创建通知broadcastReciver广播器,并初始化

                    IntentFilter intentFilter = new IntentFilter();
                    intentFilter.addAction(DownloadApkService.ACTION_START);
                    intentFilter.addAction(DownloadApkService.ACTION_UPDATE);
                    intentFilter.addAction(DownloadApkService.ACTION_FINISHED);
                    intentFilter.addAction(DownloadApkService.ACTION_CANCEL);
                    intentFilter.addAction(DownloadApkService.ACTION_ERROR);
                    intentFilter.addAction(DownloadApkService.ACTION_REDIRECT_ERROR);
                    downloadApkReceiver = new DownloadApkReceiver();
                    getActivity().registerReceiver(downloadApkReceiver, intentFilter);
                    UpdateManger.getInstance().checkUpdateInfo(getActivity(),
                            resultBean.getData().getAppUrl(), resultBean.getData().getContent(),
                            resultBean.getData().getVersionName(),resultBean.getData().getMustUpdate());
                
 // 显示更新程序对话框,供主程序调用
    public void checkUpdateInfo(Activity mContext, String apkUrl,
                                String updateMsg, String mCurrentVersionName,
                                Boolean isMustUpdate) {
        this.apkUrl = apkUrl;
        UpdateManger.mContext = mContext;
        if (updateMsg != null && !updateMsg.equals("")) {
            this.updateMsg = updateMsg;
        }
        this.mCurrentVersionName = mCurrentVersionName;
        UpdateMessageDialog updateMessageDialog =
                new UpdateMessageDialog(mContext, mCurrentVersionName,
                        updateMsg, isMustUpdate);
        updateMessageDialog.create();
        updateMessageDialog.setOnUpdateListener(this);
    }

    

package com.***.***.custom.dialog;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;

import com.***.***.R;
import com.***.***.util.dialog.*;
import com.***.***.util.networkTools.NetworkStateUtil;

/**
 * Created by CherishTang on 2017/12/13.
 * 更新弹框
 */

public class UpdateMessageDialog implements View.OnClickListener {
    private Context mContext;
    private String updateMsgString, versionName;
    public OnUpdateListener onUpdateListener;
    private Button updateBtn;
    private TextView updateTitle, updateMsg;
    private Dialog customDialog;
    private Boolean isMustUpdate;

    public UpdateMessageDialog(Context context, String versionName,
                               String updateMsgString, Boolean isMustUpdate) {
        this.mContext = context;
        this.versionName = versionName;
        this.updateMsgString = updateMsgString;
        this.isMustUpdate = isMustUpdate;
    }
    //更新dialog布局自己写了
    public void create() {
        customDialog = new Dialog(mContext, R.style.ActionSheetDialogStyle);
        @SuppressLint("InflateParams") View view = LayoutInflater.from(mContext).inflate(
                R.layout.update_dialog, null);
        Button updateBtn = (Button) view.findViewById(R.id.updateBtn);
        TextView updateTitle = (TextView) view.findViewById(R.id.updateTitle);
        TextView updateMsg = (TextView) view.findViewById(R.id.updateMsg);
        updateMsg.setText(updateMsgString);
        updateTitle.setText("是否更新到" + versionName + "版本");
        updateBtn.setOnClickListener(this);
        customDialog.setContentView(view);
        customDialog.setCancelable(isMustUpdate == null || !isMustUpdate);//此值未接口中返回的不可取消
        Window dialogWindow = customDialog.getWindow();
        dialogWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        dialogWindow.setGravity(Gravity.CENTER);
        customDialog.show();
    }

    public void setOnUpdateListener(OnUpdateListener onUpdateListener) {
        this.onUpdateListener = onUpdateListener;
    }
 

private void showMessageDialog(String message, final View v) {

//DialogHelper是我自己写的dialog封装类,大家可以自己实现
DialogHelper.getConfirmDialog(mContext, message, true, new DialogInterface.OnClickListener() { 
    @Override 
    public void onClick(DialogInterface dialogInterface, int i) {
         if (onUpdateListener != null) 
            onUpdateListener.onUpdate(customDialog, v);
     } 
    }, new DialogInterface.OnClickListener() { 
    @Override 
    public void onClick(DialogInterface dialog, int which) {
         if (customDialog != null && customDialog.isShowing()) 
            customDialog.dismiss(); 
    } 
}).show(); 

} 

@Override 
public void onClick(View v) { 
    switch (v.getId()) {
         case R.id.updateBtn:
             if (NetworkStateUtil.isMobileConnected(mContext)) {
                     showMessageDialog("您正在使用数据流量,确定继续下载吗?", v); 
                } else { 
            if (onUpdateListener != null) 
                    onUpdateListener.onUpdate(customDialog, v);
                 } 
            break; 
        } 
    }   

     //更新按钮回调 
public interface OnUpdateListener {
 void onUpdate(Dialog customDialog, View v);
 }
}

3、在点击更新时创建service 和调用广播用于下载和通知。

点击更新按钮先判断权限再启动下载任务

 if (StaticUtil.isDownLoadApk) {
            MThoast.showShort(mContext, "已存在下载任务,请勿重复下载");
            return;
        }

        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(mContext, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    0x01);
            return;
        }
        //PackageManager类中在Android Oreo版本中添加了一个方法:判断是否可以安装未知来源的应用
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !mContext.getPackageManager().canRequestPackageInstalls()) {
            //请求安装未知应用来源的权限
            DialogHelper.getConfirmDialog(mContext, "安装应用需要打开未知来源权限,请去设置中手动开启权限",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //注意这个是8.0新API
                            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                            mContext.startActivityForResult(intent, 10086);
                        }
                    }).show();
            return;
        }
        if (customDialog != null && customDialog.isShowing())
            customDialog.dismiss();
        Intent intent = new Intent(mContext, DownloadApkService.class);
        intent.setAction(DownloadApkService.ACTION_START);
        intent.putExtra("id", 0);
        intent.putExtra("url", apkUrl);
        intent.putExtra("name", "保存的应用名称.apk");
        mContext.startService(intent);
    }

    a、DownloadApkService后台下载服务。

    b、为了不占用主线程,最好把下载写在子线程中。

   c、首先获取下载地址并创建HttpURLConnection对象(于每个人用的网络框架都不一样因此这里采用原始的HttpURLConnection)。创建Url,url.openConnection()打开连接,如果你们服务端采用了https重定向的话,ResponseCode会报301的错,如果不知道301指的是什么可以百度下http常用的返回code值,我的解决方式是手动把https转为http,如果是https则转为https,不过这个完全后台可以处理的问题,更改下网络协议即可。

d、创建本地存放路径和创建通知栏,广播器。android 7.0以下读写文件必须要动态获取权限,这个不做解释了,那么通知栏和广播器是干嘛的呢。通知栏是在展示给用户下载进度(部分手机显示不了,问题最多的就是小米和oppo,需要手动开启通知栏权限),广播器用来告诉通知栏,创建通知消息,更新下载进度,下载完成告诉应用可以启动安装了。

    NotificationManager工具类代码如下

    

package com.***.***.util.update.util;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;

import com.***.***.R;
import com.***.***.activity.MainActivity;


/**
 * Created by CherighTang on 2017/10/13.
 *
 */
public class NotificationUtil {

    private Context mContext;
    private NotificationManager mManager;
    private NotificationCompat.Builder mBuilder;

    public NotificationUtil(Context context) {
        this.mContext = context;
        mManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(context,context.getPackageName()+"apkUpdate");//在最新的8.0中必须设置channelId
    }

    /**
     * 显示通知栏
     *
     * @param id
     */
    public void showNotification(final int id) {

        mBuilder.setTicker("正在下载");//Ticker是状态栏显示的提示
        mBuilder.setContentTitle("正在下载最新版本");
        mBuilder.setProgress(100, 0, false);
        mBuilder.setContentText(0 + "%");
        mBuilder.setSmallIcon(R.mipmap.icon_launcher);
        mBuilder.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.icon_launcher));//通知栏的大图标

        Intent msgIntent = new Intent();
        msgIntent.setClass(mContext, MainActivity.class);
        msgIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 100, msgIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pendingIntent);//点击跳转
        mManager.notify(id, mBuilder.build());
    }

    /**
     * 取消通知栏通知
     */
    public void cancelNotification(int id) {
        mManager.cancel(id);
    }

    /**
     * 更新通知栏进度条
     *
     * @param id       获取Notification的id
     * @param progress 获取的进度
     */
    public void updateNotification(int id, int progress) {
        if (mBuilder != null) {
            mBuilder.setTicker("开始下载");//Ticker是状态栏显示的提示
            mBuilder.setContentTitle("最好这里写应用的appname");
            mBuilder.setSmallIcon(R.mipmap.icon_launcher);
            mBuilder.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.icon_launcher));//通知栏的大图标
            mBuilder.setProgress(100, progress, false);
            mBuilder.setContentText(progress + "%");
            mManager.notify(id, mBuilder.build());
        }
    }
}

下载service代码:

package com.***.***.util.update.server;

import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;


import com.***.***.api.StaticUtil;
import com.***.***.util.log.MThoast;
import com.***.***.util.log.TLog;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by CherishTang on 2017/10/17.
 * 更新app服务
 */

public class DownloadApkService extends Service {

    public static final String ACTION_START = "ACTION_START";
    public static final String ACTION_UPDATE = "ACTION_UPDATE";
    public static final String ACTION_FINISHED = "ACTION_FINISHED";
    public static final String ACTION_CANCEL = "ACTION_CANCEL";
    public static final String ACTION_ERROR = "ACTION_ERROR";
    public static final String ACTION_REDIRECT_ERROR = "ACTION_REDIRECT_ERROR";

    // 文件的保存路径
    public static final String path = Environment.getExternalStorageDirectory().getAbsolutePath() +
            File.separator + StaticUtil.ROOTFILEPATH + File.separator + "download" + File.separator;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            if (ACTION_START.equals(intent.getAction())) {
                new DownLoadApkThread(intent.getIntExtra("id", 0)
                        , intent.getStringExtra("url"), intent.getStringExtra("name")).start();
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * http转https 这一波骚操作是因为后台http重定向的问题导致的,其实没卵用
     * http重定向会导致下载时 HttpURLConnection报301的问题,防止以后会有问题
     * 因此做个了个http和https如果任何一个code报301都互转下再试一次
     * @param downloadUrlNew 下载地址
     * @return 转换后的下载地址
     */
    private String httpToHttps(String downloadUrlNew) {
        if (downloadUrlNew.startsWith("http:")) {
            downloadUrlNew = downloadUrlNew.replace("http:", "https:");
        } else if (downloadUrlNew.startsWith("https:")) {
            downloadUrlNew = downloadUrlNew.replace("https:", "http:");
        }
        return downloadUrlNew;
    }

    public class DownLoadApkThread extends Thread {

        private int id;
        private String downloadUrl;
        private String fileName;

        public DownLoadApkThread(int id, String downloadUrl, String fileName) {
            this.id = id;
            this.downloadUrl = downloadUrl;
            this.fileName = fileName;
        }

        @Override
        public void run() {
            HttpURLConnection connLength = null;
            HttpURLConnection connFile = null;
            RandomAccessFile randomAccessFile = null;
            InputStream inputStream = null;
            URL url = null;
            try {
                url = new URL(downloadUrl);
                //获取apk文件长度
                connLength = (HttpURLConnection) url.openConnection();
                connLength.setConnectTimeout(5000);
                connLength.setRequestMethod("GET");
                int code = connLength.getResponseCode();
                int length = 0;
                if (code == HttpURLConnection.HTTP_OK) {
                    length = connLength.getContentLength();
                } else if (code == 301) {
                    downloadUrl = httpToHttps(downloadUrl);
                    url = new URL(downloadUrl);
                    //获取apk文件长度
                    connLength = (HttpURLConnection) url.openConnection();
                    connLength.setConnectTimeout(5000);
                    connLength.setRequestMethod("GET");
                    code = connLength.getResponseCode();
                    if (code == HttpURLConnection.HTTP_OK) {
                        length = connLength.getContentLength();
                    } else {
                        sendBroadcast(new Intent().setAction(ACTION_REDIRECT_ERROR));
                        return;
                    }
                } else {
                    sendBroadcast(new Intent().setAction(ACTION_ERROR));
                    return;
                }

                //判断文件是否存在,不存在则创建
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, fileName);
                randomAccessFile = new RandomAccessFile(file, "rwd");
                randomAccessFile.setLength(length);

                //下载文件
                connFile = (HttpURLConnection) url.openConnection();
                connFile.setConnectTimeout(5000);
                connFile.setRequestMethod("GET");
                connFile.setRequestProperty("Range", "bytes=" + 0 + "-" + length);
                code = connFile.getResponseCode();

                //显示通知栏进度条
                Intent intent = new Intent();
                intent.setAction(ACTION_START);
                intent.putExtra("id", id);
                sendBroadcast(intent);

                if (code == HttpURLConnection.HTTP_PARTIAL) {
                    inputStream = connFile.getInputStream();
                    int finished = 0;
                    byte[] bytes = new byte[1024 * 1024];
                    int len = -1;
                    long time = System.currentTimeMillis();
                    while ((len = inputStream.read(bytes)) != -1) {
                        //文件写入
                        randomAccessFile.write(bytes, 0, len);
                        //更新通知栏进度条
                        finished += len;
                        if (System.currentTimeMillis() - time > 1000) {
                            time = System.currentTimeMillis();
                            intent.setAction(ACTION_UPDATE);
                            int pro = (int) (((float) finished / length) * 100);
                            intent.putExtra("finished", pro);
                            sendBroadcast(intent);
                        }
                    }
                }
                //关闭通知栏
                intent.setAction(ACTION_FINISHED);
                sendBroadcast(intent);

            } catch (MalformedURLException e) {
                sendBroadcast(new Intent().setAction(ACTION_ERROR));
                e.printStackTrace();
            } catch (IOException e) {
                sendBroadcast(new Intent().setAction(ACTION_ERROR));
                e.printStackTrace();
            } finally {
                if (connLength != null) {
                    connLength.disconnect();
                }
                if (connFile != null) {
                    connFile.disconnect();
                }
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    if (randomAccessFile != null) {
                        randomAccessFile.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            super.run();
        }
    }
}

广播接收器isDownLoadApk 这个静态常量我是创建出来,防止多次下载任务,默认值未false,下载中此值设为true,下载失败、完成、取消则为false。

package com.***.***.util.update.server;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.***.***.api.StaticUtil;
import com.***.***.util.log.MThoast;
import com.***.***.util.log.TLog;
import com.***.***.util.update.UpdateManger;
import com.***.***.util.update.util.NotificationUtil;

import java.io.File;
import java.util.Calendar;

/**
 * Created by CherishTang on 2017/10/17.
 *
 */

public class DownloadApkReceiver extends BroadcastReceiver {

    private NotificationUtil mNotificationUtil;

    @Override
    public void onReceive(Context context, Intent intent) {
        mNotificationUtil = new NotificationUtil(context);

        if (DownloadApkService.ACTION_START.equals(intent.getAction())) {
            MThoast.showShort(context,"任务已转至后台下载");
            StaticUtil.isDownLoadApk = true;//单例下载,防止多任务进行
            // 下载开始的时候启动通知栏
            mNotificationUtil.showNotification(intent.getIntExtra("id", 0));
        } else if (DownloadApkService.ACTION_UPDATE.equals(intent.getAction())) {
            // 更新进度条
            mNotificationUtil.updateNotification(intent.getIntExtra("id",0), intent.getIntExtra("finished", 0));
        } else if (DownloadApkService.ACTION_FINISHED.equals(intent.getAction())) {
            StaticUtil.isDownLoadApk = false;//变更未任务未下载
            // 下载结束后取消通知
            mNotificationUtil.cancelNotification(intent.getIntExtra("id", 0));
            UpdateManger.installApk(context, new File(DownloadApkService.path + "hfzl.apk"));
//            CustomTools.installApk(context, new File(DownloadApkService.path + "宝宝.apk"));
        } else if (DownloadApkService.ACTION_CANCEL.equals(intent.getAction())) {
            // 下载结束后取消通知
            mNotificationUtil.cancelNotification(intent.getIntExtra("id", 0));
        } else if (DownloadApkService.ACTION_ERROR.equals(intent.getAction())) {
            MThoast.showShort(context, "读取文件失败,请前往官方网站扫码下载最新版本!");
        }else if (DownloadApkService.ACTION_REDIRECT_ERROR.equals(intent.getAction())) {
            MThoast.showShort(context, "下载地址重定向出现错误,请稍后再试!");
        }
    }
}

4、最后下载完成安装apk文件:这个没什么说的,android 7.0后都一样

    

 public static void installApk(Context mContext, File apkFile) {
        try{
            if (!apkFile.exists()) {
                return;
            }
            Intent i = new Intent(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT >= 24) { //适配安卓7.0
                i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK); //添加这一句表示对目标应用临时授权该Uri所代表的文件
                Uri apkFileUri = FileProvider.getUriForFile(mContext.getApplicationContext(),
                        mContext.getPackageName() + ".FileProvider", apkFile);
                i.setDataAndType(apkFileUri, "application/vnd.android.package-archive");
            } else {
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                i.setDataAndType(Uri.parse("file://" + apkFile.toString()),
                        "application/vnd.android.package-archive");// File.toString()会返回路径信息
            }
            mContext.startActivity(i);
        }catch (Exception e){
            e.printStackTrace();
            MThoast.showShort(mContext,"自动安装失败,请尝试手动安装!");
        }
    }

切记为了适配android 8.0一定要在配置文件中添加权限

<!--适配android 8.0-->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

还有切记记得在配置文件中注册service

        <service android:name=".util.update.server.DownloadApkService" />

最后粘上完整代码

package com.***.***.util.update;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.view.View;


import com.***.***.api.StaticUtil;
import com.***.***.custom.dialog.CustomProgressDialog;
import com.***.***.custom.dialog.UpdateMessageDialog;
import com.***.***.util.dialog.DialogHelper;
import com.***.***.util.log.MThoast;
import com.***.***.util.update.server.DownloadApkService;

import java.io.File;


/**
 * Created by CherishTang on 2016/11/23.
 * 软件版本更新
 */
public class UpdateManger implements UpdateMessageDialog.OnUpdateListener {
    // 应用程序Context
    private static Activity mContext;
    // 提示消息
    private String updateMsg = "有最新的软件包,请下载!";
    // 下载安装包的网络路径
    private String apkUrl;
    private String mCurrentVersionName;
    private static UpdateManger updateManger;

    //显示通知栏进度条
    public Intent intent = new Intent();
    long time;

    public UpdateManger() {

    }

    public static UpdateManger getInstance() {
        if (updateManger == null) {
            updateManger = new UpdateManger();
        }
        return updateManger;
    }

    // 显示更新程序对话框,供主程序调用
    public void checkUpdateInfo(Activity mContext, String apkUrl,
                                String updateMsg, String mCurrentVersionName,
                                Boolean isMustUpdate) {
        this.apkUrl = apkUrl;
        UpdateManger.mContext = mContext;
        if (updateMsg != null && !updateMsg.equals("")) {
            this.updateMsg = updateMsg;
        }
        this.mCurrentVersionName = mCurrentVersionName;
        UpdateMessageDialog updateMessageDialog =
                new UpdateMessageDialog(mContext, mCurrentVersionName,
                        updateMsg, isMustUpdate);
        updateMessageDialog.create();
        updateMessageDialog.setOnUpdateListener(this);
    }

    public static void installApk(Context mContext, File apkFile) {
        try{
            if (!apkFile.exists()) {
                return;
            }
            Intent i = new Intent(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT >= 24) { //适配安卓7.0
                i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK); //添加这一句表示对目标应用临时授权该Uri所代表的文件
                Uri apkFileUri = FileProvider.getUriForFile(mContext.getApplicationContext(),
                        mContext.getPackageName() + ".FileProvider", apkFile);
                i.setDataAndType(apkFileUri, "application/vnd.android.package-archive");
            } else {
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                i.setDataAndType(Uri.parse("file://" + apkFile.toString()),
                        "application/vnd.android.package-archive");// File.toString()会返回路径信息
            }
            mContext.startActivity(i);
        }catch (Exception e){
            e.printStackTrace();
            MThoast.showShort(mContext,"自动安装失败,请尝试手动安装!");
        }
    }

    @Override
    public void onUpdate(Dialog customDialog, View v) {
        if (StaticUtil.isDownLoadApk) {
            MThoast.showShort(mContext, "已存在下载任务,请勿重复下载");
            return;
        }

        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(mContext, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    0x01);
            return;
        }
        //PackageManager类中在Android Oreo版本中添加了一个方法:判断是否可以安装未知来源的应用
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !mContext.getPackageManager().canRequestPackageInstalls()) {
            //请求安装未知应用来源的权限
            DialogHelper.getConfirmDialog(mContext, "安装应用需要打开未知来源权限,请去设置中手动开启权限",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //注意这个是8.0新API
                            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                            mContext.startActivityForResult(intent, 10086);
                        }
                    }).show();
            return;
        }
        if (customDialog != null && customDialog.isShowing())
            customDialog.dismiss();
        Intent intent = new Intent(mContext, DownloadApkService.class);
        intent.setAction(DownloadApkService.ACTION_START);
        intent.putExtra("id", 0);
        intent.putExtra("url", apkUrl);
        intent.putExtra("name", "hfzl.apk");
        mContext.startService(intent);
    }

    /**
     * 打开未知来源权限
     * @param context
     */
    public static void openNonMarketAppsPerm(Context context){
        if (Build.VERSION.SDK_INT < 17) {
            int flag = Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
            if(flag == 0){
                Settings.Secure.putInt(context.getContentResolver(),
                        Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
            }
        } else {
            int flag = Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 0);
            if(flag == 0){
                Settings.Global.putInt(context.getContentResolver(),
                        Settings.Global.INSTALL_NON_MARKET_APPS, 1);
            }
        }
    }
    /**
     * 关闭未知来源权限
     * @param context
     */
    public static void closeNonMarketAppsPerm(Context context){
        if (Build.VERSION.SDK_INT < 17) {
            int flag = Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
            if(flag == 1) {
                Settings.Secure.putInt(context.getContentResolver(),
                        Settings.Secure.INSTALL_NON_MARKET_APPS, 0);
            }
        } else {
            int flag= Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 1);
            if (flag==1){
                Settings.Global.putInt(context.getContentResolver(),
                        Settings.Global.INSTALL_NON_MARKET_APPS, 0);
            }
        }
    }

    /**
     * 检查状态是否打开
     * @param context
     */
    public static boolean checkNonMarketAppsPermStatus(Context context){
        boolean unKnowSource=false;
        if (Build.VERSION.SDK_INT<17){
            unKnowSource=Settings.Secure.getInt(context.getContentResolver(),
                    Settings.Secure.INSTALL_NON_MARKET_APPS, 0)==1;
        }else{
            unKnowSource=Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.INSTALL_NON_MARKET_APPS, 0)==1;
        }
        return unKnowSource;
    }

}
 

新手上路,多多指教

猜你喜欢

转载自blog.csdn.net/fzkf9225/article/details/80969439