Android版本更新(Service下载 Notification进度条:直接拿来用)
2017-12-12 00:03
801 查看
废话不多说:直接上代码:
--------------------------------
用法:
-------------------------------
附上其他比较好的博客链接:
和:附上自动更新的祖师爷写的代码和博客!
功能:版本更新、文件后台下载以及Notification显示进度条。
效果图:
主要代码:
Java代码
<strong style="color: #262626; font-family: Simsun;">package com.ljp.download;
import java.io.File;
import android.app.ActivityGroup;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.ljp.download.service.AppUpgradeService;
import com.ljp.version.R;
public class MainActivity extends ActivityGroup {
private Button button1;
private String mDownloadUrl = "http://gdown.baidu.com/data/wisegame/ba226d3cf2cfc97b/baiduyinyue_4920.apk";
private String apkUpdateMsg = "1.内容1\n2.内容2\n3.内容3";
private Dialog updateVersionDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showDialog();
}
});
}
private void showDialog() {
updateVersionDialog = new AlertDialog.Builder(MainActivity.this).setTitle("有新版本需要更新").setMessage(apkUpdateMsg)
.setPositiveButton("现在更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
downLoadApk();
}
}).setNegativeButton("以后再说", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
}).create();
updateVersionDialog.show();
}
/**
* 文件下载
*/
private void downLoadApk() {
Intent intent = new Intent(MainActivity.this, AppUpgradeService.class);
intent.putExtra("mDownloadUrl", mDownloadUrl);
startService(intent);
updateVersionDialog.dismiss();
}
}</strong>
Java代码
package com.ljp.download.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import com.ljp.download.DownloadUtils;
import com.ljp.download.MainActivity;
import com.ljp.version.R;
/**
* 程序版本更新Service
* @author yingjun10627
*
*/
public class AppUpgradeService extends Service {
private NotificationManager mNotificationManager = null;
private Notification mNotification = null;
private PendingIntent mPendingIntent = null;
private String mDownloadUrl;
private File destDir = null;
private File destFile = null;
public static final String downloadPath = "/winner";
public static final int mNotificationId = 111;
private static final int DOWNLOAD_FAIL = -1;
private static final int DOWNLOAD_SUCCESS = 0;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWNLOAD_SUCCESS:
Toast.makeText(getApplicationContext(), "下载成功", Toast.LENGTH_LONG).show();
install(destFile);
mNotificationManager.cancel(mNotificationId);
break;
case DOWNLOAD_FAIL:
Toast.makeText(getApplicationContext(), "下载失败", Toast.LENGTH_LONG).show();
mNotificationManager.cancel(mNotificationId);
break;
default:
break;
}
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent==null){
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
mDownloadUrl = intent.getStringExtra("mDownloadUrl");
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
destDir = new File(Environment.getExternalStorageDirectory().getPath() + downloadPath);
if (destDir.exists()) {
File destFile = new File(destDir.getPath() + "/" + URLEncoder.encode(mDownloadUrl));
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
install(destFile);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
} else {
return super.onStartCommand(intent, flags, startId);
}
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotification = new Notification();
Intent completingIntent = new Intent();
completingIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
completingIntent.setClass(getApplicationContext(), AppUpgradeService.class);
// 创建Notifcation对象,设置图标,提示文字,策略
mPendingIntent = PendingIntent.getActivity(AppUpgradeService.this, R.string.app_name, completingIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.icon = R.drawable.ic_launcher;
mNotification.tickerText = "开始下载";
mNotification.contentIntent = mPendingIntent;
mNotification.contentView = new RemoteViews(getPackageName(), R.layout.app_upgrade_notification);
mNotification.contentView.setProgressBar(R.id.app_upgrade_progressbar, 100, 0, false);
mNotification.contentView.setTextViewText(R.id.app_upgrade_title, "正在下载...");
mNotification.contentView.setTextViewText(R.id.app_upgrade_text, "当前进度:0%");
mNotificationManager.cancel(mNotificationId);
mNotificationManager.notify(mNotificationId, mNotification);
new AppUpgradeThread().start();
return super.onStartCommand(intent, flags, startId);
}
/**
* 用于监听文件下载
*/
private DownloadUtils.DownloadListener downloadListener = new DownloadUtils.DownloadListener() {
@Override
public void downloading(int progress) {
System.out.println(progress);
mNotification.contentView.setProgressBar(R.id.app_upgrade_progressbar, 100, progress, false);
mNotification.contentView.setTextViewText(R.id.app_upgrade_text, "当前进度:" + progress + "%");
mNotificationManager.notify(mNotificationId, mNotification);
}
@Override
public void downloaded() {
mNotification.contentView.setViewVisibility(R.id.app_upgrade_progressbar, View.GONE);
mNotification.defaults = Notification.DEFAULT_SOUND;
mNotification.contentIntent = mPendingIntent;
mNotification.contentView.setTextViewText(R.id.app_upgrade_title, "下载完成");
mNotificationManager.notify(mNotificationId, mNotification);
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
Message msg = mHandler.obtainMessage();
msg.what = DOWNLOAD_SUCCESS;
mHandler.sendMessage(msg);
}
mNotificationManager.cancel(mNotificationId);
}
};
/**
* 用于文件下载线程
* @author yingjun10627
*
*/
class AppUpgradeThread extends Thread {
@Override
public void run() {
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
if (destDir == null) {
destDir = new File(Environment.getExternalStorageDirectory().getPath() + downloadPath);
}
if (destDir.exists() || destDir.mkdirs()) {
destFile = new File(destDir.getPath() + "/" + URLEncoder.encode(mDownloadUrl));
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
install(destFile);
} else {
try {
DownloadUtils.download(mDownloadUrl, destFile, false, downloadListener);
} catch (Exception e) {
Message msg = mHandler.obtainMessage();
msg.what = DOWNLOAD_FAIL;
mHandler.sendMessage(msg);
e.printStackTrace();
}
}
}
}
stopSelf();
}
}
/**
* apk文件安装
*
* @param apkFile
*/
public void install(File apkFile) {
Uri uri = Uri.fromFile(apkFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);
}
/**
* 判断文件是否完整
*
* @param apkFilePath
* @return
*/
public boolean checkApkFile(String apkFilePath) {
boolean result = false;
try {
PackageManager pManager = getPackageManager();
PackageInfo pInfo = pManager.getPackageArchiveInfo(apkFilePath, PackageManager.GET_ACTIVITIES);
if (pInfo == null) {
result = false;
} else {
result = true;
}
} catch (Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Java代码
package com.ljp.download;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class DownloadUtils {
private static final int CONNECT_TIMEOUT = 10000;
private static final int DATA_TIMEOUT = 40000;
private final static int DATA_BUFFER = 8192;
public interface DownloadListener {
public void downloading(int progress);
public void downloaded();
}
public static long download(String urlStr, File dest, boolean append, DownloadListener downloadListener) throws Exception {
int downloadProgress = 0;
long remoteSize = 0;
int currentSize = 0;
long totalSize = -1;
if (!append && dest.exists() && dest.isFile()) {
dest.delete();
}
if (append && dest.exists() && dest.exists()) {
FileInputStream fis = null;
try {
fis = new FileInputStream(dest);
currentSize = fis.available();
} catch (IOException e) {
throw e;
} finally {
if (fis != null) {
fis.close();
}
}
}
HttpGet request = new HttpGet(urlStr);
if (currentSize > 0) {
request.addHeader("RANGE", "bytes=" + currentSize + "-");
}
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, CONNECT_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, DATA_TIMEOUT);
HttpClient httpClient = new DefaultHttpClient(params);
InputStream is = null;
FileOutputStream os = null;
try {
HttpResponse response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
is = response.getEntity().getContent();
remoteSize = response.getEntity().getContentLength();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
is = new GZIPInputStream(is);
}
os = new FileOutputStream(dest, append);
byte buffer[] = new byte[DATA_BUFFER];
int readSize = 0;
int temp=0;
while ((readSize = is.read(buffer)) > 0) {
os.write(buffer, 0, readSize);
os.flush();
totalSize += readSize;
if (downloadListener != null) {
downloadProgress = (int) (totalSize * 100 / remoteSize);
if(downloadProgress>=temp){
temp++;
downloadListener.downloading(downloadProgress);
}
}
}
if (totalSize < 0) {
totalSize = 0;
}
}
} finally {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
}
if (totalSize < 0) {
throw new Exception("Download file fail: " + urlStr);
}
if (downloadListener != null) {
downloadListener.downloaded();
}
return totalSize;
}
}
Service启动方式说明:
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
------------------------------------
public class UpdateService extends Service { public static final String TAG = "UpdateService"; public static final String ACTION = "me.shenfan.UPDATE_APP"; public static final String STATUS = "status"; public static final String PROGRESS = "progress"; public static boolean DEBUG = true; //下载大小通知频率 public static final int UPDATE_NUMBER_SIZE = 1; public static final int DEFAULT_RES_ID = -1; public static final int UPDATE_PROGRESS_STATUS = 0; public static final int UPDATE_ERROR_STATUS = -1; public static final int UPDATE_SUCCESS_STATUS = 1; //params private static final String URL = "downloadUrl"; private static final String ICO_RES_ID = "icoResId"; private static final String ICO_SMALL_RES_ID = "icoSmallResId"; private static final String UPDATE_PROGRESS = "updateProgress"; private static final String STORE_DIR = "storeDir"; private static final String DOWNLOAD_NOTIFICATION_FLAG = "downloadNotificationFlag"; private static final String DOWNLOAD_SUCCESS_NOTIFICATION_FLAG = "downloadSuccessNotificationFlag"; private static final String DOWNLOAD_ERROR_NOTIFICATION_FLAG = "downloadErrorNotificationFlag"; private static final String IS_SEND_BROADCAST = "isSendBroadcast"; private String downloadUrl; private int icoResId; //default app ico private int icoSmallResId; private int updateProgress; //update notification progress when it add number private String storeDir; //default sdcard/Android/package/update private int downloadNotificationFlag; private int downloadSuccessNotificationFlag; private int downloadErrorNotificationFlag; private boolean isSendBroadcast; private UpdateProgressListener updateProgressListener; private LocalBinder localBinder = new LocalBinder(); /** * Class used for the client Binder. */ public class LocalBinder extends Binder{ /** * set update progress call back * @param listener */ public void setUpdateProgressListener(UpdateProgressListener listener){ UpdateService.this.setUpdateProgressListener(listener); } } private boolean startDownload;//开始下载 private int lastProgressNumber; private NotificationCompat.Builder builder; private NotificationManager manager; private int notifyId; private String appName; private LocalBroadcastManager localBroadcastManager; private Intent localIntent; private DownloadApk downloadApkTask; /** * whether debug */ public static void debug(){ DEBUG = true; } private static Intent installIntent(String path){ Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(BaseApplication.app, "com.hx.socialapp.FileProvider", new File(path)); intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); }else { Uri uri = Uri.fromFile(new File(path)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(uri, "application/vnd.android.package-archive"); } return intent; } private static Intent webLauncher(String downloadUrl){ Uri download = Uri.parse(downloadUrl); Intent intent = new Intent(Intent.ACTION_VIEW, download); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; } private static String getSaveFileName(String downloadUrl) { if (downloadUrl == null || TextUtils.isEmpty(downloadUrl)) { return "noName.apk"; } return downloadUrl.substring(downloadUrl.lastIndexOf("/")); } private static File getDownloadDir(UpdateService service){ File downloadDir = null; if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { if (service.storeDir != null){ downloadDir = new File(Environment.getExternalStorageDirectory(), service.storeDir); }else { downloadDir = new File(service.getExternalCacheDir(), "update"); } } else { downloadDir = new File(service.getCacheDir(), "update"); } if (!downloadDir.exists()) { downloadDir.mkdirs(); } return downloadDir; } @Override public void onCreate() { super.onCreate(); appName = getApplicationName(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (!startDownload && intent != null){ startDownload = true; downloadUrl = intent.getStringExtra(URL); icoResId = intent.getIntExtra(ICO_RES_ID, DEFAULT_RES_ID); icoSmallResId = intent.getIntExtra(ICO_SMALL_RES_ID, DEFAULT_RES_ID); storeDir = intent.getStringExtra(STORE_DIR); updateProgress = intent.getIntExtra(UPDATE_PROGRESS, UPDATE_NUMBER_SIZE); downloadNotificationFlag = intent.getIntExtra(DOWNLOAD_NOTIFICATION_FLAG, 0); downloadErrorNotificationFlag = intent.getIntExtra(DOWNLOAD_ERROR_NOTIFICATION_FLAG, 0); downloadSuccessNotificationFlag = intent.getIntExtra(DOWNLOAD_SUCCESS_NOTIFICATION_FLAG, 0); isSendBroadcast = intent.getBooleanExtra(IS_SEND_BROADCAST, false); if (DEBUG){ Log.d(TAG, "downloadUrl: " + downloadUrl); Log.d(TAG, "icoResId: " + icoResId); Log.d(TAG, "icoSmallResId: " + icoSmallResId); Log.d(TAG, "storeDir: " + storeDir); Log.d(TAG, "updateProgress: " + updateProgress); Log.d(TAG, "downloadNotificationFlag: " + downloadNotificationFlag); Log.d(TAG, "downloadErrorNotificationFlag: " + downloadErrorNotificationFlag); Log.d(TAG, "downloadSuccessNotificationFlag: " + downloadSuccessNotificationFlag); Log.d(TAG, "isSendBroadcast: " + isSendBroadcast); } notifyId = startId; buildNotification(); buildBroadcast(); downloadApkTask = new DownloadApk(this); downloadApkTask.execute(downloadUrl); } return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { return localBinder; } @Override public boolean onUnbind(Intent intent) { return true; } public void setUpdateProgressListener(UpdateProgressListener updateProgressListener) { this.updateProgressListener = updateProgressListener; } @Override public void onDestroy() { if (downloadApkTask != null){ downloadApkTask.cancel(true); } if (updateProgressListener != null){ updateProgressListener = null; } localIntent = null; builder = null; super.onDestroy(); } public String getApplicationName() { PackageManager packageManager = null; ApplicationInfo applicationInfo = null; try { packageManager = getApplicationContext().getPackageManager(); applicationInfo = packageManager.getApplicationInfo(getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { applicationInfo = null; } String applicationName = (String) packageManager.getApplicationLabel(applicationInfo); return applicationName; } private void buildBroadcast(){ if (!isSendBroadcast){ return; } localBroadcastManager = LocalBroadcastManager.getInstance(this); localIntent = new Intent(ACTION); } private void sendLocalBroadcast(int status, int progress){ if (!isSendBroadcast || localIntent == null){ return; } localIntent.putExtra(STATUS, status); localIntent.putExtra(PROGRESS, progress); localBroadcastManager.sendBroadcast(localIntent); } private void buildNotification(){ manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); builder = new NotificationCompat.Builder(this); builder.setContentTitle(getString(R.string.update_app_model_prepare, appName)) .setWhen(System.currentTimeMillis()) .setProgress(100, 1, false) .setSmallIcon(icoSmallResId) .setLargeIcon(BitmapFactory.decodeResource( getResources(), icoResId)) .setDefaults(downloadNotificationFlag); manager.notify(notifyId, builder.build()); } private void start(){ builder.setContentTitle(appName); builder.setContentText(getString(R.string.update_app_model_prepare, 1)); manager.notify(notifyId, builder.build()); sendLocalBroadcast(UPDATE_PROGRESS_STATUS, 1); if (updateProgressListener != null){ updateProgressListener.start(); } } /** * * @param progress download percent , max 100 */ private void update(int progress){ if (progress - lastProgressNumber > updateProgress){ lastProgressNumber = progress; builder.setProgress(100, progress, false); builder.setContentText(getString(R.string.update_app_model_progress, progress, "%")); manager.notify(notifyId, builder.build()); sendLocalBroadcast(UPDATE_PROGRESS_STATUS, progress); if (updateProgressListener != null){ updateProgressListener.update(progress); } } } private void success(String path) { builder.setProgress(0, 0, false); builder.setContentText(getString(R.string.update_app_model_success)); Intent i = installIntent(path); PendingIntent intent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(intent); builder.setDefaults(downloadSuccessNotificationFlag); Notification n = builder.build(); n.contentIntent = intent; manager.notify(notifyId, n); sendLocalBroadcast(UPDATE_SUCCESS_STATUS, 100); if (updateProgressListener != null){ updateProgressListener.success(); } startActivity(i); stopSelf(); } private void error(){ Intent i = webLauncher(downloadUrl); PendingIntent intent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentText(getString(R.string.update_app_model_error)); builder.setContentIntent(intent); builder.setProgress(0, 0, false); builder.setDefaults(downloadErrorNotificationFlag); Notification n = builder.build(); n.contentIntent = intent; manager.notify(notifyId, n); sendLocalBroadcast(UPDATE_ERROR_STATUS, -1); if (updateProgressListener != null){ updateProgressListener.error(); } stopSelf(); } private static class DownloadApk extends AsyncTask<String, Integer, String>{ private WeakReference<UpdateService> updateServiceWeakReference; public DownloadApk(UpdateService service){ updateServiceWeakReference = new WeakReference<>(service); } @Override protected void onPreExecute() { super.onPreExecute(); UpdateService service = updateServiceWeakReference.get(); if (service != null){ service.start(); } } @Override protected String doInBackground(String... params) { final String downloadUrl = params[0]; final File file = new File(UpdateService.getDownloadDir(updateServiceWeakReference.get()), UpdateService.getSaveFileName(downloadUrl)); if (DEBUG){ Log.d(TAG, "download url is " + downloadUrl); Log.d(TAG, "download apk cache at " + file.getAbsolutePath()); } File dir = file.getParentFile(); if (!dir.exists()){ dir.mkdirs(); } HttpURLConnection httpConnection = null; InputStream is = null; FileOutputStream fos = null; int updateTotalSize = 0; URL url; try { url = new URL(downloadUrl); httpConnection = (HttpURLConnection) url.openConnection(); httpConnection.setConnectTimeout(20000); httpConnection.setReadTimeout(20000); if (DEBUG){ Log.d(TAG, "download status code: " + httpConnection.getResponseCode()); } if (httpConnection.getResponseCode() != 200) { return null; } updateTotalSize = httpConnection.getContentLength(); if (file.exists()) { if (updateTotalSize == file.length()) { // 下载完成 return file.getAbsolutePath(); } else { file.delete(); } } file.createNewFile(); is = httpConnection.getInputStream(); fos = new FileOutputStream(file, false); byte buffer[] = new byte[4096]; int readSize = 0; int currentSize = 0; while ((readSize = is.read(buffer)) > 0) { fos.write(buffer, 0, readSize); currentSize += readSize; publishProgress((currentSize * 100 / updateTotalSize)); } // download success } catch (Exception e) { e.printStackTrace(); return null; } finally { if (httpConnection != null) { httpConnection.disconnect(); } if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } return file.getAbsolutePath(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (DEBUG){ Log.d(TAG, "current progress is " + values[0]); } UpdateService service = updateServiceWeakReference.get(); if (service != null){ service.update(values[0]); } } @Override protected void onPostExecute(String s) { super.onPostExecute(s); UpdateService service = updateServiceWeakReference.get(); if (service != null){ if (s != null){ service.success(s); }else { service.error(); } } } } /** * a builder class helper use UpdateService */ public static class Builder{ private String downloadUrl; private int icoResId = DEFAULT_RES_ID; //default app ico private int icoSmallResId = DEFAULT_RES_ID; private int updateProgress = UPDATE_NUMBER_SIZE; //update notification progress when it add number private String storeDir; //default sdcard/Android/package/update private int downloadNotificationFlag; private int downloadSuccessNotificationFlag; private int downloadErrorNotificationFlag; private boolean isSendBroadcast; protected Builder(String downloadUrl){ this.downloadUrl = downloadUrl; } public static Builder create(String downloadUrl){ if (downloadUrl == null) { throw new NullPointerException("downloadUrl == null"); } return new Builder(downloadUrl); } public String getDownloadUrl() { return downloadUrl; } public int getIcoResId() { return icoResId; } public Builder setIcoResId(int icoResId) { this.icoResId = icoResId; return this; } public int getIcoSmallResId() { return icoSmallResId; } public Builder setIcoSmallResId(int icoSmallResId) { this.icoSmallResId = icoSmallResId; return this; } public int getUpdateProgress() { return updateProgress; } public Builder setUpdateProgress(int updateProgress) { if (updateProgress < 1){ throw new IllegalArgumentException("updateProgress < 1"); } this.updateProgress = updateProgress; return this; } public String getStoreDir() { return storeDir; } public Builder setStoreDir(String storeDir) { this.storeDir = storeDir; return this; } public int getDownloadNotificationFlag() { return downloadNotificationFlag; } public Builder setDownloadNotificationFlag(int downloadNotificationFlag) { this.downloadNotificationFlag = downloadNotificationFlag; return this; } public int getDownloadSuccessNotificationFlag() { return downloadSuccessNotificationFlag; } public Builder setDownloadSuccessNotificationFlag(int downloadSuccessNotificationFlag) { this.downloadSuccessNotificationFlag = downloadSuccessNotificationFlag; return this; } public int getDownloadErrorNotificationFlag() { return downloadErrorNotificationFlag; } public Builder setDownloadErrorNotificationFlag(int downloadErrorNotificationFlag) { this.downloadErrorNotificationFlag = downloadErrorNotificationFlag; return this; } public boolean isSendBroadcast() { return isSendBroadcast; } public Builder setIsSendBroadcast(boolean isSendBroadcast) { this.isSendBroadcast = isSendBroadcast; return this; } public Builder build(Context context){ if (context == null){ throw new NullPointerException("context == null"); } Intent intent = new Intent(); intent.setClass(context, UpdateService.class); intent.putExtra(URL, downloadUrl); if (icoResId == DEFAULT_RES_ID){ icoResId = getIcon(context); } if (icoSmallResId == DEFAULT_RES_ID){ icoSmallResId = icoResId; } intent.putExtra(ICO_RES_ID, icoResId); intent.putExtra(STORE_DIR, storeDir); intent.putExtra(ICO_SMALL_RES_ID, icoSmallResId); intent.putExtra(UPDATE_PROGRESS, updateProgress); intent.putExtra(DOWNLOAD_NOTIFICATION_FLAG, downloadNotificationFlag); intent.putExtra(DOWNLOAD_SUCCESS_NOTIFICATION_FLAG, downloadSuccessNotificationFlag); intent.putExtra(DOWNLOAD_ERROR_NOTIFICATION_FLAG, downloadErrorNotificationFlag); intent.putExtra(IS_SEND_BROADCAST, isSendBroadcast); context.startService(intent); return this; } private int getIcon(Context context){ final PackageManager packageManager = context.getPackageManager(); ApplicationInfo appInfo = null; try { appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (appInfo != null){ return appInfo.icon; } return 0; } } }
--------------------------------
用法:
//获取版本号 private void requestAppVersion() { RequestParams params = ParamsUtil.getInstances().appUpgrade(Constant.getAppVersion(mContext) , ContantUrl.SERVER_VERSION_NAME); BaseApplication.getInstance().httpRequest.xPostjson(mContext, params, Constant.BASE_HTTP + ContantUrl.appUpgrade, new RequestResultJsonCallBack() { @Override public void onSucess(String result) { Map item = Constant.getPerson(result, Map.class); CommonEntity info = Constant.getPerson(result, CommonEntity.class); String str = item.get("object") + ""; if (info.getRetCode().equals(Constant.RETURN_SUCCESS_CODE)) { mUpdateItem = Constant.getPerson(str, UpdateEntity.class); if (mUpdateItem != null) { Log.i("downurl", mUpdateItem.getUrl()); String text = mContext.getResources().getString(R.string .check_upgrade); UpgradeDialog upgrade = new UpgradeDialog(MainActivity.this, text, new UpgradeDialog.OnClickconfirmListener() { @Override public void confirm() { if (!checkPermission(Manifest.permission .WRITE_EXTERNAL_STORAGE)) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission .WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_STORAGE); return; } UpdateService.Builder.create(mUpdateItem.getUrl()) .setStoreDir(ContantUrl.AppFile) .setDownloadSuccessNotificationFlag(Notification .DEFAULT_ALL) .setDownloadErrorNotificationFlag(Notification .DEFAULT_ALL) .build(mContext); Toast.makeText(mContext, "正在后台下载", Toast.LENGTH_LONG) .show(); } }); upgrade.show(); upgrade.setDetail(mUpdateItem.getDescription()); AppConfig.saveObject(mContext, Constant.VERSION, mUpdateItem); } } else { } } @Override public void onFailure(int errorCode, String errorMsg) { } }); }
-------------------------------
附上其他比较好的博客链接:
Android sdk version 9以上就有DownManager 使用DownManager,我们可以很简便的在各个安卓机子上升级自家的应用 本例写了一个UpdataService实现后台下载新的APK到sdcard,并自动安装更新。 [java] view plain copy /** * 检测安装更新文件的助手类 * * @author G.Y.Y * */ public class UpdataService extends Service { /** 安卓系统下载类 **/ DownloadManager manager; /** 接收下载完的广播 **/ DownloadCompleteReceiver receiver; /** 初始化下载器 **/ private void initDownManager() { manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); receiver = new DownloadCompleteReceiver(); //设置下载地址 DownloadManager.Request down = new DownloadManager.Request( Uri.parse("http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk")); // 设置允许使用的网络类型,这里是移动网络和wifi都可以 down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); // 下载时,通知栏显示途中 down.setNotificationVisibility(Request.VISIBILITY_VISIBLE); // 显示下载界面 down.setVisibleInDownloadsUi(true); // 设置下载后文件存放的位置 down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "baidumusic.apk"); // 将下载请求放入队列 manager.enqueue(down); //注册下载广播 registerReceiver(receiver, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 调用下载 initDownManager(); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { // 注销下载广播 if (receiver != null) unregisterReceiver(receiver); super.onDestroy(); } // 接受下载完成后的intent class DownloadCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //判断是否下载完成的广播 if (intent.getAction().equals( DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { //获取下载的文件id long downId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1); //自动安装apk installAPK(manager.getUriForDownloadedFile(downId)); //停止服务并关闭广播 UpdataService.this.stopSelf(); } } /** * 安装apk文件 */ private void installAPK(Uri apk) { // 通过Intent安装APK文件 Intent intents = new Intent(); intents.setAction("android.intent.action.VIEW"); intents.addCategory("android.intent.category.DEFAULT"); intents.setType("application/vnd.android.package-archive"); intents.setData(apk); intents.setDataAndType(apk,"application/vnd.android.package-archive"); intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); android.os.Process.killProcess(android.os.Process.myPid()); // 如果不加上这句的话在apk安装完成之后点击单开会崩溃 startActivity(intents); } } } AndroidManifest.xml注册service [html] view plain copy <service android:name="com.example.test.UpdataService" android:enabled="true" > </service> 添加调用DownManager的权限 [html] view plain copy <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
和:附上自动更新的祖师爷写的代码和博客!
功能:版本更新、文件后台下载以及Notification显示进度条。
效果图:
主要代码:
Java代码
<strong style="color: #262626; font-family: Simsun;">package com.ljp.download;
import java.io.File;
import android.app.ActivityGroup;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.ljp.download.service.AppUpgradeService;
import com.ljp.version.R;
public class MainActivity extends ActivityGroup {
private Button button1;
private String mDownloadUrl = "http://gdown.baidu.com/data/wisegame/ba226d3cf2cfc97b/baiduyinyue_4920.apk";
private String apkUpdateMsg = "1.内容1\n2.内容2\n3.内容3";
private Dialog updateVersionDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showDialog();
}
});
}
private void showDialog() {
updateVersionDialog = new AlertDialog.Builder(MainActivity.this).setTitle("有新版本需要更新").setMessage(apkUpdateMsg)
.setPositiveButton("现在更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
downLoadApk();
}
}).setNegativeButton("以后再说", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
}).create();
updateVersionDialog.show();
}
/**
* 文件下载
*/
private void downLoadApk() {
Intent intent = new Intent(MainActivity.this, AppUpgradeService.class);
intent.putExtra("mDownloadUrl", mDownloadUrl);
startService(intent);
updateVersionDialog.dismiss();
}
}</strong>
Java代码
package com.ljp.download.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import com.ljp.download.DownloadUtils;
import com.ljp.download.MainActivity;
import com.ljp.version.R;
/**
* 程序版本更新Service
* @author yingjun10627
*
*/
public class AppUpgradeService extends Service {
private NotificationManager mNotificationManager = null;
private Notification mNotification = null;
private PendingIntent mPendingIntent = null;
private String mDownloadUrl;
private File destDir = null;
private File destFile = null;
public static final String downloadPath = "/winner";
public static final int mNotificationId = 111;
private static final int DOWNLOAD_FAIL = -1;
private static final int DOWNLOAD_SUCCESS = 0;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWNLOAD_SUCCESS:
Toast.makeText(getApplicationContext(), "下载成功", Toast.LENGTH_LONG).show();
install(destFile);
mNotificationManager.cancel(mNotificationId);
break;
case DOWNLOAD_FAIL:
Toast.makeText(getApplicationContext(), "下载失败", Toast.LENGTH_LONG).show();
mNotificationManager.cancel(mNotificationId);
break;
default:
break;
}
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent==null){
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
mDownloadUrl = intent.getStringExtra("mDownloadUrl");
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
destDir = new File(Environment.getExternalStorageDirectory().getPath() + downloadPath);
if (destDir.exists()) {
File destFile = new File(destDir.getPath() + "/" + URLEncoder.encode(mDownloadUrl));
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
install(destFile);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
} else {
return super.onStartCommand(intent, flags, startId);
}
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotification = new Notification();
Intent completingIntent = new Intent();
completingIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
completingIntent.setClass(getApplicationContext(), AppUpgradeService.class);
// 创建Notifcation对象,设置图标,提示文字,策略
mPendingIntent = PendingIntent.getActivity(AppUpgradeService.this, R.string.app_name, completingIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.icon = R.drawable.ic_launcher;
mNotification.tickerText = "开始下载";
mNotification.contentIntent = mPendingIntent;
mNotification.contentView = new RemoteViews(getPackageName(), R.layout.app_upgrade_notification);
mNotification.contentView.setProgressBar(R.id.app_upgrade_progressbar, 100, 0, false);
mNotification.contentView.setTextViewText(R.id.app_upgrade_title, "正在下载...");
mNotification.contentView.setTextViewText(R.id.app_upgrade_text, "当前进度:0%");
mNotificationManager.cancel(mNotificationId);
mNotificationManager.notify(mNotificationId, mNotification);
new AppUpgradeThread().start();
return super.onStartCommand(intent, flags, startId);
}
/**
* 用于监听文件下载
*/
private DownloadUtils.DownloadListener downloadListener = new DownloadUtils.DownloadListener() {
@Override
public void downloading(int progress) {
System.out.println(progress);
mNotification.contentView.setProgressBar(R.id.app_upgrade_progressbar, 100, progress, false);
mNotification.contentView.setTextViewText(R.id.app_upgrade_text, "当前进度:" + progress + "%");
mNotificationManager.notify(mNotificationId, mNotification);
}
@Override
public void downloaded() {
mNotification.contentView.setViewVisibility(R.id.app_upgrade_progressbar, View.GONE);
mNotification.defaults = Notification.DEFAULT_SOUND;
mNotification.contentIntent = mPendingIntent;
mNotification.contentView.setTextViewText(R.id.app_upgrade_title, "下载完成");
mNotificationManager.notify(mNotificationId, mNotification);
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
Message msg = mHandler.obtainMessage();
msg.what = DOWNLOAD_SUCCESS;
mHandler.sendMessage(msg);
}
mNotificationManager.cancel(mNotificationId);
}
};
/**
* 用于文件下载线程
* @author yingjun10627
*
*/
class AppUpgradeThread extends Thread {
@Override
public void run() {
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
if (destDir == null) {
destDir = new File(Environment.getExternalStorageDirectory().getPath() + downloadPath);
}
if (destDir.exists() || destDir.mkdirs()) {
destFile = new File(destDir.getPath() + "/" + URLEncoder.encode(mDownloadUrl));
if (destFile.exists() && destFile.isFile() && checkApkFile(destFile.getPath())) {
install(destFile);
} else {
try {
DownloadUtils.download(mDownloadUrl, destFile, false, downloadListener);
} catch (Exception e) {
Message msg = mHandler.obtainMessage();
msg.what = DOWNLOAD_FAIL;
mHandler.sendMessage(msg);
e.printStackTrace();
}
}
}
}
stopSelf();
}
}
/**
* apk文件安装
*
* @param apkFile
*/
public void install(File apkFile) {
Uri uri = Uri.fromFile(apkFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);
}
/**
* 判断文件是否完整
*
* @param apkFilePath
* @return
*/
public boolean checkApkFile(String apkFilePath) {
boolean result = false;
try {
PackageManager pManager = getPackageManager();
PackageInfo pInfo = pManager.getPackageArchiveInfo(apkFilePath, PackageManager.GET_ACTIVITIES);
if (pInfo == null) {
result = false;
} else {
result = true;
}
} catch (Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Java代码
package com.ljp.download;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class DownloadUtils {
private static final int CONNECT_TIMEOUT = 10000;
private static final int DATA_TIMEOUT = 40000;
private final static int DATA_BUFFER = 8192;
public interface DownloadListener {
public void downloading(int progress);
public void downloaded();
}
public static long download(String urlStr, File dest, boolean append, DownloadListener downloadListener) throws Exception {
int downloadProgress = 0;
long remoteSize = 0;
int currentSize = 0;
long totalSize = -1;
if (!append && dest.exists() && dest.isFile()) {
dest.delete();
}
if (append && dest.exists() && dest.exists()) {
FileInputStream fis = null;
try {
fis = new FileInputStream(dest);
currentSize = fis.available();
} catch (IOException e) {
throw e;
} finally {
if (fis != null) {
fis.close();
}
}
}
HttpGet request = new HttpGet(urlStr);
if (currentSize > 0) {
request.addHeader("RANGE", "bytes=" + currentSize + "-");
}
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, CONNECT_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, DATA_TIMEOUT);
HttpClient httpClient = new DefaultHttpClient(params);
InputStream is = null;
FileOutputStream os = null;
try {
HttpResponse response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
is = response.getEntity().getContent();
remoteSize = response.getEntity().getContentLength();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
is = new GZIPInputStream(is);
}
os = new FileOutputStream(dest, append);
byte buffer[] = new byte[DATA_BUFFER];
int readSize = 0;
int temp=0;
while ((readSize = is.read(buffer)) > 0) {
os.write(buffer, 0, readSize);
os.flush();
totalSize += readSize;
if (downloadListener != null) {
downloadProgress = (int) (totalSize * 100 / remoteSize);
if(downloadProgress>=temp){
temp++;
downloadListener.downloading(downloadProgress);
}
}
}
if (totalSize < 0) {
totalSize = 0;
}
}
} finally {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
}
if (totalSize < 0) {
throw new Exception("Download file fail: " + urlStr);
}
if (downloadListener != null) {
downloadListener.downloaded();
}
return totalSize;
}
}
Service启动方式说明:
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
------------------------------------
相关文章推荐
- Android 实现service后台多任务下载notification进度条更新
- Android实现Service后台下载Notification进度条
- Android Apk自动更新service(直接拿来用)
- Android实现Service后台下载Notification进度条
- Android实现Service后台下载Notification进度条
- Android 实战-版本更新(okhttp3、service、notification)
- Android APK 版本更新的下载和安装 直接上代码
- Android Apk自动更新service(直接拿来用)转载
- 直接拿来用的版本更新(Android 兼容7.0)
- Android 检查更新版本(带有通知栏,进度条,Notification)
- Android Apk自动更新service(直接拿来用)
- Android Apk自动更新service(直接拿来用)
- Android程序版本更新--通知栏更新下载安装(转)
- Android----- 版本更新和 服务器下载新版本APK并安装
- 【直接拿来用のandroid公共代码模块解析与分享】の Notification和NotificationManager
- Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!
- android 7.0 apk版本更新,下载之后自动安装
- Android——Tomcat版本更新下载+头像照片上传到Tomcat
- 关于android中版本自动更新,从服务器下载下来的文件不能安装的问题
- Android 一步一步实现版本自动更新(第二步 下载和安装apk)