diff --git a/app/build.gradle b/app/build.gradle index 8d00f0b706..8787b8b41b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,7 @@ plugins { id 'com.google.devtools.ksp' alias(libs.plugins.compose.compiler) id "com.google.firebase.appdistribution" + id 'com.google.gms.google-services' } if (rootProject.ext.onCi) { @@ -243,6 +244,9 @@ dependencies { implementation libs.wireRuntime + implementation platform('com.google.firebase:firebase-bom:33.8.0') + implementation "com.google.firebase:firebase-messaging" + //Unit/Integration tests dependencies testImplementation libs.androidXTestCore testImplementation libs.junit diff --git a/app/src/debug/google-services.json b/app/src/debug/google-services.json index 8fb2edfac6..a8f6fe52fa 100644 --- a/app/src/debug/google-services.json +++ b/app/src/debug/google-services.json @@ -2,7 +2,7 @@ "project_info": { "project_number": "665406949256", "project_id": "anytype-android-debug", - "storage_bucket": "anytype-android-debug.appspot.com" + "storage_bucket": "anytype-android-debug.firebasestorage.app" }, "client": [ { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 41d84d1ad8..7e5ab748d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -144,6 +144,14 @@ + + + + + + diff --git a/app/src/main/java/com/anytypeio/anytype/other/AnytypeFirebaseMessagingService.kt b/app/src/main/java/com/anytypeio/anytype/other/AnytypeFirebaseMessagingService.kt new file mode 100644 index 0000000000..09dde77b1d --- /dev/null +++ b/app/src/main/java/com/anytypeio/anytype/other/AnytypeFirebaseMessagingService.kt @@ -0,0 +1,57 @@ +package com.anytypeio.anytype.other + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import com.anytypeio.anytype.R +import androidx.core.app.NotificationCompat +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage + +class AnytypeFirebaseMessagingService : FirebaseMessagingService() { + override fun onNewToken(token: String) { + super.onNewToken(token) + // This callback is fired whenever a new token is generated for the device. + // Send this token to your app server for registration. + } + + override fun onMessageReceived(remoteMessage: RemoteMessage) { + super.onMessageReceived(remoteMessage) + + // Check if message contains a data payload. + remoteMessage.data.let { data -> + // Handle data + } + + // Check if message contains a notification payload. + remoteMessage.notification?.let { notification -> + val title = notification.title + val body = notification.body + // Display the notification + sendNotification(title, body) + } + } + + private fun sendNotification(title: String?, body: String?) { + // Build and show a notification via NotificationManager + val channelId = "fcm_default_channel" + val notificationBuilder = NotificationCompat.Builder(this, channelId) + .setSmallIcon(R.drawable.ic_anytype_qr_code_logo) + .setContentTitle(title) + .setContentText(body) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setAutoCancel(true) + + val notificationManager = + getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + // Create channel for Android Oreo and above + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = + NotificationChannel(channelId, "FCM Channel", NotificationManager.IMPORTANCE_HIGH) + notificationManager.createNotificationChannel(channel) + } + + notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build()) + } +} \ No newline at end of file diff --git a/feature-ui-settings/build.gradle b/feature-ui-settings/build.gradle index 5239a22449..eb5cf4321b 100644 --- a/feature-ui-settings/build.gradle +++ b/feature-ui-settings/build.gradle @@ -30,6 +30,9 @@ dependencies { implementation libs.lifecycleViewModel implementation libs.lifecycleRuntime + implementation platform('com.google.firebase:firebase-bom:33.8.0') + implementation "com.google.firebase:firebase-messaging" + implementation libs.appcompat implementation libs.compose implementation libs.composeFoundation diff --git a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/about/AboutAppScreen.kt b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/about/AboutAppScreen.kt index 5658493d6d..b252025c5a 100644 --- a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/about/AboutAppScreen.kt +++ b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/about/AboutAppScreen.kt @@ -7,9 +7,12 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.verticalScroll import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource @@ -23,7 +26,9 @@ import com.anytypeio.anytype.core_ui.views.Caption1Regular import com.anytypeio.anytype.core_ui.views.Caption2Regular import com.anytypeio.anytype.core_ui.views.Title1 import com.anytypeio.anytype.core_ui.views.UXBody +import com.anytypeio.anytype.ui_settings.BuildConfig import com.anytypeio.anytype.ui_settings.R +import com.google.firebase.messaging.FirebaseMessaging @Composable fun AboutAppScreen( @@ -121,6 +126,28 @@ fun AboutAppScreen( ) ) } + val tokenState = remember { mutableStateOf(null) } + if (BuildConfig.DEBUG) { + FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> + if (!task.isSuccessful) { + return@addOnCompleteListener + } + tokenState.value = task.result + } + if (tokenState.value != null) { + SelectionContainer { + Text( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(bottom = 10.dp), + text = "FCM Token: ${tokenState.value}", + style = Caption2Regular.copy( + color = colorResource(id = R.color.text_secondary) + ) + ) + } + } + } } }