Android 更新模块 自定义Update
写这个总结是因为在项目中碰到了Android系统兼容的BUG
Android项目原本使用的是API提供的下载方法
如下:
DownloadManager downloadManager = (DownloadManager) getSystemService(Activity.DOWNLOAD_SERVICE); DownloadManager.Request request = new Request(Uri.parse(dl)); request.setTitle(getString(R.string.app_name)); request.setDestinationUri(getDownloadName(getIntent().getStringExtra("version_name"))); long reference = downloadManager.enqueue(request); UserSettingHelper.getInstance().setUpgradeKey(reference);
但如三星 华为 等手机它自带的系统中 删除掉了google服务从而导致崩溃
在网上找了资料 然后改吧改吧总算快速修复了bug:
1) 主activity
package com.example.updataapk; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; /** * * @author baozi * */ public class MainActivity extends Activity { // 地址 private String dl = "http://17shihui.cn/download/shihui.apk"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Function_Utility.setAppContext(getApplicationContext()); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Uri uri = Uri.parse(dl); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); } }); findViewById(R.id.button2).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { download(dl); } catch (Exception e) { e.printStackTrace(); } } }); } private void download(String dl) throws Exception { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { Intent service = new Intent(this, DownloadService.class); service.putExtra(DownloadService.INTENT_URL, dl); startService(service); } else { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(dl)); startActivity(intent); } } }
2) 下载模块
package com.example.updataapk; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; 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.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.widget.RemoteViews; public class DownloadService extends Service { // notification 名字 private String notify_name = "apk正在下载..."; public static final String INTENT_URL = "url"; private Context mContext = this; Notification mNotification; private static final int NOTIFY_ID = 0; private NotificationManager mNotificationManager; /* 下载包安装路径 */ private static final String savePath = Function_Utility.getUpgradePath(); private static final String saveFileName = savePath + "demo.apk"; private String apkUrl; private int progress; boolean canceled; private Thread downLoadThread; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE); } public int onStartCommand(Intent intent, int flags, int startId) { Log.i("DownloadService", "intent=" + intent.toString() + " ; flags= " + flags + " ; startId" + startId); if (intent.hasExtra(DownloadService.INTENT_URL)) { apkUrl = (String) intent.getExtras().get(DownloadService.INTENT_URL); } progress = 0; setUpNotification(); new Thread() { public void run() { // 开始下载 startDownload(); }; }.start(); return startId; }; private void startDownload() { canceled = false; downloadApk(); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: // 下载完毕 // 取消通知 mNotificationManager.cancel(NOTIFY_ID); installApk(); break; case 2: // 这里是用户界面手动取消,所以会经过activity的onDestroy();方法 // 取消通知 mNotificationManager.cancel(NOTIFY_ID); break; case 1: int rate = msg.arg1; if (rate < 100) { RemoteViews contentview = mNotification.contentView; contentview.setTextViewText(R.id.tv_progress, rate + "%"); contentview.setProgressBar(R.id.progressbar, 100, rate, false); } else { // 下载完毕后变换通知形式 mNotification.flags = Notification.FLAG_AUTO_CANCEL; mNotification.contentView = null; mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", null); stopSelf();// 停掉服务自身 } PendingIntent contentIntent2 = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT); mNotification.contentIntent = contentIntent2; mNotificationManager.notify(NOTIFY_ID, mNotification); break; case 3: mNotification.flags = Notification.FLAG_AUTO_CANCEL; RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.update_download_notification_layout); contentView.setTextViewText(R.id.name, "下载失败"); // 指定个性化视图 mNotification.contentView = contentView; Intent intent = new Intent(getApplicationContext(), MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 指定内容意图 mNotification.contentIntent = contentIntent; mNotificationManager.notify(NOTIFY_ID, mNotification); stopSelf();// 停掉服务自身 break; } } }; /** * 安装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); } private int lastRate = 0; private InputStream is = null; private FileOutputStream fos = null; /** * 下载apk * * @param url */ private void downloadApk() { downLoadThread = new Thread(mdownApkRunnable); downLoadThread.start(); } 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(); is = conn.getInputStream(); File file = new File(savePath); if (!file.exists()) { file.mkdirs(); } String apkFile = saveFileName; File ApkFile = new File(apkFile); 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 (numread <= 0) { mHandler.sendEmptyMessage(0);// 下载完成通知安装 // 下载完了,cancelled也要设置 canceled = true; break; } fos.write(buf, 0, numread); } while (!canceled);// 点击取消就停止下载. Log.i("DownloadService----------canceled", canceled + ""); fos.close(); is.close(); } catch (Exception e) { Message msg = mHandler.obtainMessage(); msg.what = 3; mHandler.sendMessage(msg); e.printStackTrace(); } finally { try { if (fos != null) { fos.close(); } is.close(); if (is != null) { is.close(); } } catch (Exception e) { e.printStackTrace(); } } } }; /** * 创建通知 */ private void setUpNotification() { int icon = R.drawable.ic_launcher; 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.update_download_notification_layout); contentView.setTextViewText(R.id.name, notify_name); // 指定个性化视图 mNotification.contentView = contentView; PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT); // 指定内容意图 mNotification.contentIntent = contentIntent; mNotificationManager.notify(NOTIFY_ID, mNotification); } }
3) 下载到手机的地址
package com.example.updataapk; import java.io.File; import java.io.IOException; import android.annotation.SuppressLint; import android.content.Context; import android.os.Environment; @SuppressWarnings("deprecation") @SuppressLint({ "DefaultLocale", "SimpleDateFormat" }) public class Function_Utility { private static Context mAppContext; public static void setAppContext(Context context) { mAppContext = context; } public static Context getAppContext() { return mAppContext; } /** * 下载到SD卡地址 */ public static String getUpgradePath() { String filePath = getAppRootPath() + "/upgrade/"; File file = new File(filePath); if (!file.isDirectory()) { file.mkdirs(); } file = null; return filePath; } public static String getAppRootPath() { String filePath = "/weimicommunity"; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { filePath = Environment.getExternalStorageDirectory() + filePath; } else { filePath = getAppContext().getCacheDir() + filePath; } File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } file = null; File nomedia = new File(filePath + "/.nomedia"); if (!nomedia.exists()) try { nomedia.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return filePath; } }
4) Androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.updataapk" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.updataapk.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.example.updataapk.DownloadService" > </service> </application> </manifest>
效果图:
下载完成后 自动安装
时间: 2024-11-03 01:58:02