From 89e35a1933ba40513a96572b27291c0aa65c918c Mon Sep 17 00:00:00 2001
From: Runt <qingingrunt2010@qq.com>
Date: Sat, 11 Oct 2025 10:21:42 +0000
Subject: [PATCH] 框架优化
---
libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt | 139 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 104 insertions(+), 35 deletions(-)
diff --git a/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt b/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt
index 3d3154a..5e1dfb0 100644
--- a/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt
+++ b/libmvi/src/main/java/com/runt/open/mvi/base/BaseActivity.kt
@@ -2,10 +2,14 @@
import android.Manifest
import android.app.ActivityManager
+import android.app.UiModeManager
+import android.content.ClipData
+import android.content.ClipboardManager
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -28,14 +32,15 @@
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.ColorRes
+import androidx.annotation.StringDef
import androidx.annotation.StringRes
-import androidx.collection.ArraySet
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.runt.open.mvi.R
import com.runt.open.mvi.base.model.BaseViewModel
import com.runt.open.mvi.base.model.ViewModelFactory
+import com.runt.open.mvi.utils.FileUtils
import com.runt.open.mvi.utils.PreferencesUtils
import java.io.File
import java.lang.reflect.ParameterizedType
@@ -63,6 +68,7 @@
private var requestFileResult:Observer<List<String>>? = null;
private var fileLauncher : ActivityResultLauncher<Intent>? = null //选择文件
+ private var multipleFileLauncher : ActivityResultLauncher<Array<String>>? = null //选择文件
private var filePermissionLauncher : ActivityResultLauncher<Intent>? = null //文件权限
private val fileUriList = mutableListOf<Uri>()
@@ -96,6 +102,36 @@
initViews() //初始化UI
mViewModel!!.onCreate(this as BaseActivity<LayoutView<BaseViewModel> , BaseViewModel>)
loadData() //加载数据
+ }
+
+ override fun onPause() {
+ super.onPause()
+ mViewModel!!.onPause()
+ Log.i(TAG , "onPause: ")
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mViewModel!!.onResume()
+ Log.i(TAG , "onResume: ")
+ }
+
+ override fun onStart() {
+ super.onStart()
+ mViewModel!!.onStart()
+ Log.i(TAG , "onStart: ")
+ }
+
+ override fun onStop() {
+ super.onStop()
+ mViewModel!!.onStop()
+ Log.i(TAG , "onStop: ")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mViewModel!!.onDestroy()
+ Log.i(TAG , "onDestroy: ")
}
abstract fun init()
@@ -134,6 +170,17 @@
Log.i(TAG,"filePermission ${result}")
onRequestFileResult();
}
+ multipleFileLauncher = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { uris ->
+ fileUriList.clear();
+ fileUriList.addAll(uris);
+ Log.i(TAG,"multipleFileLauncher ${uris}")
+ if(fileUriList.size == 0){
+ requestFileResult?.onChanged(ArrayList())
+ }else{
+ onRequestFileResult();
+ }
+ }
+
//选择文件
fileLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult() , object : ActivityResultCallback<ActivityResult?> {
override fun onActivityResult(result : ActivityResult?) {
@@ -162,7 +209,7 @@
val cR : ContentResolver = getContentResolver()
val mime = MimeTypeMap.getSingleton()
- var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(0)!!);
+ var filePath = FileUtils.getFilePathFromUri(fileUriList.get(0)!!);
//文件不存在或读写权限受限
if(filePath == null){
//android 11需要申请权限 //是否有所有问读写权限
@@ -178,14 +225,18 @@
}else{
var filePathes = ArrayList<String>()
for (i in 0 until fileUriList.size) {
- var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(i)!!);
+ var filePath = FileUtils.getFilePathFromUri(fileUriList.get(i)!!);
filePathes.add(filePath!!)
}
requestFileResult?.onChanged(filePathes)
}
}
- fun requestFile(fileType :String,maxCount:Int = 1,fileResult:Observer<List<String>>){
+ @Retention(AnnotationRetention.SOURCE)
+ @StringDef(Manifest.permission.READ_MEDIA_VIDEO, Manifest.permission.READ_MEDIA_AUDIO, Manifest.permission.READ_MEDIA_IMAGES)
+ annotation class ManifestType
+
+ fun requestFile(@ManifestType fileType :String,maxCount:Int = 1,fileResult:Observer<List<String>>){
requestFileResult = fileResult;
var permissions = "";
//android 13 权限申请细化类型
@@ -203,33 +254,33 @@
requestPermissions(permissions , object :Observer<String>{
override fun onChanged(value : String) {
if(!value.isEmpty()){
- var intent = Intent()
- // intent.action = Intent.ACTION_PICK
- // intent.action = Intent.ACTION_GET_CONTENT
-
- //intent.setType("image/*")
when(fileType){
- Manifest.permission.READ_MEDIA_VIDEO ->{
+ Manifest.permission.READ_MEDIA_VIDEO,Manifest.permission.READ_MEDIA_IMAGES ->{
+ var intent = Intent()
intent.action = MediaStore.ACTION_PICK_IMAGES
- intent.setType("video/*") // 设置文件类型,可以更具体如"application/pdf"
+ var type = if(fileType == Manifest.permission.READ_MEDIA_VIDEO) "video/*" else "image/*"
+ intent.setType(type) // 设置文件类型,可以更具体如"application/pdf"
+ // 设置可多选
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, maxCount > 1);
+ if(maxCount > 1){
+ //设置最大数量
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
+ }
+ fileLauncher!!.launch(intent)
}
Manifest.permission.READ_MEDIA_AUDIO ->{
- intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
- intent.setType("audio/*") // 设置文件类型,可以更具体如"application/pdf"
- }
- Manifest.permission.READ_MEDIA_IMAGES ->{
- intent.action = MediaStore.ACTION_PICK_IMAGES
- intent.setType("image/*") // 设置文件类型,可以更具体如"application/pdf"
+ var intent = Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI)
+ fileLauncher!!.launch(intent)
+ //multipleFileLauncher!!.launch(arrayOf("audio/*"
+ // "audio/mp3", // MP3
+ // "audio/m4a", // M4A
+ // "audio/aac", // AAC
+ // "audio/ogg", // OGG
+ // "audio/wav" // WAV
+ // ))
}
else -> {}
}
- // 设置可多选
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, maxCount > 1);
- if(maxCount > 1){
- //设置最大数量
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
- }
- fileLauncher!!.launch(intent)
}else{
requestFileResult?.onChanged(ArrayList())
}
@@ -398,22 +449,26 @@
var message = "";
if(permissions.contains(Manifest.permission.READ_EXTERNAL_STORAGE)){
title = "申请文件读取权限";
- message = "通过文件读取权限后,可无障碍使用图片、音乐、视频并添加到直播的音视频流中"
+ message = " 通过文件读取权限后,可无障碍使用图片类、音乐类、视频类文件,并将读取的文件数据添加到直播中的音视频流中。"
}else if(permissions.contains(Manifest.permission.CAMERA)){
title = "申请相机权限";
- message = "通过相机权限后,可将相机画面添加到直播画面流中"
+ message = " 通过相机权限后,可无障碍使用相机及USB采集设备,并将设备采集的画面添加到直播中的视频流中。"
}else if(permissions.contains(Manifest.permission.RECORD_AUDIO)){
title = "申请话筒权限";
- message = "通过话筒权限后,可将话筒声音添加到直播声音流中"
- }else if(permissions.contains(Manifest.permission.READ_MEDIA_IMAGES)){
+ message = " 通过话筒权限后,可无障碍使用话筒设备,并将话筒采集的音频数据添加到直播中的音频流中"
+ }else if(permissions.contains(Manifest.permission.READ_MEDIA_IMAGES) ||
+ permissions.contains(Manifest.permission.READ_MEDIA_VIDEO)){
title = "申请图片和视频文件权限";
- message = "通过图片和视频文件权限后,可将图片和视频画面添加到直播画面流中"
+ message = " 通过图片类和视频类文件权限后,可将读取的图片和视频数据添加到直播中的音视频流中。"
+ }/*else if(permissions.contains(Manifest.permission.READ_MEDIA_IMAGES)){
+ title = "申请图片文件权限";
+ message = "通过图片类文件权限后,可将读取的图片数据添加到直播中的视频流中。"
}else if(permissions.contains(Manifest.permission.READ_MEDIA_VIDEO)){
- title = "申请图片和视频文件权限";
- message = "通过图片和视频文件权限后,可将图片和视频画面添加到直播画面流中"
- }else if(permissions.contains(Manifest.permission.READ_MEDIA_AUDIO)){
+ title = "申请视频文件权限";
+ message = "通过视频类文件权限后,可将读取的视频数据添加到直播中的音视频流中。"
+ }*/else if(permissions.contains(Manifest.permission.READ_MEDIA_AUDIO)){
title = "申请音频文件权限";
- message = "通过音频文件权限后,可将音频文件的声音添加到直播声音流中"
+ message = " 通过音频文件权限后,可将音频文件的声音添加到直播中的音频流中"
}/*else if(permissions.contains(Manifest.permission.POST_NOTIFICATIONS)){
title = "申请通知栏权限";
message = "通过通知栏权限后,可开启后台服务,保证相机、话筒、截屏、扬声器等功能不被系统终止"
@@ -468,6 +523,14 @@
showToast(getString(msg))
}
+ fun copyStr(str:String){
+ // 获取系统剪贴板
+ val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ // 创建一个剪贴数据集,包含一个普通文本数据条目(需要复制的数据)
+ val clipData = ClipData.newPlainText(null ,str)
+ // 把数据集设置(复制)到剪贴板
+ clipboard.setPrimaryClip(clipData)
+ }
/**
* 获取文件保存路径 sdcard根目录/download/文件名称
* @param fileUrl
@@ -481,6 +544,12 @@
appDir.mkdirs()
}
return storePath + File.separator + fileName
+ }
+
+ fun isTabletDevice(): Boolean {
+ val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
+ return (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION).not() &&
+ (resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK >= Configuration.SCREENLAYOUT_SIZE_LARGE)
}
//===========================================
@@ -542,7 +611,7 @@
}
fun getStringSetProjectPrefrence(key : String) : Set<*> {
- return getStringSetProjectPrefrence(key, ArraySet<Any?>() )
+ return getStringSetProjectPrefrence(key, HashSet<Any?>() )
}
fun getStringSetProjectPrefrence(key : String,value : Set<*>?) : Set<*> {
@@ -574,7 +643,7 @@
}
fun getStringSetUserPrefrence(key : String) : Set<*> {
- return getStringSetUserPrefrence(key,ArraySet<Any?>())
+ return getStringSetUserPrefrence(key,HashSet<Any?>())
}
fun getStringSetUserPrefrence(key : String,value : Set<*>) : Set<*> {
--
Gitblit v1.9.1