Skip to content

Commit 354c530

Browse files
updated notification
1 parent 7e39999 commit 354c530

File tree

6 files changed

+301
-0
lines changed

6 files changed

+301
-0
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
android:roundIcon="@drawable/icon_launcher"
1717
android:supportsRtl="true"
1818
android:theme="@style/Theme.TibetanKeyboard">
19+
<service
20+
android:name=".MyFirebaseMessagingService"
21+
android:exported="false">
22+
<intent-filter>
23+
<action android:name="com.google.firebase.MESSAGING_EVENT" />
24+
</intent-filter>
25+
</service>
1926
<activity
2027
android:name=".LoginActivity"
2128
android:exported="false" />
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.kharagedition.tibetankeyboard
2+
3+
import android.app.NotificationChannel
4+
import android.app.NotificationManager
5+
import android.app.PendingIntent
6+
import android.content.ActivityNotFoundException
7+
import android.content.Context
8+
import android.content.Intent
9+
import android.graphics.Color
10+
import android.net.Uri
11+
import android.os.Build
12+
import android.util.Log
13+
import androidx.core.app.NotificationCompat
14+
import com.google.firebase.messaging.FirebaseMessagingService
15+
import com.google.firebase.messaging.RemoteMessage
16+
17+
class MyFirebaseMessagingService : FirebaseMessagingService() {
18+
19+
override fun onMessageReceived(remoteMessage: RemoteMessage) {
20+
super.onMessageReceived(remoteMessage)
21+
22+
// Check if message contains data payload for update notification
23+
remoteMessage.data.isNotEmpty().let {
24+
if (remoteMessage.data["type"] == "app_update") {
25+
handleUpdateNotification(remoteMessage.data)
26+
}
27+
}
28+
}
29+
30+
private fun handleUpdateNotification(data: Map<String, String>) {
31+
val title = data["title"] ?: "Update Available"
32+
val message = data["message"] ?: "A new version of the app is available"
33+
val version = data["version"] ?: ""
34+
35+
showUpdateNotification(title, message, version)
36+
}
37+
38+
private fun showUpdateNotification(title: String, message: String, version: String) {
39+
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
40+
val channelId = "app_update_channel"
41+
42+
// Create notification channel (for Android O and above)
43+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
44+
val channel = NotificationChannel(
45+
channelId,
46+
"App Updates",
47+
NotificationManager.IMPORTANCE_HIGH
48+
).apply {
49+
description = "Notifications for app updates"
50+
enableLights(true)
51+
lightColor = Color.BLUE
52+
enableVibration(true)
53+
}
54+
notificationManager.createNotificationChannel(channel)
55+
}
56+
57+
// Create intent to open Play Store
58+
val playStoreIntent = createPlayStoreIntent()
59+
val pendingIntent = PendingIntent.getActivity(
60+
this,
61+
0,
62+
playStoreIntent,
63+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
64+
)
65+
66+
// Build notification
67+
val notification = NotificationCompat.Builder(this, channelId)
68+
.setSmallIcon(R.drawable.ic_update) // Add your update icon
69+
.setContentTitle(title)
70+
.setContentText(message)
71+
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
72+
.setAutoCancel(true)
73+
.setPriority(NotificationCompat.PRIORITY_HIGH)
74+
.setContentIntent(pendingIntent)
75+
.addAction(
76+
R.drawable.ic_download,
77+
"Update Now",
78+
pendingIntent
79+
)
80+
.build()
81+
82+
notificationManager.notify(1001, notification)
83+
}
84+
85+
private fun createPlayStoreIntent(): Intent {
86+
val packageName = packageName
87+
88+
// Try to open Play Store app first
89+
return try {
90+
Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=$packageName"))
91+
} catch (e: ActivityNotFoundException) {
92+
// Fallback to Play Store website
93+
Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$packageName"))
94+
}
95+
}
96+
97+
override fun onNewToken(token: String) {
98+
super.onNewToken(token)
99+
// Send token to your server
100+
sendTokenToServer(token)
101+
}
102+
103+
private fun sendTokenToServer(token: String) {
104+
// Implement your server communication here
105+
// This is where you'd send the FCM token to your backend
106+
Log.d("FCM", "New token: $token")
107+
}
108+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.kharagedition.tibetankeyboard
2+
3+
import android.app.NotificationChannel
4+
import android.app.NotificationManager
5+
import android.app.PendingIntent
6+
import android.content.Context
7+
import android.content.Intent
8+
import android.content.pm.PackageManager
9+
import android.net.Uri
10+
import android.os.Build
11+
import androidx.core.app.NotificationCompat
12+
13+
class UpdateNotificationManager(private val context: Context) {
14+
15+
companion object {
16+
private const val PREFS_NAME = "app_update_prefs"
17+
private const val LAST_UPDATE_CHECK = "last_update_check"
18+
private const val CURRENT_VERSION = "current_version"
19+
}
20+
21+
private val sharedPrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
22+
23+
fun checkForUpdates() {
24+
val currentVersionCode = getCurrentVersionCode()
25+
val lastKnownVersion = sharedPrefs.getInt(CURRENT_VERSION, 0)
26+
val lastCheckTime = sharedPrefs.getLong(LAST_UPDATE_CHECK, 0)
27+
val currentTime = System.currentTimeMillis()
28+
29+
// Check once per day
30+
if (currentTime - lastCheckTime > 24 * 60 * 60 * 1000) {
31+
// Here you could make an API call to check for updates
32+
// For demo purposes, we'll simulate an update available
33+
simulateUpdateCheck(currentVersionCode, lastKnownVersion)
34+
35+
sharedPrefs.edit()
36+
.putLong(LAST_UPDATE_CHECK, currentTime)
37+
.putInt(CURRENT_VERSION, currentVersionCode)
38+
.apply()
39+
}
40+
}
41+
42+
private fun simulateUpdateCheck(currentVersion: Int, lastKnownVersion: Int) {
43+
// Simulate server response indicating update available
44+
// In real implementation, you'd call your server API here
45+
46+
// Example: Show notification if we detect user might have an older version
47+
if (shouldShowUpdateNotification()) {
48+
showLocalUpdateNotification()
49+
}
50+
}
51+
52+
private fun shouldShowUpdateNotification(): Boolean {
53+
// Add your logic here to determine when to show update notification
54+
// This could be based on server response, version comparison, etc.
55+
return true // For demo purposes
56+
}
57+
58+
private fun showLocalUpdateNotification() {
59+
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
60+
val channelId = "local_update_channel"
61+
62+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
63+
val channel = NotificationChannel(
64+
channelId,
65+
"Local Update Check",
66+
NotificationManager.IMPORTANCE_DEFAULT
67+
)
68+
notificationManager.createNotificationChannel(channel)
69+
}
70+
71+
val playStoreIntent = Intent(Intent.ACTION_VIEW).apply {
72+
data = Uri.parse("market://details?id=${context.packageName}")
73+
}
74+
75+
val pendingIntent = PendingIntent.getActivity(
76+
context,
77+
0,
78+
playStoreIntent,
79+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
80+
)
81+
82+
val notification = NotificationCompat.Builder(context, channelId)
83+
.setSmallIcon(R.drawable.ic_update)
84+
.setContentTitle("Update Available")
85+
.setContentText("Tap to update your keyboard app")
86+
.setAutoCancel(true)
87+
.setContentIntent(pendingIntent)
88+
.build()
89+
90+
notificationManager.notify(1002, notification)
91+
}
92+
93+
private fun getCurrentVersionCode(): Int {
94+
return try {
95+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
96+
context.packageManager.getPackageInfo(
97+
context.packageName,
98+
PackageManager.PackageInfoFlags.of(0)
99+
).longVersionCode.toInt()
100+
} else {
101+
@Suppress("DEPRECATION")
102+
context.packageManager.getPackageInfo(context.packageName, 0).versionCode
103+
}
104+
} catch (e: PackageManager.NameNotFoundException) {
105+
0
106+
}
107+
}
108+
}

