Since app min target SDK is 23, remove all references to older versions
This commit is contained in:
parent
0611109c04
commit
4218c5b2a9
12 changed files with 267 additions and 329 deletions
|
@ -20,7 +20,6 @@
|
|||
|
||||
package org.linphone.activities.assistant.fragments
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
@ -29,7 +28,6 @@ import org.linphone.activities.GenericFragment
|
|||
import org.linphone.activities.assistant.viewmodels.AbstractPhoneViewModel
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.mediastream.Version
|
||||
import org.linphone.utils.PermissionHelper
|
||||
import org.linphone.utils.PhoneNumberUtils
|
||||
|
||||
|
@ -55,7 +53,6 @@ abstract class AbstractPhoneFragment<T : ViewDataBinding> : GenericFragment<T>()
|
|||
}
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
protected fun checkPermissions() {
|
||||
if (!resources.getBoolean(R.bool.isTablet)) {
|
||||
if (!PermissionHelper.get().hasReadPhoneStateOrPhoneNumbersPermission()) {
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.linphone.activities.main.viewmodels.DialogViewModel
|
|||
import org.linphone.activities.navigateToEchoCancellerCalibration
|
||||
import org.linphone.activities.navigateToPhoneAccountValidation
|
||||
import org.linphone.databinding.AssistantAccountLoginFragmentBinding
|
||||
import org.linphone.mediastream.Version
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
class AccountLoginFragment : AbstractPhoneFragment<AssistantAccountLoginFragmentBinding>() {
|
||||
|
@ -136,8 +135,6 @@ class AccountLoginFragment : AbstractPhoneFragment<AssistantAccountLoginFragment
|
|||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.linphone.activities.assistant.viewmodels.PhoneAccountCreationViewMode
|
|||
import org.linphone.activities.assistant.viewmodels.SharedAssistantViewModel
|
||||
import org.linphone.activities.navigateToPhoneAccountValidation
|
||||
import org.linphone.databinding.AssistantPhoneAccountCreationFragmentBinding
|
||||
import org.linphone.mediastream.Version
|
||||
|
||||
class PhoneAccountCreationFragment :
|
||||
AbstractPhoneFragment<AssistantPhoneAccountCreationFragmentBinding>() {
|
||||
|
@ -80,8 +79,6 @@ class PhoneAccountCreationFragment :
|
|||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.linphone.activities.navigateToEchoCancellerCalibration
|
|||
import org.linphone.activities.navigateToPhoneAccountValidation
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.AssistantPhoneAccountLinkingFragmentBinding
|
||||
import org.linphone.mediastream.Version
|
||||
|
||||
class PhoneAccountLinkingFragment : AbstractPhoneFragment<AssistantPhoneAccountLinkingFragmentBinding>() {
|
||||
private lateinit var sharedViewModel: SharedAssistantViewModel
|
||||
|
@ -103,8 +102,6 @@ class PhoneAccountLinkingFragment : AbstractPhoneFragment<AssistantPhoneAccountL
|
|||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.linphone.activities.main.conference.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
|
@ -119,9 +118,7 @@ class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragm
|
|||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -137,7 +134,6 @@ class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragm
|
|||
super.onPause()
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
private fun checkPermissions() {
|
||||
val permissionsRequiredList = arrayListOf<String>()
|
||||
|
||||
|
|
|
@ -192,9 +192,7 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
|||
|
||||
checkForUpdate()
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
@ -244,7 +242,6 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
private fun checkPermissions() {
|
||||
checkReadPhoneStatePermission()
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80) && PermissionHelper.get().hasReadPhoneStatePermission()) {
|
||||
|
@ -253,7 +250,6 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
private fun checkReadPhoneStatePermission() {
|
||||
if (!PermissionHelper.get().hasReadPhoneStatePermission()) {
|
||||
Log.i("[Dialer] Asking for READ_PHONE_STATE permission")
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.linphone.activities.main.viewmodels.LogsUploadViewModel
|
|||
import org.linphone.core.CoreContext
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.LogLevel
|
||||
import org.linphone.mediastream.Version
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class AdvancedSettingsViewModel : LogsUploadViewModel() {
|
||||
|
@ -183,6 +182,6 @@ class AdvancedSettingsViewModel : LogsUploadViewModel() {
|
|||
vfs.value = prefs.vfsEnabled
|
||||
disableSecureFragment.value = prefs.disableSecureMode
|
||||
|
||||
batterySettingsVisibility.value = Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)
|
||||
batterySettingsVisibility.value = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,9 +114,7 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
|
|||
|
||||
val systemWideOverlayListener = object : SettingListenerStub() {
|
||||
override fun onBoolValueChanged(newValue: Boolean) {
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
if (newValue) systemWideOverlayEnabledEvent.value = Event(true)
|
||||
}
|
||||
if (newValue) systemWideOverlayEnabledEvent.value = Event(true)
|
||||
prefs.systemWideCallOverlay = newValue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.linphone.activities.voip
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
|
@ -178,9 +177,7 @@ class CallActivity : ProximitySensorActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
|
@ -252,7 +249,6 @@ class CallActivity : ProximitySensorActivity() {
|
|||
super.onDestroy()
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
private fun checkPermissions() {
|
||||
val permissionsRequiredList = arrayListOf<String>()
|
||||
|
||||
|
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.compatibility
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.*
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Vibrator
|
||||
import android.provider.MediaStore
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import org.linphone.R
|
||||
import org.linphone.core.Content
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.FileUtils
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@TargetApi(21)
|
||||
class Api21Compatibility {
|
||||
companion object {
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getDeviceName(context: Context): String {
|
||||
val adapter = BluetoothAdapter.getDefaultAdapter()
|
||||
var name = adapter?.name
|
||||
if (name == null) {
|
||||
name = Settings.Secure.getString(
|
||||
context.contentResolver,
|
||||
"bluetooth_name"
|
||||
)
|
||||
}
|
||||
if (name == null) {
|
||||
name = Build.MANUFACTURER + " " + Build.MODEL
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun eventVibration(vibrator: Vibrator) {
|
||||
val pattern = longArrayOf(0, 100, 100)
|
||||
vibrator.vibrate(pattern, -1)
|
||||
}
|
||||
|
||||
fun getBitmapFromUri(context: Context, uri: Uri): Bitmap {
|
||||
return MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
|
||||
}
|
||||
|
||||
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Images.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Images.Media.getContentUri("external")
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Video.Media.TITLE, fileName)
|
||||
put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Video.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Video.Media.getContentUri("external")
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Audio.Media.TITLE, fileName)
|
||||
put(MediaStore.Audio.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Audio.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Audio.Media.getContentUri("external")
|
||||
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private suspend fun addContentValuesToCollection(
|
||||
context: Context,
|
||||
filePath: String,
|
||||
collection: Uri,
|
||||
values: ContentValues
|
||||
): String {
|
||||
try {
|
||||
val fileUri = context.contentResolver.insert(collection, values)
|
||||
if (fileUri == null) {
|
||||
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
|
||||
return ""
|
||||
}
|
||||
|
||||
context.contentResolver.openOutputStream(fileUri).use { out ->
|
||||
if (FileUtils.copyFileTo(filePath, out)) {
|
||||
return fileUri.toString()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("[Media Store] Exception: $e")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
fun setShowWhenLocked(activity: Activity, enable: Boolean) {
|
||||
if (enable) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||
} else {
|
||||
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||
}
|
||||
}
|
||||
|
||||
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
|
||||
if (enable) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||
} else {
|
||||
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestDismissKeyguard(activity: Activity) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
|
||||
}
|
||||
|
||||
fun getUpdateCurrentPendingIntentFlag(): Int {
|
||||
return PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
|
||||
fun getImeFlagsForSecureChatRoom(): Int {
|
||||
return EditorInfo.IME_FLAG_NO_EXTRACT_UI
|
||||
}
|
||||
|
||||
fun startForegroundService(context: Context, intent: Intent) {
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
fun startForegroundService(service: Service, notifId: Int, notif: Notification?) {
|
||||
service.startForeground(notifId, notif)
|
||||
}
|
||||
|
||||
fun hideAndroidSystemUI(hide: Boolean, window: Window) {
|
||||
val decorView = window.decorView
|
||||
val uiOptions = if (hide) {
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
} else {
|
||||
View.SYSTEM_UI_FLAG_VISIBLE
|
||||
}
|
||||
decorView.systemUiVisibility = uiOptions
|
||||
|
||||
if (hide) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,13 +20,36 @@
|
|||
package org.linphone.compatibility
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Vibrator
|
||||
import android.provider.MediaStore
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.linphone.R
|
||||
import org.linphone.core.Content
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.FileUtils
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
@TargetApi(23)
|
||||
class Api23Compatibility {
|
||||
companion object {
|
||||
fun hasPermission(context: Context, permission: String): Boolean {
|
||||
|
@ -40,5 +63,224 @@ class Api23Compatibility {
|
|||
fun canDrawOverlay(context: Context): Boolean {
|
||||
return Settings.canDrawOverlays(context)
|
||||
}
|
||||
|
||||
fun getBitmapFromUri(context: Context, uri: Uri): Bitmap {
|
||||
return MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun eventVibration(vibrator: Vibrator) {
|
||||
val pattern = longArrayOf(0, 100, 100)
|
||||
vibrator.vibrate(pattern, -1)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getDeviceName(context: Context): String {
|
||||
val adapter = BluetoothAdapter.getDefaultAdapter()
|
||||
var name = adapter?.name
|
||||
if (name == null) {
|
||||
name = Settings.Secure.getString(
|
||||
context.contentResolver,
|
||||
"bluetooth_name"
|
||||
)
|
||||
}
|
||||
if (name == null) {
|
||||
name = Build.MANUFACTURER + " " + Build.MODEL
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
fun setShowWhenLocked(activity: Activity, enable: Boolean) {
|
||||
if (enable) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||
} else {
|
||||
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
|
||||
}
|
||||
}
|
||||
|
||||
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
|
||||
if (enable) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||
} else {
|
||||
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
|
||||
fun requestDismissKeyguard(activity: Activity) {
|
||||
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
|
||||
}
|
||||
|
||||
fun startForegroundService(context: Context, intent: Intent) {
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
fun startForegroundService(service: Service, notifId: Int, notif: Notification?) {
|
||||
service.startForeground(notifId, notif)
|
||||
}
|
||||
|
||||
fun hideAndroidSystemUI(hide: Boolean, window: Window) {
|
||||
val decorView = window.decorView
|
||||
val uiOptions = if (hide) {
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
} else {
|
||||
View.SYSTEM_UI_FLAG_VISIBLE
|
||||
}
|
||||
decorView.systemUiVisibility = uiOptions
|
||||
|
||||
if (hide) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
} else {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
}
|
||||
}
|
||||
|
||||
fun getUpdateCurrentPendingIntentFlag(): Int {
|
||||
return PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
|
||||
fun getImeFlagsForSecureChatRoom(): Int {
|
||||
return EditorInfo.IME_FLAG_NO_EXTRACT_UI
|
||||
}
|
||||
|
||||
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Images.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Images.Media.getContentUri("external")
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Video.Media.TITLE, fileName)
|
||||
put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Video.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Video.Media.getContentUri("external")
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
||||
val plainFilePath = content.plainFilePath.orEmpty()
|
||||
val isVfsEncrypted = plainFilePath.isNotEmpty()
|
||||
Log.w("[Media Store] Content is encrypted, requesting plain file path")
|
||||
val filePath = if (isVfsEncrypted) plainFilePath else content.filePath
|
||||
if (filePath == null) {
|
||||
Log.e("[Media Store] Content doesn't have a file path!")
|
||||
return false
|
||||
}
|
||||
|
||||
val appName = AppUtils.getString(R.string.app_name)
|
||||
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
|
||||
val fileName = content.name
|
||||
val mime = "${content.type}/${content.subtype}"
|
||||
Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(MediaStore.Audio.Media.TITLE, fileName)
|
||||
put(MediaStore.Audio.Media.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.Audio.Media.MIME_TYPE, mime)
|
||||
}
|
||||
val collection = MediaStore.Audio.Media.getContentUri("external")
|
||||
|
||||
val mediaStoreFilePath = addContentValuesToCollection(context, filePath, collection, values)
|
||||
if (isVfsEncrypted) {
|
||||
Log.w("[Media Store] Content was encrypted, delete plain version: $plainFilePath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
}
|
||||
if (mediaStoreFilePath.isNotEmpty()) {
|
||||
content.userData = mediaStoreFilePath
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private suspend fun addContentValuesToCollection(
|
||||
context: Context,
|
||||
filePath: String,
|
||||
collection: Uri,
|
||||
values: ContentValues
|
||||
): String {
|
||||
try {
|
||||
val fileUri = context.contentResolver.insert(collection, values)
|
||||
if (fileUri == null) {
|
||||
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
|
||||
return ""
|
||||
}
|
||||
|
||||
context.contentResolver.openOutputStream(fileUri).use { out ->
|
||||
if (FileUtils.copyFileTo(filePath, out)) {
|
||||
return fileUri.toString()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("[Media Store] Exception: $e")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import android.app.PendingIntent
|
|||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
|
@ -51,10 +50,7 @@ class Compatibility {
|
|||
const val BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT"
|
||||
|
||||
fun hasPermission(context: Context, permission: String): Boolean {
|
||||
return when (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
true -> Api23Compatibility.hasPermission(context, permission)
|
||||
else -> context.packageManager.checkPermission(permission, context.packageName) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
return Api23Compatibility.hasPermission(context, permission)
|
||||
}
|
||||
|
||||
// See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers
|
||||
|
@ -102,7 +98,7 @@ class Compatibility {
|
|||
fun getDeviceName(context: Context): String {
|
||||
return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) {
|
||||
true -> Api25Compatibility.getDeviceName(context)
|
||||
else -> Api21Compatibility.getDeviceName(context)
|
||||
else -> Api23Compatibility.getDeviceName(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +114,7 @@ class Compatibility {
|
|||
|
||||
fun setShowWhenLocked(activity: Activity, enable: Boolean) {
|
||||
if (Version.sdkStrictlyBelow(Version.API27_OREO_81)) {
|
||||
Api21Compatibility.setShowWhenLocked(activity, enable)
|
||||
Api23Compatibility.setShowWhenLocked(activity, enable)
|
||||
} else {
|
||||
Api27Compatibility.setShowWhenLocked(activity, enable)
|
||||
}
|
||||
|
@ -126,7 +122,7 @@ class Compatibility {
|
|||
|
||||
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
|
||||
if (Version.sdkStrictlyBelow(Version.API27_OREO_81)) {
|
||||
Api21Compatibility.setTurnScreenOn(activity, enable)
|
||||
Api23Compatibility.setTurnScreenOn(activity, enable)
|
||||
} else {
|
||||
Api27Compatibility.setTurnScreenOn(activity, enable)
|
||||
}
|
||||
|
@ -134,7 +130,7 @@ class Compatibility {
|
|||
|
||||
fun requestDismissKeyguard(activity: Activity) {
|
||||
if (Version.sdkStrictlyBelow(Version.API27_OREO_81)) {
|
||||
Api21Compatibility.requestDismissKeyguard(activity)
|
||||
Api23Compatibility.requestDismissKeyguard(activity)
|
||||
} else {
|
||||
Api27Compatibility.requestDismissKeyguard(activity)
|
||||
}
|
||||
|
@ -142,7 +138,7 @@ class Compatibility {
|
|||
|
||||
fun getBitmapFromUri(context: Context, uri: Uri): Bitmap {
|
||||
return if (Version.sdkStrictlyBelow(Version.API29_ANDROID_10)) {
|
||||
Api21Compatibility.getBitmapFromUri(context, uri)
|
||||
Api23Compatibility.getBitmapFromUri(context, uri)
|
||||
} else {
|
||||
Api29Compatibility.getBitmapFromUri(context, uri)
|
||||
}
|
||||
|
@ -224,7 +220,7 @@ class Compatibility {
|
|||
} else if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
Api26Compatibility.startForegroundService(context, intent)
|
||||
} else {
|
||||
Api21Compatibility.startForegroundService(context, intent)
|
||||
Api23Compatibility.startForegroundService(context, intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,17 +228,14 @@ class Compatibility {
|
|||
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) {
|
||||
Api31Compatibility.startForegroundService(service, notifId, notif)
|
||||
} else {
|
||||
Api21Compatibility.startForegroundService(service, notifId, notif)
|
||||
Api23Compatibility.startForegroundService(service, notifId, notif)
|
||||
}
|
||||
}
|
||||
|
||||
/* Call */
|
||||
|
||||
fun canDrawOverlay(context: Context): Boolean {
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
return Api23Compatibility.canDrawOverlay(context)
|
||||
}
|
||||
return false
|
||||
return Api23Compatibility.canDrawOverlay(context)
|
||||
}
|
||||
|
||||
fun enterPipMode(activity: Activity) {
|
||||
|
@ -261,7 +254,7 @@ class Compatibility {
|
|||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
Api26Compatibility.eventVibration(vibrator)
|
||||
} else {
|
||||
Api21Compatibility.eventVibration(vibrator)
|
||||
Api23Compatibility.eventVibration(vibrator)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +269,7 @@ class Compatibility {
|
|||
if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
|
||||
Api30Compatibility.hideAndroidSystemUI(hide, window)
|
||||
} else {
|
||||
Api21Compatibility.hideAndroidSystemUI(hide, window)
|
||||
Api23Compatibility.hideAndroidSystemUI(hide, window)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,35 +325,35 @@ class Compatibility {
|
|||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) {
|
||||
return Api29Compatibility.addImageToMediaStore(context, content)
|
||||
}
|
||||
return Api21Compatibility.addImageToMediaStore(context, content)
|
||||
return Api23Compatibility.addImageToMediaStore(context, content)
|
||||
}
|
||||
|
||||
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) {
|
||||
return Api29Compatibility.addVideoToMediaStore(context, content)
|
||||
}
|
||||
return Api21Compatibility.addVideoToMediaStore(context, content)
|
||||
return Api23Compatibility.addVideoToMediaStore(context, content)
|
||||
}
|
||||
|
||||
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) {
|
||||
return Api29Compatibility.addAudioToMediaStore(context, content)
|
||||
}
|
||||
return Api21Compatibility.addAudioToMediaStore(context, content)
|
||||
return Api23Compatibility.addAudioToMediaStore(context, content)
|
||||
}
|
||||
|
||||
fun getUpdateCurrentPendingIntentFlag(): Int {
|
||||
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) {
|
||||
return Api31Compatibility.getUpdateCurrentPendingIntentFlag()
|
||||
}
|
||||
return Api21Compatibility.getUpdateCurrentPendingIntentFlag()
|
||||
return Api23Compatibility.getUpdateCurrentPendingIntentFlag()
|
||||
}
|
||||
|
||||
fun getImeFlagsForSecureChatRoom(): Int {
|
||||
if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
|
||||
return Api26Compatibility.getImeFlagsForSecureChatRoom()
|
||||
}
|
||||
return Api21Compatibility.getImeFlagsForSecureChatRoom()
|
||||
return Api23Compatibility.getImeFlagsForSecureChatRoom()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue