android 6.0以上系统apk自动安装失败问题

参考博客:http://blog.csdn.net/u013277740/article/details/51737080

最近做用DownloadManager进行自更新升级,下载安装时!发现6.0以上的系统有的机型,下载完成后,无法自动安装,

原来是这么写的,也没注意过:

          // 通过Intent安装APK文件  
            Intent intents = new Intent();
            intents.setAction(
Intent.ACTION_DEFAULT);
            intents.addCategory(
Intent.CATEGORY_DEFAULT);
            intents.setDataAndType(uri, "application/vnd.android.package-archive");
            intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intents);

但是最近6.0有些系统安装不了,发现是这句话里的uri问题,

intents.setDataAndType(uri, "application/vnd.android.package-archive");

以前这个uri是通过DownloadManager里面的getUriForDownloadedFile(longid)获取的!而现在上面的这行代码没有获取uri对应的文件的真实路径,没能成功解析这个uri(具体原因,感兴趣的童鞋,可以去看源码!)所以现在我现在换成下面的写法:

           

                 Intent intent = new Intent();
                 intent.setAction(Intent.ACTION_DEFAULT);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
                 File apkFile = queryDownloadedApk();
                 if(apkFile.exists()){
                  intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                  startActivity(intent);
                 }
    通过queryDownloadedApk()获取真实文件,然后再生成uri = Uri.fromFile(apkFile);
public File queryDownloadedApk() {
    File targetApkFile = null;
    if (downloadId != -1) {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(downloadId);
        query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
        Cursor cur = downloadManager.query(query);
        if (cur != null) {
            if (cur.moveToFirst()) {
                String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                if (!OdyUtil.isEmpty(uriString)) {
                    targetApkFile = new File(Uri.parse(uriString).getPath());
                }
            }
            cur.close();
        }
    }
    return targetApkFile;
}

    当然也可以通过下面的方法getRealFilePath(final Context context, final Uri uri)正确解析DownloadManager里面的getUriForDownloadedFile(long id)获取的uri
然后再放入intents.setDataAndType()方法中:
public String getRealFilePath(final Context context, final Uri uri) {
    if (null == uri) return null;
    final String scheme = uri.getScheme();
    String data = null;
    if (scheme == null)
        data = uri.getPath();
    else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
        data = uri.getPath();
    } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
        Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
        if (null != cursor) {
            if (cursor.moveToFirst()) {
                int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                if (index > -1) {
                    data = cursor.getString(index);
                }
            }
            cursor.close();
        }
    }
    return data;
}
下面代码是一个简单的防止重复下载判断:
 
  
private boolean isNeedDownloadAgain() {
    boolean isNeedDownloadAgain = true;
    DownloadManager.Query query = new DownloadManager.Query();
    downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    long id = ServiceProviderApplication.getValueByKey("serviceProviderDownloadManagerId", -1L);
    // Toast.makeText(getApplicationContext(), "id..."+id, Toast.LENGTH_SHORT).show();
    if (id != -1) {
        query.setFilterById(id);
        Cursor cursor = downloadManager.query(query);
        if (cursor != null && cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
            int status = cursor.getInt(columnIndex);
            int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
            int reason = cursor.getInt(columnReason);
            switch (status) {
                case DownloadManager.STATUS_FAILED:
                    switch (reason) {
                        case DownloadManager.ERROR_CANNOT_RESUME:
                            //some possibly transient error occurred but we can't resume the download  
                            break;
                        case DownloadManager.ERROR_DEVICE_NOT_FOUND:
                            //no external storage device was found. Typically, this is because the SD card is not mounted  
                            break;
                        case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
                            //the requested destination file already exists (the download manager will not overwrite an existing file)  
                            break;
                        case DownloadManager.ERROR_FILE_ERROR:
                            //a storage issue arises which doesn't fit under any other error code  
                            break;
                        case DownloadManager.ERROR_HTTP_DATA_ERROR:
                            //an error receiving or processing data occurred at the HTTP level  
                            break;
                        case DownloadManager.ERROR_INSUFFICIENT_SPACE://sd卡满了  
                            //here was insufficient storage space. Typically, this is because the SD card is full  
                            break;
                        case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
                            //there were too many redirects  
                            break;
                        case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
                            //an HTTP code was received that download manager can't handle  
                            break;
                        case DownloadManager.ERROR_UNKNOWN:
                            //he download has completed with an error that doesn't fit under any other error code  
                            break;
                    }
                    isNeedDownloadAgain = true;
                    break;
                case DownloadManager.STATUS_PAUSED:
                    switch (reason) {
                        case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
                            //the download exceeds a size limit for downloads over the mobile network and the download manager is waiting for a Wi-Fi connection to proceed  

                            break;
                        case DownloadManager.PAUSED_UNKNOWN:
                            //the download is paused for some other reason  
                            break;
                        case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
                            //the download is waiting for network connectivity to proceed  
                            break;
                        case DownloadManager.PAUSED_WAITING_TO_RETRY:
                            //the download is paused because some network error occurred and the download manager is waiting before retrying the request  
                            break;
                    }
                    isNeedDownloadAgain = false;
                    break;
                case DownloadManager.STATUS_PENDING:
                    isNeedDownloadAgain = false;
                    //  Toast.makeText(getApplicationContext(), "STATUS_PENDING...", Toast.LENGTH_SHORT).show();
                    break;
                case DownloadManager.STATUS_RUNNING:
                    Toast.makeText(getApplicationContext(), "正在下载...", Toast.LENGTH_SHORT).show();
                    isNeedDownloadAgain = false;
                    break;
                case DownloadManager.STATUS_SUCCESSFUL:
                    //the download has successfully completed  
                    isNeedDownloadAgain = true;
                    // isNeedDownloadAgain = false;
                    //  installApk(id, downloadManager, mContext);
                    break;

            }
        }

    }

    return isNeedDownloadAgain;
}

