diff --git a/changelog.d/5185.sdk b/changelog.d/5185.sdk new file mode 100644 index 00000000000..9eda2e7c9b8 --- /dev/null +++ b/changelog.d/5185.sdk @@ -0,0 +1 @@ +Deprecates Matrix.initialize and Matrix.getInstance in favour of the client providing its own singleton instance via Matrix.createInstance \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt index 901ba75d169..5fedff53f0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt @@ -99,12 +99,31 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo private lateinit var instance: Matrix private val isInit = AtomicBoolean(false) + /** + * Creates a new instance of Matrix, it's recommended to manage this instance as a singleton. + * To make use of the built in singleton use Matrix.initialize() and/or Matrix.getInstance(context) instead + **/ + fun createInstance(context: Context, matrixConfiguration: MatrixConfiguration): Matrix { + return Matrix(context.applicationContext, matrixConfiguration) + } + + /** + * Initializes a singleton instance of Matrix for the given MatrixConfiguration + * This instance will be returned by Matrix.getInstance(context) + */ + @Deprecated("Use Matrix.createInstance and manage the instance manually") fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) { if (isInit.compareAndSet(false, true)) { instance = Matrix(context.applicationContext, matrixConfiguration) } } + /** + * Either provides an already initialized singleton Matrix instance or queries the application context for a MatrixConfiguration.Provider + * to lazily create and store the instance. + */ + @Suppress("deprecation") // suppressing warning as this method is unused but is still provided for SDK clients + @Deprecated("Use Matrix.createInstance and manage the instance manually") fun getInstance(context: Context): Matrix { if (isInit.compareAndSet(false, true)) { val appContext = context.applicationContext @@ -113,7 +132,8 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo instance = Matrix(appContext, matrixConfiguration) } else { throw IllegalStateException("Matrix is not initialized properly." + - " You should call Matrix.initialize or let your application implements MatrixConfiguration.Provider.") + " If you want to manage your own Matrix instance use Matrix.createInstance" + + " otherwise you should call Matrix.initialize or let your application implement MatrixConfiguration.Provider.") } } return instance diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt index 306ed455003..c87f21d7ac3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt @@ -66,6 +66,7 @@ data class MatrixConfiguration( /** * Can be implemented by your Application class. */ + @Deprecated("Use Matrix.createInstance and manage the instance manually instead of Matrix.getInstance") interface Provider { fun providesMatrixConfiguration(): MatrixConfiguration } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt index 0ecf91f6fae..97ae9b3a689 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt @@ -192,12 +192,14 @@ abstract class SyncService : Service() { } } + abstract fun provideMatrix(): Matrix + private fun initialize(intent: Intent?): Boolean { if (intent == null) { Timber.d("## Sync: initialize intent is null") return false } - val matrix = Matrix.getInstance(applicationContext) + val matrix = provideMatrix() val safeSessionId = intent.getStringExtra(EXTRA_SESSION_ID) ?: return false syncTimeoutSeconds = intent.getIntExtra(EXTRA_TIMEOUT_SECONDS, getDefaultSyncTimeoutSeconds()) syncDelaySeconds = intent.getIntExtra(EXTRA_DELAY_SECONDS, getDefaultSyncDelaySeconds()) diff --git a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt index fb7b9dcb419..69fe63fb7b2 100644 --- a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt +++ b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt @@ -38,7 +38,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.platform.app.InstrumentationRegistry +import im.vector.app.core.utils.getMatrixInstance import im.vector.app.features.MainActivity import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.home.HomeActivity @@ -47,7 +47,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.session.Session @RunWith(AndroidJUnit4::class) @@ -61,8 +60,7 @@ class SecurityBootstrapTest : VerificationTestBase() { @Before fun createSessionWithCrossSigning() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = getMatrixInstance() val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) stubAllExternalIntents() diff --git a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt index 982a421425a..c82b543a08b 100644 --- a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt +++ b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt @@ -33,7 +33,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.platform.app.InstrumentationRegistry +import im.vector.app.core.utils.getMatrixInstance import im.vector.app.features.MainActivity import im.vector.app.features.home.HomeActivity import org.hamcrest.CoreMatchers.not @@ -41,7 +41,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth @@ -66,8 +65,7 @@ class VerifySessionInteractiveTest : VerificationTestBase() { @Before fun createSessionWithCrossSigning() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = getMatrixInstance() val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) doSync { diff --git a/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt b/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt index c51ff296698..80d8315a0ed 100644 --- a/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt +++ b/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt @@ -34,6 +34,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.getMatrixInstance import im.vector.app.features.MainActivity import im.vector.app.features.crypto.quads.SharedSecureStorageActivity import im.vector.app.features.crypto.recover.BootstrapCrossSigningTask @@ -45,7 +46,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth @@ -67,7 +67,7 @@ class VerifySessionPassphraseTest : VerificationTestBase() { @Before fun createSessionWithCrossSigningAnd4S() { val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = getMatrixInstance() val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) doSync { @@ -90,7 +90,7 @@ class VerifySessionPassphraseTest : VerificationTestBase() { runBlocking { task.execute(Params( - userInteractiveAuthInterceptor = object : UserInteractiveAuthInterceptor { + userInteractiveAuthInterceptor = object : UserInteractiveAuthInterceptor { override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation) { promise.resume( UserPasswordAuth( diff --git a/vector/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt b/vector/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt new file mode 100644 index 00000000000..322f5fa23d9 --- /dev/null +++ b/vector/src/androidTest/java/im/vector/app/core/utils/TestMatrixHelper.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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.app.core.utils + +import androidx.test.platform.app.InstrumentationRegistry +import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider +import org.matrix.android.sdk.api.Matrix +import org.matrix.android.sdk.api.MatrixConfiguration + +fun getMatrixInstance(): Matrix { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val configuration = MatrixConfiguration( + roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context) + ) + return Matrix.createInstance(context, configuration) +} diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index e64188765e2..a3f4ffcfcd5 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -55,7 +55,6 @@ import im.vector.app.features.pin.PinLocker import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.rageshake.VectorFileLogger import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler -import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ThemeUtils @@ -63,7 +62,6 @@ import im.vector.app.features.version.VersionProvider import im.vector.app.push.fcm.FcmHelper import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.matrix.android.sdk.api.Matrix -import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.legacy.LegacySessionImporter import timber.log.Timber @@ -77,7 +75,6 @@ import androidx.work.Configuration as WorkConfiguration @HiltAndroidApp class VectorApplication : Application(), - MatrixConfiguration.Provider, WorkConfiguration.Provider { lateinit var appContext: Context @@ -100,6 +97,7 @@ class VectorApplication : @Inject lateinit var autoRageShaker: AutoRageShaker @Inject lateinit var vectorFileLogger: VectorFileLogger @Inject lateinit var vectorAnalytics: VectorAnalytics + @Inject lateinit var matrix: Matrix // font thread handler private var fontThreadHandler: Handler? = null @@ -220,16 +218,9 @@ class VectorApplication : } } - override fun providesMatrixConfiguration(): MatrixConfiguration { - return MatrixConfiguration( - applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, - roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(this) - ) - } - override fun getWorkManagerConfiguration(): WorkConfiguration { return WorkConfiguration.Builder() - .setWorkerFactory(Matrix.getInstance(this.appContext).workerFactory()) + .setWorkerFactory(matrix.workerFactory()) .setExecutor(Executors.newCachedThreadPool()) .build() } diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 0e19cd43881..b4bee417b49 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -26,6 +26,7 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import im.vector.app.BuildConfig import im.vector.app.EmojiCompatWrapper import im.vector.app.EmojiSpanify import im.vector.app.core.dispatchers.CoroutineDispatchers @@ -42,12 +43,14 @@ import im.vector.app.features.navigation.DefaultNavigator import im.vector.app.features.navigation.Navigator import im.vector.app.features.pin.PinCodeStore import im.vector.app.features.pin.SharedPrefPinCodeStore +import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider import im.vector.app.features.ui.SharedPreferencesUiStateRepository import im.vector.app.features.ui.UiStateRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import org.matrix.android.sdk.api.Matrix +import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.HomeServerHistoryService import org.matrix.android.sdk.api.legacy.LegacySessionImporter @@ -107,8 +110,17 @@ object VectorStaticModule { } @Provides - fun providesMatrix(context: Context): Matrix { - return Matrix.getInstance(context) + fun providesMatrixConfiguration(vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider): MatrixConfiguration { + return MatrixConfiguration( + applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, + roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider + ) + } + + @Provides + @Singleton + fun providesMatrix(context: Context, configuration: MatrixConfiguration): Matrix { + return Matrix.createInstance(context, configuration) } @Provides diff --git a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt index a6f6d8d82f3..8621c28d579 100644 --- a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt +++ b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt @@ -35,6 +35,7 @@ import im.vector.app.R import im.vector.app.core.platform.PendingIntentCompat import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.settings.BackgroundSyncMode +import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.internal.session.sync.job.SyncService import timber.log.Timber import javax.inject.Inject @@ -75,6 +76,9 @@ class VectorSyncService : SyncService() { } @Inject lateinit var notificationUtils: NotificationUtils + @Inject lateinit var matrix: Matrix + + override fun provideMatrix() = matrix override fun getDefaultSyncDelaySeconds() = BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 2c554716d23..b6454b89e49 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -73,7 +73,8 @@ class BugReporter @Inject constructor( private val versionProvider: VersionProvider, private val vectorPreferences: VectorPreferences, private val vectorFileLogger: VectorFileLogger, - private val systemLocaleProvider: SystemLocaleProvider + private val systemLocaleProvider: SystemLocaleProvider, + private val matrix: Matrix ) { var inMultiWindowMode = false @@ -265,7 +266,7 @@ class BugReporter @Inject constructor( val builder = BugReporterMultipartBody.Builder() .addFormDataPart("text", text) .addFormDataPart("app", rageShakeAppNameForReport(reportType)) - .addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent()) + .addFormDataPart("user_agent", matrix.getUserAgent()) .addFormDataPart("user_id", userId) .addFormDataPart("can_contact", canContact.toString()) .addFormDataPart("device_id", deviceId) diff --git a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt index 33e63434ce4..0be2a21ef46 100644 --- a/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt +++ b/vector/src/main/java/im/vector/app/features/room/VectorRoomDisplayNameFallbackProvider.kt @@ -19,8 +19,9 @@ package im.vector.app.features.room import android.content.Context import im.vector.app.R import org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider +import javax.inject.Inject -class VectorRoomDisplayNameFallbackProvider( +class VectorRoomDisplayNameFallbackProvider @Inject constructor( private val context: Context ) : RoomDisplayNameFallbackProvider {