Skip to content

Commit

Permalink
FCm Notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
hdhimalay committed May 20, 2024
1 parent 71eaf47 commit 67b39ea
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 83 deletions.
1 change: 1 addition & 0 deletions TalkIn/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion TalkIn/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions TalkIn/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion TalkIn/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.firebase:firebase-auth-ktx:23.0.0'
implementation 'com.google.firebase:firebase-firestore-ktx:23.0.3'

implementation 'com.google.firebase:firebase-messaging-ktx:24.0.0'
implementation 'com.android.volley:volley:1.2.1'
implementation 'com.google.firebase:firebase-database:21.0.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.activity:activity:1.8.0'
Expand Down
10 changes: 10 additions & 0 deletions TalkIn/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<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.WAKE_LOCK"/>
<uses-permission android:name="android.permission.VIBRATE" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand Down Expand Up @@ -41,6 +45,12 @@
</activity>
<activity android:name=".MainActivity" />

<service android:name=".FCMNotificationService" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
Expand Down
93 changes: 70 additions & 23 deletions TalkIn/app/src/main/java/com/example/talk_in/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,22 @@ class ChatActivity : AppCompatActivity() {
private lateinit var messageAdapter: MessageAdapter
private lateinit var messageList: ArrayList<Message>
private lateinit var mDbRef: DatabaseReference
var receiverRoom: String?=null
var senderRoom: String?=null
private var receiverRoom: String? = null
private var senderRoom: String? = null
private lateinit var receiverUid: String
private lateinit var senderName: String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)


val name= intent.getStringExtra("name")
val receiveruid= intent.getStringExtra("uid")
val name = intent.getStringExtra("name")
receiverUid = intent.getStringExtra("uid") ?: ""
val senderUid= FirebaseAuth.getInstance().currentUser?.uid
mDbRef= FirebaseDatabase.getInstance().getReference()
senderRoom= receiveruid+senderUid
receiverRoom=senderUid+receiveruid
senderRoom = "$receiverUid$senderUid"
receiverRoom = "$senderUid$receiverUid"
supportActionBar?.hide()

chatRecyclerView=findViewById(R.id.chatRecyclerView)
Expand All @@ -54,36 +56,39 @@ class ChatActivity : AppCompatActivity() {

chatRecyclerView.layoutManager=LinearLayoutManager(this)
chatRecyclerView.adapter=messageAdapter
//logic to add data to recyclerview
mDbRef.child("chats").child(senderRoom!!).child("messages")
.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
messageList.clear()

for (postSnapshot in snapshot.children){
val message = postSnapshot.getValue(Message::class.java)
messageList.add(message!!)
}
messageAdapter.notifyDataSetChanged()

// Fetch sender's name
senderUid?.let {
mDbRef.child("user").child(it).addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
senderName = dataSnapshot.child("name").value.toString()
// Load chat messages
loadChatMessages()
}

override fun onCancelled(error: DatabaseError) {
override fun onCancelled(databaseError: DatabaseError) {

}

})
//adding message to data base
sendButton.setOnClickListener{
val message=messageBox.text.toString()
val messageObject= Message(message,senderUid)
}

// Adding message to database
sendButton.setOnClickListener {
val message = messageBox.text.toString()
val messageObject = Message(message, senderUid)
mDbRef.child("chats").child(senderRoom!!).child("messages").push()
.setValue(messageObject).addOnSuccessListener {
mDbRef.child("chats").child(receiverRoom!!).child("messages").push()
.setValue(messageObject)

.addOnSuccessListener {
sendNotificationToReceiver(receiverUid, message)
}
}
messageBox.setText("")
}


backbtnImage.setOnClickListener {
val intent = Intent(this@ChatActivity, MainActivity::class.java)
startActivity(intent)
Expand Down Expand Up @@ -122,4 +127,46 @@ class ChatActivity : AppCompatActivity() {
}
popupMenu.show()
}

private fun loadChatMessages() {
mDbRef.child("chats").child(senderRoom!!).child("messages").addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
messageList.clear()
for (postSnapshot in snapshot.children) {
val message = postSnapshot.getValue(Message::class.java)
messageList.add(message!!)
}
messageAdapter.notifyDataSetChanged()
// Scroll RecyclerView to the bottom
chatRecyclerView.scrollToPosition(messageAdapter.itemCount - 1)
}

