android 客户端版本检测更新,服务下载,通知栏显示
2015-07-01 09:44
851 查看
android客户端版本检测更新,服务下载,通知栏显示
看图, 只要点击取消或是下载完毕 通知才会消失!![](http://img.my.csdn.net/uploads/201211/30/1354285876_7193.png)
![](http://img.my.csdn.net/uploads/201211/30/1354286035_6750.png)
代码是大部分是借用别人的,再自己修改,达到自己所需要的效果
xml文件
update.xml
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/newlogin_bg"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginTop="10dp"
android:text="正在下载..."
android:textColor="#000" />
<TextView
android:id="@+id/currentPos"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginLeft="4dp"
android:layout_marginTop="10dp"
android:textColor="#000" />
<ProgressBar
android:id="@+id/progressbar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:max="100"
android:progress="0" />
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:minWidth="200dp"
android:text="取消" />
</LinearLayout>
download_notification_layout.xml
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical" >
<LinearLayout
android:layout_centerInParent="true"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:orientation="vertical" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/icon" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:orientation="vertical" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="xxxx.apk"
android:textColor="#000" />
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:minWidth="60dp"
android:textColor="#000" />
</LinearLayout>
<ProgressBar
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:layout_marginTop="3dp"
android:max="100"
android:progress="0"
android:text="xxxx.apk" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
MyApp
[java] view
plaincopy
package com.zeng.update;
import android.app.Application;
public class MyApp extends Application {
private boolean isDownload;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
isDownload = false;
}
public boolean isDownload() {
return isDownload;
}
public void setDownload(boolean isDownload) {
this.isDownload = isDownload;
}
}
Main
[java] view
plaincopy
package com.zeng.update;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Main extends Activity {
private Button btn_check;
private MyApp app;
private int currentVersionCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
app = (MyApp) getApplication();
btn_check = (Button) findViewById(R.id.check);
btn_check.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PackageManager manager = Main.this.getPackageManager();
try {
PackageInfo info = manager.getPackageInfo(Main.this.getPackageName(), 0);
String appVersion = info.versionName; // 版本名
currentVersionCode = info.versionCode; // 版本号
System.out.println(currentVersionCode + " " + appVersion);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch blockd
e.printStackTrace();
}
//上面是获取manifest中的版本数据,我是使用versionCode
//在从服务器获取到最新版本的versionCode,比较
showUpdateDialog();
}
});
}
private void showUpdateDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("检测到新版本");
builder.setMessage("是否下载更新?");
builder.setPositiveButton("下载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Intent it = new Intent(Main.this, NotificationUpdateActivity.class);
startActivity(it);
// MapApp.isDownload = true;
app.setDownload(true);
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
builder.show();
}
}
NotificationUpdateActivity 这个我加了一个启动模式 SingleTask
[java] view
plaincopy
package com.zeng.update;
import com.zeng.update.DownloadService.DownloadBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class NotificationUpdateActivity extends Activity {
private Button btn_cancel;// btn_update,
private TextView tv_progress;
private DownloadBinder binder;
private boolean isBinded;
private ProgressBar mProgressBar;
// 获取到下载url后,直接复制给MapApp,里面的全局变量
private String downloadUrl;
//
private boolean isDestroy = true;
private MyApp app;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.update);
app = (MyApp) getApplication();
// btn_update = (Button) findViewById(R.id.update);
btn_cancel = (Button) findViewById(R.id.cancel);
tv_progress = (TextView) findViewById(R.id.currentPos);
mProgressBar = (ProgressBar) findViewById(R.id.progressbar1);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
binder.cancel();
binder.cancelNotification();
finish();
}
});
}
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
isBinded = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
binder = (DownloadBinder) service;
System.out.println("服务启动!!!");
// 开始下载
isBinded = true;
binder.addCallback(callback);
binder.start();
}
};
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if (isDestroy && app.isDownload()) {
Intent it = new Intent(NotificationUpdateActivity.this, DownloadService.class);
startService(it);
bindService(it, conn, Context.BIND_AUTO_CREATE);
}
System.out.println(" notification onresume");
}
@Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
if (isDestroy && app.isDownload()) {
Intent it = new Intent(NotificationUpdateActivity.this, DownloadService.class);
startService(it);
bindService(it, conn, Context.BIND_AUTO_CREATE);
}
System.out.println(" notification onNewIntent");
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println(" notification onPause");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
isDestroy = false;
System.out.println(" notification onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isBinded) {
System.out.println(" onDestroy unbindservice");
unbindService(conn);
}
if (binder != null && binder.isCanceled()) {
System.out.println(" onDestroy stopservice");
Intent it = new Intent(this, DownloadService.class);
stopService(it);
}
}
private ICallbackResult callback = new ICallbackResult() {
@Override
public void OnBackResult(Object result) {
// TODO Auto-generated method stub
if ("finish".equals(result)) {
finish();
return;
}
int i = (Integer) result;
mProgressBar.setProgress(i);
// tv_progress.setText("当前进度 => "+i+"%");
// tv_progress.postInvalidate();
mHandler.sendEmptyMessage(i);
}
};
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
tv_progress.setText("当前进度 : " + msg.what + "%");
};
};
public interface ICallbackResult {
public void OnBackResult(Object result);
}
}
DownloadService
[java] view
plaincopy
package com.zeng.update;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import com.zeng.update.NotificationUpdateActivity.ICallbackResult;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.RemoteViews;
public class DownloadService extends Service {
private static final int NOTIFY_ID = 0;
private int progress;
private NotificationManager mNotificationManager;
private boolean canceled;
// 返回的安装包url
private String apkUrl = "http://softfile.3g.qq.com:8080/msoft/179/24659/43549/qq_hd_mini_1.4.apk";
// private String apkUrl = MyApp.downloadApkUrl;
/* 下载包安装路径 */
private static final String savePath = "/sdcard/updateApkDemo/";
private static final String saveFileName = savePath + "3GQQ_AppUpdate.apk";
private ICallbackResult callback;
private DownloadBinder binder;
private MyApp app;
private boolean serviceIsDestroy = false;
private Context mContext = this;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 0:
app.setDownload(false);
// 下载完毕
// 取消通知
mNotificationManager.cancel(NOTIFY_ID);
installApk();
break;
case 2:
app.setDownload(false);
// 这里是用户界面手动取消,所以会经过activity的onDestroy();方法
// 取消通知
mNotificationManager.cancel(NOTIFY_ID);
break;
case 1:
int rate = msg.arg1;
app.setDownload(true);
if (rate < 100) {
RemoteViews contentview = mNotification.contentView;
contentview.setTextViewText(R.id.tv_progress, rate + "%");
contentview.setProgressBar(R.id.progressbar, 100, rate, false);
} else {
System.out.println("下载完毕!!!!!!!!!!!");
// 下载完毕后变换通知形式
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
mNotification.contentView = null;
Intent intent = new Intent(mContext, NotificationUpdateActivity.class);
// 告知已完成
intent.putExtra("completed", "yes");
// 更新参数,注意flags要使用FLAG_UPDATE_CURRENT
PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", contentIntent);
//
serviceIsDestroy = true;
stopSelf();// 停掉服务自身
}
mNotificationManager.notify(NOTIFY_ID, mNotification);
break;
}
}
};
//
// @Override
// public int onStartCommand(Intent intent, int flags, int startId) {
// // TODO Auto-generated method stub
// return START_STICKY;
// }
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("是否执行了 onBind");
return binder;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("downloadservice ondestroy");
// 假如被销毁了,无论如何都默认取消了。
app.setDownload(false);
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("downloadservice onUnbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
// TODO Auto-generated method stub
super.onRebind(intent);
System.out.println("downloadservice onRebind");
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
binder = new DownloadBinder();
mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
setForeground(true);// 这个不确定是否有作用
app = (MyApp) getApplication();
}
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;
}
}
private void startDownload() {
// TODO Auto-generated method stub
canceled = false;
downloadApk();
}
//
Notification mNotification;
// 通知栏
/**
* 创建通知
*/
private void setUpNotification() {
int icon = R.drawable.icon;
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_layout);
contentView.setTextViewText(R.id.name, "腾讯QQ.apk 正在下载...");
// 指定个性化视图
mNotification.contentView = contentView;
Intent intent = new Intent(this, NotificationUpdateActivity.class);
// 下面两句是 在按home后,点击通知栏,返回之前activity 状态;
// 有下面两句的话,假如service还在后台下载, 在点击程序图片重新进入程序时,直接到下载界面,相当于把程序MAIN 入口改了 - -
// 是这么理解么。。。
// intent.setAction(Intent.ACTION_MAIN);
// intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 指定内容意图
mNotification.contentIntent = contentIntent;
mNotificationManager.notify(NOTIFY_ID, mNotification);
}
//
/**
* 下载apk
*
* @param url
*/
private Thread downLoadThread;
private void downloadApk() {
downLoadThread = new Thread(mdownApkRunnable);
downLoadThread.start();
}
/**
* 安装apk
*
* @param url
*/
private void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
callback.OnBackResult("finish");
}
private int lastRate = 0;
private Runnable mdownApkRunnable = new Runnable() {
@Override
public void run() {
try {
URL url = new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File file = new File(savePath);
if (!file.exists()) {
file.mkdirs();
}
String apkFile = saveFileName;
File ApkFile = new File(apkFile);
FileOutputStream fos = new FileOutputStream(ApkFile);
int count = 0;
byte buf[] = new byte[1024];
do {
int numread = is.read(buf);
count += numread;
progress = (int) (((float) count / length) * 100);
// 更新进度
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.arg1 = progress;
if (progress >= lastRate + 1) {
mHandler.sendMessage(msg);
lastRate = progress;
if (callback != null)
callback.OnBackResult(progress);
}
if (numread <= 0) {
// 下载完成通知安装
mHandler.sendEmptyMessage(0);
// 下载完了,cancelled也要设置
canceled = true;
break;
}
fos.write(buf, 0, numread);
} while (!canceled);// 点击取消就停止下载.
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
}
参照博客
http://blog.csdn.net/liuhe688/article/details/6623924
还有些代码是另一个下载的demo的 不过忘了哪下的~
源码下载
http://download.csdn.net/detail/zgf1991/5725471
版权声明:本文为博主原创文章,未经博主允许不得转载。
上一篇类似网易新闻客户端首页的图片浏览,右下角显示当前第几个图片
下一篇schedule(TimerTask
task, long delay, long period) 抛 IllegalArgumentException
主题推荐android
猜你在找
iOS8开发技术(Swift版):iOS基础知识
反编译Android应用
Struts实战-使用SSH框架技术开发学籍管理系统
零基础学Java系列从入门到精通
火星人敏捷开发1001问(第一季)
android ScrollView中嵌套GridViewListView只显示一行的解决办法
Android Service 详解四开始停止service
MIUI的root权限管理分析
android ListView几个比较特别的属性
Android网络连接的理解
准备好了么? 跳吧 !更多职位尽在 CSDN
JOB
HTML/CSS/JS前端工程师
百洋健康网
|
5-8K/月
我要跳槽
java,android,ios开发
杭州洽诚网络技术有限公司
|
10-15K/月
我要跳槽
J***A/JSP开发工程师
天津信航惠民商务信息咨询有限公司
|
8-12K/月
我要跳槽
J***A(JSP)软件工程师
同方知好乐教育科技(北京)有限公司
|
15-20K/月
我要跳槽
查看评论
4楼 宠爱是种习惯 2014-01-02 11:39发表 [回复]
![](http://avatar.csdn.net/1/4/D/3_u010246312.jpg)
请问您判断了版本是否更新吗?我没有找到方法,问下
Re: zgf1991 2014-01-03 12:35发表 [回复]
![](http://avatar.csdn.net/F/D/3/3_zgf1991.jpg)
回复u010246312:这个是测试demo,没有。这个调接口就行啊,具体怎么体现需要更新,和服务器协商好就行
Re: 宠爱是种习惯 2014-01-03 14:42发表 [回复]
![](http://avatar.csdn.net/1/4/D/3_u010246312.jpg)
回复zgf1991:好的,谢谢你了!
3楼 androidk123 2013-07-08 16:07发表 [回复]
![](http://avatar.csdn.net/1/1/9/3_u011338758.jpg)
求manifest.xml文件
Re: zgf1991 2013-07-09 14:24发表 [回复]
![](http://avatar.csdn.net/F/D/3/3_zgf1991.jpg)
回复u011338758: 已上传资源
2楼 yang735642758 2013-06-19 11:56发表 [回复] [引用] [举报]
![](http://avatar.csdn.net/7/A/A/3_yang735642758.jpg)
邮箱1657369437@qq.com
Re: zgf1991 2013-07-02 15:40发表 [回复] [引用] [举报]
![](http://avatar.csdn.net/F/D/3/3_zgf1991.jpg)
回复yang735642758:不好意思,上次回家后就忘了,这么久了 不用了吧.... 有时间我上传个资源.
1楼 yang735642758 2013-06-19 11:56发表 [回复]
![](http://avatar.csdn.net/7/A/A/3_yang735642758.jpg)
有没有源码能不能发一份给我
我照着写没有错但是下载不了
求源码行吗
相关文章推荐
- Android关键字模糊查询,并带有高亮效果
- Android SDK Manager安装API
- android - anim translate中 fromXDelta、toXDelta、fromYDelta、toXDelta属性
- Android 开发HTML5应用-总结(不跳转到系统浏览器)
- Android完全退出程序退出所有Activity
- android应用程序的优先级
- android根据Uri获取文件路径
- Android安全篇
- Android多媒体篇
- Android图像篇
- android 学习笔记-2
- android Vibrator 使用
- android中src和background区别
- wifi连接android设备进行调试
- GitHub 优秀的 Android 开源项目
- android ichart ColumnStacked2D图表无法显示解决方案
- android 系统怎么将修改好的kernel打包成boot.img
- 【Android Demo】通过WebService获取今日天气情况--转
- Android开源项目SlidingMenu本学习笔记(两)
- android webview js交互 第一节 (java和js交互)