Merge pull request #1176 from vector-im/feature/target-sdk-29

Increase targetSdk to 29
This commit is contained in:
Benoit Marty 2020-04-15 14:32:16 +02:00 committed by GitHub
commit c57fa3f0d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 116 additions and 142 deletions

View file

@ -23,10 +23,10 @@ android:
- platform-tools
# The BuildTools version used by your project
- build-tools-28.0.3
- build-tools-29.0.3
# The SDK version used to compile your project
- android-28
- android-29
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock

View file

@ -9,6 +9,7 @@ Features ✨:
Improvements 🙌:
- Verification DM / Handle concurrent .start after .ready (#794)
- Reimplementation of multiple attachment picker
- Cross-Signing | Update Shield Logic for DM (#963)
- Cross-Signing | Complete security new session design update (#1135)
- Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201)
@ -30,10 +31,10 @@ Translations 🗣:
-
SDK API changes ⚠️:
-
- Increase targetSdkVersion to 29
Build 🧱:
-
- Compile with Android SDK 29 (Android Q)
Other changes:
- Increase File Logger capacities ( + use dev log preferences)

View file

@ -3,11 +3,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"

View file

@ -19,12 +19,12 @@ androidExtensions {
}
android {
compileSdkVersion 28
compileSdkVersion 29
testOptions.unitTests.includeAndroidResources = true
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "0.0.1"
// Multidex is useful for tests

View file

@ -29,3 +29,7 @@ annotation class SessionCacheDirectory
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class CacheDirectory
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ExternalFilesDirectory

View file

@ -56,6 +56,9 @@ internal interface MatrixComponent {
@CacheDirectory
fun cacheDir(): File
@ExternalFilesDirectory
fun externalFilesDir(): File?
fun olmManager(): OlmManager
fun taskExecutor(): TaskExecutor

View file

@ -57,6 +57,13 @@ internal object MatrixModule {
return context.cacheDir
}
@JvmStatic
@Provides
@ExternalFilesDirectory
fun providesExternalFilesDir(context: Context): File? {
return context.getExternalFilesDir(null)
}
@JvmStatic
@Provides
@MatrixScope

View file

@ -14,6 +14,9 @@
* limitations under the License.
*/
// This BroadcastReceiver is used only if the build code is below 24.
@file:Suppress("DEPRECATION")
package im.vector.matrix.android.internal.network
import android.content.BroadcastReceiver

View file

@ -16,7 +16,6 @@
package im.vector.matrix.android.internal.session
import android.os.Environment
import arrow.core.Try
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.content.ContentUrlResolver
@ -25,6 +24,7 @@ import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
import im.vector.matrix.android.internal.di.CacheDirectory
import im.vector.matrix.android.internal.di.ExternalFilesDirectory
import im.vector.matrix.android.internal.di.SessionCacheDirectory
import im.vector.matrix.android.internal.di.Unauthenticated
import im.vector.matrix.android.internal.extensions.foldToCallback
@ -44,6 +44,8 @@ import javax.inject.Inject
internal class DefaultFileService @Inject constructor(
@CacheDirectory
private val cacheDirectory: File,
@ExternalFilesDirectory
private val externalFilesDirectory: File?,
@SessionCacheDirectory
private val sessionCacheDirectory: File,
private val contentUrlResolver: ContentUrlResolver,
@ -103,7 +105,7 @@ internal class DefaultFileService @Inject constructor(
private fun copyFile(file: File, downloadMode: FileService.DownloadMode): File {
return when (downloadMode) {
FileService.DownloadMode.TO_EXPORT ->
file.copyTo(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), file.name), true)
file.copyTo(File(externalFilesDirectory, file.name), true)
FileService.DownloadMode.FOR_EXTERNAL_SHARE ->
file.copyTo(File(File(cacheDirectory, "ext_share"), file.name), true)
FileService.DownloadMode.FOR_INTERNAL_USE ->

View file

@ -23,11 +23,9 @@ internal class Debouncer(private val handler: Handler) {
private val runnables = HashMap<String, Runnable>()
fun debounce(identifier: String, r: Runnable, millis: Long): Boolean {
if (runnables.containsKey(identifier)) {
// debounce
val old = runnables[identifier]
handler.removeCallbacks(old)
}
// debounce
runnables[identifier]?.let { runnable -> handler.removeCallbacks(runnable) }
insertRunnable(identifier, r, millis)
return true
}

View file

@ -17,7 +17,7 @@ PARAM_KEYSTORE_PATH=$1
PARAM_APK=$2
# Other params
BUILD_TOOLS_VERSION="28.0.3"
BUILD_TOOLS_VERSION="29.0.3"
MIN_SDK_VERSION=19
echo "Signing APK with build-tools version ${BUILD_TOOLS_VERSION} for min SDK version ${MIN_SDK_VERSION}..."

View file

@ -104,13 +104,13 @@ ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].
def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
applicationId "im.vector.riotx"
// Set to API 19 because motionLayout is min API 18.
// In the future we may consider using an alternative of MotionLayout to support API 16. But for security reason, maybe not.
minSdkVersion 19
targetSdkVersion 28
targetSdkVersion 29
multiDexEnabled true
// `develop` branch will have version code from timestamp, to ensure each build from CI has a incremented versionCode.

View file

@ -21,7 +21,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import androidx.core.content.edit
import im.vector.riotx.core.utils.lsFiles
import timber.log.Timber

View file

@ -19,7 +19,7 @@ package im.vector.riotx.push.fcm
import android.app.Activity
import android.content.Context
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.widget.Toast
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability

View file

@ -171,7 +171,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
MultiDex.install(this)
}
override fun onConfigurationChanged(newConfig: Configuration?) {
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
vectorConfiguration.onConfigurationChanged()
}

View file

@ -17,7 +17,10 @@
package im.vector.riotx.core.files
import android.app.DownloadManager
import android.content.ContentValues
import android.content.Context
import android.os.Build
import android.provider.MediaStore
import androidx.annotation.WorkerThread
import arrow.core.Try
import okio.buffer
@ -54,10 +57,24 @@ fun addEntryToDownloadManager(context: Context,
mimeType: String,
title: String = file.name,
description: String = file.name) {
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager?
try {
downloadManager?.addCompletedDownload(title, description, true, mimeType, file.absolutePath, file.length(), true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.TITLE, title)
put(MediaStore.Downloads.DISPLAY_NAME, description)
put(MediaStore.Downloads.MIME_TYPE, mimeType)
put(MediaStore.Downloads.SIZE, file.length())
}
context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)?.let { uri ->
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
outputStream.sink().buffer().write(file.inputStream().use { it.readBytes() })
}
}
} else {
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager?
@Suppress("DEPRECATION")
downloadManager?.addCompletedDownload(title, description, true, mimeType, file.absolutePath, file.length(), true)
}
} catch (e: Exception) {
Timber.e(e, "## addEntryToDownloadManager(): Exception")
}

View file

@ -95,7 +95,7 @@ class VectorGlideDataFetcher(private val activeSessionHolder: ActiveSessionHolde
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
Timber.v("Load data: $data")
if (data.isLocalFile()) {
if (data.isLocalFile() && data.url != null) {
val initialFile = File(data.url)
callback.onDataReady(FileInputStream(initialFile))
return

View file

@ -1,72 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotx.core.images
import android.content.Context
import android.net.Uri
import android.provider.MediaStore
import androidx.exifinterface.media.ExifInterface
import timber.log.Timber
import javax.inject.Inject
class ImageTools @Inject constructor(private val context: Context) {
/**
* Gets the [ExifInterface] value for the orientation for this local bitmap Uri.
*
* @param uri The URI to find the orientation for. Must be local.
* @return The orientation value, which may be [ExifInterface.ORIENTATION_UNDEFINED].
*/
fun getOrientationForBitmap(uri: Uri): Int {
var orientation = ExifInterface.ORIENTATION_UNDEFINED
if (uri.scheme == "content") {
val proj = arrayOf(MediaStore.Images.Media.DATA)
try {
val cursor = context.contentResolver.query(uri, proj, null, null, null)
cursor?.use {
if (it.moveToFirst()) {
val idxData = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
val path = it.getString(idxData)
if (path.isNullOrBlank()) {
Timber.w("Cannot find path in media db for uri $uri")
return orientation
}
val exif = ExifInterface(path)
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
}
}
} catch (e: Exception) {
// eg SecurityException from com.google.android.apps.photos.content.GooglePhotosImageProvider URIs
// eg IOException from trying to parse the returned path as a file when it is an http uri.
Timber.e(e, "Cannot get orientation for bitmap")
}
} else if (uri.scheme == "file") {
try {
val path = uri.path
if (path != null) {
val exif = ExifInterface(path)
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
}
} catch (e: Exception) {
Timber.e(e, "Cannot get EXIF for file uri $uri")
}
}
return orientation
}
}

View file

@ -333,7 +333,7 @@ class EllipsizingTextView @JvmOverloads constructor(context: Context, attrs: Att
* @param workingText text to strip end punctuation from
* @return Text without end punctuation.
*/
fun stripEndPunctuation(workingText: CharSequence?): String {
fun stripEndPunctuation(workingText: CharSequence): String {
return mEndPunctPattern!!.matcher(workingText).replaceFirst("")
}
}

View file

@ -134,7 +134,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
restorables.forEach { it.onSaveInstanceState(outState) }
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
restorables.forEach { it.onRestoreInstanceState(savedInstanceState) }
super.onRestoreInstanceState(savedInstanceState)
}

View file

@ -128,13 +128,13 @@ class CallService : VectorService() {
* Display a call in progress notification.
*/
private fun displayCallInProgressNotification(intent: Intent) {
val callId = intent.getStringExtra(EXTRA_CALL_ID)
val callId = intent.getStringExtra(EXTRA_CALL_ID) ?: ""
val notification = notificationUtils.buildPendingCallNotification(
intent.getBooleanExtra(EXTRA_IS_VIDEO, false),
intent.getStringExtra(EXTRA_ROOM_NAME),
intent.getStringExtra(EXTRA_ROOM_ID),
intent.getStringExtra(EXTRA_MATRIX_ID),
intent.getStringExtra(EXTRA_ROOM_NAME) ?: "",
intent.getStringExtra(EXTRA_ROOM_ID) ?: "",
intent.getStringExtra(EXTRA_MATRIX_ID) ?: "",
callId)
startForeground(NOTIFICATION_ID, notification)

View file

@ -17,7 +17,7 @@
package im.vector.riotx.core.ui.views
import android.content.Context
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup

View file

@ -37,9 +37,10 @@ class Debouncer(private val handler: Handler) {
fun cancel(identifier: String) {
if (runnables.containsKey(identifier)) {
val old = runnables[identifier]
handler.removeCallbacks(old)
runnables.remove(identifier)
runnables[identifier]?.let {
handler.removeCallbacks(it)
runnables.remove(identifier)
}
}
}

View file

@ -73,7 +73,7 @@ private fun logAction(file: File): Boolean {
*/
private fun recursiveActionOnFile(file: File, action: ActionOnFile): Boolean {
if (file.isDirectory) {
file.list().forEach {
file.list()?.forEach {
val result = recursiveActionOnFile(File(file, it), action)
if (!result) {

View file

@ -20,7 +20,7 @@ import android.content.Context
import android.media.Ringtone
import android.media.RingtoneManager
import android.net.Uri
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import androidx.core.content.edit
import im.vector.riotx.features.settings.VectorPreferences

View file

@ -84,7 +84,7 @@ fun requestDisablingBatteryOptimization(activity: Activity, fragment: Fragment?,
*/
fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = true, @StringRes toastMessage: Int = R.string.copied_to_clipboard) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText("", text)
clipboard.setPrimaryClip(ClipData.newPlainText("", text))
if (showToast) {
context.toast(toastMessage)
}

View file

@ -35,8 +35,8 @@ object TextUtils {
if (value < 1000) return value.toString() // deal with easy case
val e = suffixes.floorEntry(value)
val divideBy = e.key
val suffix = e.value
val divideBy = e?.key
val suffix = e?.value
val truncated = value / (divideBy!! / 10) // the number part of the output times 10
val hasDecimal = truncated < 100 && truncated / 10.0 != (truncated / 10).toDouble()

View file

@ -43,7 +43,7 @@ class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
}
fun getOutput(intent: Intent): List<ContentAttachmentData> {
return intent.getParcelableArrayListExtra(ATTACHMENTS_PREVIEW_RESULT)
return intent.getParcelableArrayListExtra(ATTACHMENTS_PREVIEW_RESULT) ?: emptyList()
}
fun getKeepOriginalSize(intent: Intent): Boolean {

View file

@ -40,7 +40,7 @@ class KeysExporter(private val session: Session) {
runCatching {
val data = awaitCallback<ByteArray> { session.cryptoService().exportRoomKeys(password, it) }
withContext(Dispatchers.IO) {
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val parentDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
val file = File(parentDir, "riotx-keys-" + System.currentTimeMillis() + ".txt")
writeToFile(data, file)

View file

@ -95,7 +95,7 @@ class KeysBackupRestoreFromPassphraseFragment @Inject constructor(): VectorBaseF
// used just to have default link representation
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View?) {}
override fun onClick(widget: View) {}
}
val start = helperText.indexOf(clickableText)
val end = start + clickableText.length

View file

@ -153,7 +153,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
}
override fun onFailure(failure: Throwable) {
toast(failure.localizedMessage)
toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
hideWaitingView()
}
})

View file

@ -167,7 +167,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment()
GlobalScope.launch(Dispatchers.Main) {
Try {
withContext(Dispatchers.IO) {
val parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val parentDir = context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
val file = File(parentDir, "recovery-key-" + System.currentTimeMillis() + ".txt")
writeToFile(data, file)

View file

@ -163,8 +163,8 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: SharedSecureStorageViewState): SharedSecureStorageViewModel? {
val activity: SharedSecureStorageActivity = viewModelContext.activity()
val args: SharedSecureStorageActivity.Args = activity.intent.getParcelableExtra(MvRx.KEY_ARG)
return activity.viewModelFactory.create(state, args)
val args: SharedSecureStorageActivity.Args? = activity.intent.getParcelableExtra(MvRx.KEY_ARG)
return args?.let { activity.viewModelFactory.create(state, it) }
}
}
}

View file

@ -384,7 +384,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
Unit
}
} catch (failure: Throwable) {
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage))
_viewEvents.post(
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
}
}

View file

@ -17,7 +17,7 @@
package im.vector.riotx.features.disclaimer
import android.app.Activity
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AlertDialog

View file

@ -782,7 +782,7 @@ class RoomDetailFragment @Inject constructor(
updateComposerText("")
}
is RoomDetailViewEvents.SlashCommandResultError -> {
displayCommandError(sendMessageResult.throwable.localizedMessage)
displayCommandError(sendMessageResult.throwable.localizedMessage ?: getString(R.string.unexpected_error))
}
is RoomDetailViewEvents.SlashCommandNotImplemented -> {
displayCommandError(getString(R.string.not_implemented))

View file

@ -440,11 +440,11 @@ class MessageItemFactory @Inject constructor(
Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
spannable.setSpan(object : ClickableSpan() {
override fun onClick(widget: View?) {
override fun onClick(widget: View) {
callback?.onEditedDecorationClicked(informationData)
}
override fun updateDrawState(ds: TextPaint?) {
override fun updateDrawState(ds: TextPaint) {
// nop
}
},

View file

@ -56,10 +56,17 @@ class ImageMediaViewerActivity : VectorBaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(im.vector.riotx.R.layout.activity_image_media_viewer)
mediaData = intent.getParcelableExtra(EXTRA_MEDIA_DATA)
if (intent.hasExtra(EXTRA_MEDIA_DATA)) {
mediaData = intent.getParcelableExtra(EXTRA_MEDIA_DATA)!!
} else {
finish()
}
intent.extras?.getString(EXTRA_SHARED_TRANSITION_NAME)?.let {
ViewCompat.setTransitionName(imageTransitionView, it)
}
if (mediaData.url.isNullOrEmpty()) {
supportFinishAfterTransition()
return

View file

@ -37,11 +37,14 @@ class VideoMediaViewerActivity : VectorBaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(im.vector.riotx.R.layout.activity_video_media_viewer)
val mediaData = intent.getParcelableExtra<VideoContentRenderer.Data>(EXTRA_MEDIA_DATA)
configureToolbar(videoMediaViewerToolbar, mediaData)
imageContentRenderer.render(mediaData.thumbnailMediaData, ImageContentRenderer.Mode.FULL_SIZE, videoMediaViewerThumbnailView)
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerLoading, videoMediaViewerVideoView, videoMediaViewerErrorView)
if (intent.hasExtra(EXTRA_MEDIA_DATA)) {
val mediaData = intent.getParcelableExtra<VideoContentRenderer.Data>(EXTRA_MEDIA_DATA)!!
configureToolbar(videoMediaViewerToolbar, mediaData)
imageContentRenderer.render(mediaData.thumbnailMediaData, ImageContentRenderer.Mode.FULL_SIZE, videoMediaViewerThumbnailView)
videoContentRenderer.render(mediaData, videoMediaViewerThumbnailView, videoMediaViewerLoading, videoMediaViewerVideoView, videoMediaViewerErrorView)
}
}
private fun configureToolbar(toolbar: Toolbar, mediaData: VideoContentRenderer.Data) {

View file

@ -97,7 +97,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
val message = getReplyMessage(intent)
val roomId = intent.getStringExtra(KEY_ROOM_ID)
if (message.isNullOrBlank() || roomId.isBlank()) {
if (message.isNullOrBlank() || roomId.isNullOrBlank()) {
// ignore this event
// Can this happen? should we update notification?
return

View file

@ -77,7 +77,7 @@ class VectorFileLogger @Inject constructor(val context: Context, private val vec
sFileHandler?.formatter = LogFormatter()
sLogger.useParentHandlers = false
sLogger.level = Level.ALL
sLogger.addHandler(sFileHandler)
sFileHandler?.let { sLogger.addHandler(it) }
}
} catch (e: Throwable) {
Timber.e(e, "Failed to initialize FileLogger")

View file

@ -70,7 +70,7 @@ class RoomPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
if (isFirstCreation()) {
val args = intent.getParcelableExtra<RoomPreviewData>(ARG)
if (args.worldReadable) {
if (args?.worldReadable == true) {
// TODO Room preview: Note: M does not recommend to use /events anymore, so for now we just display the room preview
// TODO the same way if it was not world readable
addFragment(R.id.simpleFragmentContainer, RoomPreviewNoPreviewFragment::class.java, args)

View file

@ -19,7 +19,7 @@ package im.vector.riotx.features.settings
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import androidx.core.content.edit
import im.vector.riotx.BuildConfig
import im.vector.riotx.R
@ -59,9 +59,9 @@ object VectorLocale {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
if (preferences.contains(APPLICATION_LOCALE_LANGUAGE_KEY)) {
applicationLocale = Locale(preferences.getString(APPLICATION_LOCALE_LANGUAGE_KEY, ""),
preferences.getString(APPLICATION_LOCALE_COUNTRY_KEY, ""),
preferences.getString(APPLICATION_LOCALE_VARIANT_KEY, "")
applicationLocale = Locale(preferences.getString(APPLICATION_LOCALE_LANGUAGE_KEY, "")!!,
preferences.getString(APPLICATION_LOCALE_COUNTRY_KEY, "")!!,
preferences.getString(APPLICATION_LOCALE_VARIANT_KEY, "")!!
)
} else {
applicationLocale = Locale.getDefault()

View file

@ -29,7 +29,6 @@ import im.vector.riotx.R
import im.vector.riotx.features.homeserver.ServerUrlsRepository
import im.vector.riotx.features.themes.ThemeUtils
import timber.log.Timber
import java.io.File
import javax.inject.Inject
class VectorPreferences @Inject constructor(private val context: Context) {
@ -68,7 +67,7 @@ class VectorPreferences @Inject constructor(private val context: Context) {
const val SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY"
const val SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY"
const val SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY"
const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY"
@ -427,11 +426,11 @@ class VectorPreferences @Inject constructor(private val context: Context) {
val toneUri = getNotificationRingTone() ?: return null
try {
val proj = arrayOf(MediaStore.Audio.Media.DATA)
val proj = arrayOf(MediaStore.Audio.Media.DISPLAY_NAME)
return context.contentResolver.query(toneUri, proj, null, null, null)?.use {
val columnIndex = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)
val columnIndex = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)
it.moveToFirst()
File(it.getString(columnIndex)).nameWithoutExtension
it.getString(columnIndex)
}
} catch (e: Exception) {
Timber.e(e, "## getNotificationRingToneName() failed")

View file

@ -332,7 +332,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
}
override fun onFailure(failure: Throwable) {
appContext.toast(failure.localizedMessage)
appContext.toast(failure.localizedMessage ?: getString(R.string.unexpected_error))
hideLoadingView()
}
})