app/src/main/java/com/kharagedition/tibetankeyboard/ui/HomeActivity.kt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package com.kharagedition.tibetankeyboard.ui
22

3+
import android.Manifest
34
import android.annotation.SuppressLint
45
import android.content.Intent
6+
import android.content.pm.PackageManager
57
import android.net.Uri
8+
import android.os.Build
69
import android.os.Bundle
710
import android.provider.Settings
811
import android.util.Log
912
import android.view.View.GONE
1013
import android.view.View.VISIBLE
1114
import android.view.inputmethod.InputMethodManager
1215
import androidx.appcompat.app.AppCompatDelegate
16+
import androidx.core.app.ActivityCompat
17+
import androidx.core.content.ContextCompat
1318
import com.bumptech.glide.Glide
1419
import com.google.android.gms.ads.*
1520
import com.google.android.gms.ads.nativead.NativeAd
1621
import com.google.android.gms.ads.nativead.NativeAdOptions
22+
import com.google.firebase.messaging.FirebaseMessaging
1723
import com.kharagedition.tibetankeyboard.application.InputMethodActivity
1824
import com.kharagedition.tibetankeyboard.R
1925
import com.kharagedition.tibetankeyboard.SettingsActivity
@@ -23,6 +29,7 @@ import com.kharagedition.tibetankeyboard.util.AppConstant
2329
import com.kharagedition.tibetankeyboard.util.BottomSheetDialog
2430
import com.kharagedition.tibetankeyboard.util.CommonUtils
2531
import com.kharagedition.tibetankeyboard.BuildConfig
32+
import com.kharagedition.tibetankeyboard.UpdateNotificationManager
2633
import com.kharagedition.tibetankeyboard.auth.AuthManager
2734
import com.kharagedition.tibetankeyboard.subscription.RevenueCatManager
2835

