Skip to content

Commit

Permalink
Replace deprecated calls
Browse files Browse the repository at this point in the history
Fix lifecycle related calls
  • Loading branch information
wec43 committed Jul 19, 2024
1 parent 1502cf5 commit bb33170
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 106 deletions.
18 changes: 8 additions & 10 deletions app-android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ android {
// https://issuetracker.google.com/issues/181593646
ksp {
arg("room.schemaLocation", "$projectDir/schemas".toString())
arg("room.generateKotlin", "true")
}
externalNativeBuild {
cmake {
Expand Down Expand Up @@ -138,16 +139,14 @@ dependencies {

implementation "de.tutao:tutasdk"

// Important: cannot be updated without additional measures as Android 6 and 7 do not have Java 9
//noinspection GradleDependency
implementation 'commons-io:commons-io:2.16.1'

implementation 'androidx.core:core-ktx:1.13.1'
implementation "androidx.activity:activity-ktx:$activity_version"
implementation "androidx.browser:browser:1.8.0"
implementation "androidx.browser:browser:1.8.0"
implementation "androidx.biometric:biometric:1.1.0"
implementation "androidx.core:core-splashscreen:1.0.1"
implementation "androidx.datastore:datastore-preferences:1.1.1"
implementation "androidx.core:core-splashscreen:1.0.1"
implementation "androidx.datastore:datastore-preferences:1.1.1"

if (file("../libs/android-database-sqlcipher-4.5.0.aar").exists()) {
implementation fileTree(include: ['*.aar'], dir: '../libs')
Expand All @@ -156,7 +155,7 @@ dependencies {
}
implementation 'androidx.sqlite:sqlite-ktx:2.4.0'

implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
ksp "androidx.room:room-compiler:$room_version"

if (file("../libs/android-database-sqlcipher-4.5.0.aar").exists()) {
Expand All @@ -167,11 +166,10 @@ dependencies {
implementation 'androidx.sqlite:sqlite-ktx:2.4.0'

implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.3'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"

// TLS1.3 backwards compatibility for Android < 10
implementation 'org.conscrypt:conscrypt-android:2.5.2'
Expand All @@ -184,8 +182,8 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.13'
testImplementation 'org.mockito.kotlin:mockito-kotlin:5.4.0'
// JVM-based unit tests (that don't need a real device or emulator)
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
// JVM-based unit tests (that don't need a real device or emulator)
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"

androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'androidx.test:runner:1.6.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import android.content.res.Configuration.UI_MODE_NIGHT_MASK
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.graphics.drawable.ColorDrawable
import android.util.Log
import android.view.View
import androidx.annotation.ColorInt
import androidx.core.view.WindowInsetsControllerCompat
import de.tutao.tutanota.ipc.ThemeFacade
import org.json.JSONException
import org.json.JSONObject
Expand Down Expand Up @@ -105,15 +105,16 @@ class AndroidThemeFacade(
// It is not an accident that navBg and headerBg seem to be swapped, the original color scheme was reused in
// this way.

val decorView = activity.window.decorView
val navBg = getColor(theme, "header_bg")

@ColorInt val navColor = parseColor(navBg)
val isNavBarLight = navBg.isLightHexColor()
var visibilityFlags = 0
activity.window.navigationBarColor = navColor

val windowInsetController = WindowInsetsControllerCompat(activity.window, activity.window.decorView)

if (isNavBarLight) {
visibilityFlags = visibilityFlags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
windowInsetController.isAppearanceLightNavigationBars = true
}

val headerBg = getColor(theme, "navigation_bg")
Expand All @@ -128,10 +129,8 @@ class AndroidThemeFacade(
// we change lightStatusBar flag accordingly.
activity.window.statusBarColor = statusBarColor
if (isStatusBarLight) {
visibilityFlags = visibilityFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
windowInsetController.isAppearanceLightStatusBars = true
}

decorView.systemUiVisibility = visibilityFlags
}

private fun getColor(theme: Map<String, String>, key: String): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ abstract class LifecycleJobService : JobService(), LifecycleOwner {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
super.onDestroy()
}

override val lifecycle: Lifecycle
get() = lifecycleRegistry
}
89 changes: 46 additions & 43 deletions app-android/app/src/main/java/de/tutao/tutanota/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import android.webkit.WebView
import android.webkit.WebView.HitTestResult
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.activity.addCallback
import androidx.annotation.MainThread
import androidx.annotation.RequiresPermission
import androidx.browser.customtabs.CustomTabsIntent
Expand All @@ -39,6 +40,8 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat.setSystemGestureExclusionRects
import androidx.core.view.doOnLayout
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import de.tutao.tutanota.alarms.AlarmNotificationsManager
import de.tutao.tutanota.alarms.SystemAlarmFacade
Expand Down Expand Up @@ -87,7 +90,6 @@ interface WebauthnHandler {
}



class MainActivity : FragmentActivity() {
lateinit var webView: WebView
private set
Expand Down Expand Up @@ -116,8 +118,8 @@ class MainActivity : FragmentActivity() {

val db = AppDatabase.getDatabase(this, false)
sseStorage = SseStorage(
db,
createAndroidKeyStoreFacade()
db,
createAndroidKeyStoreFacade()
)
val localNotificationsFacade = LocalNotificationsFacade(this, sseStorage)
val fileFacade =
Expand Down Expand Up @@ -283,6 +285,11 @@ class MainActivity : FragmentActivity() {

setContentView(webView)

// Set callback for back press
onBackPressedDispatcher.addCallback(this) {
onBackPressedCallback()
}

lifecycleScope.launch {
val queryParameters = mutableMapOf<String, String>()
// If opened from notifications, tell Web app to not login automatically, we will pass
Expand All @@ -291,15 +298,18 @@ class MainActivity : FragmentActivity() {
queryParameters["noAutoLogin"] = "true"
}

webView.post { // use webView.post to switch to main thread again to be able to observe sseStorage
sseStorage.observeUsers().observe(this@MainActivity) { userInfos ->
if (userInfos!!.isEmpty()) {
Log.d(TAG, "invalidateAlarms")
lifecycleScope.launchWhenCreated {

// Start observing SSE users in the background.
// If there are no users we need to tell web part to invalidate alarms.
launch {
sseStorage.observeUsers()
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.collect { userInfos ->
if (userInfos.isEmpty()) {
Log.d(TAG, "invalidateAlarms")
commonNativeFacade.invalidateAlarms()
}
}
}
}

startWebApp(queryParameters)
Expand Down Expand Up @@ -375,7 +385,7 @@ class MainActivity : FragmentActivity() {
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart")
lifecycleScope.launchWhenCreated {
lifecycleScope.launch {
mobileFacade.visibilityChange(true)
}
}
Expand Down Expand Up @@ -421,35 +431,35 @@ class MainActivity : FragmentActivity() {
handleIntent(intent)
}

private fun handleIntent(intent: Intent) = lifecycleScope.launchWhenCreated {
// When we redirect to the app from outside, for example after doing payment verification,
// we don't want to do any kind of intent handling
val data = intent.data
private fun handleIntent(intent: Intent) = lifecycleScope.launch {
// When we redirect to the app from outside, for example after doing payment verification,
// we don't want to do any kind of intent handling
val data = intent.data

if (data != null && data.scheme == "tutanota" && data.host == "webauthn") {
handleWebauthn(intent, data)
}
if (data != null && data.scheme == "tutanota" && data.host == "webauthn") {
handleWebauthn(intent, data)
}

if (data != null && data.toString().startsWith("tutanota://")) {
return@launchWhenCreated
}
if (data != null && data.toString().startsWith("tutanota://")) {
return@launch
}

if (intent.action != null && !intent.getBooleanExtra(ALREADY_HANDLED_INTENT, false)) {
when (intent.action) {
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE, Intent.ACTION_SENDTO -> share(
if (intent.action != null && !intent.getBooleanExtra(ALREADY_HANDLED_INTENT, false)) {
when (intent.action) {
Intent.ACTION_SEND, Intent.ACTION_SEND_MULTIPLE, Intent.ACTION_SENDTO -> share(
intent
)
)

OPEN_USER_MAILBOX_ACTION -> openMailbox(intent)
OPEN_CALENDAR_ACTION -> openCalendar(intent)
Intent.ACTION_VIEW -> {
when (intent.scheme) {
"mailto" -> share(intent)
"file" -> view(intent)
"content" -> view(intent)
OPEN_USER_MAILBOX_ACTION -> openMailbox(intent)
OPEN_CALENDAR_ACTION -> openCalendar(intent)
Intent.ACTION_VIEW -> {
when (intent.scheme) {
"mailto" -> share(intent)
"file" -> view(intent)
"content" -> view(intent)
}
}
}
}
}
}

Expand Down Expand Up @@ -552,7 +562,6 @@ class MainActivity : FragmentActivity() {
}
}

@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val continuation = activityRequests.remove(requestCode)
Expand Down Expand Up @@ -642,11 +651,9 @@ class MainActivity : FragmentActivity() {
mailToUrlString
)
} catch (e: RemoteExecutionException) {
val name = if (e.message != null) {
val element = Json.parseToJsonElement(e.message!!)
val name = e.message?.let { message ->
val element = Json.parseToJsonElement(message)
element.jsonObject["name"]?.jsonPrimitive?.content
} else {
null
}
Log.d(TAG, "failed to create a mail editor because of a ${name ?: "unknown error"}")
}
Expand Down Expand Up @@ -715,13 +722,9 @@ class MainActivity : FragmentActivity() {
commonNativeFacade.openCalendar(userId)
}

// this still works, but there's onBackPressedDispatcher.addCallback
// it should work on all API levels we support:
// https://stackoverflow.com/questions/72634225/onbackpressed-is-deprecated-what-is-the-alternative
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
private fun onBackPressedCallback() {
if (commonSystemFacade.initialized) {
lifecycleScope.launchWhenCreated {
lifecycleScope.launch {
val result = mobileFacade.handleBackPress()
try {
if (!result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ class IdTuple(
) {

@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = IdTuple::class)
companion object IdTupleSerializer : KSerializer<IdTuple> {
override val descriptor: SerialDescriptor = listSerialDescriptor<String>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class AndroidNativeCredentialsFacade(
}

override suspend fun loadAll(): List<PersistedCredentials> {
return db.credentialsDao().allPersistedCredentials.map { e -> e.toObject() }
return db.credentialsDao().allPersistedCredentials().map { e -> e.toObject() }
}

override suspend fun store(credentials: UnencryptedCredentials) {
Expand Down Expand Up @@ -61,7 +61,7 @@ class AndroidNativeCredentialsFacade(
Log.d(TAG, "Encryption mode migration complete")
}
val encryptedCredentials =
db.credentialsDao().allPersistedCredentials.firstOrNull { e -> e.userId == id }?.toObject()
db.credentialsDao().allPersistedCredentials().firstOrNull { e -> e.userId == id }?.toObject()
return if (encryptedCredentials != null) this.decryptCredentials(
encryptedCredentials,
credentialsKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ interface CredentialsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertPersistedCredentials(persistedCredentials: PersistedCredentialsEntity)

@get:Query("SELECT * FROM PersistedCredentials")
val allPersistedCredentials: List<PersistedCredentialsEntity>
@Query("SELECT * FROM PersistedCredentials")
fun allPersistedCredentials(): List<PersistedCredentialsEntity>

@Query("DELETE FROM PersistedCredentials WHERE userId = :userId")
fun deletePersistedCredentials(userId: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ interface AlarmInfoDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAlarmNotification(alarmNotification: AlarmNotificationEntity)

@get:Query("SELECT * FROM AlarmNotification")
val alarmNotifications: List<AlarmNotificationEntity>
@Query("SELECT * FROM AlarmNotification")
fun alarmNotifications(): List<AlarmNotificationEntity>

@Query("DELETE FROM AlarmNotification WHERE identifier = :identifier")
fun deleteAlarmNotification(identifier: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package de.tutao.tutanota.data

import androidx.lifecycle.LiveData
import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
abstract class UserInfoDao {
@get:Query("SELECT * FROM User")
abstract val users: List<User>
@Query("SELECT * FROM User")
abstract fun users(): List<User>

@Query("SELECT * FROM User")
abstract fun observeUsers(): LiveData<List<User>>
abstract fun observeUsers(): Flow<List<User>>

@Query("SELECT * FROM PushIdentifierKey WHERE pushIdentifierId = :pushIdentifier")
abstract fun getPushIdentifierKey(pushIdentifier: String): PushIdentifierKey?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,6 @@ class LocalNotificationsFacade(private val context: Context, private val sseStor
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
// FIXME: Do we want to ask permission here?
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return
}
notificationManager.notify(mailNotificationId("downloads"), notification)
Expand Down
Loading

0 comments on commit bb33170

Please sign in to comment.