一个成熟的商业APP必须不断的退出新的版本。那么,不可能让用户自己去应用市场去下载新版本的应用,我们应该在应用内部提供自动升级的功能。自动升级其实包含两个层面,一个是整个APP的升级,也就是下载新版本的APP,然后安装替换掉现有的。还有一种升级是模块升级,这种升级一般采用静默升级,就是用户完全不知道。这个在我大迅雷里面经常做的,拿各个渠道去试错,对于一个互联网公司而言是再普通不过的了。而这些模块,肯定是诸如,解析库,下载库,播放库,这些后台库。。
不过今天,我要说的是APP的自动升级,模块的静默升级我们下次有时间再说。
private static final class UpgradeLoader extends AsyncTask<Void, Void, UpdateInfo> { private WeakReference<Activity> mContext; private boolean mAuto; private IUpgradeCheck mUpgradeCheckListener; protected boolean mChecked; public UpgradeLoader(Activity context, boolean auto, IUpgradeCheck listener) { mContext = new WeakReference<Activity>(context); mAuto = auto; mUpgradeCheckListener = listener; } @Override protected void onPreExecute() { if (mUpgradeCheckListener != null) { mUpgradeCheckListener.beforeCheck(); } } @Override protected UpdateInfo doInBackground(Void... params) { if (mUpgradeCheckListener != null) { mUpgradeCheckListener.onCheck(); } Context ctx = mContext.get(); String channel = ""; if (ctx != null) { channel = Util.getChannelID(ctx); } return DataProxy.getInstance().getUpdateInfo(Util.getVersionName(MyApplication.sInstance), Util.getOSVersion(), channel); //去服务器查询版本信息,这个是我们对http的一个封装,在这里,每个公司可以自己定义一些自己的地址和参数,非常简单的。 } @Override protected void onPostExecute(UpdateInfo result) {//从服务器查询回来,决定要不要升级 if (mUpgradeCheckListener != null) { mUpgradeCheckListener.afterCheck(); } if (!isCancelled()) { if (result == null) { if (!mAuto) { UIHelper.showToast(MyApplication.sInstance, "检查更新失败", Toast.LENGTH_SHORT); } } else { switch (result.type) { case UpdateInfo.NO_UPGRADE: if (!mAuto) { UIHelper.showToast(KankanApplication.sInstance, "已经是最新版本,没有更新", Toast.LENGTH_SHORT); } break; case UpdateInfo.UPDATE_NOT_TIPS: if (!mAuto) { buildDialog(result); } else { downloadApk(KankanApplication.sInstance, result.latestUrl); } break; case UpdateInfo.UPDATE_TIPS: case UpdateInfo.UPDATE_FOURCE: if (!(mAuto && PreferenceManager.instance(mContext.get()).isVerionSkiped(result.latestVersion))) { buildDialog(result); } default: break; } } } }注意上述代码。我们仅仅是示意,所以不可能把所有代码提供给大家学习。就是你第一步是去服务器查询版本信息。然后确定要下载APK的时候,则会调用downloadApk函数。对APK进行下载。
private static void downloadApk(Context context, String url) { DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse(url); String scheme = uri.getScheme(); if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) { LOG.error("only supports http/https url={}", url); } else { try { DownloadManager.Request down = new DownloadManager.Request(uri); down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); down.setShowRunningNotification(true); down.setVisibleInDownloadsUi(true); down.setDestinationInExternalFilesDir(context, null, APK_NAME); manager.enqueue(down);//开始下载 } catch (Exception e) { e.printStackTrace(); UIHelper.showToast(context, "下载应用失败,请您去应用市场升级", Toast.LENGTH_LONG); } } }这样,使用 DownloadManager可以非常方便的实现APK的下载。如果想对这个类进行更加深入的了解,大家可以去查询相关的资料。你可以查询下载进度等等相关的信息。
public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {//监听下载完成 long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (id > -1) { File file = queryFile(context, id); if (file != null && file.exists()) { Intent startInent = new Intent(); startInent.setAction(Intent.ACTION_VIEW); startInent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startInent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); context.startActivity(startInent);//安装APK } } } }
<receiver android:name=".AppInstallReceiver" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REPLACED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver>然后是接收端:
public class AppInstallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { PackageManager manager = context.getPackageManager(); if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) { String packageName = intent.getData().getSchemeSpecificPart(); Toast.makeText(context, "安装成功"+packageName, Toast.LENGTH_LONG).show(); } if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { String packageName = intent.getData().getSchemeSpecificPart(); Toast.makeText(context, "卸载成功"+packageName, Toast.LENGTH_LONG).show(); } if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) { String packageName = intent.getData().getSchemeSpecificPart(); Toast.makeText(context, "替换成功"+packageName, Toast.LENGTH_LONG).show();
<span style="white-space:pre"> </span>doanloadApk.delete();//从SD中删除刚刚下载的APK文件 } } }