接下来就是全部的代码,代码有点乱,请获取自己需要的内容即可:
public class ApplicationUpdateService extends Service {
    private String path = "http://gdown.baidu.com/data/wisegame/91319a5a1dfae322/baidu_16785426.apk";
    /**
     * 安卓系统下载类
     **/
    private DownloadManager downloadManager;
    private long downloadId;
    /**
     * 接收下载完的广播
     **/
    DownloadCompleteReceiver receiver;
 

    /**
     * 初始化下载器
     **/
    private void initDownManager(String url) {

//        downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        receiver = new DownloadCompleteReceiver();

        //设置下载地址  
        DownloadManager.Request request = new DownloadManager.Request(
                Uri.parse(url));
        Log.v("url:", url);
        // 设置允许使用的网络类型,这里是移动网络和wifi都可以  
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE
                | DownloadManager.Request.NETWORK_WIFI);

        request.setMimeType("application/vnd.android.package-archive");

        // 下载时,通知栏显示途中  
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

        // 显示下载界面  
        request.setVisibleInDownloadsUi(true);
        // 设置下载后文件存放的位置  
        request.setDestinationInExternalFilesDir(this,
                Environment.DIRECTORY_DOWNLOADS, getPackageName());
        //
        request.setTitle(getApplicationContext().getResources().getString(R.string.app_name));
        request.setDescription("新版本更新");

