Since app min target SDK is 23, remove all references to older versions

This commit is contained in:
Sylvain Berfini 2022-05-16 12:00:47 +02:00
parent 0611109c04
commit 4218c5b2a9
12 changed files with 267 additions and 329 deletions

View file

@ -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()) {

View file

@ -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()
}
}

View file

@ -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()
}
}

View file

@ -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()
}
}

View file

@ -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>()

View file

@ -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")

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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>()

View file

@ -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)
}
}
}
}

View file

@ -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 ""
}
}
}

View file

@ -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()
}
}
}