一开始,我们先向服务器请求数据获取版本
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 }