直接拿来用的版本更新(Android 兼容7.0)
2017-06-01 16:10
337 查看
1、需求:
版本更新,一个经常用到的功能。写一个工具类,拿去直接用。2、实现思路:
1、请求数据 拿到后台的apk的版本号、版本名、更新内容、下载地址(可能还会包括是否强制更新的标志位)。这里有一点需要注意,如果有强制更新的概念,这时候请求数据的时候要给服务器你当前的版本号。如果你现在的版本号是1 ,用户很久没有操作,期间版本更新了2(强制更新)、3(不强制更新)。这时候用户打开版本号为1的版本,应该是要强制更新的。2、和本地的apk版本号对比时候需要更新
3、这里用户可能会忽略此版本,这时候我要存储一个版本号,用户忽略的版本号
4、在步骤2以后 如果需要更新,先判断步骤3里边存储的版本号,比较大小, 如果用户忽略更新这个版本,那就不更新了;如果用户没有忽略过此版本,继续往下
5、这时候给用户一个提示,展示内容是有新版本是否更新,更新内容
5.1 这里可能涉及到一个强制更新,如果是强制更新的,那就要求,用户没有更新,就退出程序;不是强制更新的,可以忽略此版本
6、启动下载服务
7、下载完成之后的自动安装
3、代码实现
这里使用DownLoadManager来做下载,在UpdateAppService类中。在UpdateAppUtils检测是否要下载
UpdateAppUtils.java
package com.example.lql.updateappdemo; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Handler; import android.os.Message; import com.example.lql.updateappdemo.message.ExitappMessage; import com.example.lql.updateappdemo.service.UpdateAppService; import com.example.lql.updateappdemo.utils.FinalData; import com.example.lql.updateappdemo.utils.PreferenceUtils; import com.example.lql.updateappdemo.utils.PublicStaticData; import com.example.lql.updateappdemo.utils.T; import org.greenrobot.eventbus.EventBus; import java.lang.ref.WeakReference; /** * 类描述:版本更新工具类 * 这里使用DownLoadManager来做下载,在UpdateAppService类中 * 在UpdateAppUtils检测是否要下载 * 逻辑关系说明: * 1、请求数据 拿到后台的apk的版本号、版本名、更新内容、下载地址(可能还会包括是否强制更新的标志位) * 2、和本地的apk版本号对比时候需要更新 * 3、这里用户可能会忽略此版本,这时候我要存储一个版本号,用户忽略的版本号,如果用户的是主动更新的,都要提示。如果不是主动更新的判断一下,判断一下。 * 4、在步骤2以后 如果需要更新,先判断步骤3里边存储的版本号,比较大小, * 如果用户忽略更新这个版本,那就不更新了;如果用户没有忽略过此版本,继续往下 * 5、这时候给用户一个提示,展示内容是有新版本是否更新,更新内容 * 5.1 这里可能涉及到一个强制更新,如果是强制更新的,那就要求,用户没有更新,就退出程序,不是强制更新的,可以忽略此版本 * 6、启动下载服务 * 7、下载完成之后的自动安装 * 使用说明: * 在外部直接调用UpdateApp()方法 * 作 者:李清林 * 时 间:2017.5.12 * 修改备注: */ public class UpdateAppUtils { public static int versionCode = 0;//当前版本号 public static String versionName = "";//当前版本名称 private static Context mContext; public UpdateAppUtils() { } /** * @param mContext 上下文 * @param newVersionCode 服务器的版本号 * @param newVersionName 服务器的版本名称 * @param content 更新了的内容 * @param downUrl 下载地址 * @param IsUpdate 是否强制更新 * @param IsToast 是否提示用户当前已经是最新版本 */ public static void UpdateApp(Context mContext, int newVersionCode, String newVersionName, String content, String downUrl, boolean IsUpdate, boolean IsToast) { UpdateAppUtils.mContext = mContext; //首先拿到当前的版本号和版本名 try { UpdateAppUtils.mContext = mContext; PackageManager pm = mContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), 0); versionName = pi.versionName; versionCode = pi.versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (versionCode < newVersionCode) {//第2步骤 if (PreferenceUtils.getInt(FinalData.VERSIONCODE, 0) < newVersionCode || IsToast) {//第3步骤 //这时候要去更新,展示下载的对话框 showDownLoadDialog(newVersionName, newVersionCode, content, downUrl, IsUpdate); } } else { if (IsToast) { T.shortToast(mContext, "当前已是最新版本"); } } } /** * 下载对话框 * * @param versionname 要下载的版本名 * @param versionCode 要下载的版本号 * @param desc 更新说明 * @param downloadurl 下载地址 * @param isUpdate 是否强制更新 */ private static void showDownLoadDialog(String versionname, final int versionCode, String desc, final String downloadurl, final boolean isUpdate) { AlertDialog dialog = new AlertDialog.Builder(mContext).setCancelable(false) .setTitle("更新到 " + versionname).setMessage(desc) .setPositiveButton("下载", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) {//第6步骤,下载 T.shortToast(mContext, "正在下载..."); new Thread(new Runnable() { @Override public void run() { PublicStaticData.downLoadUrl = downloadurl; //启动服务 Intent service = new Intent(mContext, UpdateAppService.class); mContext.startService(service); } }).start(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //这里涉及到下载的强制更新,是不是强制更新 强制更新,点取消按钮,退出程序 if (isUpdate) { T.shortToast(mContext, "此版本需要更新,程序即将退出"); MyHandler myHandler = new MyHandler(new UpdateAppUtils()); myHandler.sendEmptyMessageDelayed(0, 1000 * 3); } else { PreferenceUtils.setInt(FinalData.VERSIONCODE, versionCode); dialog.dismiss(); } } }) .create(); dialog.show(); } static class MyHandler extends Handler { WeakReference<UpdateAppUtils> mWeakReference; public MyHandler(UpdateAppUtils mUpdateAppUtils) { mWeakReference = new WeakReference<UpdateAppUtils>(mUpdateAppUtils); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); mWeakReference.get().exitApp(); } } /** * 这里使用EventBus像Activity发送消息,当然你也可以使用广播 */ private void exitApp() { EventBus.getDefault().post(new ExitappMessage("")); } }
UpdateAppService.java
package com.example.lql.updateappdemo.service; import android.app.DownloadManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.IBinder; import android.support.v4.content.FileProvider; import android.text.TextUtils; import com.example.lql.updateappdemo.utils.LogUtils; import com.example.lql.updateappdemo.utils.PublicStaticData; import com.example.lql.updateappdemo.utils.T; import java.io.File; /** * 类描述:下载服务 * 作 者:李清林 * 时 间: * 修改备注:兼容7.0 */ public class UpdateAppService extends Service { public UpdateAppService() { } /** 安卓系统下载类 **/ DownloadManager manager; /** 接收下载完的广播 **/ DownloadCompleteReceiver receiver; /** 初始化下载器 **/ private void initDownManager() { manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); receiver = new DownloadCompleteReceiver(); if(TextUtils.isEmpty(PublicStaticData.downLoadUrl)){ T.shortToast(UpdateAppService.this,"下载地址为空"); return; } //设置下载地址 String urlPath = PublicStaticData.downLoadUrl; Uri parse = Uri.parse(urlPath); DownloadManager.Request down = new DownloadManager.Request(parse); // 设置允许使用的网络类型,这里是移动网络和wifi都可以 down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); // 下载时,通知栏显示途中 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); } // 显示下载界面 down.setVisibleInDownloadsUi(true); // 设置下载后文件存放的位置 String apkName = parse.getLastPathSegment(); down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, apkName); // 将下载请求放入队列 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) { DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) { DownloadManager.Query query = new DownloadManager.Query(); // 在广播中取出下载任务的id long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0); query.setFilterById(id); Cursor c = manager.query(query); if (c.moveToFirst()) { int fileUriIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI); String fileUri = c.getString(fileUriIdx); String fileName = null; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { if (fileUri != null) { fileName = Uri.parse(fileUri).getPath(); } } else { //Android 7.0以上的方式:请求获取写入权限,这一步报错 int fileNameIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME); fileName = c.getString(fileNameIdx); } if (null!=fileName&&!TextUtils.isEmpty(fileName)) { install1(context, fileName); } //停止服务并关闭广播 UpdateAppService.this.stopSelf(); } } } private boolean install1(Context context, String filePath) { Intent i = new Intent(Intent.ACTION_VIEW); File file = new File(filePath); if (file != null && file.length() > 0 && file.exists() && file.isFile()) { //判断是否是AndroidN以及更高的版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); LogUtils.Loge("context.getPackageName():" + context.getPackageName() + ".provider"); Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file); i.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { i.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(i); return true; } return false; } } }
“`
最后别忘了在清单文件中注册服务。
4、就这样结束啦。附上源码下载地址(demo已更新):
https://github.com/LiQinglin007/UpdateAppDemo相关文章推荐
- Android 版本更新工具 兼容7.0
- Android使用DownloadMange进行版本更新(兼容7.0)
- Android版本更新-----兼容android7.0
- Android版本更新(Service下载 Notification进度条:直接拿来用)
- android 使用FileProvider 兼容apk 在7.0版本无法安装
- Android 7.0 版本更新
- Android 版本更新下载自动安装APK,并解决Android6.0,7.0安装失败的问题
- Android应用更新详解,兼容7.0
- Android Apk自动更新service(直接拿来用)
- Android调用系统相机、相册功能,适配6.0权限获取以及7.0以后获取URI(兼容多版本)
- Android版本更新(适用于6.0/7.0)
- APP版本更新(兼容6.0,7.0系统)
- Android APK 版本更新的下载和安装 直接上代码
- Android 版本更新(非热更新) 适配7.0更新 以及三星 note系列读取内存相关目录无权限问题
- Android app内更新,兼容7.0
- Android Apk自动更新service(直接拿来用)
- Android下载更新(兼容7.0文件,支持5.0通知栏显示Icon)
- App版本更新兼容7.0
- Android apk升级 兼容6.0 7.0 低版本 华为手机
- android 7.0 apk版本更新,下载之后自动安装