Android push notification using Firebase
Step 1: Add following Libraries/Dependencies in your gradle (App-Level) :
//messaging
implementation 'com.google.firebase:firebase-messaging:20.2.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
//Database
implementation 'com.google.firebase:firebase-analytics:17.2.0'
implementation 'com.google.firebase:firebase-database:19.2.0'
implementation 'com.google.firebase:firebase-auth:19.1.0'
Step 2: Make A Package “SendNotificationPack” and add the following classes, two services and an interface:
Interface: APIService.java // use to send request for notification to firebase server
package com.example.connect.SendNotificationPackage;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface APIService {
@Headers( {
"Content-Type:application/json",
"Authorization:key=xxxxxxxxxxxxxxxx " // Your server key
} )
@POST("fcm/send")
Call<MyResponse> sendNotifcation(@Body NotificationSender body); }
Server key:firebase console->settings->users and permissions->cloud Messaging->server key
Class: Client.java // use to get connect with firebase could messaging and initialize the object of APIService
package com.example.connect.SendNotificationPackage;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class Client {
private static Retrofit retrofit=null;
public static Retrofit getClient(String url)
{
if(retrofit==null)
{
retrofit=new Retrofit.Builder().baseUrl(url).addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
Class: MyResponse.java // use to get result of send notification or not in integer format as result Response
package com.example.connect.SendNotificationPackage;
public class MyResponse {
public int success;
}
Class: Token.java // use to get unique token for each user
package com.example.connect.SendNotificationPackage;
public class Token
{
private String token;
public Token(String token)
{
this.token = token;
}
public Token() { }
public String getToken()
{
return token;
}
public void setToken(String token)
{
this.token = token;
}
}
Class: Data.java // use wrap two parts of notification “Title and message” ad an data object , Note you can send more data as more different parts with more variables and getter setter for those in Data class
package com.example.connect.SendNotificationPackage;
public class Data {
private String Title;
private String Message;
public Data(String title, String message) {
Title = title; Message = message; }
public Data() { }
public String getTitle() {
return Title; }
public void setTitle(String title) {
this.Title = title; }
public String getMessage() {
return Message; }
public void setMessage(String message) {
this.Message = message; }
}
Class: NotificationSender.java // use wrap two parts : data object and the token of the user to whom you want to send the notification .
package com.example.connect.SendNotificationPackage;
public class NotificationSender {
public Data data;
public String to;
public NotificationSender(Data data, String to)
{
this.data = data; this.to = to;
}
public NotificationSender()
{
}
}
Class: MyFirebaseIdService.java (Service) // continuously keeps on updating your user token in background after certain interval and when your data network ip change.
package com.example.connect.SendNotificationPackage;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessagingService;
public class MyFirebaseIdService extends FirebaseMessagingService
{
@Override public void onNewToken(String s)
{
super.onNewToken(s);
FirebaseUser firebaseUser= FirebaseAuth.getInstance().getCurrentUser();
String refreshToken= FirebaseInstanceId.getInstance().getToken();
if(firebaseUser!=null){
updateToken(refreshToken);
}
}
private void updateToken(String refreshToken)
{
FirebaseUser firebaseUser= FirebaseAuth.getInstance().getCurrentUser();
Token token1= new Token(refreshToken);
//as per your convenience change the path
FirebaseDatabase.getInstance().getReference().child("Users").child(firebaseUser.getUid()).setValue(token1);
}
}
Class: MyFireBaseMessagingService.java (Service) // continuously keeps on checking in background on any message(notification) received and if any then extracts data from it and shows it in notification form.
package com.example.connect.SendNotificationPackage;
import android.app.Notification;
import android.app.NotificationManager; import android.content.Context;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import com.example.connect.R;
import com.example.connect.Utils.Common;
import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage;
import java.util.Map;
import java.util.Random;
public class MyFireBaseMessagingService extends FirebaseMessagingService {
String title,message;
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if(remoteMessage.getData() != null)
{
//above Oreo version;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
sendNotificationWithChannel(remoteMessage);
//bellow Oreo version
else
sendNotification(remoteMessage);
}
}
private void sendNotification(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
title=remoteMessage.getData().get("Title");
message=remoteMessage.getData().get("Message");
String Ntitle = title;
String content = message;
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder= new NotificationCompat.Builder(this )
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(Ntitle)
.setContentText(content)
.setSound(defaultSound)
.setAutoCancel(false);
//.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(new Random().nextInt(),builder.build());
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void sendNotificationWithChannel(RemoteMessage remoteMessage) {
Map<String,String> data = remoteMessage.getData();
title=remoteMessage.getData().get("Title");
message=remoteMessage.getData().get("Message");
String Ntitle = title;
String content = message;
NotificationHelper helper;
Notification.Builder builder;
Uri defaoultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
helper = new NotificationHelper(this);
builder = helper.getRealtimeTrackingNotification(Ntitle,content,defaoultSound);
helper.getManager().notify(new Random().nextInt(),builder.build());
}
}
Class : NotificationHelper(create channel)//for the oreo and above versons
package com.example.connect.SendNotificationPackage;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.example.connect.Home;
import com.example.connect.R;
public class NotificationHelper extends ContextWrapper {
private static final String EDMT_CHANNEL_ID = "com.example.connect";
private static final String EDMT_CHANNEL_NAME = "connect";
private NotificationManager manager;
public NotificationHelper(Context base) {
super(base);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createChannel();
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void createChannel() {
NotificationChannel edmtChannel = new NotificationChannel(EDMT_CHANNEL_ID,EDMT_CHANNEL_NAME
,NotificationManager.IMPORTANCE_DEFAULT);
edmtChannel.enableLights(false);
edmtChannel.enableVibration(true);
edmtChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
getManager().createNotificationChannel(edmtChannel);
}
public NotificationManager getManager() {
if(manager == null)
manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
return manager;
}
@RequiresApi(api = Build.VERSION_CODES.O)
public Notification.Builder getRealtimeTrackingNotification(String title, String content, Uri defaultSound) {
Intent notificactionIntent = new Intent(this, Home.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificactionIntent,0);
return new Notification.Builder(getApplicationContext(),EDMT_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setContentText(content)
.setSound(defaultSound)
.setContentIntent(pendingIntent)
.setAutoCancel(false);
}
}
class: NotificationBackground(background service for oreo and above)
package com.example.connect.SendNotificationPackage;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
public class NotificationBackground extends Application {
public static final String CHANNEL_ID = "exampleServiceChannel";
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel()
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,"Connect service channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = (getSystemService(NotificationManager.class));
manager.createNotificationChannel(serviceChannel);
}
}
}
Step 3: To send notification you need to be login only then you can get token and secondly to send notification so making two activity:
public class MainActivity extends AppCompatActivity{
private APIService apiService
Button NotificationB;
EditText Token; //u can manually enter or by firebase stored token also use
@Override
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
UpdateToken()
setContentView(R.layout.activity_main);
NotificationB = findViewById(R.id.notify); //on click of button send the notification
Token = findViewById(R.id. Token);
//spacified user notification
apiService = Client.getClient("https://fcm.googleapis.com/").create(APIService.class);
//Initialize the object of APIService with client class
NotificationB.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
usertoken = Token.getText().toString().trim(); //based on token value it send the notifiaction
sendNotifications(usertoken,"Title",”message”);
}
}}
//update token
private void UpdateToken(){
FirebaseUser firebaseUser= FirebaseAuth.getInstance().getCurrentUser();
String refreshToken= FirebaseInstanceId.getInstance().getToken();
Token token= new Token(refreshToken);
FirebaseDatabase.getInstance().getReference().child("Users").child(firebaseUser.getUid()).child("token").setValue(token.getToken());
}
//send notif
public void sendNotifications(String usertoken, String title, String message)
{
Data data = new Data(title, message);
NotificationSender sender = new NotificationSender(data, usertoken);
apiService.sendNotifcation(sender).enqueue(new Callback<MyResponse>()
{
@Override
public void onResponse(Call<MyResponse> call, retrofit2.Response<MyResponse> response) {
if (response.code() == 200) {
if (response.body().success != 1) {
Toast.makeText(CreateEvent.this, "Failed ", Toast.LENGTH_LONG);
}
}
}
@Override
public void onFailure(Call<MyResponse> call, Throwable t)
{
Toast.makeText(CreateEvent.this, "Failed ", Toast.LENGTH_LONG);
}
});
}
Step 4: This Step is most important you have coded all perfectly but you won’t get notification useless your service keep running in background and check for message to do so you need to add following in AndroidManifest.xml ie registering your services:
android:name=".SendNotificationPackage.NotificationBackground"
<service android:name=".SendNotificationPackage.MyFireBaseMessagingService" android:enabled="true" android:exported="true">
<intent-filter><action android:name="com.google.firebase.MESSAGING_EVENT" /></intent-filter>
</service>
<service android:name=".SendNotificationPackage.MyFirebaseIdService"
android:enabled="true" android:exported="true">
<intent-filter> <
action android:name="com.google.firebase.INSTANCE_ID_EVENT" /></intent-filter>
</service>
General notification for all installed device from firebase
Assign variable
//notification general
private RequestQueue mRequestQue;
private String URL = "https://fcm.googleapis.com/fcm/send";
Inside Oncreate method
// mass notification
mRequestQue= Volley.newRequestQueue(this);
FirebaseMessaging.getInstance().subscribeToTopic("news"); // this is for the mass notification group(it will work only by enabling " sendGeneralNotification ()"
Method to send notification
//send notification
private void sendGeneralNotification(){
JSONObject mainObj = new JSONObject();
try {
mainObj.put("to", "/topics/" + "news");
JSONObject notificationObj = new JSONObject();
notificationObj.put("title","title");
notificationObj.put("body","any body");
mainObj.put("notification",notificationObj);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, URL, mainObj,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
//success it run
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//fail it run
}
}){
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> header = new HashMap<>();
header.put("Content-Type", "application/json");
header.put("Authorization","key=xxxxxxxxxxxxx "); //server key
return header;
}
};
mRequestQue.add(request);
}
catch (JSONException e)
{
e.printStackTrace();
}
}
Comments
Post a Comment