安卓 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
原创粉丝点击