override fun onCancelled(error: DatabaseError) {
}
})
}

private fun sendNotificationToReceiver(receiverUid: String, message: String) {
// Fetch receiver's device token
mDbRef.child("users-device-tokens").child(receiverUid).addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val receiverDeviceToken = dataSnapshot.child("deviceToken").value.toString()

val notificationSender = FcmNotificationsSender(
receiverDeviceToken,
"New Message from $senderName",
message,
FirebaseAuth.getInstance().currentUser?.uid ?: "",
senderName,
applicationContext,
this@ChatActivity
)
notificationSender.sendNotifications()
}

override fun onCancelled(databaseError: DatabaseError) {

}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.example.talk_in

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Vibrator
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class FCMNotificationService : FirebaseMessagingService() {

private lateinit var mNotificationManager: NotificationManager

override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)

// Play notification sound
val notification: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val r = RingtoneManager.getRingtone(applicationContext, notification)
r.play()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
r.isLooping = false
}

// Vibrate the device
val v = getSystemService(VIBRATOR_SERVICE) as Vibrator
val pattern = longArrayOf(100, 300, 300, 300)
v.vibrate(pattern, -1)

val resourceImage = resources.getIdentifier(remoteMessage.notification?.icon, "drawable", packageName)

val builder = NotificationCompat.Builder(this, "CHANNEL_ID")
builder.setSmallIcon(resourceImage)

// Extract data payload
val senderUid = remoteMessage.data["senderUid"]
val senderName = remoteMessage.data["senderName"]

// Open ChatActivity when notification is clicked
val resultIntent = Intent(this, ChatActivity::class.java).apply {
putExtra("uid", senderUid)
putExtra("name", senderName)
}

val pendingIntent = PendingIntent.getActivity(this, 1, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT)

builder.setContentTitle(remoteMessage.notification?.title)
builder.setContentText(remoteMessage.notification?.body)
builder.setContentIntent(pendingIntent)
builder.setStyle(NotificationCompat.BigTextStyle().bigText(remoteMessage.notification?.body))
builder.setAutoCancel(true)
builder.priority = Notification.PRIORITY_MAX

mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = "Your_channel_id"
val channel = NotificationChannel(
channelId,
"Messages Notification",
NotificationManager.IMPORTANCE_HIGH
)
mNotificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}

mNotificationManager.notify(100, builder.build())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.example.talk_in

import android.app.Activity
import android.content.Context
import android.util.Log
import com.android.volley.AuthFailureError
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import org.json.JSONException
import org.json.JSONObject
import java.util.HashMap

class FcmNotificationsSender(
private val userFcmToken: String,
private val title: String,
private val body: String,
private val senderUid: String,
private val senderName: String,
private val mContext: Context,
private val mActivity: Activity
) {
private val requestQueue: RequestQueue = Volley.newRequestQueue(mContext)
private val postUrl = "https://fcm.googleapis.com/fcm/send"
private val fcmServerKey = "AAAAt0loRzU:APA91bE7oxyox_4Q2dHihHCKlQCe9pV7wbGgPXL4uvRsC-1kKfV-H0v37M4prqmV784RdKK7nW8c7POGh3Psyb-gAaqq78wya6yoEdimE0XLARHPtvi1VHdG5VrwHx4n9m6YRqZvY7-s"

fun sendNotifications() {
Log.d(TAG, "Sending FCM notification")
val mainObj = JSONObject()
try {
mainObj.put("to", userFcmToken)
val notiObject = JSONObject()
notiObject.put("title", title)
notiObject.put("body", body)
notiObject.put("icon", R.drawable.talkin)
mainObj.put("notification", notiObject)

// Add data payload
val dataObject = JSONObject()
dataObject.put("senderUid", senderUid)
dataObject.put("senderName", senderName)
dataObject.put("message", body)
mainObj.put("data", dataObject)

val request = object : JsonObjectRequest(
Request.Method.POST, postUrl, mainObj,
Response.Listener { response ->

},
Response.ErrorListener { error ->

}
) {
@Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val header = HashMap<String, String>()
header["content-type"] = "application/json"
header["authorization"] = "key=$fcmServerKey"
return header
}
}
requestQueue.add(request)
} catch (e: JSONException) {
e.printStackTrace()
}
}

companion object {
private const val TAG = "FcmNotificationsSender"
}
}
Loading

0 comments on commit 67b39ea

Please sign in to comment.