Runt
2025-08-29 f2a3965a672fca33831d361872874fec104846d5
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,8 +32,8 @@
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
@@ -63,6 +67,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>()
@@ -134,6 +139,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?) {
@@ -185,7 +201,11 @@
        }
    }
    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 +223,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 +418,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 +492,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 +513,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 +580,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 +612,7 @@
    }
    fun getStringSetUserPrefrence(key : String) : Set<*> {
        return getStringSetUserPrefrence(key,ArraySet<Any?>())
        return getStringSetUserPrefrence(key,HashSet<Any?>())
    }
    fun getStringSetUserPrefrence(key : String,value : Set<*>) : Set<*> {