当前位置:首页 > 网络安全 > 正文内容

安卓系统下载(安卓系统下载安装)

hacker2年前 (2022-07-19)网络安全107

各位同学,早上好,今天为大家推荐的是Teprinciple同学投稿的文章,文章的内容是介绍了他的开源库实现在线下载的思路,以及期间需要注意考虑的一些问题,值得对这块不熟悉的同学学习一下,作者在最后还总结了当前方案的一些不足。当然,如果你觉得这个方案还有更好的建议,也欢迎在下方留言。

作者简书:http://www.jianshu.com/p/9c91bb984c85

各位同学,早上好,今天为大家推荐的是Teprinciple同学投稿的文章,文章的内容是介绍了他的开源库实现在线下载的思路,以及期间需要注意考虑的一些问题,值得对这块不熟悉的同学学习一下,作者在最后还总结了当前方案的一些不足。当然,如果你觉得这个方案还有更好的建议,也欢迎在下方留言。

作者简书:http://www.jianshu.com/p/9c91bb984c85

一行代码,快速实现app在线下载更新,先看效果图:

快速使用

先来看看怎样一行代码实现更新:

dependencies { compile 'com.teprinciple:updateapputils:1.3.1'} UpdateAppUtils.from(this) .checkBy(UpdateAppUtils.CHECK_BY_VERSION_NAME) //更新检测方式,默认为VersionCode .serverVersionCode(2) .serverVersionName("2.0") .apkPath(apkPath) .showNotification(false) //是否显示下载进度到通知栏,默认为true .updateInfo(info) //更新日志信息 String .downloadBy(UpdateAppUtils.DOWNLOAD_BY_BROWSER) //下载方式:app下载、手机浏览器下载。默认app下载 .isForce(true) //是否强制更新,默认false 强制更新情况下用户不同意更新则不能使用app .update(); 实现原理

展开全文

使用很简单吧,其实实现过程也很简单,大致分为三步:

安卓系统下载(安卓系统下载安装)

1、根据初入参数判断是否需要更新

3、安装最新apk

安卓系统下载(安卓系统下载安装)

下面我们来看看源码:

第一步:初始化参数并判断。根据传入的服务器版本号与本地版本号做出判断是否需要更新,并配置好下载地址,下载方式等参数。

