今天咱们来讲一下 Android的版本升级模块
随着Android版本的不断更新,andriod对权限的的控制越来越严格。下面咱们就一步一步的写着讲着。
一:请求服务器获取最新的安装包文件,这一步感觉像是废话。肯定要往服务器上下载最新的安装包文件了。
二:开始咱们的正题,安装apk文件。
- application/vnd.android.package-archive 。 大家先要明白这着是什么。"application/vnd.android.package-archive"是文件类型,具体对应apk类型。不是这个Android就不知道你这个是apk文件
final String[][] MIME_MapTable={ //{后缀名,MIME类型} {".3gp", "video/3gpp"}, {".apk", "application/vnd.android.package-archive"}, {".asf", "video/x-ms-asf"}, {".avi", "video/x-msvideo"}, {".bin", "application/octet-stream"}, {".bmp", "image/bmp"}, {".c", "text/plain"}, {".class", "application/octet-stream"}, {".conf", "text/plain"}, {".cpp", "text/plain"}, {".doc", "application/msword"}, {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, {".xls", "application/vnd.ms-excel"}, {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, {".exe", "application/octet-stream"}, {".gif", "image/gif"}, {".gtar", "application/x-gtar"}, {".gz", "application/x-gzip"}, {".h", "text/plain"}, {".htm", "text/html"}, {".html", "text/html"}, {".jar", "application/java-archive"}, {".java", "text/plain"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"}, {".js", "application/x-javascript"}, {".log", "text/plain"}, {".m3u", "audio/x-mpegurl"}, {".m4a", "audio/mp4a-latm"}, {".m4b", "audio/mp4a-latm"}, {".m4p", "audio/mp4a-latm"}, {".m4u", "video/vnd.mpegurl"}, {".m4v", "video/x-m4v"}, {".mov", "video/quicktime"}, {".mp2", "audio/x-mpeg"}, {".mp3", "audio/x-mpeg"}, {".mp4", "video/mp4"}, {".mpc", "application/vnd.mpohun.certificate"}, {".mpe", "video/mpeg"}, {".mpeg", "video/mpeg"}, {".mpg", "video/mpeg"}, {".mpg4", "video/mp4"}, {".mpga", "audio/mpeg"}, {".msg", "application/vnd.ms-outlook"}, {".ogg", "audio/ogg"}, {".pdf", "application/pdf"}, {".png", "image/png"}, {".pps", "application/vnd.ms-powerpoint"}, {".ppt", "application/vnd.ms-powerpoint"}, {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, {".prop", "text/plain"}, {".rc", "text/plain"}, {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, {".sh", "text/plain"}, {".tar", "application/x-tar"}, {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, {".wmv", "audio/x-ms-wmv"}, {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, {".z", "application/x-compress"}, {".zip", "application/x-zip-compressed"}, {"", "*/*"} };
参考下面代码使用
Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent);
-
知道这一点。就可以拿着你的apk文件升级了? Android7.0之前是可以的,直接打开这个文件。但是Android7.0之后就不行了。因为Android的访问文件的权限更改了。Android 7.0强制启用了被称作 StrictMode的策略,带来的影响就是你的App对外无法暴露
file://
类型的URI了。如果你使用Intent携带这样的URI去打开外部App(比如:打开系统相机拍照),那么会抛出FileUriExposedException异常。
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mydomain.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
上面这是讲了一下Android7.0之后的访问文件的权限问题。讲的比较笼统,自己再去看一下别的博客详细学习一下。烟鬼正传,访问到咱们的apk文件后,是不是就可以升级了?
-
使用FileProvider使用大概分为以下几个步骤:
- manifest中申明FileProvider
-
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mydomain.fileprovider" android:exported="false" android:grantUriPermissions="true"> ... </provider> <!--android:name:provider你可以使用v4包提供的FileProvider,或者自定义您自己的,只需要在name申明就好了,一般使用系统的就足够了。 android:authorities:类似schema,命名空间之类,后面会用到。 android:exported:false表示我们的provider不需要对外开放。 android:grantUriPermissions:申明为true,你才能获取临时共享权限。-->
-
- res/xml中定义对外暴露的文件夹路径
- res/xml中定义对外暴露的文件夹路径:
新建file_paths.xml
,文件名随便起,后面会引用到。 -
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="my_images" path="images"/> </paths>
name:一个引用字符串。
path:文件夹“相对路径”,完整路径取决于当前的标签类型 -
path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。
- res/xml中定义对外暴露的文件夹路径:
- 生成content://类型的Uri
-
我们分别看下这几个步骤的具体实现吧
- 给Uri授予临时权限
- 使用Intent传递Uri
-
-
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ XLog.w("7.0以上"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent); }else{ XLog.w("7.0以下"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent); }
注意:还有最后一步。
-
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
-
完美的适配Android8.0未知来源应用安装权限方案
-
Android8.0的诸多新特性中有一个非常重要的特性:未知来源应用权限
以前安装未知来源应用的时候一般会弹出一个弹窗让用户去设置允许还是拒绝,并且设置为允许之后,所有的未知来源的应用都可以被安装。
Android8.0的变化是,未知应用安装权限的开关被除掉,取而代之的是未知来源应用的管理列表,需要在里面打开每个应用的未知来源的安装权限。Google这么做是为了防止一开始正经的应用后来开始通过升级来做一些不合法的事情,侵犯用户权益。
当你的应用直接适配到Android8之后,内部启动应用安装是会被阻塞的,如果不处理好这个未知来源的权限,会导致应用根本无法更新,只能去应用市场重新下载。
那么如何来适配8.0这一个新变化呢?
1、在清单文件中增加请求安装权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
1
2、我们还需要在代码里面对权限进行处理
首先用canRequestPackageInstalls()方法判断你的应用是否有这个权限
haveInstallPermission = getPackageManager().canRequestPackageInstalls();
1
如果haveInstallPermission 为 true,则说明你的应用有安装未知来源应用的权限,你直接执行安装应用的操作即可。
如果haveInstallPermission 为 false,则说明你的应用没有安装未知来源应用的权限,则无法安装应用。由于这个权限不是运行时权限,所以无法再代码中请求权限,还是需要用户跳转到设置界面中自己去打开权限。
具体的操作是:
弹出dialog,告知用户
“安装应用需要打开未知来源权限,请去设置中开启权限”
然后用户点击确定之后跳转到未知来源应用权限管理列表:
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
startActivityForResult(intent, 10086);
然后在onActivityResult中去接收结果:
if (resultCode == RESULT_OK && requestCode == 10086) {
installProcess();//再次执行安装流程,包含权限判等
}