zoukankan      html  css  js  c++  java
  • Android App自动更新解决方案(DownloadManager)

    一开始,我们先向服务器请求数据获取版本

     1    public ObservableField<VersionBean> appVersion = new ObservableField<>();
     2     
     3     /**
     4      * 获取服务器版本并判断是否需要更新
     5      */
     6     public void getServiceAppVersionEvent() {
     7         resource.getAppVersionEvent()
     8                 .observeOn(AndroidSchedulers.mainThread())
     9                 .subscribe(response -> {
    10                     if (EmptyUtil.isNotEmpty(response.body)) {
    11                         appVersion.set(response.body);
    12                         if (UpdateAppUtil.checkAppVersion(response.body)) {
    13                             checkUpdate.set("发现新版本" + response.body.getVersion());
    14                         }
    15                     }
    16                 });
    17     }

    服务器返回的数据

     1  2 
     3 /**
     4  * Created by hyx on 17-9-29.
     5  */
     6 
     7 public class VersionBean {
     8 
     9     private String description;
    10     private String url;
    11     private String version;
    12 
    13 
    14 
    15     public String getUrl() {
    16         return url;
    17     }
    18 
    19     public void setUrl(String url) {
    20         this.url = url;
    21     }
    22 
    23   
    24 
    25     public String getVersion() {
    26         return version;
    27     }
    28 
    29     public void setVersion(String version) {
    30         this.version = version;
    31     }
    32 
    33     public String getDescription() {
    34         return description;
    35     }
    36 
    37     public void setDescription(String description) {
    38         this.description = description;
    39     }
    40 }

    对比服务器和本地判断是否需要更新,我这里是根据VersionName判断

       /**
         * 获取versionName
         *
         * @return
         */
        public static String getAppVersionName() {
            if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) {
                try {
                    PackageManager manager = CtrAppImpl.getContext().getPackageManager();
                    PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0);
                    return info.versionName;
                } catch (Exception e) {
                    e.printStackTrace();
                    return "";
                }
    
            } else {
                return null;
            }
        }
    
    
        /**
         * 获取versionId
         *
         * @return
         */
        public static int getAppVersionCode() {
            if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) {
                try {
                    PackageManager manager = CtrAppImpl.getContext().getPackageManager();
                    PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0);
                    return info.versionCode;
                } catch (Exception e) {
                    e.printStackTrace();
                    return -1;
                }
    
            } else {
                return -1;
            }
        }
    
        /**
         * true 表示需要更新,false 表示当前版本是最新的
         *
         * @param versionBean
         * @return
         */
        public static boolean checkAppVersion(VersionBean versionBean) {
            if (EmptyUtil.isNotEmpty(versionBean)) {
                if (!getAppVersionName().equals(versionBean.getVersion())) {
                    return true;
                } else {
                    return false;
                }
            }
            return false;
        }

    如果需要更新,我们根据存储的downloadId去查询下载状态,因为有可能用户之前已经下载了,没有安装,亦或正在下载中,下载暂停等情况,

     1  if (UpdateAppUtil.checkAppVersion(getViewModel().appVersion.get())) {
     2                 //根据downloadId查询下载状态
     3                 long downloadId = (long) SPUtil.get(PersonalActivity.this, "downloadId", -1L);
     4                 UpdateAppUtil.checkDownloadStatus(downloadId, new DataBack<Integer>() {
     5                     @Override
     6                     public void take(Integer status) {
     7                         if (status == -1) {
     8                             new MaterialDialog.Builder(PersonalActivity.this)
     9                                     .title("版本更新")
    10                                     .content("发现新版本,是否更新?")
    11                                     .positiveText("确定")
    12                                     .negativeText("取消")
    13                                     .onPositive(((materialDialog, dialogAction) -> {
    14                                         ToastUtil.showShortToast("正在后台为您下载");
    15                                         UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk");
    16                                     }))
    17                                     .onNegative((materialDialog, dialogAction) -> {
    18                                         materialDialog.dismiss();
    19                                     })
    20                                     .show();
    21                         } else if (status == DownloadManager.STATUS_FAILED) {
    22                             ToastUtil.showShortToast("下载失败,正在为您重新下载");
    23                             UpdateAppUtil.downloadAPK(getViewModel().appVersion.get(), "ctrshoppix.apk");
    24                         } else if (status == DownloadManager.STATUS_SUCCESSFUL) {
    25                             if (UpdateAppUtil.compareApk(UpdateAppUtil.getApkInfo(UpdateAppUtil.getDownloadPath(downloadId)))) {
    26                                 UpdateAppUtil.installApp(UpdateAppUtil.getDownloadUri(downloadId));
    27                             } else {
    28                                 UpdateAppUtil.removeDownloadId(downloadId);
    29                             }
    30                         }
    31                     }
    32                 });

    具体的方法在下面UpdateAppUtil中查看,备注写的很清楚

      1 import android.app.Activity;
      2 import android.app.DownloadManager;
      3 import android.content.BroadcastReceiver;
      4 import android.content.Context;
      5 import android.content.Intent;
      6 import android.content.pm.PackageInfo;
      7 import android.content.pm.PackageManager;
      8 import android.database.Cursor;
      9 import android.net.Uri;
     10 import android.os.Build;
     11 import android.os.Environment;
     12 import android.support.v4.content.FileProvider;
     13 import android.text.BoringLayout;
     14 
     15 import java.io.File;
     16 import java.io.IOException;
     17 
     18 import ppm.ctr.cctv.ctr.application.CtrAppImpl;
     19 import ppm.ctr.cctv.ctr.common.AsyncCall;
     20 import ppm.ctr.cctv.ctr.common.DataBack;
     21 import ppm.ctr.cctv.ctr.network.entity.VersionBean;
     22 import ppm.ctr.cctv.ctr.services.file.UriPraseUtil;
     23 
     24 /**
     25  * Created by css on 2017/10/30.
     26  */
     27 
     28 public class UpdateAppUtil {
     29     private static DownloadManager downloadManager;
     30 
     31     /**
     32      * 获取versionName
     33      *
     34      * @return
     35      */
     36     public static String getAppVersionName() {
     37         if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) {
     38             try {
     39                 PackageManager manager = CtrAppImpl.getContext().getPackageManager();
     40                 PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0);
     41                 return info.versionName;
     42             } catch (Exception e) {
     43                 e.printStackTrace();
     44                 return "";
     45             }
     46 
     47         } else {
     48             return null;
     49         }
     50     }
     51 
     52 
     53     /**
     54      * 获取versionId
     55      *
     56      * @return
     57      */
     58     public static int getAppVersionCode() {
     59         if (EmptyUtil.isNotEmpty(CtrAppImpl.getContext())) {
     60             try {
     61                 PackageManager manager = CtrAppImpl.getContext().getPackageManager();
     62                 PackageInfo info = manager.getPackageInfo(CtrAppImpl.getContext().getPackageName(), 0);
     63                 return info.versionCode;
     64             } catch (Exception e) {
     65                 e.printStackTrace();
     66                 return -1;
     67             }
     68 
     69         } else {
     70             return -1;
     71         }
     72     }
     73 
     74     /**
     75      * true 表示需要更新,false 表示当前版本是最新的
     76      *
     77      * @param versionBean
     78      * @return
     79      */
     80     public static boolean checkAppVersion(VersionBean versionBean) {
     81         if (EmptyUtil.isNotEmpty(versionBean)) {
     82             if (!getAppVersionName().equals(versionBean.getVersion())) {
     83                 return true;
     84             } else {
     85                 return false;
     86             }
     87         }
     88         return false;
     89     }
     90 
     91     /**
     92      * 检查下载状态
     93      *
     94      * @param downloadId
     95      * @param dataBack
     96      */
     97     public static void checkDownloadStatus(long downloadId, DataBack<Integer> dataBack) {
     98         DownloadManager.Query query = new DownloadManager.Query();
     99         //通过下载的id查找
    100         query.setFilterById(downloadId);
    101         //获取DownloadManager
    102         if (EmptyUtil.isEmpty(downloadManager)) {
    103             downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
    104         }
    105         Cursor c = downloadManager.query(query);
    106         if (c.moveToFirst()) {
    107             int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
    108             switch (status) {
    109                 case -1:
    110                     dataBack.take(-1);
    111                     break;
    112                 //下载暂停
    113                 case DownloadManager.STATUS_PAUSED:
    114                     ToastUtil.showShortToast("下载暂停");
    115                     break;
    116                 //下载延迟
    117                 case DownloadManager.STATUS_PENDING:
    118                     ToastUtil.showShortToast("下载延迟");
    119                     break;
    120                 //正在下载
    121                 case DownloadManager.STATUS_RUNNING:
    122                     ToastUtil.showShortToast("正在下载");
    123                     break;
    124                 //下载完成
    125                 case DownloadManager.STATUS_SUCCESSFUL:
    126                     dataBack.take(DownloadManager.STATUS_SUCCESSFUL);
    127 
    128                     break;
    129                 //下载失败
    130                 case DownloadManager.STATUS_FAILED:
    131                     dataBack.take(DownloadManager.STATUS_FAILED);
    132                     break;
    133                 default:
    134                     dataBack.take(-1);
    135                     break;
    136             }
    137 
    138             dataBack.take(status);
    139         } else {
    140             //可能用户误删之前已经下载得apk
    141             dataBack.take(-1);
    142         }
    143         c.close();
    144     }
    145 
    146 
    147     /**
    148      * 根据downloadID获取本地存储的文件path
    149      *
    150      * @param downloadId
    151      * @return
    152      */
    153     public static String getDownloadPath(long downloadId) {
    154         //获取DownloadManager
    155         if (EmptyUtil.isEmpty(downloadManager)) {
    156             downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
    157         }
    158         String downloadPath = new File(UriPraseUtil.uriToFile(downloadManager.getUriForDownloadedFile(downloadId), CtrAppImpl.getContext())).toString();
    159         return downloadPath;
    160     }
    161 
    162     /**
    163      * 根据downloadID 获取获取本地文件存储的uri
    164      *
    165      * @param downloadId
    166      * @return
    167      */
    168     public static Uri getDownloadUri(long downloadId) {
    169         //获取DownloadManager
    170         if (EmptyUtil.isEmpty(downloadManager)) {
    171             downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
    172         }
    173         Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);
    174         //适配不同的手机,有的手机不能识别,所以再转一遍
    175         Uri uri = Uri.fromFile(new File(UriPraseUtil.uriToFile(downloadFileUri, CtrAppImpl.getContext())));
    176         return uri;
    177     }
    178 
    179 
    180     /**
    181      * 获取apk程序信息
    182      *
    183      * @param path apk path
    184      */
    185     public static PackageInfo getApkInfo(String path) {
    186         PackageManager pm = CtrAppImpl.getContext().getPackageManager();
    187         PackageInfo info = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
    188         if (info != null) {
    189             return info;
    190         }
    191         return null;
    192     }
    193 
    194 
    195     /**
    196      * 下载的apk和当前程序版本比较
    197      *
    198      * @param apkInfo apk file's packageInfo
    199      * @return 如果当前应用版本小于apk的版本则返回true
    200      */
    201     public static boolean compareApk(PackageInfo apkInfo) {
    202         if (apkInfo == null) {
    203             return false;
    204         }
    205         if (!apkInfo.versionName.equals(getAppVersionName())) {
    206             return true;
    207         }
    208         return false;
    209 
    210     }
    211 
    212 
    213     /**
    214      * 下载apk
    215      *
    216      * @param versionBean
    217      * @param apkName
    218      */
    219     public static void downloadAPK(VersionBean versionBean, String apkName) {
    220         //创建下载任务
    221         DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionBean.getUrl()));
    222         //移动网络情况下是否允许漫游
    223         request.setAllowedOverRoaming(false);
    224 //        设置在通知栏是否显示下载通知(下载进度), 有 3 个值可选:
    225 //        VISIBILITY_VISIBLE:                   下载过程中可见, 下载完后自动消失 (默认)
    226 //        VISIBILITY_VISIBLE_NOTIFY_COMPLETED:  下载过程中和下载完成后均可见
    227 //        VISIBILITY_HIDDEN:                    始终不显示通知
    228         request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    229         request.setTitle("单单拍");
    230         request.setDescription("");
    231         request.setVisibleInDownloadsUi(true);
    232 
    233         //设置下载的路径
    234         request.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath(), apkName);
    235 
    236         //获取DownloadManager
    237         if (EmptyUtil.isEmpty(downloadManager)) {
    238             downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
    239         }
    240         //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
    241         long downloadId = downloadManager.enqueue(request);
    242         SPUtil.put(CtrAppImpl.getContext(), "downloadId", downloadId);
    243     }
    244 
    245 
    246     /**
    247      * 移除本地存储的downloadid 和相关文件
    248      *
    249      * @param downloadId
    250      */
    251     public static void removeDownloadId(long downloadId) {
    252         //获取DownloadManager
    253         if (EmptyUtil.isEmpty(downloadManager)) {
    254             downloadManager = (DownloadManager) CtrAppImpl.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
    255         }
    256         downloadManager.remove(downloadId);
    257         SPUtil.remove(CtrAppImpl.getContext(), "downloadId");
    258     }
    259 
    260 
    261     /**
    262      * 安装app
    263      *
    264      * @param uri
    265      */
    266     public static void installApp(Uri uri) {
    267         Intent intent = new Intent();
    268         intent.setDataAndType(uri, "application/vnd.android.package-archive");
    269         intent.setAction(Intent.ACTION_VIEW);
    270         intent.addCategory(Intent.CATEGORY_DEFAULT);
    271         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    272         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    273         CtrAppImpl.getContext().startActivity(intent);
    274     }
    275 
    276 
    277     /**
    278      * 安装app
    279      *
    280      * @param apkPath
    281      */
    282     public static void installApp(String apkPath) {
    283         File file = new File(apkPath);
    284         Uri uri = null;
    285         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    286             String command = "chmod " + "777" + " " + file;
    287             Runtime runtime = Runtime.getRuntime();
    288             try {
    289                 runtime.exec(command);
    290             } catch (IOException e) {
    291                 e.printStackTrace();
    292             }
    293             uri = FileProvider.getUriForFile(CtrAppImpl.getContext(), "ppm.ctr.cctv.ctr.provider", file);
    294         } else {
    295             uri = Uri.fromFile(file);
    296         }
    297         Intent intent = new Intent();
    298         intent.setDataAndType(uri, "application/vnd.android.package-archive");
    299         intent.setAction(Intent.ACTION_VIEW);
    300         intent.addCategory(Intent.CATEGORY_DEFAULT);
    301         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    302         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    303         CtrAppImpl.getContext().startActivity(intent);
    304     }
    305 
    306 }
  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/bdsdkrb/p/8085284.html
Copyright © 2011-2022 走看看