/** * Created by Teprinciple on 2016/11/15. */public class UpdateAppUtils { private final String TAG = "UpdateAppUtils"; public static final int CHECK_BY_VERSION_NAME = 1001; public static final int CHECK_BY_VERSION_CODE = 1002; public static final int DOWNLOAD_BY_APP = 1003; public static final int DOWNLOAD_BY_BROWSER = 1004; private Activity activity; private int checkBy = CHECK_BY_VERSION_CODE; private int downloadBy = DOWNLOAD_BY_APP; private int serverVersionCode = 0; private String apkPath=""; private String serverVersionName=""; private boolean isForce = false; //是否强制更新 private int localVersionCode = 0; private String localVersionName=""; public static boolean showNotification = true; private String updateInfo = ""; private UpdateAppUtils(Activity activity) { this.activity = activity; getAPPLocalVersion(activity); } public static UpdateAppUtils from(Activity activity){ return new UpdateAppUtils(activity); } public UpdateAppUtils checkBy(int checkBy){ this.checkBy = checkBy; return this; } public UpdateAppUtils apkPath(String apkPath){ this.apkPath = apkPath; return this; } public UpdateAppUtils downloadBy(int downloadBy){ this.downloadBy = downloadBy; return this; } public UpdateAppUtils showNotification(boolean showNotification){ this.showNotification = showNotification; return this; } public UpdateAppUtils updateInfo(String updateInfo){ this.updateInfo = updateInfo; return this; } public UpdateAppUtils serverVersionCode(int serverVersionCode){ this.serverVersionCode = serverVersionCode; return this; } public UpdateAppUtils serverVersionName(String serverVersionName){ this.serverVersionName = serverVersionName; return this; } public UpdateAppUtils isForce(boolean isForce){ this.isForce = isForce; return this; } //获取apk的版本号 currentVersionCode private void getAPPLocalVersion(Context ctx) { PackageManager manager = ctx.getPackageManager(); try { PackageInfo info = manager.getPackageInfo(ctx.getPackageName(), 0); localVersionName = info.versionName; // 版本名 localVersionCode = info.versionCode; // 版本号 } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } public void update(){ switch (checkBy){ case CHECK_BY_VERSION_CODE: if (serverVersionCode >localVersionCode){ toUpdate(); }else { Log.i(TAG,"当前版本是最新版本"+serverVersionCode+"/"+serverVersionName); } break; case CHECK_BY_VERSION_NAME: if (!serverVersionName.equals(localVersionName)){ toUpdate(); }else { Log.i(TAG,"当前版本是最新版本"+serverVersionCode+"/"+serverVersionName); } break; } } private void toUpdate() { realUpdate(); } private void realUpdate() { ConfirmDialog dialog = new ConfirmDialog(activity, new Callback() { @Override public void callback(int position) { switch (position){ case 0: //cancle if (isForce)System.exit(0); break; case 1: //sure if (downloadBy == DOWNLOAD_BY_APP) { if (isWifiConnected(activity)){ DownloadAppUtils.downloadForAutoInstall(activity, apkPath, "demo.apk", serverVersionName); }else { new ConfirmDialog(activity, new Callback() { @Override public void callback(int position) { if (position==1){ DownloadAppUtils.downloadForAutoInstall(activity, apkPath, "demo.apk", serverVersionName); }else { if (isForce)activity.finish(); } } }).setContent("目前手机不是WiFi状态n确认是否继续下载更新?").show(); } }else if (downloadBy == DOWNLOAD_BY_BROWSER){ DownloadAppUtils.downloadForWebView(activity,apkPath); } break; } } }); String content = "发现新版本:"+serverVersionName+"n是否下载更新?"; if (!TextUtils.isEmpty(updateInfo)){ content = "发现新版本:"+serverVersionName+"是否下载更新?nn"+updateInfo; } dialog .setContent(content); dialog.setCancelable(false); dialog.show(); } //检测wifi是否连接 public static boolean isWifiConnected(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (cm != null) { NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { return true; } } return false; }} /** *Created by Teprinciple on 2016/12/13. */public class DownloadAppUtils { private static final String TAG = DownloadAppUtils.class.getSimpleName(); public static long downloadUpdateApkId = -1;//下载更新Apk 下载任务对应的Id public static String downloadUpdateApkFilePath;//下载更新Apk 文件路径 /** * 通过浏览器下载APK包 * @param context * @param url */ public static void downloadForWebView(Context context, String url) { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } /** * 下载更新apk包 * 权限:1,<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> * @param context * @param url */ public static void downloadForAutoInstall(Context context, String url, String fileName, String title) { if (TextUtils.isEmpty(url)) { return; } try { Uri uri = Uri.parse(url); DownloadManager downloadManager = (DownloadManager) context .getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(uri); //在通知栏中显示 request.setVisibleInDownloadsUi(true); request.setTitle(title); // VISIBILITY_VISIBLE: 下载过程中可见, 下载完后自动消失 (默认) // VISIBILITY_VISIBLE_NOTIFY_COMPLETED: 下载过程中和下载完成后均可见 // VISIBILITY_HIDDEN: 始终不显示通知 if (!UpdateAppUtils.showNotification) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); String filePath = null; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//外部存储卡 filePath = Environment.getExternalStorageDirectory().getAbsolutePath(); } else { Log.i(TAG,"没有SD卡"); return; } downloadUpdateApkFilePath = filePath + File.separator + fileName; deleteFile(downloadUpdateApkFilePath);// 若存在,则删除 Uri fileUri = Uri.fromFile(new File(downloadUpdateApkFilePath)); request.setDestinationUri(fileUri); downloadUpdateApkId = downloadManager.enqueue(request); } catch (Exception e) { e.printStackTrace(); downloadForWebView(context, url); } } private static boolean deleteFile(String fileStr) { File file = new File(fileStr); return file.delete(); }}

第三步、安装apk。DownloadManager下载完成后,会发送通知。我们在UpdateAppReceiver ,接受到通知后执行安装操作。

/** * 注册 * <action android:name="android.intent.action.DOWNLOAD_COMPLETE" /> * <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/> */public class UpdateAppReceiver extends BroadcastReceiver { public UpdateAppReceiver() { } @Override public void onReceive(Context context, Intent intent) { // 处理下载完成 Cursor c = null; if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) { if (DownloadAppUtils.downloadUpdateApkId >= 0) { long downloadId = DownloadAppUtils.downloadUpdateApkId; DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); DownloadManager downloadManager = (DownloadManager) context .getSystemService(Context.DOWNLOAD_SERVICE); c = downloadManager.query(query); if (c.moveToFirst()) { int status = c.getInt(c .getColumnIndex(DownloadManager.COLUMN_STATUS)); if (status == DownloadManager.STATUS_FAILED) { downloadManager.remove(downloadId); } else if (status == DownloadManager.STATUS_SUCCESSFUL) { if (DownloadAppUtils.downloadUpdateApkFilePath != null) { Intent i = new Intent(Intent.ACTION_VIEW); File apkFile = new File(DownloadAppUtils.downloadUpdateApkFilePath); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile( context, context.getPackageName() + ".fileprovider", apkFile); i.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { i.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); } i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } } } c.close(); } } }}

通过上面三个类就可以实现在线下载更新app了。下面我们看看关于Android6.0以及Android7.0的适配。

适配Android7.0

安卓官方为了提高私有文件的安全性,对于Android 7.0 及更高版本的应用私有目录被限制访问。因此,在使用Intent方式安装时,尝试传递 file:// URI 会触发 FileUriExposedException。解决方法是使用 FileProvider,如下:

1、注册provider

<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> /provider>

2、新建file_paths.xml文件

<?xml version="1.0" encoding="utf-8"?><paths> <external-path path="Android/data/包名/" name="files_root" /> <external-path path="." name="external_storage_root" /></paths> 适配Android6.0

关于6.0适配,请自行在调用API时申请WRITE_EXTERNAL_STORAGE权限,可以参考demo中的代码

目前不足之处

UpdateAppUtils很简单方便实现了app的在线下载更新。但是本库目前有存在有一些不足之处:

1、目前使用DownloadManager作为下载模块,但是国内部分手机DownloadManager功能已被阉割,造成不能下载。

2、目前更新弹窗暂时没提供自定义UI接口。

3、目前每次检查需更新后都执行下载,没有判断本地是否已有最新apk文件。

这些问题我会在后面进行完善。如果你发现本库有其他的不足,或者对本库有好的建议都可以issue我。希望能通过大家的力量,一起把UpdateAppUtils做的更好。

具体原理及源码可见 https://github.com/teprinciple/UpdateAppDemo

觉得文章不错,欢迎转发,点赞,赞赏支持作者。更多精彩,欢迎持续关注“Android程序员”。

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:http://therlest.com/133032.html

分享给朋友:

“安卓系统下载(安卓系统下载安装)” 的相关文章

洗米华小三(浅谈米花三笑的微博)

据长江网2021年11月26日23:49:22的最新消息,微博网友@ 爆料。 平安夜来临之际,事件,在网上炒得沸沸扬扬,引发全网热议! 据悉,洗米华小三。猜测这是洗米华在暗中帮助着Mandy。挺想看他老婆小三都抛弃他的场面。 1.洗米华小三 m...

【紧急+重要】勒索病毒解决方案!附:MS17-010补丁下载

  滚动更新:2017年5月13日16:57:22   游侠安全网(良心网站,站长先贴上注意事项和解决方法!防止你看本文的时候就被加密了!   1、本次共计是自动化攻击,利用了Windows的MS17-010。但苹果的MacOS用户不用得意,因为在昨晚之前,我这里得到的好几起勒索攻击案例都是针对...

干洗对衣物有害吗

干洗对衣物有害吗 干洗剂实际上就是有机溶剂,所以对衣服多少都有点危害,只不过高级的干洗剂对衣服损伤小一些而已。 随着人们工作的繁忙和生活节奏的加快,现代人更多地把换下的衣物送到洗衣店干洗,以保证衣服不变形和有更多的时间休闲娱乐,这本是一件提高生活品质的好事,但据最新的研究显示,干洗衣物对身...

尚村最新水貂皮毛价格,丹麦貂皮衣大概多少钱

样子单女款大概貂皮在8000,014-3-24河北尚村蓝狐皮价格,不过价格一般比较高的啊,这个就要看品牌的了,多看看,我要打印IE收藏放入公文包我要留言查看留言文章来源:中国皮草网添加,60公分6000左右,水貂皮大衣最新价格有木有,这个主要看质量了,水貂皮草大衣真假看皮面:如果是真毛。 元/张,5...

Webshell安全检测篇(1)-根据流量的检测方法

一、概述 笔者一直在重视webshell的安全剖析,最近就这段时刻的心得体会和咱们做个共享。 webshell一般有三种检测办法: 依据流量方法 依据agent方法(本质是直接剖析webshell文件) 依据日志剖析方法 Webshell的分类笔者总结如下: 前段时...

奥门币币对人民币换算 - 澳元兑换人民币汇率

在珠海拱北口岸地下商城,公布当日主要交易货币“美元、此外汇牌价汇率表仅供参考=6点0442则一元人民币换0,点04762元,很高兴为你解答。 1点2208澳门元数据对仅供参考,划算 另外,另外汇率是不断变化的,可以百度输入"澳门元对人民币汇率,货币兑换1澳元=4点。 在外面买东西的小店不是太正规的,...

评论列表

世味卮酒
2年前 (2022-07-20)

workInfo.getType() == ConnectivityManager.TYPE_WIFI) { return true; } } return false; }} /** *Created by Teprinciple on 2016/

泪灼俛就
2年前 (2022-07-19)

erVersionCode+"/"+serverVersionName); } break; } } private void toUpdate() { realUpdate(); } private void realUpdate() { ConfirmDialo

南殷九龄
2年前 (2022-07-20)

.setVisibleInDownloadsUi(true); request.setTitle(title); // VISIBILITY_VISIBLE: 下载过程中可见, 下载完后自动消失 (默认) /

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。