android中app升级的两种常用写法
16lz
2021-01-23
android中,做APP开发难免会遇到程序升级问题,本文简单介绍一下两种常用的写法,第一种是使用DownloadManager来进行下载安装,第二种是直接使用HttpURLConnection来得到获取数据。一般的升级程序都是放在service中进行,我们新建一个DownloadService。
一般程序安装的代码部分如下所示:
Intent intent = new Intent(Intent.ACTION_VIEW); intent .setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); mContext.startActivity(intent );
一、利用DownloadManager来写的代码如下:
public class DownloadService extends Service {private long _dwonloadID;private BroadcastReceiver _receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long dwonloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if(_dwonloadID != dwonloadID) return; DownloadManager dManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE); Uri downloadFileUri = dManager.getUriForDownloadedFile(dwonloadID); Intent install = new Intent(Intent.ACTION_VIEW); install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive"); startActivity(install); stopSelf(); } };@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { registerReceiver(_receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); startDownload(); return Service.START_STICKY;}@Overridepublic void onDestroy() { unregisterReceiver(_receiver); super.onDestroy();}private void startDownload() {DownloadManager dManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(UpdateInfo.url_appDownload)); request.setMimeType("application/vnd.android.package-archive"); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, UpdateInfo.APP_NAME); request.setTitle("TestApp"); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); _dwonloadID = dManager.enqueue(request);}}
第二种,利用 HttpURLConnection 进行下载,然后调用Intent来安装。
public class DownloadService extends Service {public static final String BUNDLE_KEY_DOWNLOAD_URL = "download_url";public static final String BUNDLE_KEY_TITLE = "title";private final String tag = "download";private static final int NOTIFY_ID = 0;private int progress;private NotificationManager mNotificationManager;private boolean canceled;private String downloadUrl;private String mTitle = "正在下载%s";private String saveFileName = AppConfig.DEFAULT_SAVE_FILE_PATH;private ICallbackResult callback;private DownloadBinder binder;private boolean serviceIsDestroy = false;private Context mContext = this;private Thread downLoadThread;private Notification mNotification;private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);switch (msg.what) {case 0:// 下载完毕mNotificationManager.cancel(NOTIFY_ID);installApk();break;case 2:// 取消通知mNotificationManager.cancel(NOTIFY_ID);break;case 1:int rate = msg.arg1;if (rate < 100) {RemoteViews contentview = mNotification.contentView;contentview.setTextViewText(R.id.tv_download_state, mTitle + "(" + rate+ "%" + ")");contentview.setProgressBar(R.id.pb_download, 100, rate,false);} else {// 下载完毕后变换通知形式mNotification.flags = Notification.FLAG_AUTO_CANCEL;mNotification.contentView = null;Intent intent = new Intent(mContext, MainActivity.class);// 告知已完成intent.putExtra("completed", "yes");// 更新参数,注意flags要使用FLAG_UPDATE_CURRENTPendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);//mNotification.setLatestEventInfo(mContext, "下载完成",//"文件已下载完毕", contentIntent);serviceIsDestroy = true;stopSelf();// 停掉服务自身}mNotificationManager.notify(NOTIFY_ID, mNotification);break;}}};@Overridepublic IBinder onBind(Intent intent) {downloadUrl = intent.getStringExtra(BUNDLE_KEY_DOWNLOAD_URL);saveFileName = saveFileName + getSaveFileName(downloadUrl); mTitle = String.format(mTitle, intent.getStringExtra(BUNDLE_KEY_TITLE));return binder;}private String getSaveFileName(String downloadUrl) {if (downloadUrl == null || StringUtils.isEmpty(downloadUrl)) {return "";}return downloadUrl.substring(downloadUrl.lastIndexOf("/"));}@Overridepublic void onCreate() {super.onCreate();binder = new DownloadBinder();mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);stopForeground(true);// 这个不确定是否有作用}private void startDownload() {canceled = false;downloadApk();}/** * 创建通知 */private void setUpNotification() {int icon = R.drawable.ic_notification;CharSequence tickerText = "准备下载";long when = System.currentTimeMillis();mNotification = new Notification(icon, tickerText, when);;// 放置在"正在运行"栏目中mNotification.flags = Notification.FLAG_ONGOING_EVENT;RemoteViews contentView = new RemoteViews(getPackageName(),R.layout.download_notification_show);contentView.setTextViewText(R.id.tv_download_state, mTitle);// 指定个性化视图mNotification.contentView = contentView;Intent intent = new Intent(this, MainActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);// 指定内容意图mNotification.contentIntent = contentIntent;mNotificationManager.notify(NOTIFY_ID, mNotification);}private void downloadApk() {downLoadThread = new Thread(mdownApkRunnable);downLoadThread.start();}/** * 安装apk */private void installApk() {File apkfile = new File(saveFileName);if (!apkfile.exists()) {return;}installAPK(mContext, apkfile);}private Runnable mdownApkRunnable = new Runnable() {@Overridepublic void run() {File file = new File(AppConfig.DEFAULT_SAVE_FILE_PATH);if (!file.exists()) {file.mkdirs();}String apkFile = saveFileName;File saveFile = new File(apkFile);try {downloadUpdateFile(downloadUrl, saveFile);} catch (Exception e) {e.printStackTrace();}}};public long downloadUpdateFile(String downloadUrl, File saveFile)throws Exception {int downloadCount = 0;int currentSize = 0;long totalSize = 0;int updateTotalSize = 0;HttpURLConnection httpConnection = null;InputStream is = null;FileOutputStream fos = null;try {URL url = new URL(downloadUrl);httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestProperty("User-Agent", "PacificHttpClient");if (currentSize > 0) {httpConnection.setRequestProperty("RANGE", "bytes="+ currentSize + "-");}httpConnection.setConnectTimeout(10000);httpConnection.setReadTimeout(20000);updateTotalSize = httpConnection.getContentLength();if (httpConnection.getResponseCode() == 404) {throw new Exception("fail!");}is = httpConnection.getInputStream();fos = new FileOutputStream(saveFile, false);byte buffer[] = new byte[1024];int readsize = 0;while ((readsize = is.read(buffer)) > 0) {fos.write(buffer, 0, readsize);totalSize += readsize;// 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次if ((downloadCount == 0)|| (int) (totalSize * 100 / updateTotalSize) - 10 >= downloadCount) {downloadCount += 10;// 更新进度Message msg = mHandler.obtainMessage();msg.what = 1;msg.arg1 = downloadCount;mHandler.sendMessage(msg);if (callback != null)callback.OnBackResult(progress);}}// 下载完成通知安装mHandler.sendEmptyMessage(0);// 下载完了,cancelled也要设置canceled = true;} finally {if (httpConnection != null) {httpConnection.disconnect();}if (is != null) {is.close();}if (fos != null) {fos.close();}}return totalSize;}public class DownloadBinder extends Binder {public void start() {if (downLoadThread == null || !downLoadThread.isAlive()) {progress = 0;setUpNotification();new Thread() {public void run() {// 下载startDownload();};}.start();}}public void cancel() {canceled = true;}public int getProgress() {return progress;}public boolean isCanceled() {return canceled;}public boolean serviceIsDestroy() {return serviceIsDestroy;}public void cancelNotification() {mHandler.sendEmptyMessage(2);}public void addCallback(ICallbackResult callback) {DownloadService.this.callback = callback;}}}
上述代码是参考 oschina的代码,有兴趣的朋友们可以参考oschina的源码。 更多相关文章
- Android 通过蓝牙控制小车源代码+视频
- [置顶] 如何修改Android应用程序能够使用的默认最大内存值
- (转)Android 应用程序退出后不在运行列表中显示的方法
- Android用Adb安装和卸载应用程序
- Android SQLite详解及示例代码
- 部署应用程序到Android手机上