在Android7.0的手机上,自动更新的时候出现包解析异常,在其他的手机上没有这个问题。
原因:
Android7.0引入私有目录被限制访问和StrictMode API 。私有目录被限制访问是指在Android7.0中为了提高应用的安全性,在7.0上应用私有目录将被限制访问。StrictMode API是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,则会报出异常。
解决办法:
第一步:在AndroidManifest.xml中注册provider,provider可以向应用外提供数据。
//在第二步的时候会有介绍
第二步:在res/xml中创建file_paths.xml文件。
第三步:贴出我的自动更新下载的代码
public class UpdateManager { private Context mContext; private static String savePath ; private String saveFileName ; private ProgressBar mProgress; //下载进度条控件 private static final int DOWNLOADING = 1; //表示正在下载 private static final int DOWNLOADED = 2; //下载完毕 private static final int DOWNLOAD_FAILED = 3; //下载失败 private int progress; //下载进度 private boolean cancelFlag = false; //取消下载标志位 private String serverVersion; //从服务器获取的版本号 private String apkUrl; // private String apkUrl = "http://liuliu.lejuhuyu.com/AndroidApk/liuliu-dashou-app-1.0.2.apk"; private String clientVersion; //客户端当前的版本号 private String updateDescription = "请更新当前最新版本"; //更新内容描述信息 private String forceUpdate; //是否强制更新 private String update; private VersionBean mVersionBean; private AlertDialog alertDialog1, alertDialog2; //表示提示对话框、进度条对话框 public UpdateManager(Context context,VersionBean versionBean) { this.mContext = context; this.mVersionBean = versionBean; apkUrl = "http://liuliu.lejuhuyu.com/AndroidApk/liuliu-dashou-app-"+versionBean.getLastVersion()+".apk"; savePath = Environment.DIRECTORY_DOWNLOADS; saveFileName = savePath + "/liuliu-dashou-app-"+versionBean.getLastVersion()+".apk"; } /** 显示更新对话框 */ public void showNoticeDialog() { serverVersion = mVersionBean.getLastVersion(); clientVersion = mVersionBean.getVersion(); L.e("apkUrl="+apkUrl); L.e("savePath="+savePath); L.e("saveFileName="+saveFileName); // forceUpdate = StringUtils.getVersion(); // forceUpdate = "1"; forceUpdate = mVersionBean.getImportant(); update = mVersionBean.getUpdate(); //如果版本最新,则不需要更新 if (serverVersion.equals(clientVersion)) return; if (update.equals("2")) return; AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); dialog.setTitle("发现新版本 :" + serverVersion); dialog.setMessage(updateDescription); dialog.setPositiveButton("现在更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // TODO Auto-generated method stub arg0.dismiss(); showDownloadDialog(); } }); //是否强制更新 if (forceUpdate.equals("2")) { dialog.setNegativeButton("待会更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // TODO Auto-generated method stub arg0.dismiss(); } }); } alertDialog1 = dialog.create(); alertDialog1.setCancelable(false); alertDialog1.show(); } /** 显示进度条对话框 */ public void showDownloadDialog() { AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); dialog.setTitle("正在更新"); final LayoutInflater inflater = LayoutInflater.from(mContext); View v = inflater.inflate(R.layout.softupdate_progress, null); mProgress = (ProgressBar) v.findViewById(R.id.update_progress); dialog.setView(v); //如果是强制更新,则不显示取消按钮 // if (forceUpdate.equals("1")) { // dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { // @Override // public void onClick(DialogInterface arg0, int arg1) { // // TODO Auto-generated method stub // arg0.dismiss(); // cancelFlag = false; // } // }); // } alertDialog2 = dialog.create(); alertDialog2.setCancelable(false); alertDialog2.show(); //下载apk downloadAPK(); } DownloadManager manager; Cursor cursor; DownloadManager.Request down; DownloadManager.Query query; ContentObserver contentObserver; /** 下载apk的线程 */ public void downloadAPK() { manager = (DownloadManager) LiuLiuApplication.getContext().getSystemService(Context.DOWNLOAD_SERVICE); down = new DownloadManager.Request(Uri.parse(apkUrl)); // 设置允许使用的网络类型,这里是移动网络和wifi都可以 down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); // 显示下载界面 down.setVisibleInDownloadsUi(true); // 设置下载路径和文件名 down.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "liuliu-dashou-app-"+mVersionBean.getLastVersion() + ".apk"); down.setMimeType("application/vnd.android.package-archive"); // 设置为可被媒体扫描器找到 down.allowScanningByMediaScanner(); down.setAllowedOverRoaming(false); // down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); long id = manager.enqueue(down); query = new DownloadManager.Query().setFilterById(id); contentObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { // super.onChange(selfChange); boolean downloading = true; while(downloading){ cursor = manager.query(query); try { if (cursor != null && cursor.moveToFirst()) { int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); progress = (int) ((bytes_downloaded * 100) / bytes_total); mHandler.sendEmptyMessage(DOWNLOADING); if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))==DownloadManager.STATUS_SUCCESSFUL) { mHandler.sendEmptyMessage(DOWNLOADED); }else if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))==DownloadManager.STATUS_FAILED){ mHandler.sendEmptyMessage(DOWNLOAD_FAILED); } } }catch (Exception e){ e.printStackTrace(); mHandler.sendEmptyMessage(DOWNLOAD_FAILED); }finally { if (cursor != null){ downloading = false; cursor.close(); } } } } }; mContext.getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),true,contentObserver); } /** 更新UI的handler */ private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub switch (msg.what) { case DOWNLOADING: mProgress.setProgress(progress); break; case DOWNLOADED: if (alertDialog2 != null) alertDialog2.dismiss(); installAPK(); break; case DOWNLOAD_FAILED: ToastUtil.getInstance(mContext,"网络断开,请稍候再试",false).show(); break; default: break; } } }; /** 下载完成后自动安装apk */ public void installAPK() { File apkFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"liuliu-dashou-app-"+mVersionBean.getLastVersion() + ".apk"); if (!apkFile.exists()) { return; } if (Build.VERSION.SDK_INT>=24){ Uri apkUri = FileProvider.getUriForFile(mContext, LiuLiuApplication.getContext().getPackageName()+".fileprovider", apkFile); Intent install = new Intent(Intent.ACTION_VIEW); install.addCategory(Intent.CATEGORY_DEFAULT); install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); install.setDataAndType(apkUri, "application/vnd.android.package-archive"); mContext.startActivity(install); } else { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setType("application/vnd.android.package-archive"); intent.setData(Uri.fromFile(apkFile)); intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } } }