| | |
| | | package com.runt.open.mvi.base |
| | | |
| | | import android.Manifest |
| | | import android.app.ActivityManager |
| | | import android.content.ContentResolver |
| | | import android.content.Context |
| | | import android.content.Intent |
| | | import android.content.pm.ActivityInfo |
| | | import android.content.pm.PackageManager |
| | | import android.net.Uri |
| | | import android.os.Build |
| | | import android.os.Bundle |
| | | import android.os.Environment |
| | | import android.provider.MediaStore |
| | | import android.provider.Settings |
| | | import android.text.TextUtils |
| | | import android.util.Log |
| | | import android.view.MotionEvent |
| | | import android.view.View |
| | | import android.view.WindowManager |
| | | import android.view.inputmethod.InputMethodManager |
| | | import android.webkit.MimeTypeMap |
| | | import android.widget.EditText |
| | | import android.widget.Toast |
| | | import androidx.activity.ComponentActivity |
| | |
| | | import androidx.activity.result.contract.ActivityResultContracts |
| | | import androidx.annotation.ColorRes |
| | | import androidx.annotation.StringRes |
| | | import androidx.collection.ArraySet |
| | | import androidx.core.content.ContextCompat |
| | | import androidx.lifecycle.Observer |
| | | import androidx.lifecycle.ViewModelProvider |
| | |
| | | |
| | | val PARAMS_TITLE = "title" |
| | | |
| | | private var requestFileResult:Observer<List<String>>? = null; |
| | | |
| | | private var fileLauncher : ActivityResultLauncher<Intent>? = null //选择文件 |
| | | private var filePermissionLauncher : ActivityResultLauncher<Intent>? = null //文件权限 |
| | | private val fileUriList = mutableListOf<Uri>() |
| | | |
| | | override fun onCreate(savedInstanceState : Bundle?) { |
| | | super.onCreate(savedInstanceState) // get genericity "B" |
| | |
| | | init(); |
| | | //setContentView(mLayout) |
| | | setContent { |
| | | mLayout!!.layout() |
| | | mLayout!!.layoutFrame() |
| | | } |
| | | mContext = this |
| | | TAG = this.javaClass.simpleName |
| | |
| | | mViewModel!!.onCreate(this as BaseActivity<LayoutView<BaseViewModel> , BaseViewModel>) |
| | | loadData() //加载数据 |
| | | } |
| | | |
| | | abstract fun init() |
| | | |
| | | abstract fun initViews() |
| | | |
| | | abstract fun loadData() |
| | | |
| | | fun registerPermissionResult(){ |
| | | protected fun registerPermissionResult(){ |
| | | permissionsLauncher = this.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> |
| | | if (result == null || result.size === 0) { |
| | | permissionObserver !!.onChanged("") |
| | | return@registerForActivityResult |
| | | } |
| | | mViewModel!!.hidePopupWindow() |
| | | Log.d(TAG , "result:" + result + " size:" + result.size) |
| | | var allGranted = true |
| | | for (key in result.keys) { |
| | |
| | | permissionObserver !!.onChanged(com.google.gson.Gson().toJson(result.keys).replace("[" , "").replace("]" , "").replace("\"" , "")) |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected fun registerFileResult(){ |
| | | |
| | | filePermissionLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> |
| | | Log.i(TAG,"filePermission ${result}") |
| | | onRequestFileResult(); |
| | | } |
| | | //选择文件 |
| | | fileLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult() , object : ActivityResultCallback<ActivityResult?> { |
| | | override fun onActivityResult(result : ActivityResult?) { |
| | | Log.i(TAG,"fileLauncher ${result!!.data?.data}") |
| | | Log.i(TAG,"fileLauncher clipData= ${result!!.data?.clipData}") |
| | | fileUriList.clear(); |
| | | result!!.data?.data?.let{ |
| | | fileUriList.add(it); |
| | | } |
| | | result!!.data?.clipData?.let{ |
| | | val count = it.itemCount |
| | | for (i in 0 until count) { |
| | | fileUriList.add(it.getItemAt(i).uri) |
| | | } |
| | | } |
| | | if(fileUriList.size == 0){ |
| | | requestFileResult?.onChanged(ArrayList()) |
| | | }else{ |
| | | onRequestFileResult(); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | private fun onRequestFileResult(){ |
| | | |
| | | val cR : ContentResolver = getContentResolver() |
| | | val mime = MimeTypeMap.getSingleton() |
| | | var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(0)!!); |
| | | //文件不存在或读写权限受限 |
| | | if(filePath == null){ |
| | | //android 11需要申请权限 //是否有所有问读写权限 |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && ! Environment.isExternalStorageManager()) { |
| | | //跳转到打开权限页面 |
| | | var intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); |
| | | |
| | | intent.setData(Uri.parse("package:" + mContext!!.getPackageName())); |
| | | filePermissionLauncher!!.launch(intent) |
| | | return; |
| | | } |
| | | requestFileResult?.onChanged(ArrayList()) |
| | | }else{ |
| | | var filePathes = ArrayList<String>() |
| | | for (i in 0 until fileUriList.size) { |
| | | var filePath = mViewModel!!.getFilePathFromUri(fileUriList.get(i)!!); |
| | | filePathes.add(filePath!!) |
| | | } |
| | | requestFileResult?.onChanged(filePathes) |
| | | } |
| | | } |
| | | |
| | | fun requestFile(fileType :String,maxCount:Int = 1,fileResult:Observer<List<String>>){ |
| | | requestFileResult = fileResult; |
| | | var permissions = ""; |
| | | //android 13 权限申请细化类型 |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { |
| | | permissions = fileType ; |
| | | //android 14 选择文件授权 |
| | | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { |
| | | permissions+=","+ Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED; |
| | | } |
| | | }else{ |
| | | //读取权限 |
| | | permissions = Manifest.permission.READ_EXTERNAL_STORAGE ; |
| | | } |
| | | //申请权限 |
| | | 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 ->{ |
| | | intent.action = MediaStore.ACTION_PICK_IMAGES |
| | | intent.setType("video/*") // 设置文件类型,可以更具体如"application/pdf" |
| | | } |
| | | 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" |
| | | } |
| | | 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()) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | fun registerForActivityResult(callback : ActivityResultCallback<ActivityResult>):ActivityResultLauncher<Intent>{ |
| | |
| | | return result |
| | | } |
| | | |
| | | @Suppress("DEPRECATION") |
| | | protected fun isMyServiceRunning(serviceClass: Class<*>): Boolean { |
| | | val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager |
| | | for (service in manager.getRunningServices(Integer.MAX_VALUE)) { |
| | | if (serviceClass.name == service.service.className) { |
| | | return true |
| | | } |
| | | } |
| | | return false |
| | | } |
| | | |
| | | /** |
| | | * 检查权限 |
| | |
| | | allGranted = false |
| | | if (showPop) { |
| | | // TODO: |
| | | //showPermissionPopu(permission) |
| | | var title = "" |
| | | var message = ""; |
| | | if(permissions.contains(Manifest.permission.READ_EXTERNAL_STORAGE)){ |
| | | title = "申请文件读取权限"; |
| | | message = " 通过文件读取权限后,可无障碍使用图片类、音乐类、视频类文件,并将读取的文件数据添加到直播中的音视频流中。" |
| | | }else if(permissions.contains(Manifest.permission.CAMERA)){ |
| | | title = "申请相机权限"; |
| | | message = " 通过相机权限后,可无障碍使用相机及USB采集设备,并将设备采集的画面添加到直播中的视频流中。" |
| | | }else if(permissions.contains(Manifest.permission.RECORD_AUDIO)){ |
| | | title = "申请话筒权限"; |
| | | message = " 通过话筒权限后,可无障碍使用话筒设备,并将话筒采集的音频数据添加到直播中的音频流中" |
| | | }else if(permissions.contains(Manifest.permission.READ_MEDIA_IMAGES) || |
| | | permissions.contains(Manifest.permission.READ_MEDIA_VIDEO)){ |
| | | title = "申请图片和视频文件权限"; |
| | | 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.POST_NOTIFICATIONS)){ |
| | | title = "申请通知栏权限"; |
| | | message = "通过通知栏权限后,可开启后台服务,保证相机、话筒、截屏、扬声器等功能不被系统终止" |
| | | }*/ |
| | | if(!TextUtils.isEmpty(title)){ |
| | | mViewModel!!.showPopupWindow(title = title, message = message) |
| | | } |
| | | } |
| | | break |
| | | } |
| | |
| | | |
| | | var permissionsLauncher : ActivityResultLauncher<Array<String>>? = null //权限 |
| | | var permissionObserver : Observer<String>? = null //权限和文件请求回调 |
| | | |
| | | /** |
| | | * 统一权限申请 |
| | | */ |
| | |
| | | |
| | | //=========================================== |
| | | //以下为preferences操作 |
| | | fun getBooleanUserPrefrence(key : String?) : Boolean { |
| | | return PreferencesUtils.getBoolean(this , key , false , PreferencesUtils.USER) |
| | | fun getBooleanUserPrefrence(key : String) : Boolean { |
| | | return getBooleanUserPrefrence(key,false) |
| | | } |
| | | |
| | | fun getBooleanProjectPrefrence(key : String?) : Boolean { |
| | | return PreferencesUtils.getBoolean(this , key , false , PreferencesUtils.PROJECT) |
| | | fun getBooleanUserPrefrence(key : String,value : Boolean) : Boolean { |
| | | return PreferencesUtils.getBoolean(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun getStringUserPrefrence(key : String?) : String { |
| | | return PreferencesUtils.getString(this , key , "" , PreferencesUtils.USER) |
| | | fun getBooleanProjectPrefrence(key : String) : Boolean { |
| | | return getBooleanProjectPrefrence(key,false) |
| | | } |
| | | |
| | | fun getStringProjectPrefrence(key : String?) : String { |
| | | return PreferencesUtils.getString(this , key , "" , PreferencesUtils.PROJECT) |
| | | fun getBooleanProjectPrefrence(key : String,value : Boolean) : Boolean { |
| | | return PreferencesUtils.getBoolean(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getIntProjectPrefrence(key : String?) : Int { |
| | | return PreferencesUtils.getInt(this , key , 0 , PreferencesUtils.PROJECT) |
| | | fun getStringUserPrefrence(key : String) : String { |
| | | return getStringUserPrefrence(key,""); |
| | | } |
| | | |
| | | fun getLongProjectPrefrence(key : String?) : Long { |
| | | return PreferencesUtils.getLong(this , key , 0 , PreferencesUtils.PROJECT) |
| | | fun getStringUserPrefrence(key : String,value : String?) : String { |
| | | return PreferencesUtils.getString(this , key , value, PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun getFloatProjectPrefrence(key : String?) : Float { |
| | | return PreferencesUtils.getFloat(this , key , 0f , PreferencesUtils.PROJECT) |
| | | fun getStringProjectPrefrence(key : String) : String { |
| | | return getStringProjectPrefrence(key,""); |
| | | } |
| | | |
| | | fun getStringSetProjectPrefrence(key : String?) : Set<*> { |
| | | return PreferencesUtils.getStringSet(this , key , PreferencesUtils.PROJECT) |
| | | fun getStringProjectPrefrence(key : String,value : String?) : String { |
| | | return PreferencesUtils.getString(this , key , value, PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getIntUserPrefrence(key : String?) : Int { |
| | | return PreferencesUtils.getInt(this , key , 0 , PreferencesUtils.USER) |
| | | fun getIntProjectPrefrence(key : String) : Int { |
| | | return getIntProjectPrefrence(key,0); |
| | | } |
| | | |
| | | fun getLongUserPrefrence(key : String?) : Long { |
| | | return PreferencesUtils.getLong(this , key , 0 , PreferencesUtils.USER) |
| | | fun getIntProjectPrefrence(key : String,value : Int) : Int { |
| | | return PreferencesUtils.getInt(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getFloatUserPrefrence(key : String?) : Float { |
| | | return PreferencesUtils.getFloat(this , key , 0f , PreferencesUtils.USER) |
| | | fun getLongProjectPrefrence(key : String) : Long { |
| | | return getLongProjectPrefrence(key,0); |
| | | } |
| | | |
| | | fun getStringSetUserPrefrence(key : String?) : Set<*> { |
| | | return PreferencesUtils.getStringSet(this , key , PreferencesUtils.USER) |
| | | fun getLongProjectPrefrence(key : String,value : Long) : Long { |
| | | return PreferencesUtils.getLong(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getFloatProjectPrefrence(key : String) : Float { |
| | | return getFloatProjectPrefrence(key,0f); |
| | | } |
| | | |
| | | fun putBooleanUserPrefrence(key : String? , value : Boolean) { |
| | | fun getFloatProjectPrefrence(key : String,value : Float) : Float { |
| | | return PreferencesUtils.getFloat(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getStringSetProjectPrefrence(key : String) : Set<*> { |
| | | return getStringSetProjectPrefrence(key, ArraySet<Any?>() ) |
| | | } |
| | | |
| | | fun getStringSetProjectPrefrence(key : String,value : Set<*>?) : Set<*> { |
| | | return PreferencesUtils.getStringSet(this , key ,value, PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun getIntUserPrefrence(key : String) : Int { |
| | | return getIntUserPrefrence(key,0) |
| | | } |
| | | |
| | | fun getIntUserPrefrence(key : String,value : Int) : Int { |
| | | return PreferencesUtils.getInt(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun getLongUserPrefrence(key : String) : Long { |
| | | return getLongUserPrefrence(key,0) |
| | | } |
| | | |
| | | fun getLongUserPrefrence(key : String,value : Long) : Long { |
| | | return PreferencesUtils.getLong(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun getFloatUserPrefrence(key : String) : Float { |
| | | return getFloatUserPrefrence(key,0f) |
| | | } |
| | | |
| | | fun getFloatUserPrefrence(key : String,value : Float) : Float { |
| | | return PreferencesUtils.getFloat(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun getStringSetUserPrefrence(key : String) : Set<*> { |
| | | return getStringSetUserPrefrence(key,ArraySet<Any?>()) |
| | | } |
| | | |
| | | fun getStringSetUserPrefrence(key : String,value : Set<*>) : Set<*> { |
| | | return PreferencesUtils.getStringSet(this , key ,value, PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putBooleanUserPrefrence(key : String , value : Boolean) { |
| | | PreferencesUtils.putBoolean(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putBooleanProjectPrefrence(key : String? , value : Boolean) { |
| | | fun putBooleanProjectPrefrence(key : String , value : Boolean) { |
| | | PreferencesUtils.putBoolean(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putStringUserPrefrence(key : String? , value : String?) { |
| | | fun putStringUserPrefrence(key : String , value : String?) { |
| | | PreferencesUtils.putString(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putStringProjectPrefrence(key : String? , value : String?) { |
| | | fun putStringProjectPrefrence(key : String , value : String?) { |
| | | PreferencesUtils.putString(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putIntProjectPrefrence(key : String? , value : Int) { |
| | | fun putIntProjectPrefrence(key : String , value : Int) { |
| | | PreferencesUtils.putInt(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putLongProjectPrefrence(key : String? , value : Long) { |
| | | fun putLongProjectPrefrence(key : String , value : Long) { |
| | | PreferencesUtils.putLong(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putFloatProjectPrefrence(key : String? , value : Float) { |
| | | fun putFloatProjectPrefrence(key : String , value : Float) { |
| | | PreferencesUtils.putFloat(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putStringSetProjectPrefrence(key : String? , value : Set<*>?) { |
| | | fun putStringSetProjectPrefrence(key : String , value : Set<*>?) { |
| | | PreferencesUtils.putStringSet(this , key , value , PreferencesUtils.PROJECT) |
| | | } |
| | | |
| | | fun putIntUserPrefrence(key : String? , value : Int) { |
| | | fun putIntUserPrefrence(key : String , value : Int) { |
| | | PreferencesUtils.putInt(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putLongUserPrefrence(key : String? , value : Long) { |
| | | fun putLongUserPrefrence(key : String , value : Long) { |
| | | PreferencesUtils.putLong(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putFloatUserPrefrence(key : String? , value : Float) { |
| | | fun putFloatUserPrefrence(key : String , value : Float) { |
| | | PreferencesUtils.putFloat(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun putStringSetUserPrefrence(key : String? , value : Set<*>?) { |
| | | fun putStringSetUserPrefrence(key : String , value : Set<*>?) { |
| | | PreferencesUtils.putStringSet(this , key , value , PreferencesUtils.USER) |
| | | } |
| | | |
| | | |
| | | fun removeUserKey(key : String?) { |
| | | fun removeUserKey(key : String) { |
| | | PreferencesUtils.removeKey(this , key , PreferencesUtils.USER) |
| | | } |
| | | |
| | | fun removeProjectKey(key : String?) { |
| | | fun removeProjectKey(key : String) { |
| | | PreferencesUtils.removeKey(this , key , PreferencesUtils.PROJECT) |
| | | } |
| | | |