安卓 app 本地升级下载后自动安装(小米手机安装包解析失败问题)
强制升级:
1.新建服务
package com.jy.mango.project.service; import android.app.DownloadManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Environment; import android.os.IBinder; import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import android.util.LongSparseArray; import android.webkit.MimeTypeMap; import com.jy.mango.project.application.installutils.IOUtils; import com.jy.mango.project.application.installutils.InstallUtil; import com.jy.mango.project.application.installutils.SystemManager; import com.jy.mango.project.utils.T; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; /** * Created by mango on 2017/11/6. */ public class UpdateService extends Service {private DownloadManager mDownloadManager; private DownloadBinder mBinder = new DownloadBinder(); private LongSparseArray<String> mApkPaths; private DownloadFinishReceiver mReceiver; @Override public void onCreate() {super.onCreate(); mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); mApkPaths = new LongSparseArray<>(); //注册下载完成的广播 mReceiver = new DownloadFinishReceiver(); registerReceiver(mReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); }@Nullable @Override public IBinder onBind(Intent intent) {return mBinder; }@Override public void onDestroy() {unregisterReceiver(mReceiver);//取消注册广播接收者 super.onDestroy(); }public class DownloadBinder extends Binder {/** * 下载 * @param apkUrl 下载的url */ public long startDownload(String apkUrl){//点击下载 //删除原有的APK IOUtils.clearApk(UpdateService.this,"app.apk"); //使用DownLoadManager来下载 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl)); //将文件下载到自己的Download文件夹下,必须是External的 //这是DownloadManager的限制 File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "app.apk"); request.setDestinationUri(Uri.fromFile(file)); //添加请求 开始下载 long downloadId = mDownloadManager.enqueue(request); Log.d("DownloadBinder", file.getAbsolutePath()); mApkPaths.put(downloadId,file.getAbsolutePath()); return downloadId; }/** * 获取进度信息 * @param downloadId 要获取下载的id * @return 进度信息 max-100 */ public int getProgress(long downloadId) {//查询进度 DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId); Cursor cursor = null; int progress = 0; try {cursor = mDownloadManager.query(query);//获得游标 if (cursor != null && cursor.moveToFirst()) {//当前的下载量 int downloadSoFar = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); //文件总大小 int totalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); progress = (int) (downloadSoFar * 1.0f / totalBytes * 100); }} finally {if (cursor != null) {cursor.close(); }}return progress; }}//下载完成的广播 private class DownloadFinishReceiver extends BroadcastReceiver{@Override public void onReceive(Context context, Intent intent) {//下载完成的广播接收者 long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); String apkPath = mApkPaths.get(completeDownloadId); Log.d("DownloadFinishReceiver", apkPath); if (!apkPath.isEmpty()){SystemManager.setPermission(apkPath);//提升读写权限,否则可能出现解析异常 InstallUtil.install(context,apkPath); }else {Log.e("DownloadFinishReceiver", "apkPath is null"); }}}}
2.配置manifest文件
<service android:name=".UpdateService"/> <provider android:name="android.support.v4.content.FileProvider" android:authorities="包名" android:grantUriPermissions="true" android:exported="false"> <!--元数据--> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path" /> </provider>
3.指定path
在res下新建文件夹xml 新建xml文件命名为path
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <paths> <external-path path="" name="download"/> </paths> </resources>
4. 启动服务下载文件
private UpdateService.DownloadBinder mDownloadBinder; private ServiceConnection mConnection = new ServiceConnection() {@Override public void onServiceConnected(ComponentName name, IBinder service) {mDownloadBinder = (UpdateService.DownloadBinder) service; }@Override public void onServiceDisconnected(ComponentName name) {mDownloadBinder = null; } };
启动服务
Intent intent = new Intent(this, UpdateService.class); startService(intent); bindService(intent, mConnection, BIND_AUTO_CREATE);//绑定服务
开始下载
//开始监听进度 private void startCheckProgress(long downloadId) {Observable.interval(100, 200, TimeUnit.MILLISECONDS, Schedulers.io())//无限轮询,准备查询进度,在io线程执行 .filter(times -> mDownloadBinder != null).map(i -> mDownloadBinder.getProgress(downloadId))//获得下载进度 .takeUntil(progress -> progress >= 100)//返回true就停止了,当进度>=100就是下载完成了 .distinct()//去重复 .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new ProgressObserver()); }//观察者 private class ProgressObserver implements Observer<Integer> {@Override public void onSubscribe(Disposable d) {}@Override public void onNext(Integer progress){//设置进度 }@Override public void onError(Throwable throwable) {throwable.printStackTrace(); Toast.makeText(MainActivity.this, "出错", Toast.LENGTH_SHORT).show(); }@Override public void onComplete() {Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show(); } }
if (mDownloadBinder != null) {long downloadId = mDownloadBinder.startDownload(serviceUrl); startCheckProgress(downloadId); dialog.dismiss(); }
监听下载
5. 修改文件权限,并且在下载完成后删除文件,关闭文件流
class SystemManager {/** * 应用程序运行命令获取 Root权限,设备必须已破解(获得ROOT权限) * * @param command 命令:String apkRoot="chmod 777 "+getPackageCodePath(); * @return 0 命令执行成功 */ public static int RootCommand(String command) {Process process = null; DataOutputStream os = null; try {process = Runtime.getRuntime().exec("su"); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(command + "\n"); os.writeBytes("exit\n"); os.flush(); int i = process.waitFor(); Log.d("SystemManager", "i:" + i); return i; } catch (Exception e) {Log.d("SystemManager", e.getMessage()); return -1; } finally {try {if (os != null) {os.close(); }process.destroy(); } catch (Exception e) {}}}/** * 提升读写权限 * @param filePath 文件路径 * @return * @throws IOException */ public static void setPermission(String filePath) {String command = "chmod " + "777" + " " + filePath; Runtime runtime = Runtime.getRuntime(); try {runtime.exec(command); } catch (IOException e) {e.printStackTrace(); }}
关闭文件流及成功后删除APK文件
IOUtils {public static void closeIO(Closeable... closeables) {if (closeables != null) {for (Closeable closeable : closeables) {if (closeable != null) {try {closeable.close(); } catch (IOException e) {e.printStackTrace(); }}}}}/** * 删除之前的apk * * @param apkName apk名字 * @return */ public static File clearApk(Context context, String apkName) {File apkFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), apkName); if (apkFile.exists()) {apkFile.delete(); }return apkFile; } }
6.
OK啦!判断权限,并请求权限,6.0存储权限要申请,解决拒绝后的闪退事件。
权限判断
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {if (requestCode == MY_PERMISSIONS_REQUEST_CALL_PHONE) {if (grantResults[0] == PackageManager.PERMISSION_GRANTED){if (mDownloadBinder != null) {long downloadId = mDownloadBinder.startDownload(serviceUrl); startCheckProgress(downloadId); }} else{T.showLong("该应用已被禁止存储权限" +"\n请在设置>权限管理中授权"); alertDialog.show(); }return; }super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
安卓 app 本地升级下载后自动安装(小米手机安装包解析失败问题)相关推荐
- 华为mate 30 安装时提示安装包解析失败
今天遇到一个问题,从服务器端下载的apk,安装的时候,提示解析包失败. 我本地也有一个包,自己的红米android9.0 可以下载安装,邮件发给用户,用户说依然报解析包失败. 然后,我给安装包apk通 ...
- 【Android】 安装时安装包解析失败
可能原因 用户的安卓系统版本过低 此处设置的最小sdk版本为20,对应于安卓4.4W 安卓版本低于4.4W的手机,安装时都会出现安装包解析失败的情况
- Sony电视安装KODI提示安装包解析错误的处理办法
姨夫不再微笑 为了守护姨夫的微笑,为了信仰,家里的电视都是索尼的,之前用着也没啥毛病,KODI播放NAS上的电影爽歪歪. 突然,在2019年6.1儿童节这一天,收到了sony大法推送的电视固件更新,心 ...
- 根据浏览器判断是下载IOS还是其它的手机安装包
http://tiao.67767.cn/DownLoad.aspx?cid=3509 <!DOCTYPE html> <html> <hea ...
- Android——app内打开安装包,安装包解析失败
7.0,8.0以上安装权限都配置完毕,Provider也配置完毕 检查是否有读写权限 <uses-permission android:name="android.permission ...
- win10兼容android下载安装,Win10手机运行安卓App兼容工具下载!
[PConline 资讯]不久前有人从泄漏的Windows 10手机版build 10240中,解包出了微软内置的可以让Windows 10手机版兼容安卓App的模块,详情可以点此查看.不过,Wind ...
- Android7.0下载Apk自动安装
Android7.0下载Apk自动安装 1. 整体需求 下载APK文件 使用DownloadManager来下载 在应用界面中展示下载进度 安装下载后的APK文件 root模式: 可以自动安装,不需要 ...
- app闪退后重启_Android app 如何实现崩溃后自动重启
Android app 如何实现崩溃后自动重启 由于有很多场景需要让自己的app一直保持运行状态,比如客户的launcher,或者定制app. 都希望在自己的app崩溃之后还可以自重启. 对于这样子 ...
- 爬虫bing的图片,近千张,下载后自动更换为windows壁纸
爬虫bing的图片,下载后自动更换为windows壁纸 由于百度的广告太多了,就用了一段时间bing.com搜索,发现每次打开背景大图都很漂亮,而且每次切换,于是就想把它下载下来,作为桌面背景,也是很 ...
最新文章
- linux message日志只有4k,命令长期运行 常用技巧 Linux 服务器 · 404k的前后端日志...
- python库pickle的用法
- 青龙面板薅羊毛–都爱玩(日收益2元左右)
- Where is number of opportunities not displayed message poped up
- Mac版本Navicat下载
- Linux 终端操纵之扼要疾速指南(2)
- The Bits(找规律)
- CSDN博客下载器的使用教程
- java sql注入 正则表达式_有效防止SQL注入的5种方法总结
- Revit工作时处理CAD图层的5种方法,快get起来
- java 文件传输_Java开发之如何通过HTTP方式传输文件
- windows安装ffmpeg,yasm,opencv
- 《刷新》读书笔记1-3章
- Python计算机视觉-仿射扭曲简单实例
- 微信手机浏览器多图片即时预览
- STM32 TIM高级定时器死区时间的计算
- 三十八、C++ 信号捕获
- Ubuntu 中文字体设置备忘
- Python基础详解(十三):(视频符号化)将视频转换成ASCII符号形式展示出来
- 无法将void类型转为object类型
热门文章
- 【SDX62】ERROR: Error executing a python function in exec_python_func() autogenerated:
- Windows中怎么下载桌面便签小工具 便签小工具简单使用教程
- NLP 学习教程 第一节 简介
- python两个数组合并排序_合并Python中的排序数组
- ali arthas 火焰图_手把手教你看懂Chrome火焰图!(调试性能必备)
- 上微信怎么同时用计算机,电脑端微信双开,教你两种简单的方法,上手即用!...
- Vue中3.0版本严格模式运行项目报错
- Android中View绘制各种状态的背景图片原理深入分析以及StateListDrawable使用
- Android-O wifi PNO扫描流程
- linux mac地址远程开机,用MAC地址远程开机的开机棒你见过吗?