时间:2021-05-21
在Android7.0的手机上,自动更新的时候出现包解析异常,在其他的手机上没有这个问题。
原因:
Android7.0引入私有目录被限制访问和StrictMode API 。私有目录被限制访问是指在Android7.0中为了提高应用的安全性,在7.0上应用私有目录将被限制访问。StrictMode API是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,则会报出异常。
解决办法:
第一步:在AndroidManifest.xml中注册provider,provider可以向应用外提供数据。
<provider android:authorities="包名.fileprovider" android:name="android.support.v4.content.FileProvider" android:grantUriPermissions="true"//这是设置uri的权限 android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/>//在第二步的时候会有介绍</provider>第二步:在res/xml中创建file_paths.xml文件。
<?xml version="1.0" encoding="utf-8"?><resources> <paths> <external-path path="" name="download" /> </paths></resources>第三步:贴出我的自动更新下载的代码
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); } }}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言#Android7.0已经发布很久了,虽然市场份额还不是很高,但是流行起来都是早晚的事,所以适配Android7.0刻不容缓。Android7.0对系统进行
前言Android7.0系统发布后,拿到能升级的nexus6P,就开始了7.0的适配。发现在Android7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些
Android安装apk文件并适配Android7.0详解首先在AndroidManifest.xml文件,activity同级节点注册provider:将ap
Android7.0行为变更FileUriExposedException解决方法当我们开发关于【在应用间共享文件】相关功能的时候,在Android7.0上经常
本文实例讲述了Android7.0开发获取存储设备信息的方法。分享给大家供大家参考,具体如下:Android7.0开发相较之前有不少改进,具体可参考前面的文章A