admin管理员组文章数量:1558098
Android app内部更新适配安卓10、11版本
前言
App内部更新现在基本每个app中都有,由于安卓各大应用市场不统一,不像Ios那样只有一个应用商城。并且现在安卓已经更新到11版本了,中间有几个版本还需对App内部更新做适配,所以说这里记录一下。本笔记目前适配Android11版本。本文只讲下载和安装的核心,不对更新版本的校验和更新弹出框做优化,有需要的可以自行添加。这里参考了android两位大神的文章https://blog.csdn/lmj623565791/article/details/72859156?spm=1001.2014.3001.5502、https://guolin.blog.csdn/article/details/105419420。
6.0版本之前
其实在6.0版本之前是什么都不要做的,直接将apk文件下载到sd卡目录中再调用如下代码就可以了
File file = new File(Environment.getExternalStorageDirectory(), "testandroid7-debug.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
6.0-7.0之间
到了6.0之后如果将文件存储到sd的目录和读取sd卡下载好的文件中需要申请READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE这两个读写权限。就是Environment.开头调用的这些目录。除了sdcard/Android/data/你的包名下/…这是你app的私有目录无需申请权限。
7.0之后
在官方7.0的以上的系统中,尝试传递 file://URI
可能会触发FileUriExposedException
。而你用之前的sd获得的路径恰好就是这种,接下来说说解决方案:
-
在清单文件AndroidManifest.xml配置如下
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths"/> </provider>
name是固定的
authorities是应用的唯一标识一般用应用的包名再拼上一些随便的字符,
exported=false固定的,
grantUriPermissions=true固定的
meta中的name固定的
resource这边需要再res下创建一个xml文件夹,在xml文件夹下创建一个文件,文件内容如下
<?xml version="1.0" encoding="utf-8"?> <resources> <external-files-path name="app" path="/updateApp" /> </resources>
可配置标签说明
<root-path/> 代表设备的根目录new File("/"); <files-path/> 代表context.getFilesDir() <cache-path/> 代表context.getCacheDir() <external-path/> 代表Environment.getExternalStorageDirectory() <external-files-path>代表context.getExternalFilesDirs() <external-cache-path>代表getExternalCacheDirs()
因为我这里用的的sdcard/Android/data/你的包名下/updateApp/updateApp.apk所以无需请求权限,但是这个目录下的文件是会计算到你应用的大小中的并且应用一卸载这里面的内容也会跟着卸载。
安装apk稍作修改
private fun getUriForFile(file:File) = if(Build.VERSION.SDK_INT >= 24) getUriForFile24(file) else Uri.fromFile(file) private fun getUriForFile24(file:File) = FileProvider.getUriForFile(this,"$packageName.fileprovider",file) private fun setIntentDataAndType(intent: Intent,type:String,file: File,writeAble:Boolean) { if(Build.VERSION.SDK_INT >= 24){ intent.setDataAndType(getUriForFile(file),type) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) if(writeAble) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) } }else { intent.setDataAndType(Uri.fromFile(file),type) } }
调用安装
File file = new File(Environment.getExternalStorageDirectory(), "testandroid7-debug.apk"); Intent intent = new Intent(Intent.ACTION_VIEW); // 调用上面的方法 setIntentDataAndType(intent, "application/vnd.android.package-archive",file,true); startActivity(intent);
10.0之后
其实安卓10之后增加了作用域访问权限,已经不能使用之前的那种File(路径)的方式去访问sd卡下的路径了,专门有需要使用contentResolver结合MediaStore去访问,这里不展开讲解。可以去看郭神的文章https://guolin.blog.csdn/article/details/105419420而我们为了规避掉这个事情,还是上面的将apk的包下载到自己应用下的目录就可以无需做任何改动。
我也尝试将apk下载到download下,下载可以,但是我不知道怎么取出来,所以放弃了。有知道的大佬可以告知我一声。
代码示例
package com.qmc.update import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider import pub.devrel.easypermissions.EasyPermissions import java.io.File import java.io.FileOutputStream import java.net.HttpURLConnection import java.net.URL class MainActivity : AppCompatActivity(),EasyPermissions.PermissionCallbacks { val TAG = this.javaClass.simpleName override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) downLoadApp() } private fun downLoadApp() { Thread { val url = URL("http://192.168.1.120:3001/yanyue/updateApp.apk") val httpURLConnection = url.openConnection() as HttpURLConnection httpURLConnection.requestMethod = "GET" httpURLConnection.connect() try { val responseCode = httpURLConnection.responseCode if (responseCode == HttpURLConnection.HTTP_OK) { val inputStream = httpURLConnection.inputStream val downLoadPath = getExternalFilesDir(null)?.absolutePath + File.separator + "/updateApp" val file = File(downLoadPath) if(!file.exists()) { file.mkdir() } val outputStream = FileOutputStream("$downLoadPath/update.apk") val byteArray = ByteArray(1024) var count: Int do { count = inputStream.read(byteArray) if (count != -1) { outputStream.write(byteArray, 0, count) } else { inputStream.close() outputStream.close() break } } while (true) inputStream.close() outputStream.close() val updateFile = File("$downLoadPath/update.apk") if(file.exists()){ runOnUiThread { val installIntent = Intent(Intent.ACTION_VIEW) setIntentDataAndType(installIntent,"application/vnd.android.package-archive",updateFile,true) startActivity(installIntent) } } else { Log.e(TAG, "downLoadApp: 文件不存在") } } } catch (e: Exception) { Log.e(TAG, "downLoadApp: ${e.message}") } }.start() } private fun getUriForFile(file:File) = if(Build.VERSION.SDK_INT >= 24) getUriForFile24(file) else Uri.fromFile(file) private fun getUriForFile24(file:File) = FileProvider.getUriForFile(this,"$packageName.fileprovider",file) private fun setIntentDataAndType(intent: Intent,type:String,file: File,writeAble:Boolean) { if(Build.VERSION.SDK_INT >= 24){ intent.setDataAndType(getUriForFile(file),type) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) if(writeAble) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) } }else { intent.setDataAndType(Uri.fromFile(file),type) } } override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) { Toast.makeText(this,"权限拒绝",Toast.LENGTH_SHORT).show() } override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) { downLoadApp() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) EasyPermissions.onRequestPermissionsResult(requestCode,permissions,grantResults,this) } }
注意在清单文件中添加网络权限!!!
版权声明:本文标题:Androidapp更新适配安卓10、11版本 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1727319862a1108202.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论