今天实现APP更新功能,Notification实现在通知栏显示下载详情,更新完成安装过程。
在通知栏显示更新,点击不能取消通知
下载完成之后弹出安装提示,通知栏点击进行安装,点击一次之后清除通知。
下面是代码(这里使用了Xutils下载apk安装包):
UpdateManager.class 弹出dialog,提示更新,和发送通知在该类中
public class UpdateManager {
private Context mContext;
// 提示语
private String updateMsg = "有最新的软件包哦,亲快下载吧~";
// 返回的安装包url,这里测试使用的android版的QQ进行测试,在app中安装app会先卸载,通知就会清除,但是测试的下载是QQ,不是一个app,所以通知不会清除,不是BUG。
private String apkUrl = "http://sqdd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";
private Dialog noticeDialog;
/* 下载包安装路径 */
private static final String savePath = "/sdcard/updatedemo/";
private static final String saveFileName = savePath+ "UpdateDemoRelease.apk";
NotificationManager notificationManager;
private int notificationId = 333;
private Notification notification = null;
public UpdateManager(Context context) {
this.mContext = context;
}
public UpdateManager() {
}
// 外部接口让主Activity调用
public void checkUpdateInfo() {
showNoticeDialog();
}
/**
* 初始化通知
*/
private void showNitifity() {
notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
RemoteViews view = new RemoteViews(mContext.getPackageName(),
R.layout.notifiy);
builder.setContent(view);
builder.setContentText("测试").setSmallIcon(R.drawable.ic_launcher, 100)
.setContentText("测试内容").setTicker("开始下载").setPriority(1000);
notification = builder.build();
notification.flags = Notification.FLAG_NO_CLEAR;
notificationManager.notify(notificationId, notification);
}
private void downLoad() {
HttpLine.download(apkUrl, savePath + "aa.apk",
new RequestCallBack<File>() {
@Override
public void onSuccess(ResponseInfo<File> arg0) {
installApk();
// notification.defaults=Notification.DEFAULT_SOUND;//设置下载完成,提示音
notification.flags=Notification.FLAG_AUTO_CANCEL;
notification.contentView.setTextViewText(R.id.title, "下载完成 ");
Intent notificationIntent = new Intent(mContext, InstallApkService.class);
notificationIntent.putExtra("savePath", savePath);
notificationIntent.putExtra("saveFileName", saveFileName);
//在通知栏中点击通知也可以进行安装
PendingIntent intent= PendingIntent.getService(mContext, 0, notificationIntent, 10);
notification.contentIntent=intent;
notificationManager.notify(notificationId, notification);
}
@Override
public void onFailure(HttpException arg0, String arg1) {
log.e("下载失败", arg1);
dowmFailure();
}
@Override
public void onLoading(long total, long current,
boolean isUploading) {
super.onLoading(total, current, isUploading);
changeProgressStatus(current, total);
}
@Override
public void onStart() {
super.onStart();
showNitifity();
}
});
}
//下载失败
public void dowmFailure(){
if (notification.contentView != null ) {
notification.contentView.setTextViewText(R.id.title, "很抱歉,下载失败! ");
notificationManager.notify(notificationId, notification);
}
}
/**
* 更改自定义布局文件中的进度条的值
*
* @param current 当前下载字节数
* @param total apk 总共字节数
*
*/
public void changeProgressStatus(long current, long total) {
BigDecimal b1 = new BigDecimal(total);
BigDecimal b2 = new BigDecimal(current);
double totaleM = b1.divide(new BigDecimal(1000 * 1000))
.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();// apk大小兆
int percent = b2.divide(b1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();// 百分比
//当前下载的数量k/m
String j = (current > 1000&¤t<1000*1000) ?
b2.divide(new BigDecimal(1000)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue() +"K":
b2.divide(new BigDecimal(1000*1000)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()+"M";
if (notification.contentView != null ) {
notification.contentView.setTextViewText(R.id.title, "app正在下载。。。("+ j+ "/" + totaleM + "M " + percent + "%) ");
notification.contentView.setProgressBar(R.id.progressBar1, 100,percent, false);
}
notificationManager.notify(notificationId, notification);
}
/**
* 更改自定义布局文件中的进度条的值,未使用
*
* @param p
* 进度值(0~100)
*/
public void changeProgressStatus(int p) {
if (notification.contentView != null) {
if (p == 0)
notification.contentView.setTextViewText(R.id.title, "下载失败! ");
else if (p >= 100) {
notification.contentView.setTextViewText(R.id.title,
"下载完成,请点击安装");
notificationManager.cancel(notificationId);// 取消通知
return;
} else
notification.contentView.setTextViewText(R.id.title,
"app正在下载。。。(" + p + "%) ");
notification.contentView.setProgressBar(R.id.progressBar1, 100, p,
false);
}
notificationManager.notify(notificationId, notification);
}
private void showNoticeDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("软件版本更新");
builder.setMessage(updateMsg);
builder.setPositiveButton("下载", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
downLoad();
}
});
builder.setNegativeButton("以后再说", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
noticeDialog = builder.create();
noticeDialog.show();
}
/**
* 安装apk
*
* @param url
*/
public void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
"application/vnd.android.package-archive");
mContext.startActivity(i);
}
}
dialog的notifiy.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:background="#EEEEEE"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_marginLeft="3dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginLeft="20dp"
android:text="app正在下载"
android:gravity="center_vertical"
android:textColor="@color/black"
android:textSize="16sp" >
</TextView>
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:progress="0" />
</LinearLayout>
</LinearLayout>
InstallApkService.class当用户没有在app中进行安装,在通知栏中点击通知,通知栏点击后消失,也可以进行安装。
public class InstallApkService extends Service {
/* 下载包安装路径 */
private String savePath ;
private String saveFileName ;
private UpdateManager mUpdateManager;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
savePath=intent.getStringExtra("savePath");
saveFileName=intent.getStringExtra("saveFileName");
installApk();
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
/**
* 安装apk
*
* @param url
*/
private void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()),"application/vnd.android.package-archive");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
在Activity中:
private UpdateManager mUpdateManager;
最后在Activity中调用后台接口,发现有更新调用:
mUpdateManager = new UpdateManager(HomeActivity.this);
mUpdateManager.checkUpdateInfo();