Android12实现插入U盘更新Apk
1.添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
2.在res/xml文件夹中创建 file_paths.xml 物理地址文件.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="files_root"
path="Android/data/com.ruihan.handrehabilitation/" />
<external-path
name="external_storage_root"
path="." />
<!--root-path代表/也就是Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录。-->
<root-path
name="root"
path="/" />
</paths>
在AndroidMaindest中引用
<permission-group android:name="${applicationId}.andpermission" />
<application>
<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/file_paths" />
</provider>
</application>
3.静态方式
3.1创建一个广播,进行全局广播监听
public class UsbUpGradeReceiver extends BroadcastReceiver {
private final static String U_DISK_FILE_NAME = "包名.apk";
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case Intent.ACTION_MEDIA_MOUNTED:
// 获取挂载路径, 读取U盘文件
Uri uri = intent.getData();
if (uri != null) {
String filePath = uri.getPath();
File rootFile = new File(filePath);
for (File file : rootFile.listFiles()) {
// 文件列表,进行相应操作...
if (file.getName().equals(U_DISK_FILE_NAME)) {
try {
String authority = context.getApplicationContext().getPackageName() + ".fileprovider";
Uri fileUri = FileProvider.getUriForFile(context, authority, file);
PackageManager pm = context.getPackageManager();
PackageInfo pkgInfo = pm.getPackageArchiveInfo(file.getPath(), PackageManager.GET_ACTIVITIES);
if (pkgInfo != null) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
LogUtils.e(info.packageName + " " + info.versionName + " " + info.versionCode);
if (appInfo.packageName.equals(info.packageName)) {
if (pkgInfo.versionCode > info.versionCode) {
Intent intents = new Intent(Intent.ACTION_VIEW);
intents.setDataAndType(fileUri, "application/vnd.android.package-archive");
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intents.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intents);
} else {
ToastUtils.showLong("当前需要安装的apk小于当前版本,请检查apk文件");
}
} else ToastUtils.showLong("当前需要安装apk不正确,请检查apk文件!");
}
break;
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}
break;
}
}
}
3.2 注册全局广播,并添加相应监听事件
<receiver
android:name=".UsbUpGradeReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_CHECKING" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.MEDIA_EJECT" />
<action android:name="android.intent.action.MEDIA_UNMOUNTED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
4.动态方式
class XXX{
private var mReceiver: UdiskReceiver? = UdiskReceiver()
//U盘更新
private fun uUpdateListener() {
val filter = IntentFilter()
filter.addAction("android.hardware.usb.action.USB_STATE")
filter.addAction("android.hardware.action.USB_DISCONNECTED")
filter.addAction("android.hardware.action.USB_CONNECTED")
filter.addAction("android.intent.action.UMS_CONNECTED")
filter.addAction("android.intent.action.UMS_DISCONNECTED")
filter.addAction(Intent.ACTION_MEDIA_CHECKING)
filter.addAction(Intent.ACTION_MEDIA_MOUNTED)
filter.addAction(Intent.ACTION_MEDIA_EJECT)
filter.addAction(Intent.ACTION_MEDIA_REMOVED)
filter.addDataScheme("file") // 系统中每个组件,如果想收取隐式事件(未指定接收者),则必须声明自己的IntentFilter(自我介绍,我对什么样的信件感兴趣)。
registerReceiver(mReceiver, filter)
}
//U盘插拔监听
inner class UdiskReceiver : BroadcastReceiver() {
override fun onReceive(arg0: Context, arg1: Intent) {
val action = arg1.action
if (action == Intent.ACTION_MEDIA_CHECKING) {
// Toast.makeText(getApplicationContext(), "正在挂载U盘",
// Toast.LENGTH_SHORT).show();
} else if (action == Intent.ACTION_MEDIA_MOUNTED) {
//todo 这里兼容GenStar设备
// String uPanPath = arg1.getData().getPath() + "/DEMO_v10__1.apk";
val uPanPath = arg1.data!!.path + "/DEMO_v10__1.apk"
LogUtils.e("U盘:$uPanPath")
val fileExists = FileUtils.isFileExists(File(uPanPath))
LogUtils.e("U盘apk:$fileExists")
if (fileExists) {
showUpdateDialog(uPanPath)
}
} else if (action == Intent.ACTION_MEDIA_EJECT) {
LogUtils.e("U盘移除")
}
}
}
fun showUpdateDialog(uPanPath: String) {
val dialog: Dialog = AlertDialog.Builder(this@AuthActivity)
.setTitle("发现软件")
.setMessage("是否更新") // 设置内容
.setPositiveButton(
"更新"
) // 设置确定按钮
{ dialog, which ->
val fileName = uPanPath
val file: File = File(fileName)
try {
val authority: String =
getApplicationContext().getPackageName() + ".fileprovider"
val fileUri = FileProvider.getUriForFile(this, authority, file)
val intents = Intent(Intent.ACTION_VIEW)
intents.setDataAndType(
fileUri,
"application/vnd.android.package-archive"
)
intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intents.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(intents)
} catch (e: PackageManager.NameNotFoundException) {
throw RuntimeException(e)
}
}
.setNegativeButton(
"暂不更新"
) { dialog, whichButton -> // 点击"取消"按钮之后退出程序
finish()
}.create() // 创建
dialog.show()
}
override fun onDestroy() {
super.onDestroy()
NetStatusBus.getInstance().unregister(this@AuthActivity);//网络状态监听
unregisterReceiver(mReceiver)
}
}