看图, 只要点击取消或是下载完毕 通知才会消失!
代码是大部分是借用别人的,再自己修改,达到自己所需要的效果
xml文件
update.xml
<?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>
<?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
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; } }
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(); } }
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); } }
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