In my application I have implemented Push Notification functionality.
I added a button for the user, which allows him to turn off the notification completely. However it doesn't work as I excpected. Here's the code snippet:
From MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FirebaseMessaging.getInstance().subscribeToTopic("test_topic");
((SwitchCompat)findViewById(R.id.notification_switch)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
Toast.makeText(MainActivity.this, "Switch activated ", Toast.LENGTH_LONG).show();
FirebaseMessaging.getInstance().subscribeToTopic("test_topic");
}else {
Toast.makeText(MainActivity.this, "Switch deactivated ", Toast.LENGTH_LONG).show();
FirebaseMessaging.getInstance().unsubscribeFromTopic("test_topic");
new Thread(new Runnable() {
#Override
public void run() {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
});
}
FirebaseMessagingService class to handle the message:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static String TAG = MyFirebaseMessagingService.class.getName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage){
super.onMessageReceived(remoteMessage);
Log.e(TAG, "onMessageReceived() --> " + remoteMessage.getNotification().getTitle());
}
// #Override
// public void onNewToken(String s) {
// super.onNewToken(s);
// Log.e(TAG, "onNewToken() --> " + s);
// }
}
When I try to send a notification using topic I don't get any notification. If I send the notification to all devices with the app, I still get the notification. How can I completely prevent my app from getting notifications?
Unregistration and Unsubscription
There are three methods a client app can use to stop receiving messages and/or topic subscriptions from the app server:
InstanceID deleteToken() with audience set to the app server's sender ID and scope set to GCM. This stops messages (including topic messages) from a specific app server
InstanceID deleteID(). This stops messages from all previous registrations and topic subscriptions for all app servers
GCMPubSub unsubscribe(). This stops topic messages from the specific topic of the app server
For FCM, it should be the FirebaseInstanceId.
Try to set setAutoInitEnabled(false) before FirebaseInstanceId.getInstance().deleteInstanceId().
When enabled, FCM generates a registration token on app startup if there is no valid one and generates a new token when it is deleted (which prevents deleteInstanceId() from stopping the periodic sending of data). This setting is persisted across app restarts and overrides the setting specified in your manifest.
By default, FCM auto-initialization is enabled.
For more information: FirebaseMessaging
Related
I will try to show personal single notification on my phone tray, but I can't rich, so help.
I am having an issue with FireBase Cloud Messaging in which I get the Token from the device and send the notification test through the Google Firebase notification console, however, the notification is never logged nor pushed to the android virtual device. The documentation for FCM is almost exactly the code that I have below and little else in the way of what else you would have to do to get push notifications working with firebase. I have gone through all of the setup information (build.gradle additions, Installing google play services, etc...) as specified in the documentation, but still do not have messages generating. What is wrong with the code that I am not receiving my push notifications to the logcat or the device? Please let me know any further information that would be helpful. Thanks.
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION))
{
String message = intent.getStringExtra("message");
Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
txtMessage.setText(message);
}
}
};
displayFirebaseRegId();
}
private void displayFirebaseRegId() {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
String regId = pref.getString("regId", null);
Log.e(TAG, "Firebase reg id: " + regId);
if (!TextUtils.isEmpty(regId))
txtRegId.setText("Firebase Reg Id: " + regId);
else
txtRegId.setText("Firebase Reg Id is not received yet!");
}
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.REGISTRATION_COMPLETE));
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.PUSH_NOTIFICATION));
NotificationUtils.clearNotifications(getApplicationContext());
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
super.onPause();
}
And I will add lib of fire base messaging is:
compile 'com.google.firebase:firebase-messaging:11.0.4'
You don't need to subscribe inside the BroadcastReceiver you can just do it inside the onTokenRefresh method in the FirebaseInstanceIdService
You don't need to get the push notification in the BroadcastReceiver, you have to do it inside the onMessageReceive in the FirebaseMessagingService
FCM is extremely unreliable with emulators, simply use a real device, I have struggled with this and in some cases I even get the notification days later when opening the emulator for other projects, test this with real phones
I have successfully implemented Firebase messaging in my app. Works great in the background and onMessageReceived() gets called when the app is in the foreground (yippee!).
The issue I have is that I need to update the UI dynamically and I am stuck on the best way to achieve this. I don't want to send the user an in-app notification (as the sample code shows), I'm not sure I want to send a broadcast, all I want to do is to access the MainActivity in order to call a method already there, however I have no reference to the MainActivity in the service.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification().getBody() != null) {
Log.d(LOG_TAG, "Message received: " + remoteMessage.getNotification().getBody());
} else {
Log.d(LOG_TAG, "Message received: " + remoteMessage.getData().get("message"));
}
// Call method in MainActivity
// <<< What goes Here?>>>>
}
This seems a simple use case but I can't find anything online to help.
Thanks in advance
Yes, you can update UI and pass value to your activity by using Local Broadcast
In your onMessageReceived() Firebase Service.
broadcaster = LocalBroadcastManager.getInstance(getBaseContext());
Intent intent = new Intent(REQUEST_ACCEPT);
intent.putExtra("Key", value);
intent.putExtra("key", value);
broadcaster.sendBroadcast(intent);
and register local Broadcast in your Activity or fragment method
#Override
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver((receiver),
new IntentFilter(PushNotificationService.REQUEST_ACCEPT)
);
}
#Override
public void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
}
and Handle Your update event like this, do your update UI work Here, it will call automatically when notification received and onMessageReceived() send a broadcast.
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
String value= intent.getStringExtra("key");
String value= intent.getStringExtra("key");
} catch (Exception e) {
e.printStackTrace();
}
}
};
I believe you should send a Local Broadcast with the data and register a receiver wherever you want that data to be utilised. This is a very good design pattern(Observer) as it decouples your Activity from the Service.
If the activity wants to do something with the data it will, else it won't. They are both separate entities and it would be much easier to maintain this code in the future, as far as I know.
Hope this helped.
How to listen incoming messages for multi user chat and single user chat on same listener. now for single user chat i am using following code:
chatManager.addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean createdLocally) {
chat.addMessageListener(new ChatStateListener() {
#Override
public void stateChanged(Chat chat, ChatState state) {
Log.d(TAG,"...stateChanged called...");
if (ChatState.composing.equals(state)) {
Log.d("Chat State",chat.getParticipant() + " is typing..");
} else if (ChatState.gone.equals(state)) {
Log.d("Chat State",chat.getParticipant() + " has left the conversation.");
} else {
Log.d("Chat State",chat.getParticipant() + ": " + state.name());
}
}
#Override
public void processMessage(Chat chat, Message message) {
Log.d(TAG,"---Received a message---");
Log.d(TAG,"participant: "+chat.getParticipant());
Log.d(TAG,"message.getBody(): "+message.getBody());
Log.d(TAG,"message.getFrom(): "+message.getFrom());
Log.d(TAG,"message.getType(): "+message.getType());
Log.d(TAG,"message.getSubject(): "+message.getSubject());
String from=message.getFrom();
String sender_id="";
if(from.contains("/"))
{
sender_id=from.split("/")[0];
Log.d(TAG,"The real sender_id is :" +sender_id);
}
else
{
sender_id=from;
}
Intent intent=new Intent(ChattingConnectionService.NEW_MESSAGE);
intent.setPackage(mContext.getPackageName());
intent.putExtra(ChattingConnectionService.BUNDLE_FROM_USERID,sender_id);
intent.putExtra(ChattingConnectionService.BUNDLE_MESSAGE_BODY,message.getBody());
mContext.sendBroadcast(intent);
Log.d(TAG,"Received message from :"+sender_id+" broadcast sent.");
}
});
}
});
And for multi user chat i am using following code:
multiUserChat=multiUserChatManager.getMultiUserChat(stringExtra);
multiUserChat.addMessageListener(new MessageListener() {
#Override
public void processMessage(Message message) {
Log.d(TAG,"---process message called in joinRoom method");
Log.d(TAG,"---Received a message from: "+message.getFrom());
Log.d(TAG,"message.getBody(): "+message.getBody());
Log.d(TAG,"message.getFrom(): "+message.getFrom());
Log.d(TAG,"message.getType(): "+message.getType());
Log.d(TAG,"message.getSubject(): "+message.getSubject());
if(message.getBody()!=null)
{
Intent intent=new Intent(ChattingConnectionService.NEW_MESSAGE);
intent.setPackage(mContext.getPackageName());
intent.putExtra(ChattingConnectionService.BUNDLE_FROM_USERID,message.getFrom());
intent.putExtra(ChattingConnectionService.BUNDLE_MESSAGE_BODY,message.getBody());
mContext.sendBroadcast(intent);
Log.d(TAG,"Received message from :"+message.getFrom()+" broadcast sent.");
}
}
});
I want to listen all these incoming messages on same listener? please help me? I am on fire in office. Thanks in advance.
I don't know how your infrastructure for the chat looks like, but anyhow I would recommend using the Firebase Cloud Messaging Api (former Google Cloud Messaging)
When user A is sending a message to user B, when the server gets this message you can use the Firebase Cloud Messaging to send a message or payload to user B and notify the user that he/she has received a message.
For a groupchats you can either use the solution above, when user A has sent a message to the groupchat workaholics your chat-server is querying all the recipients in that room, e.g the users B and C.
Another tip for handling a listener for a groupchat would be to use the Topic Messaging feature from Firebase Cloud Messaging found here:
https://firebase.google.com/docs/cloud-messaging/android/topic-messaging
FCM (Firebase Cloud Messaging) is the way to go when you want to send notifications to specific devices or groups of devices. Works for both Android, iOS and more..
I have integrated OneSignal in to my android app to use for push notifications, all is working fine and the notifications come through. However what do i need to change in order to handle these notifications in a custom manner? The receiver needs to parse the JSON payload from the notification and send the user to the correct point in the app based on what is received.
You need to setup a NotificationOpenedHandler class to handle the opening of a notification. See the following example code to set it up.
import com.onesignal.OneSignal;
public class YourAppClass extends Application {
#Override
public void onCreate() {
super.onCreate();
OneSignal.startInit(this)
.setNotificationOpenedHandler(new ExampleNotificationOpenedHandler())
.init();
}
// This fires when a notification is opened by tapping on it or one is received while the app is running.
private class ExampleNotificationOpenedHandler implements NotificationOpenedHandler {
#Override
public void notificationOpened(String message, JSONObject additionalData, boolean isActive) {
try {
if (additionalData != null) {
if (additionalData.has("actionSelected"))
Log.d("OneSignalExample", "OneSignal notification button with id " + additionalData.getString("actionSelected") + " pressed");
Log.d("OneSignalExample", "Full additionalData:\n" + additionalData.toString());
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
If you need to change which Activity is started when your app is opened see the OneSignal Changing the open action of a notification instructions.
I have done a lot of reading on Parse push notifications. I have push notifications working perfectly if the app is running or sitting in the background (user gets out of the app by pushing the home button or back button). I know I cannot get notifications to appear if the app has been force quit but if I close the app/force quit the app, is there a way to get the notifications to pop up the next time the app opens?
I have implemented MainApplication and made sure my manifest is correct but if the app is completely closed, then I do a push notification from Parse and then go to open the app it is as if it has not received it and never will display. Is that normal behavior?
Thanks,
Adam
Main Application
public class MainApplication extends Application {
private static MainApplication instance = new MainApplication();
public MainApplication()
{
instance=this;
}
public static Context getContext()
{
return instance;
}
#Override
public void onCreate() {
super.onCreate();
Parse.enableLocalDatastore(this);
//initialise whatson from parse.com
Parse.initialize(this, "xxxxx", "xxxxx");
PushService.setDefaultPushCallback(this, MainActivity.class);
//to register device to get push notifications and register the install
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
} else {
Log.e("com.parse.push", "failed to subscribe for push", e);
}
}
});
ParseInstallation.getCurrentInstallation().saveInBackground();
}
}