        // 将下载请求放入队列  
        downloadId = downloadManager.enqueue(request);
        ServiceProviderApplication.putValueByKey("serviceProviderDownloadManagerId", downloadId);
        //注册下载广播  
        registerReceiver(receiver, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       //url是传过来的下载路径,如果想直接用,可以用上面的百度apk地址path代替
        String url = intent.getStringExtra("url");
        if (url != null && !"".equals(url)) {
            if (isNeedDownloadAgain()) {
                Toast.makeText(getApplicationContext(), "开始下载...", Toast.LENGTH_SHORT).show();
                // 调用下载  
                initDownManager(url);
            }
        }
        return Service.START_REDELIVER_INTENT;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onDestroy() {

        // 注销下载广播  
        if (receiver != null)
            unregisterReceiver(receiver);

        super.onDestroy();
    }
    private boolean isNeedDownloadAgain() {
        boolean isNeedDownloadAgain = true;
        DownloadManager.Query query = new DownloadManager.Query();
        downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        long id = ServiceProviderApplication.getValueByKey("serviceProviderDownloadManagerId", -1L);
        // Toast.makeText(getApplicationContext(), "id..."+id, Toast.LENGTH_SHORT).show();
        if (id != -1) {
            query.setFilterById(id);
            Cursor cursor = downloadManager.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                int status = cursor.getInt(columnIndex);
                int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
                int reason = cursor.getInt(columnReason);
                switch (status) {
                    case DownloadManager.STATUS_FAILED:
                        switch (reason) {
                            case DownloadManager.ERROR_CANNOT_RESUME:
                                //some possibly transient error occurred but we can't resume the download  
                                break;
                            case DownloadManager.ERROR_DEVICE_NOT_FOUND:
                                //no external storage device was found. Typically, this is because the SD card is not mounted  
                                break;
                            case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
                                //the requested destination file already exists (the download manager will not overwrite an existing file)  
                                break;
                            case DownloadManager.ERROR_FILE_ERROR:
                                //a storage issue arises which doesn't fit under any other error code  
                                break;
                            case DownloadManager.ERROR_HTTP_DATA_ERROR:
                                //an error receiving or processing data occurred at the HTTP level  
                                break;
                            case DownloadManager.ERROR_INSUFFICIENT_SPACE://sd卡满了  
                                //here was insufficient storage space. Typically, this is because the SD card is full  
                                break;
                            case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
                                //there were too many redirects  
                                break;
                            case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
                                //an HTTP code was received that download manager can't handle  
                                break;
                            case DownloadManager.ERROR_UNKNOWN:
                                //he download has completed with an error that doesn't fit under any other error code  
                                break;
                        }
                        isNeedDownloadAgain = true;
                        break;
                    case DownloadManager.STATUS_PAUSED:
                        switch (reason) {
                            case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
                                //the download exceeds a size limit for downloads over the mobile network and the download manager is waiting for a Wi-Fi connection to proceed  

                                break;
                            case DownloadManager.PAUSED_UNKNOWN:
                                //the download is paused for some other reason  
                                break;
                            case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
                                //the download is waiting for network connectivity to proceed  
                                break;
                            case DownloadManager.PAUSED_WAITING_TO_RETRY:
                                //the download is paused because some network error occurred and the download manager is waiting before retrying the request  
                                break;
                        }
                        isNeedDownloadAgain = false;
                        break;
                    case DownloadManager.STATUS_PENDING:
                        isNeedDownloadAgain = false;
                        //  Toast.makeText(getApplicationContext(), "STATUS_PENDING...", Toast.LENGTH_SHORT).show();
                        break;
                    case DownloadManager.STATUS_RUNNING:
                        Toast.makeText(getApplicationContext(), "正在下载...", Toast.LENGTH_SHORT).show();
                        isNeedDownloadAgain = false;
                        break;
                    case DownloadManager.STATUS_SUCCESSFUL:
                        //the download has successfully completed  
                        isNeedDownloadAgain = true;
                        // isNeedDownloadAgain = false;
                        //  installApk(id, downloadManager, mContext);
                        break;

                }
            }

        }

        return isNeedDownloadAgain;
    }
    
    // 接受下载完成后的intent  
    class DownloadCompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            //判断是否下载完成的广播  
            if (intent.getAction().equals(
                    DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {

                //获取下载的文件id  
                long completeDownloadId = intent.getLongExtra(
                        DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                Uri uri = downloadManager.getUriForDownloadedFile(completeDownloadId);
                if (uri != null) {
                    //自动安装apk  
                    installAPK(downloadManager.getUriForDownloadedFile(completeDownloadId));
                } else {
                    Toast.makeText(getApplicationContext(), "下载失败!", Toast.LENGTH_SHORT).show();
                }
                //停止服务并关闭广播  
                ApplicationUpdateService.this.stopSelf();

            }
        }

      
       /**
         * 安装apk文件
         */
        private void installAPK(Uri apk) {

            // 通过Intent安装APK文件
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_DEFAULT);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            File apkFile = queryDownloadedApk();
 
  
//            String path = getRealFilePath(getApplicationContext(), apk);
//            File apkFile = new File(path);
if(apkFile.exists()){  
                intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                
                startActivity(intent);           
             }else {               
                OdyUtil.showShortToast("安装文件不存在");     
             }    
    }
  //解析uri,,获取下载文件真实路径
 
  
public String getRealFilePath(final Context context, final Uri uri) {
    if (null == uri) return null;
    final String scheme = uri.getScheme();
    String data = null;
    if (scheme == null)
        data = uri.getPath();
    else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
        data = uri.getPath();
    } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
        Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
        if (null != cursor) {
            if (cursor.moveToFirst()) {
                int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                if (index > -1) {
                    data = cursor.getString(index);
                }
            }
            cursor.close();
        }
    }
    return data;
}

//获取下载文件
public File queryDownloadedApk() {
    File targetApkFile = null;
    if (downloadId != -1) {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(downloadId);
        query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
        Cursor cur = downloadManager.query(query);
        if (cur != null) {
            if (cur.moveToFirst()) {
                String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                if (!OdyUtil.isEmpty(uriString)) {
                    targetApkFile = new File(Uri.parse(uriString).getPath());
                }
            }
            cur.close();
        }
    }
    return targetApkFile;
}
}
}


你可能感兴趣的:(android 6.0以上系统apk自动安装失败问题)