安卓 app 本地升级下载后自动安装(小米手机安装包解析失败问题)
来源:互联网 发布:蓝天ecview源码 编辑:程序博客网 时间:2024/04/28 07:12
强制升级:
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);//绑定服务
开始下载
if (mDownloadBinder != null) { long downloadId = mDownloadBinder.startDownload(serviceUrl); startCheckProgress(downloadId); dialog.dismiss();}监听下载//开始监听进度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(); }}
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存储权限要申请,解决拒绝后的闪退事件。
权限判断
@Overridepublic 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);}
阅读全文
0 0
- 安卓 app 本地升级下载后自动安装(小米手机安装包解析失败问题)
- 升级gradle版本之后小米手机调试安装失败
- 安卓service后台下载安装升级包
- android 应用升级 下载安装包 完成后 自动安装apk文件
- android 应用升级 下载安装包 完成后 自动安装apk文件
- Android下载app完成后自动安装
- android app升级(下载)完毕后自动弹出安装界面的实现
- 安卓app版本更新安装失败
- 安卓开发:魅族手机安装apk安装包提示安装失败、更新包不兼容问题的解决方法
- 解决APK下载到Cache目录安装提示“解析安装包失败”的问题
- 安卓程序升级自动安装,安装完成后提示是否打开程序(个人学习笔记)
- Android Studio 小米手机安装程序失败
- 小米手机安装失败错误码
- (Mac-使用问题)Mac升级到 10.12后,下载的一些安装包提示损坏。
- 安卓应用下载自动安装代码
- 安卓安装包版本解析
- 安卓开发debug-app卸载不干净,导致安装、升级不成功问题的解决办法
- 安卓开发debug-app卸载不干净,导致安装、升级不成功问题的解决办法
- 游戏服务端技术路线
- js学习
- Mysql Concat 函数
- win编程--文件操作
- img 标签的新属性Srcset应用
- 安卓 app 本地升级下载后自动安装(小米手机安装包解析失败问题)
- 关于kafka连接的一个小问题
- Django的STATIC_ROOT和STATIC_URL以及STATICFILES_DIRS
- 模仿微信的"我"界面的demo
- ios模仿微信的"我"界面的demo
- 解密:Apache Hive 2.1性能提升26倍!
- 学习
- 动态数据源测试数据库连接问题
- jquery $.ajax $.get $.post的区别