@@ -31,6 +38,8 @@ class HomeActivity : InputMethodActivity() {
3138
private lateinit var homeBinding: ActivityHomeBinding
3239
private var isPremiumUser:Boolean = false;
3340
private lateinit var authManager: AuthManager
41+
private lateinit var updateManager: UpdateNotificationManager
42+
3443
override fun onResume() {
3544
checkKeyboardIsEnabledOrNot()
3645
premiumListener()
@@ -51,7 +60,56 @@ class HomeActivity : InputMethodActivity() {
5160
authManager = AuthManager(this)
5261
checkKeyboardIsEnabledOrNot()
5362
initClickListener()
63+
updateManager = UpdateNotificationManager(this)
64+
requestNotificationPermission()
65+
66+
// subscribe to all-users topic
67+
subscribeToAllUsersTopic()
68+
// Initialize Firebase and get FCM token
69+
initializeFirebase()
70+
71+
72+
updateManager.checkForUpdates()
73+
}
74+
75+
private fun subscribeToAllUsersTopic() {
76+
FirebaseMessaging.getInstance().subscribeToTopic("all-users")
77+
.addOnCompleteListener { task ->
78+
var msg = "Subscribed to all-users topic"
79+
if (!task.isSuccessful) {
80+
msg = "Failed to subscribe to all-users topic"
81+
}
82+
Log.d("FCM", msg)
83+
}
84+
}
85+
86+
private fun initializeFirebase() {
87+
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
88+
if (!task.isSuccessful) {
89+
Log.w("FCM", "Fetching FCM registration token failed", task.exception)
90+
return@addOnCompleteListener
91+
}
92+
93+
val token = task.result
94+
Log.d("FCM", "FCM Registration Token: $token")
5495

96+
// Send token to your server
97+
}
98+
}
99+
private fun requestNotificationPermission() {
100+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
101+
if (ContextCompat.checkSelfPermission(
102+
this,
103+
Manifest.permission.POST_NOTIFICATIONS
104+
) != PackageManager.PERMISSION_GRANTED
105+
) {
106+
ActivityCompat.requestPermissions(
107+
this,
108+
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
109+
101
110+
)
111+
}
112+
}
55113
}
56114

57115
@SuppressLint("NewApi")
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorOnSurface">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/>
10+
</vector>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorOnSurface">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M12,20q-3.35,0 -5.675,-2.325Q4,15.35 4,12q0,-3.35 2.325,-5.675Q8.65,4 12,4q1.725,0 3.3,0.713q1.575,0.712 2.7,1.937l-1.425,1.425q-0.85,-0.85 -2.012,-1.313Q13.4,6.3 12,6.3q-2.425,0 -4.113,1.687Q6.2,9.575 6.2,12t1.687,4.013Q9.575,17.7 12,17.7q2.425,0 4.113,-1.687Q17.8,14.425 17.8,12h-2.3l2.85,-2.85L21.2,12h-1.4q0,3.35 -2.325,5.675Q15.35,20 12,20ZM15.175,16.175 12.825,13.825V8.5h1.35v4.675l1.75,1.75Z"/>
10+
</vector>

0 commit comments

Comments
 (0)