app版本更新和下载,通知栏实时进度(使用服务和广播)
来源:互联网 发布:男人至死都是少年 知乎 编辑:程序博客网 时间:2024/04/30 00:25
每个app都需要有版本更新的功能,下面简单介绍一下最近在项目中使用的app更新功能。
1、首先需要使用服务和广播实现后台更新,使用到了xUtils,其他的网络请求框架代码类似。
服务代码如下,注释写的很详细
import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.support.annotation.Nullable;import android.text.TextUtils;import android.util.Log;import org.xutils.common.Callback;import org.xutils.ex.HttpException;import org.xutils.http.RequestParams;import org.xutils.x;import java.io.File;import java.text.NumberFormat;/** * 下载的services,配合xutils的httputils使用,完成notification的下载功能 */public class UpdateService extends Service { //是否已经开始下载 private boolean isBegin = false; Intent intent; private NumberFormat numberFormat; public static Callback.Cancelable downLoadHandler; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); intent = new Intent(); numberFormat = NumberFormat.getInstance(); numberFormat.setMaximumFractionDigits(2); } @Override public int onStartCommand(Intent intent, int flags, int startId) { String downUrl = intent.getStringExtra("downUrl"); String filePath = intent.getStringExtra("filePath"); //如果下载地址为空,则什么都不干 if (TextUtils.isEmpty(downUrl)) { stopSelf();// throw new IllegalArgumentException("the download url is empty!!!!"); return START_NOT_STICKY; } if (isBegin) { //此时已经开始了 return START_NOT_STICKY; } else { isBegin = true; } downLoad(downUrl,filePath); return super.onStartCommand(intent, flags, startId); } int progress = -1; private void downLoad(final String downUrl,String filePath) { RequestParams requestParams = new RequestParams(downUrl); requestParams.setSaveFilePath(filePath); downLoadHandler = x.http().get(requestParams, new Callback.ProgressCallback<File>() { @Override public void onSuccess(File result) { intent.setAction("com.ycb.www.complete"); intent.putExtra("filepath", result.getAbsolutePath()); Log.i("tag", "onSuccess"); Log.i("tag", result.getAbsolutePath()); sendBroadcast(intent); stopSelf(); } @Override public void onError(Throwable ex, boolean isOnCallback) { intent.setAction("com.ycb.www.failed"); intent.putExtra("downUrl", downUrl); Log.i("tag", "onFailure!!!"+ex.getMessage());// sendBroadcast(intent); if (ex instanceof HttpException) { HttpException httpEx = (HttpException) ex; Log.i("tag","onError:"+httpEx.getCode()+httpEx.getMessage()); } } @Override public void onCancelled(CancelledException cex) { Log.i("tag", "onCancelled"); stopSelf(); } @Override public void onFinished() { Log.i("tag", "onFinished");// stopSelf(); } @Override public void onWaiting() { Log.i("tag", "onWaiting"); } @Override public void onStarted() { Log.i("tag","Started"); intent.putExtra("rate",0); intent.setAction("com.ycb.www.updating"); sendBroadcast(intent); } @Override public void onLoading(long total, long current, boolean isDownloading) { Double rate= (double)current / (double)total; String format = numberFormat.format(rate); int r= (int) (Double.valueOf(format)*100); Log.i("tag", ""+r); intent.putExtra("rate", r); intent.setAction("com.ycb.www.updating"); sendBroadcast(intent); } }); }}
2、然后添加一个广播,用于实时处理下载进度,并在通知栏实时显示
import android.annotation.TargetApi;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.net.Uri;import android.os.Build;import android.widget.RemoteViews;import java.io.File;/** * notification更新的广播接收者,根据action不同,做出的结果不同, * 其中intent因为是同一个intent的,所以并没有new 新的 */public class UpdateReceiver extends BroadcastReceiver { private NotificationManager manager; private RemoteViews views; private Notification notification; @Override public void onReceive(Context context, Intent intent) { if (notification == null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) initNotification(context); else { initNotificationForLowVersion(context); } } String action = intent.getAction(); switch (action) { case "com.ycb.www.cancel": manager.cancel(0); UpdateService.downLoadHandler.cancel(); break; case "com.ycb.www.failed": intent.setAction("com.ycb.www.restart"); PendingIntent failedpendingIntent = PendingIntent.getBroadcast(context, 200, intent, PendingIntent.FLAG_CANCEL_CURRENT); views.setOnClickPendingIntent(R.id.ll_content, failedpendingIntent); views.setTextViewText(R.id.tv_info, "下载失败,点击重试"); manager.notify(0, notification); break; case "com.ycb.www.restart": manager.cancel(0); intent.setClass(context, UpdateService.class); context.startService(intent); break; case "com.ycb.www.install": manager.cancel(0); Intent startInstall = new Intent(); startInstall.setAction(Intent.ACTION_VIEW); String filepath = intent.getStringExtra("filepath"); startInstall.setDataAndType(Uri.fromFile(new File(filepath)), "application/vnd.android.package-archive"); startInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(startInstall); break; case "com.ycb.www.complete": intent.setAction("com.ycb.www.install"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 200, intent, PendingIntent.FLAG_CANCEL_CURRENT); views.setOnClickPendingIntent(R.id.ll_content, pendingIntent); views.setTextViewText(R.id.tv_info, "下载完成,点击安装"); views.setProgressBar(R.id.progressBar, 100, 100, false); manager.notify(0, notification); break; case "com.ycb.www.updating": int rate = intent.getIntExtra("rate", 0); views.setTextViewText(R.id.tv_info, "正在下载...." + rate + "%"); views.setProgressBar(R.id.progressBar, 100, rate, false); manager.notify(0, notification); } } private void initNotificationForLowVersion(Context context) { //设置notifiction布局 views = new RemoteViews(context.getPackageName(), R.layout.notification_update); notification = new Notification(); notification.when = System.currentTimeMillis(); notification.tickerText = "xxxx新版正在下载"; //设置view notification.contentView = views; //设置小图标 notification.icon = R.mipmap.icon; //设置布局文件中的textView的内容 views.setTextViewText(R.id.tv_info, "下载中....0%"); //设置布局文件中的ProgressBar进度 views.setProgressBar(R.id.progressBar, 100, 0, false); //退出的intent Intent intent = new Intent("com.ycb.www.cancel"); //退出的延迟意图 PendingIntent mPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 200, intent, PendingIntent.FLAG_UPDATE_CURRENT); //点击之后退出 views.setOnClickPendingIntent(R.id.ib_close, mPendingIntent); } /** * 初始化notification * * @param context */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void initNotification(Context context) { manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); views = new RemoteViews(context.getPackageName(), R.layout.notification_update); Notification.Builder builder = new Notification.Builder(context.getApplicationContext()); notification = builder.setAutoCancel(false).setSmallIcon(R.mipmap.icon).setContentText("下载中").setContentTitle("下载"). setWhen(System.currentTimeMillis()).setTicker("xxxxx新版正在下载") .setContent(views).build(); views.setTextViewText(R.id.tv_info, "下载中....0%"); views.setProgressBar(R.id.progressBar, 100, 0, false); Intent intent = new Intent("com.ycb.www.cancel"); PendingIntent mPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 200, intent, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.ib_close, mPendingIntent); }}
3、在MainActivity或者LoginActivity页面检测app版本是否有更新,若有更新,开启服务,注册广播,开始下载更新操作
在onCreate方法中添加如下代码:
//检查版本更新 private void checkAppVersion() { try { PackageManager manager = this.getPackageManager(); PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0); versionCode = info.versionName; System.out.println("versionCode:" + versionCode); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } new Thread(new Runnable() { @Override public void run() { OkHttpUtils.get() .url(Constant.DB_URL + Constant.PORT + Constant.XHB_DIR + Constant.GET_APP_VERSION_DATA) .addParams("type", "0") .build() .execute(new StringCallback() { @Override public void onError(Call call, Exception e) { Toast.makeText(LoginActivity.this, "网络异常", Toast.LENGTH_SHORT).show(); } @Override public void onResponse(String response) { System.out.println("downApp:" + response); //版本号对比,若不同下载app downLoadApp(response); } }); } }).start(); }
倘若有更新时,开启服务执行下载操作,执行下面方法:
//比对版本号,更新app private void downLoadApp(String response) { final AppVersionResponse appVersionResponse = new Gson().fromJson(response, AppVersionResponse.class); AppVersionResponse.DataBean dataBean = appVersionResponse.getData(); if (appVersionResponse.isIsSuccess() && dataBean != null) { if (!versionCode.equals(appVersionResponse.getData().getCode())) { //强制更新 if(dataBean.getIsForced() == 1){ btn_land.setEnabled(false); //弹出窗口是否强制更新版本 AlertDialog alertDialog = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info).setTitle("版本升级") .setMessage(dataBean.getContent()) .setCancelable(false) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //下载操作 downLoad(appVersionResponse.getData().getCode()); } }).create(); alertDialog.show(); }else if(dataBean.getIsForced() == 0){ //非强制更新// btn_land.setEnabled(false); //弹出窗口是否强制更新版本 AlertDialog alertDialog = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info).setTitle("版本升级提示") .setMessage(dataBean.getContent()) .setCancelable(false) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //下载操作 downLoad(appVersionResponse.getData().getCode()); } }).create(); alertDialog.show(); } } } }
//下载app private void downLoad(final String version) { updateReceiver = new UpdateReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("com.ycb.www.cancel"); filter.addAction("com.ycb.www.failed"); filter.addAction("com.ycb.www.restart"); filter.addAction("com.ycb.www.install"); filter.addAction("com.ycb.www.complete"); filter.addAction("com.ycb.www.updating"); registerReceiver(updateReceiver,filter); Intent intent = new Intent(this, UpdateService.class); String url = Constant.DB_URL + Constant.PORT + Constant.XHB_DIR + Constant.DOWNLOAD_APP_URL; intent.putExtra("downUrl", url); intent.putExtra("filePath",Environment.getExternalStorageDirectory().getPath()+"/Downloads/xiahubao_"+version+".apk"); startService(intent); }
另外需要在配置文件中添加下面的服务和广播注册
<receiver android:name=".appUpdateUtils.UpdateReceiver"> <intent-filter> <action android:name="com.ycb.www.complete" /> <action android:name="com.ycb.www.install" /> <action android:name="com.ycb.www.cancel" /> <action android:name="com.ycb.www.updating" /> <action android:name="com.ycb.www.failed" /> <action android:name="com.ycb.www.restart" /> </intent-filter> </receiver> <service android:name=".appUpdateUtils.UpdateService" />
最后,在通知栏显示的自定义进度条代码如下,紧供参考
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <ImageView android:id="@+id/img_menu" android:layout_width="40dp" android:layout_height="40dp" android:src="@mipmap/icon" /> <LinearLayout android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:layout_marginLeft="10dp" android:layout_marginTop="6dp" android:orientation="vertical"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:progressDrawable="@drawable/seek_bar_progress_bg" /> <TextView android:id="@+id/tv_info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="6dp" android:textColor="@color/textBlackColor" /> </LinearLayout> <ImageButton android:id="@+id/ib_close" android:layout_width="15dp" android:layout_height="15dp" android:layout_marginLeft="10dp" android:layout_marginRight="3dp" android:background="@null" android:src="@android:drawable/ic_menu_close_clear_cancel" /></LinearLayout>
progressDrawable的配置如下,显示的更美观
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape> <solid android:color="#c6c6c6" /> <corners android:radius="3dp"/> </shape> </item> <item android:id="@android:id/secondaryProgress"> <clip> <shape> <solid android:color="#c6c6c6" /> <corners android:radius="3dp"/> </shape> </clip> </item> <item android:id="@android:id/progress"> <clip> <shape> <solid android:color="#06a7fa" /> <corners android:radius="3dp"/> </shape> </clip> </item></layer-list>
0 0
- app版本更新和下载,通知栏实时进度(使用服务和广播)
- 一个APP下载升级的Demo(通知栏实时更新下载进度)------(一)
- 一个APP下载升级的Demo(通知栏实时更新下载进度)------(二)
- 一个APP下载升级的Demo(通知栏实时更新下载进度)------(一)
- app版本更新下载服务
- Android下载,在通知栏更新进度
- android客户端版本检测更新,服务下载,通知栏显示
- android客户端版本检测更新,服务下载,通知栏显示
- android 客户端版本检测更新,服务下载,通知栏显示
- App下载更新、数据库断点续传、通知栏更新下载进度、Https传服务器Json并且解析对象
- Android通知栏实现APP下载更新(DownloadManager和自定义Notification2种方式实现)
- Android通知栏实现APP下载更新(DownloadManager和自定义Notification2种方式实现)
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- Notification使用 通过服务更新进度通知&在Activity中监听服务进度
- Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
- Android 6.0 RK3288 ROM编译详解+命令详解
- error while performing database login with the Dome driver:unable to create connection.check yoururl
- 9path 导致的一场冤假错案
- 学习c语言先要搞清楚编译器
- list,set,map集合随记
- app版本更新和下载,通知栏实时进度(使用服务和广播)
- 2.28学习内容
- Read the result of DOS command in C++
- php字符串函数总结
- msql 锁机制详解
- 中奖消息循环提醒
- 推荐!手把手教你使用Git
- ros下Kinect的“跟屁虫”
- 效率提高数倍的Android Studio快捷键收集