美文网首页
Android版本更新

Android版本更新

作者: Hi丶_cc25 | 来源:发表于2019-05-17 18:16 被阅读0次

    添加依赖:

     implementation 'com.github.LuoGuoXin:BaseAndroid:1.0.5'//版本更新
    

    在project—build.gradle下配置

    allprojects {
        repositories {
           ...
            maven { url 'https://jitpack.io' }
        }
    }
    

    添加下载apk权限及注册内容提供者(安装APK在Android7.0后需要用到)

    <!--请求安装应用权限-->
        <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.everywhere.trip"
                android:exported="false"
                android:grantUriPermissions="true">
    
                <!-- 元数据 -->
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_path" />
            </provider>
    

    向服务器获取版本号之后

    VersionName版本检测

     UpdateManager instance = UpdateManager.getInstance();
            info = versionInfo.getResult().getInfo();
            if (instance.updateApp(instance.getVersionName(this), info.getVersion())){
                int type = 0;
                if(luo.library.base.utils.UpdateManager.getInstance().isWifi(this)) {
                    type = 1;
                }
                if(false) {
                    type = 2;
                }
                String downLoadPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/downloads/";
                File dir = new File(downLoadPath);
                if(!dir.exists()) {
                    dir.mkdir();
                }
                                                               //getDownload_url()为接口中的下载路径
                fileName = info.getDownload_url().substring(info.getDownload_url().lastIndexOf("/") + 1, info.getDownload_url().length());
                if(fileName == null && TextUtils.isEmpty(fileName) && !fileName.contains(".apk")) {
                    fileName = this.getPackageName() + ".apk";
                }
                File file = new File(downLoadPath + fileName);
                UpdateManager.getInstance().setType(type).setUrl(info.getDownload_url()).setUpdateMessage("更新了UI\n添加图片缩放功能").setFileName(fileName).setIsDownload(file.exists());
                if(type == 1 && !file.exists()) {
                    UpdateManager.getInstance().downloadFile(this);
                } else {
                    UpdateManager.getInstance().showDialog(this);
                }
            }
    

    VersionCode版本检测

    BaseAndroid.checkUpdate(MainActivity.this, 2, downloadUrl,"更新了XXX\n修复OOO", false);
    

    下面进行代码分析哈:首先是主方法

     /**
         * 版本更新
         *
         * @param context
         * @param versionCode   版本号
         * @param url           apk下载地址
         * @param updateMessage 更新内容
         * @param isForced      是否强制更新
         */
        public static void checkUpdate(Context context, int versionCode, String url, String updateMessage, boolean isForced) {
            if (versionCode > UpdateManager.getInstance().getVersionCode(context)) {
                int type = 0;//更新方式,0:引导更新,1:安装更新,2:强制更新
                if (UpdateManager.getInstance().isWifi(context)) {
                    type = 1;
                }
                if (isForced) {
                    type = 2;
                }
    
                //检测是否已下载
                String downLoadPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/downloads/";
                File dir = new File(downLoadPath);
                if (!dir.exists()) {
                    dir.mkdir();
                }
                String fileName = url.substring(url.lastIndexOf("/") + 1, url.length());
                if (fileName == null && TextUtils.isEmpty(fileName) && !fileName.contains(".apk")) {
                    fileName = context.getPackageName() + ".apk";
                }
                File file = new File(downLoadPath + fileName);
    
                //设置参数
                UpdateManager.getInstance().setType(type).setUrl(url).setUpdateMessage(updateMessage).setFileName(fileName).setIsDownload(file.exists());
                if (type == 1 && !file.exists()) {
                    UpdateManager.getInstance().downloadFile(context);
                } else {
                    UpdateManager.getInstance().showDialog(context);
                }
            }
        }
    

    然后就是UpdateManager的封装啦,自己看代码吧

    /**
     * 版本更新
     */
    
    public class UpdateManager {
        private String downLoadPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/downloads/";
        private int type = 0;//更新方式,0:引导更新,1:安装更新,2:强制更新
        private String url = "";//apk下载地址
        private String updateMessage = "";//更新内容
        private String fileName = null;//文件名
        private boolean isDownload = false;//是否下载
        private NotificationManager mNotifyManager;
        private NotificationCompat.Builder mBuilder;
        private AlertDialog dialog;
        private ProgressDialog progressDialog;
    
        public static UpdateManager updateManager;
    
        public static UpdateManager getInstance() {
            if (updateManager == null) {
                updateManager = new UpdateManager();
            }
            return updateManager;
        }
    
        private UpdateManager() {
    
        }
    
        /**
         * 弹出版本更新提示框
         */
        public void showDialog(final Context context) {
            String title = "";
            String left = "";
            boolean cancelable = true;
            if (type == 1 | isDownload) {
                title = "安装新版本";
                left = "立即安装";
            } else {
                title = "发现新版本";
                left = "立即更新";
            }
            if (type == 2) {
                cancelable = false;
            }
            dialog = new AlertDialog.Builder(context).setTitle(title).setMessage(updateMessage).setCancelable(cancelable)
                    .setNegativeButton(left, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (type == 1 | isDownload) {
                                InstallUtil.installApk(context,downLoadPath+fileName);
                            } else {
                                if (url != null && !TextUtils.isEmpty(url)) {
                                    if (type == 2) {
                                        createProgress(context);
                                    } else {
                                        createNotification(context);
                                    }
                                    downloadFile(context);
                                } else {
                                    Toast.makeText(context, "下载地址错误", Toast.LENGTH_SHORT).show();
                                }
                            }
                            dialog.dismiss();
                        }
                    })
                    .setPositiveButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (type == 2) {
                                System.exit(0);
                            }
                        }
                    })
                    .create();
            dialog.show();
        }
    
        private static final String TAG = "UpdateManager";
        /**
         * 下载apk
         *
         */
        public void downloadFile(final Context context) {
            RequestParams params = new RequestParams(url);
            params.setSaveFilePath(downLoadPath + fileName);
            x.http().request(HttpMethod.GET, params, new Callback.ProgressCallback<File>() {
    
                @Override
                public void onSuccess(File result) {
    
                }
    
                @Override
                public void onError(Throwable ex, boolean isOnCallback) {
                    Toast.makeText(context, ex.getMessage(), Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onCancelled(CancelledException cex) {
    
                }
    
                @Override
                public void onFinished() {
    
                }
    
                @Override
                public void onWaiting() {
    
                }
    
                @Override
                public void onStarted() {
    
                }
    
                @Override
                public void onLoading(long total, long current, boolean isDownloading) {
                    //实时更新通知栏进度条
                    if (type == 0) {
                        Log.e(TAG, "onLoading:"+current+"/"+total );
                        notifyNotification(current, total);
                    } else if (type == 2) {
                        progressDialog.setProgress((int) (current * 100 / total));
                    }
                    if (total == current) {
                        if (type == 0) {
                            mBuilder.setContentText("下载完成");
                            mNotifyManager.notify(10086, mBuilder.build());
                        } else if (type == 2) {
                            progressDialog.setMessage("下载完成");
                        }
                        if (type == 1) {
                            showDialog(context);
                        } else {
                            InstallUtil.installApk(context,downLoadPath+fileName);
                        }
                    }
                }
            });
        }
    
        /**
         * 强制更新时显示在屏幕的进度条
         *
         */
        private void createProgress(Context context) {
            progressDialog = new ProgressDialog(context);
            progressDialog.setMax(100);
            progressDialog.setCancelable(false);
            progressDialog.setMessage("正在下载...");
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.show();
        }
    
        /**
         * 创建通知栏进度条
         *
         */
        private void createNotification(Context context) {
            mNotifyManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
            mBuilder = new NotificationCompat.Builder(context);
            mBuilder.setSmallIcon(BaseAndroid.getBaseConfig().getAppLogo());
            mBuilder.setContentTitle("版本更新");
            mBuilder.setContentText("正在下载...");
            mBuilder.setProgress(0, 0, false);
            Notification notification = mBuilder.build();
            notification.flags = Notification.FLAG_AUTO_CANCEL;
            mNotifyManager.notify(10086, notification);
        }
    
        /**
         * 更新通知栏进度条
         *
         */
        private void notifyNotification(long percent, long length) {
            mBuilder.setProgress((int) length, (int) percent, false);
            mNotifyManager.notify(10086, mBuilder.build());
        }
    
        /**
         * 安装apk
         *
         * @param context 上下文
         * @param file    APK文件
         */
        private void installApk(Context context, File file) {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            context.startActivity(intent);
        }
    
        /**
         * @return 当前应用的版本号
         */
        public int getVersionCode(Context context) {
            try {
                PackageManager manager = context.getPackageManager();
                PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
                int version = info.versionCode;
    //            String versionName = info.versionName;
                return version;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * @return 当前应用的版本名
         */
        public String getVersionName(Context context) {
            try {
                PackageManager manager = context.getPackageManager();
                PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
    //            int version = info.versionCode;
                String version = info.versionName;
                return version;
            } catch (Exception e) {
                e.printStackTrace();
                return "1.0";
            }
        }
    
        /**
         * 判断当前网络是否wifi
         */
        public boolean isWifi(Context mContext) {
            ConnectivityManager connectivityManager = (ConnectivityManager) mContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                return true;
            }
            return false;
        }
    
        public UpdateManager setUrl(String url) {
            this.url = url;
            return this;
        }
    
        public UpdateManager setType(int type) {
            this.type = type;
            return this;
        }
    
        public UpdateManager setUpdateMessage(String updateMessage) {
            this.updateMessage = updateMessage;
            return this;
        }
    
        public UpdateManager setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }
    
        public UpdateManager setIsDownload(boolean download) {
            isDownload = download;
            return this;
        }
    
        /**
         * 判断当前是否为最新版本
         * @param localVersion 当前安装的版本
         * @param newVersion    获取到的最新版本
         * @return
         */
        public boolean updateApp(String localVersion, String newVersion) {
            String[] localVersionArray = localVersion.split("\\.");
            String[] newVersionArray = newVersion.split("\\.");
            if (localVersionArray.length < newVersionArray.length) {
                int cha = newVersionArray.length - localVersionArray.length;
                for (int i = 0; i < cha; i++) {
                    localVersion = localVersion + ".0";
                }
                localVersionArray = localVersion.split("\\.");
            }
            try {
                for (int i = 0; i < newVersionArray.length; i++) {
                    int temp = Integer.parseInt(newVersionArray[i]);
                    int compar = Integer.parseInt(localVersionArray[i]);
                    if (temp > compar) {
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    }
    

    然后是安装APK用到的工具类:

    public class InstallUtil {
    
        /*调用安装的Activity中复写onActivityResult()方法
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == InstallUtil.UNKNOWN_CODE) {
                InstallUtil.installApk(this,mPath);//再次执行安装流程,包含权限判等
            }
        }*/
    
        public static final int UNKNOWN_CODE = 2019;
    
        public static void installApk(Context context, String path) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startInstallO(context, path);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                startInstallN(context, path);
            } else {
                startInstall(context, path);
            }
        }
    
        /**
         * android1.x-6.x
         *
         * @param path 文件的路径
         */
        public static void startInstall(Context context, String path) {
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
            install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(install);
        }
    
        /**
         * android7.x
         *
         * @param path 文件路径
         */
        @RequiresApi(api = Build.VERSION_CODES.N)
        public static void startInstallN(Context context, String path) {
            //参数1 上下文, 参数2 在AndroidManifest中的android:authorities值, 参数3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(context, "com.everywhere.trip", new File(path));
            Intent install = new Intent(Intent.ACTION_VIEW);
            //由于没有在Activity环境下启动Activity,设置下面的标签
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            install.setDataAndType(apkUri, "application/vnd.android.package-archive");
            context.startActivity(install);
        }
    
        /**
         * android8.x
         */
        @RequiresApi(api = Build.VERSION_CODES.O)
        private static void startInstallO(final Context context, String path) {
            boolean isGranted = context.getPackageManager().canRequestPackageInstalls();
            if (isGranted) {
                startInstallN(context, path);//安装应用的逻辑(写自己的就可以)
            } else {
                new AlertDialog.Builder(context)
                        .setCancelable(false)
                        .setTitle("安装应用需要打开未知来源权限,请去设置中开启权限")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface d, int w) {
                                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
                                Activity act = (Activity) context;
                                act.startActivityForResult(intent, UNKNOWN_CODE);
                            }
                        })
                        .show();
            }
        }
    }
    

    FileProvider:

    /**
     * 类:FileProviderUtils
     * 从APP向外共享的文件URI时,必须使用该类进行适配,
     * 否则在7.0以上系统,会报错:FileUriExposedException(文件Uri暴露异常)
     */
    public class FileProviderUtils {
        /**
         * 从文件获得URI
         * @param activity 上下文
         * @param file 文件
         * @return 文件对应的URI
         */
        public static Uri uriFromFile(Activity activity, File file) {
            Uri fileUri;
            //7.0以上进行适配
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                String p = activity.getPackageName() + "";
                fileUri = FileProvider.getUriForFile(
                        activity,
                        p,
                        file);
            } else {
                fileUri = Uri.fromFile(file);
            }
            return fileUri;
        }
    
        /**
         * 设置Intent的data和类型,并赋予目标程序临时的URI读写权限
         * @param activity 上下文
         * @param intent 意图
         * @param type 类型
         * @param file 文件
         * @param writeAble 是否赋予可写URI的权限
         */
        public static void setIntentDataAndType(Activity activity,
                                                Intent intent,
                                                String type,
                                                File file,
                                                boolean writeAble) {
            //7.0以上进行适配
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setDataAndType(uriFromFile(activity, file), type);
                //临时赋予读写Uri的权限
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (writeAble) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            } else {
                intent.setDataAndType(Uri.fromFile(file), type);
            }
        }
    
        /**
         * 设置Intent的data和类型,并赋予目标程序临时的URI读写权限
         * @param context 上下文
         * @param intent 意图
         * @param type 类型
         * @param fileUri 文件uri
         * @param writeAble 是否赋予可写URI的权限
         */
        public static void setIntentDataAndType(Context context,
                                                Intent intent,
                                                String type,
                                                Uri fileUri,
                                                boolean writeAble) {
            //7.0以上进行适配
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setDataAndType(fileUri, type);
                //临时赋予读写Uri的权限
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (writeAble) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            } else {
                intent.setDataAndType(fileUri, type);
            }
        }
    }
    

    用到的xml文件,在res文件下创建xml包,在此包下创建:


    image.png
    <resources xmlns:android="http://schemas.android.com/apk/res/android">
        <root-path
            name="root"
            path="" />
    
        <files-path
            name="files"
            path="" />
    
        <cache-path
            name="cache"
            path="" />
    
        <external-path
            name="external"
            path="" />
    
        <external-files-path
            name="external_file"
            path="" />
    
        <external-cache-path
            name="external_cache"
            path="" />
    </resources>
    

    相关文章

      网友评论

          本文标题:Android版本更新

          本文链接:https://www.haomeiwen.com/subject/hnewaqtx.html