• 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 }
  • 相关阅读:
    第十六天-面向对象02-成员
    第十五天-面向对象01
    第十四天-内置函数
    第十三天-生成器
    第十二天-函数名 迭代器
    第十一天-函数进阶
    第十天-初识函数
    第九天- 文件操作 r w a 文件复制/修改
    objectives-c基本语法。
    今天开始了objective-c的学习!
  • 原文地址:https://www.cnblogs.com/bdsdkrb/p/8085284.html
Copyright © 2020-2023  润新知