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 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2024 CODEPRJ.COM