WIP notificaciones push

This commit is contained in:
erike 2024-02-28 22:04:32 -06:00
parent 896912d514
commit c87e12caab
11 changed files with 162 additions and 7 deletions

View File

@ -61,6 +61,7 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "androidx.datastore:datastore-preferences:1.0.0"
// Hilt
implementation "com.google.dagger:hilt-android:2.47"
@ -131,5 +132,5 @@ dependencies {
implementation(platform("com.google.firebase:firebase-bom:32.7.1"))
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-messaging-ktx")
}

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:name=".MyApplication"
android:allowBackup="true"
@ -50,6 +51,15 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<service android:name=".push_notifications.FcmService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@ -1,10 +1,16 @@
package com.isolaatti
import android.app.Application
import android.content.Context
import android.net.ConnectivityManager
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import com.isolaatti.connectivity.ConnectivityCallbackImpl
import dagger.hilt.android.HiltAndroidApp
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
@HiltAndroidApp
class MyApplication : Application() {

View File

@ -1,14 +1,21 @@
package com.isolaatti.home
import android.Manifest
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.view.Menu
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.core.content.ContextCompat
import androidx.datastore.preferences.core.edit
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.isolaatti.R
import com.isolaatti.common.IsolaattiBaseActivity
import com.isolaatti.dataStore
import com.isolaatti.databinding.ActivityHomeBinding
import com.isolaatti.home.presentation.FeedViewModel
@ -16,6 +23,18 @@ class HomeActivity : IsolaattiBaseActivity() {
private lateinit var viewBinding: ActivityHomeBinding
private val feedViewModel: FeedViewModel by viewModels()
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
if (!isGranted) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.push_notifications_dialog_title)
.setMessage(R.string.push_notifications_dialog_rejected_message)
.show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityHomeBinding.inflate(layoutInflater)
@ -24,6 +43,8 @@ class HomeActivity : IsolaattiBaseActivity() {
viewBinding.bottomNavigation?.setupWithNavController(navHostFragment.navController)
viewBinding.navigationRail?.setupWithNavController(navHostFragment.navController)
askNotificationPermission()
if(savedInstanceState == null) {
feedViewModel.getFeed(false)
}
@ -34,7 +55,28 @@ class HomeActivity : IsolaattiBaseActivity() {
return super.onCreateOptionsMenu(menu)
}
override fun onDestroy() {
super.onDestroy()
private fun askNotificationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
PackageManager.PERMISSION_GRANTED
) {
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.push_notifications_dialog_title)
.setMessage(R.string.push_notifications_dialog_message)
.setPositiveButton(R.string.accept) { _, _ ->
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
.setNegativeButton(R.string.no, null)
.show()
} else {
// Directly ask for the permission
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
} else {
}
}
}

View File

@ -0,0 +1,10 @@
package com.isolaatti.home.notifications.data
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface NotificationsApi {
@GET("/api/Notifications/list")
fun getNotifications(@Query("after") after: Long?): Call<NotificationsDto>
}

View File

@ -0,0 +1,22 @@
package com.isolaatti.home.notifications.data
import java.time.ZonedDateTime
data class NotificationsDto(
val result: List<NotificationDto>
)
data class NotificationDto(
val id: Long,
val date: ZonedDateTime,
val userId: Int,
val read: Boolean,
val payload: NotificationPayload
)
data class NotificationPayload(
val type: String,
val authorId: Int,
val authorName: String?,
val intentData: String?
)

View File

@ -0,0 +1,25 @@
package com.isolaatti.push_notifications
import android.Manifest
import android.util.Log
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessagingService
import dagger.hilt.EntryPoint
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class FcmService : FirebaseMessagingService() {
companion object {
const val LOG_TAG = "FcmService"
}
@Inject
lateinit var pushNotificationsApi: PushNotificationsApi
override fun onNewToken(token: String) {
pushNotificationsApi.registerDevice(token)
Log.d(LOG_TAG, token)
}
}

View File

@ -0,0 +1,16 @@
package com.isolaatti.push_notifications
import com.isolaatti.connectivity.RetrofitClient
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
class Module {
@Provides
fun providePushNotificationsApi(retrofitClient: RetrofitClient): PushNotificationsApi {
return retrofitClient.client.create(PushNotificationsApi::class.java)
}
}

View File

@ -0,0 +1,14 @@
package com.isolaatti.push_notifications
import retrofit2.Call
import retrofit2.http.Multipart
import retrofit2.http.PUT
import retrofit2.http.Part
interface PushNotificationsApi {
@PUT("/api/push_notifications/register_device")
@Multipart
fun registerDevice(@Part("token") token: String): Call<Any>
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -186,4 +186,7 @@
<string name="select_audio">Select audio</string>
<string name="delete_audio_message">Do you really want to remove this audio? Discussions with this audio linked will still be pointing to it.</string>
<string name="delete_audio_title">Remove audio?</string>
<string name="push_notifications_dialog_title">Push notifications</string>
<string name="push_notifications_dialog_message">Receive notifications to stay informed about your profile activity</string>
<string name="push_notifications_dialog_rejected_message">You won\'t receive notifications. You can change this on your device settings.</string>
</resources>