I’m new to android.I programmed an app that uses Firebase to get push notifications. If I send a notification from the Firebase interface, the device receives the notification only when the app is running. Is there a way to get the notifications when the app is not running or at least to get all the unseen notifications when the app starts up?
Thank you in advance!
I add my code...
This is the class extending the FirebaseMessagingService:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public MyFirebaseMessagingService() {
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage.getNotification().getBody());
}
private void sendNotification(String messageBody)
{
//Intent intent = new Intent (this, MainActivity.class);
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
notificationBuilder.setContentTitle("My app");
notificationBuilder.setContentText(messageBody);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSound(defaultSoundUri);
//notificationBuilder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
}
}
and this is the class extending the FirebaseInstanceIdService:
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService{
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token)
{
}
}
Finally, this is the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="user.pushnotificationexample">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
This is Xamarin Android solution, but it should get you close to native.
Try test sending a "data" push notification from an online tester like "pushwatch". Make sure to click the json checkbox and add a json payload that includes the key, "data":
{"data": {"title":"This is a title!","body":"This is the body text!"}}
The OnMessageReceived(RemoteMessage message) method, message parameter, has a dictionary property "Data": i.e. message.Data. You'll find the json payload key value pairs (title & body) in that dictionary.
Note, if the app is STOPPED, the user will OPEN the notification and Android will open the app, targeting the Activity used in the pending intent created and used to build the local notification (see below). You will need to handle the notification intent from the OnCreate method of your target Activity ( otherwise if the app is running, you'll handle the intent from an override of OnNewIntent).
public class MainActivity....
{
protected override void OnCreate(Bundle bundle)
{
...
var pushExtra = Intent.GetStringExtra("your.pushextra.key");
if(pushExtra != null)
{
MyType myType = JsonConvert.Deserialize<MyType>(pushExtra);
//if you have a framework like MVVM or startup process
//and your type
//is used for app navigation, you may need to store
//the string value in shared preferences and deserialize
//and use it later
//after the app has completely finished starting
}
}
}
Save yourself some effort, if you need a type or dictionary here, make sure to serialize the object when putting the extra (when you create the local notification) and then deserialize the pushExtra to your concrete type to use an instance of it above. You may find most examples put a string, or int or dictionary of key value pairs.
void ConfigureLocalNotification(MyType typeInstance)
{
...
var intent = new Intent(context, typeof(MainActivity));
var jsonData = JsonConvert.SerializeObject(typeInstance);
Log.Info(TAG, $"Adding IntentExtra: {jsonData}");
intent.PutExtra("your.pushextra.key", jsonData);
intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop |
ActivityFlags.IncludeStoppedPackages); //| ActivityFlags.NewTask);
var pendingIntent = PendingIntent.GetActivity(context, 0, intent,
PendingIntentFlags.OneShot);
....
NotificationCompat.Builder builder = null;
builder = new NotificationCompat.Builder(context ...);
builder.SetContentIntent(pendingIntent) ....
}
Hope this helps
Related
I have a small application where I receive the message from the Firabase cloud Messaging just fine while the app is running our while is on background. I search a lot about this and I could not find a proper answer on how to receive/create notifications in android while the app is closed so please do not think this is a duplicate question. Can someone show me an example about this and how its done?
This is my Firebase messaging service class
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String tag = "TAG";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(tag,"FROM"+remoteMessage.getFrom());
//check if message contains data
if(remoteMessage.getData().size()>0){
Log.d(tag,"Message Data" + remoteMessage.getData());
}
//check if message constains notification
if(remoteMessage.getNotification() != null){
sendNotification(remoteMessage.getNotification().getBody());
}
}
private void sendNotification(String body){
Intent i = new Intent(this,MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Firebase CLoud Messaging")
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
}
}
This is my manifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
As per the docs, there are two types of notifications you can send through FCM.
Notification message
Data message
The firebase console can only send the first type of message. And the Notification message will be handled by the system if your app is in the backgroud, but it won't work if your app is stopped.
Switch to your own API, and send data messages.
So after hours with this problem and with the help of #Mauker I finally did it. These are the steps I took and all the information I received from the internet.
First of all forget Firebase Cloud Message to send notifications to your mobile app.
Second use postman to do those actions.
Notifications are of two types, group notifications where all the people receive the notification at the same time and direct notifications where the notification itself is only for the user to see.
1º If you want group notifications you have to do in you Application launcher class this:
FirebaseMessaging.getInstance().subscribeToTopic("groupNameChoosenByYou");
2º Then you have to create a class to handle this
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String myCustomKey = data.get("title"); //received from postman POST as you can see above
Intent i = new Intent(this,MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(myCustomKey)
.setContentText(myCustomKey+myCustomKey)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
}
}
3º Go to postman and do this in your body
This should be your URL : https://fcm.googleapis.com/fcm/send
{
"to":"/topics/groupNameChoosenByYou",
"data":
{
"title":"Your title",
"message":"Your message"
}
}
4º While in postman and do this in your Headers
Authorization -> Project settings in Firebase -> Cloud Messaging and take the Server key
Content-type -> application/json
5º If you want to do a direct notification for some specific user in the
"to":"/topics/groupNameChoosenByYou", replace with the device token id that is generated on the first connection with firebase(when the application is installed)
6º If you want to send notifications while the application is closed some ROMs dont allow this except facebook, whatsapp(golden apps) etc you must go to your battery optimization and put your app in the protected application(this changes from brand to brand). The ideal approach is to give the user an initial popup to help him do this.
This is what I learned and it works for me. Any question post above, I will try to research more about this and update while I get more information.
I am trying to add notifications to my Android app using GCM. I started out by following this
tutorial and using this example project as a reference.
I followed all the steps and created all needed classes and services, but I am still not receiving any notifications.
I'm checking for Google Play Services and seem to register my device successfully on my server. I added the google-services.json file to my project and added all permissions and libraries to the project.
What is going wrong?
Did I forget anything? Do I still need to do something? I'm very confused at this point.
AndroidManifest
Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<permission android:name="com.manager_android.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.manager_android.permission.C2D_MESSAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Receiver and services
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.manager_android" />
<!--here-->
</intent-filter>
</receiver>
<service
android:name=".Activities.GcmIntentService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".Activities.TokenRefreshListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<service android:name=".Activities.RegistrationService"
android:exported="false">
</service>
Added to app build.gradle
compile 'com.google.android.gms:play-services-gcm:11.0.4'
apply plugin: 'com.google.gms.google-services'
Added to project build.gradle
classpath 'com.google.gms:google-services:3.1.0'
RegistrationService
public class RegistrationService extends IntentService {
public RegistrationService() {
super("");
}
private final String TAG = "RegistrationInfo";
#Override
protected void onHandleIntent(#Nullable Intent intent) {
registerDevice();
}
private void registerDevice() {
InstanceID myID = InstanceID.getInstance(getApplicationContext());
String registratonToken = "";
try {
registratonToken = myID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
log.d("Registration Token", registratonToken);
Map<String, String> params = new HashMap<>();
params.put("user_id", registratonToken);
params.put("platform", "GCM");
SaveSharedPreference.setToken(getApplicationContext(), registratonToken);
//Register token on server
Communication.post(getString(R.string.register_device_url), new RequestParams(params), new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Log.i(TAG, "Registration was successful");
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.i(TAG, "Registration failed.");
}
});
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Couldn't register device", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
TokenRefreshListenerService
public class TokenRefreshListenerService extends InstanceIDListenerService {
#Override
public void onTokenRefresh() {
Intent i = new Intent(this, RegistrationService.class);
startService(i);
}
}
GCMIntentService
public class GcmIntentService extends GcmListenerService {
private int testId = 1234;
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
sendNotification(message);
}
private void sendNotification(String message) {
Intent intent = new Intent(this, MainScreenActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), testId, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis());
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(testId, notificationBuilder.build());
}
}
I start the RegistrationService as a service when the user logs in to register the device.
This documentation can help you understand about notifications.
A notification is a message you display to the user outside of your
app's normal UI. When you tell the system to issue a notification, it
first appears as an icon in the notification area. To see the details
of the notification, the user opens the notification drawer. Both the
notification area and the notification drawer are system-controlled
areas that the user can view at any time.
It also provides sample codes on every topic that you will tackle.
For GCM, you can refer to this documentation.
Google Cloud Messaging (GCM) is a free service that enables developers
to send messages between servers and client apps. This includes
downstream messages from servers to client apps, and upstream messages
from client apps to servers.
It will help you understand about the concept of GCM. Also it provides sample to start with.
I am just adding chat Functionality into my app after adding core function of apps.I start implementing Firebase push notification into app and follow all steps from official documentation.So whenever i send message from Firebase notification console it shows when app in foreground but when app in background it shows these lines in logcat but no notification
09-27 16:11:37.645 19946-19946/com.example.com.appD/dalvikvm: DexOpt: couldn't find field Landroid/os/Message;.sendingUid
09-27 16:11:37.645 19946-19946/com.example.com.appW/dalvikvm: VFY: unable to resolve instance field 135
09-27 16:11:37.645 19946-19946/com.example.com.appD/dalvikvm: VFY: replacing opcode 0x52 at 0x0000
Here is my Firebase Instance ID Service class
public class FireBase_InstanceID_Service extends FirebaseInstanceIdService {
public static final String TAG="==Firebase ID===";
private static final String SubscribeTopic="Chat";
String refreshedToken;
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
refreshedToken= FirebaseInstanceId.getInstance().getToken();
Log.d(TAG,"Here Is Token "+refreshedToken);
FirebaseMessaging.getInstance().subscribeToTopic(SubscribeTopic);
}
private void sendRegistrationToServer(String Token){
//TODO: Send Token To APP server
}
}
Here is my Firebase Messaging Service class
public class FireBase_Messaging_Service extends FirebaseMessagingService {
public static final String TAG="==FireBase MSG==";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG,"From "+remoteMessage.getFrom());
if (remoteMessage.getData().size()>0){
Log.d(TAG,"Message Data "+remoteMessage.getData());
}
if (remoteMessage.getNotification()!=null){
Log.d(TAG,"Message Notification Body "+remoteMessage.getNotification().getBody());
}
Log.d(TAG,"FCM Message ID "+remoteMessage.getMessageId());
Log.d(TAG,"FCM Notification Message: "+remoteMessage.getNotification());
Log.d(TAG,"FCM Data Message "+remoteMessage.getData());
showNotification(remoteMessage.getNotification().getBody());
}
private void showNotification(String Message){
Intent intent=new Intent(this, UserProfile.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(this,5,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder= (NotificationCompat.Builder) new NotificationCompat.Builder (this)
.setAutoCancel(true)
.setContentTitle("New Notification")
.setContentText(Message)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal)
.setContentIntent(pendingIntent);
NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(5,builder.build());
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.com.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".Navigation_Drawer"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER"></category>
</intent-filter>
</activity>
<service
android:name=".ImageDownloading"
android:enabled="true"
android:exported="false">
</service>
<!--FIREBASE SERVICES -->
<service android:name=".FireBase_Messaging_Service">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"></action>
</intent-filter>
</service>
<service android:name=".FireBase_InstanceID_Service">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"></action>
</intent-filter>
</service>
<!--FIREBASE SERVICES -->
</application>
</manifest>
So for me i am unable to get push notification in Notification Tray in background or when app is closed With these entries in logcat (which i don't understand)
This is working as intended, notification messages are delivered to your onMessageReceived callback only when your app is in the foreground. If your app is in the background or closed then a notification message is shown in the notification center, and any data from that message is passed to the intent that is launched as a result of the user tapping on the notification.
You can specify a click_action to indicate the intent that should be launched when the notification is tapped by the user. The main activity is used if no click_action is specified.
When the intent is launched you can use the
getIntent().getExtras();
to retrieve a Set that would include any data sent along with the notification message.
For more on notification message see docs.
I've searched a lot about notifications when the app is in the background or closed. I'm using Firebase Cloud Messaging by the way. It won't work for me. I've used the Android setup and when the app is in the foreground or the phone is not locked the notification is received.
When installed the token is printed correctly and subscribed to the topic.
When I send a notification when the app is active in the foreground (so screen is unlocked and app is shown) I receive the notification and title as stated in the onMessageReceived.
When I send a notification when the app is not shown but is still in recent apps and screen is unlocked I receive the notification with title and message as stated in notification payload.
When I send a notification when the app is not shown but is still in recent apps and screen is locked nothing is received.
When I send a notification when app is *closed and removed from recent apps nothing is received.
How can I change this so the app will always receive the notifications, even when closed or the phone is locked?
Ps. I read about the Doze modus with protected apps, even when I put my app with the protected ones I receive nothing. I'm testing on a Huawei P8 Lite.
AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".activities.MainActivity"
android:configChanges="orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".services.MyAppFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".services.FirebaseIDService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<receiver android:name=".services.NotificationReceiver" />
</application>
Gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.google.firebase:firebase-core:9.2.0'
compile 'com.google.firebase:firebase-messaging:9.2.0'
}
apply plugin: 'com.google.gms.google-services'
FirebaseMessagingService
public class MyAppFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
showNotification(getApplicationContext());
}
public static void showNotification(Context context){
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("FCM Message")
.setContentText("FCM Body")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
FirebaseInstanceIDService
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
System.out.println("Devicetoken: " + refreshedToken);
FirebaseMessaging.getInstance().subscribeToTopic("/topics/myapp");
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(refreshedToken);
}
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
}
Notification payload
{
"to": "/topics/mytopic",
"priority": "high",
"notification": {
"sound": "default",
"badge": "1",
"body": "the body text",
"title": "title text"
},
"data": {
"id": "id",
"channel": "channel"
}
}
EDIT - Add code for WakeFulBroadcastReceiver
public class NotificationReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// cancel any further alarms
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.cancel(alarmIntent);
completeWakefulIntent(intent);
// start the GcmTaskService
MyAppFirebaseMessagingService.showNotification(context);
}
}
UPDATE PAYLOAD
If I change my payload to the suggested way in the comments like this it is still not working. Maybe it has something to do with the Huawei P8 Lite that I'm testing on with Android 6.0.1 installed.
{
"to": "/topics/mytopic",
"priority": "high",
"data": {
"sound": "default",
"badge": "1",
"body": "the body text",
"title": "title text"
}
}
UPDATE 2.0
I've tested on multiple devices and versions. On devices with Android 5 it was working fine, also without app open and screen locked. Only device it wasn't working was my own Huawei P8 Lite. Still can't figure out why it's not working on that one.
When the app is closed, it shutdowns the service. You must to restart the service.
On your Application class, implements ActivityLifecycleCallbacks and on onActivityDestroyed restart the service with an alarm.
public class YourApplication extends Application implements Application.ActivityLifecycleCallbacks {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityDestroyed(Activity activity) {
Intent restartService = new Intent(getApplicationContext(), MyAppFirebaseMessagingService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),1,restartService,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME,5000,pendingIntent);
}
}
I also had issues with devices not receiving the notifications when they were closed, like they would be after a restart.
Turned out, it wasn't working with a DEBUG version of the solution, so that had to be tested in RELEASE MODE. For those using Android Studio, press the Green Play Button next to the debug button.
Firebase has different types of notifications, and each has special handling.
Assuming you're using a data push, you don't need special handling or a WakefulBroadcastReceiver.
If you're using a notification push, the notification will appear automatically in the system tray. You cannot do any special handling there.
Check the official documents here: https://firebase.google.com/docs/cloud-messaging/android/receive
I have made an forum application in android and used phpmyadmin as my database. But when a question gets a new answer the application should show a notification to all users so how can i do it is there a need to use firebase or by just using a webservice!
Firstly, you need to go to the firebase console and create an app. (For this you will need to login into your google account) and follow the steps provided here.
https://firebase.google.com/docs/
Once that is done you will need to add these services to your Manifest.xml file
<service
android:name=".firebase.FirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".firebase.FirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
FirebaseInstanceIdService.class
public class FirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseInstanceIDService";
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "OnTokenRefresh callback. Token received : " + token);
}
}
FirebaseMessagingService.class
public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
private static final String TAG = "FirebaseMessagingService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG,"onMessageReceived.");
showNotification(remoteMessage.getData().get("message"));
}
private void showNotification(String message) {
Intent i = new Intent(this, HomeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setContentTitle("Slapr Notification Demo")
.setContentText(message)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
}
Now you can get the tokenId in your activity by doing the following
Log.d(TAG, "Recieved token : " + FirebaseInstanceId.getInstance().getToken());
This are the most helpful tutorials that i had found when i started. I hope it helps you.
https://www.youtube.com/watch?v=LiKCEa5_Cs8
https://www.youtube.com/watch?v=MYZVhs6T_W8