功能:版本更新、文件后台下载以及Notification显示进度条。
效果图:
主要代码:
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(); } }
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; } }
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。
相关推荐
本教程将详细讲解如何在Android中使用Service进行后台下载,并实时更新Notification的进度条。 首先,我们需要创建一个Service,通常继承自`IntentService`。`IntentService`是一个单线程的Service,自动管理工作...
"Notification中更新进度条"这个主题聚焦于如何在Notification上动态地显示任务的进度,比如下载、上传等操作。 首先,我们要了解`Notification`的基本结构。在Android中,`Notification`对象由`NotificationCompat...
本文将深入探讨如何实现一个自定义的通知栏,以动态更新进度条来模拟下载过程。虽然这里并不涉及实际的下载逻辑,但我们会讨论如何创建一个能够展示进度的自定义通知。 首先,我们需要理解Android的通知系统。在...
在Android系统中,Notification是应用与用户交互的重要方式之一,特别是在后台运行时,它能将信息传达给用户,如消息提醒、下载进度等。本文将深入探讨如何利用Android的Notification API来实现动态下载过程的可视化...
"带有进度条的APP下载更新"这一主题,聚焦于如何在应用程序中实现这样一个功能,使得用户在等待下载或更新过程中能清晰地看到进度,并通过通知(notification)来方便地管理和启动安装过程。 首先,我们需要理解APP...
在Android开发中,通知栏(Notification)是一种向用户传达应用状态和信息的重要方式,而进度条(Progress Bar)则是展示任务执行进度的关键组件。本文将深入探讨如何在Android通知栏中使用常见方法以及如何显示...
本教程将详细介绍如何使用Android Service来实现文件下载,并在前台显示进度,同时通过通知栏同步更新下载进度。 首先,我们需要创建一个服务类(Service)来处理下载任务。在Android Studio中,可以通过右键点击...
"用服务更新软件的安装包配合notification更新进度条" 这一主题主要涉及到如何在后台执行文件下载,并通过服务(Service)来监控下载进度,同时利用Notification向用户反馈下载状态。以下是对这一主题的详细阐述: ...
综上所述,解决"Android 2.3版本Notification通知栏不显示的Bug"需要正确创建和更新Notification,同时结合Service和断点续传技术来实现后台下载。通过多线程下载,可以进一步提升用户体验。注意在不同Android版本上...
这个“下载的进度条功能实现的Demo”就是针对这一需求的具体实现,它允许开发者在Android的通知栏展示一个动态更新的进度条,让用户能够实时了解后台任务的进展。 首先,我们要理解Android的通知系统。Android的...
7. **通知栏更新**: 可以结合`Notification`,在通知栏显示下载进度,这样用户可以在不打开应用的情况下监控下载状态。 8. **线程同步**: 为了确保数据一致性,需要正确处理线程间的同步,例如在更新UI进度时使用`...
本示例“Android高级应用源码-app更新,实现service下载.zip”提供了一个使用服务(Service)进行后台下载更新的解决方案。以下是关于这个主题的详细知识点: 1. **Android Service**: 在Android系统中,Service是...
以上就是一个基本的Android Service下载文件并显示Notification进度的例子。它展示了如何在后台执行耗时操作,如文件下载,并通过Notification向用户反馈进度。请注意,实际的下载任务可能需要处理更多细节,例如...
在Android开发中,实现文件下载进度条是一项常见的需求,它能提供用户友好的界面体验,让用户了解文件下载的状态。本文将详细讲解如何在Android中实现文件下载并展示进度条。 首先,我们需要创建一个用于下载任务的...
在Android 7.0系统中,开发者可以利用API来实现文件下载和上传过程中状态栏进度条的显示,以及用户点击文件后直接打开的功能。这一特性极大地提升了用户体验,使得用户能够实时了解文件操作的状态,并且方便地访问已...
本教程将详细讲解如何在Android的状态栏中显示进度条,并同步更新到当前Activity中的进度条,确保用户能够直观地了解操作的进度。 首先,我们需要在AndroidManifest.xml中为应用请求显示系统通知的权限: ```xml ...
"Service下载apk通过notification显示下载进度"这个主题涉及到的是如何利用Service来下载APK,并且通过通知栏(Notification)实时更新下载进度,下载完成后自动安装APK。这里将详细讲解这一过程的关键知识点。 ...
本篇将深入探讨如何通过线程和服务两种方式实现网络下载,并利用广播来同步更新进度条和通知栏。这两种方法都是为了优化用户体验,确保用户能够实时了解下载状态。 首先,我们来看线程下载。在Android中,由于主线...