I have implemented Parse push notifications but there is an issue on the Android side for me. Whenever I send a notification from Parse, all Android devices receive two notifications, one with the text that I have sent and the other with empty text.
Please suggest what might be wrong here
Note : I have also added native Android notifications (GCM notifications) to my project. Is it possible that they are causing this issue?
Thanks.
The AndroidManifest is setup as follows:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:name=".activityApplication"
android:label="#string/app_name"
android:icon="#drawable/icon">
<activity android:name=".activity"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
<!-- gcm -->
<receiver
android:name="com.company.activity.GCBroadcastReceiver"
android:exported="true"
android:process=":remote"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.company.activity" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParseBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
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.company.activity" />
</intent-filter>
</receiver>
</application>
And this is my Broadcast Receiver :
public class GCBroadcastReceiver extends BroadcastReceiver
{
private static final String TAG = "GCBroadcastReceiver";
Context ctx;
#Override
public void onReceive(Context context, Intent intent)
{
ctx = context;
// Local notification.
Bundle bundle = intent.getExtras();
String message = bundle.getString("message");
String notificationID = bundle.getString("notificationID");
Log.v(TAG,"Notification message : " + message + "With ID : " + notificationID);
sendNotification(message, notificationID);
}
// Put the GCM message into a notification and post it.
private void sendNotification(final String message, final String notificationID)
{
Intent notificationIntent = new Intent(ctx, Activity.class);
PendingIntent intent = PendingIntent.getActivity(ctx, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx);
mBuilder.setContentIntent(intent);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
mBuilder.setWhen(System.currentTimeMillis());
mBuilder.setSmallIcon(R.drawable.icon);
mBuilder.setContentTitle(ctx.getString(R.string.app_name));
mBuilder.setContentText(message);
mBuilder.setLights(Color.RED, 400, 400);
mBuilder.setAutoCancel(true);
//mBuilder.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + ctx.getPackageName() + "/raw/" + sound));
mBuilder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE);
NotificationManager mNotificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
}
Parse uses GCM, so if you are sending a notification to an application that uses Parse, and in addition you handle the GCM message with native Android code that displays a notification, the notification may be handled twice (one time by your code and one time by Parse), which will cause it to be displayed twice.
As to why one of the notifications has empty text - the code that displays it probably expects the text to be in an extra parameter that wasn't sent by the server, and therefore there was no text to display.
UPDATE:
Now that I see you code, I can add the following :
You have two broadcast receivers that handle incoming GCM messages - com.parse.GcmBroadcastReceiver and com.company.activity.GCBroadcastReceiver. Both of them attempt to process the notifications sent to your device from Parse (from your comment below, I understand that the problem doesn't occur when you send your "local" notifications).
I'm assuming that the Parse library registers on its own to GCM. If you are using a different sender ID (API project ID) for the parse registration and for your native GCM registration, you can fix your problem by checking intent.getExtras ().get("from") in your onReceive method. If it doesn't contain the sender ID of your local notifications, don't call sendNotification(message, notificationID);, and the second notification with the empty text won't be shown.
public void onReceive(Context context, Intent intent)
{
ctx = context;
// Local notification.
Bundle bundle = intent.getExtras();
String message = bundle.getString("message");
String notificationID = bundle.getString("notificationID");
Log.v(TAG,"Notification message : " + message + "With ID : " + notificationID);
if (intent.getExtras ().get("from").equals (YOUR_SENDER_ID_FOR_LOCAL_NOTIFICATIONS))
sendNotification(message, notificationID);
}
Now, if you are using the same sender ID for both types of notifications, you can either start using different sender IDs, or you can use a different condition - check if intent.getExtras ().get("message") has a value. Your local notifications require this parameter, and I'm assuming the Parse notifications don't (which explains the notifications without text you are seeing).
Using two GCM broadcast receivers may cause other problems too, so I suggest you look at this question for further reading.
Related
I have tried some solution from the stackoverflow . But not working properly in my case.
Below is my MyFirebaseMessagingService class which extends FirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
String url , title , body ;
Map<String,String> data = new HashMap<>();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
title = remoteMessage.getNotification().getTitle();
body = remoteMessage.getNotification().getBody();
if(remoteMessage.getData().size()>0){
Log.d("DATA", remoteMessage.getData().toString());
try{
data = remoteMessage.getData();
url = data.get("url");
}
catch (Exception e){
Log.e("Error", e.toString());
}
showNotification(url , title , body);
}
}
private void showNotification(String url, String title, String body) {
Intent intent = new Intent(this, NotificationViewer.class);
intent.putExtra("URL",url);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) ;
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(body);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSmallIcon(R.drawable.logo);
notificationBuilder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
}
}
Below is my AndroidManifest.xml code .
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dcastalia.com.munshijobsportal">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:name=".Controller.AppController"
android:allowBackup="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activity.SplashActivity"
android:noHistory="true"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".firebase.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".firebase.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<activity android:name=".activity.NotificationViewer"
android:exported="true">
</activity>
</application>
</manifest>
I have tried out some solution but not working in my case. Everything is working fine when app is foreground but not working in background. I want to open a particular activity name NotificationViewer.Java activity when user click on the notification. But when my app is in background it keep opening my Launcher Activity.
You need to set click action in your json payload in notification request
'click_action' => 'YourTAG' and apply same tag in your manifest activity
<activity
android:name=".activity.NotificationViewer">
<intent-filter>
<action android:name="YourTAG" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
You are most likely using the Firebase Notification message instead of the Data message.
If this is the case, using Data FCM message should do the trick for you.
As can be seen in https://firebase.google.com/docs/cloud-messaging/concept-options
Use notification messages when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want to process the messages on your client app.
Notification Messages:
When your application is in the foreground, it receives the payload, but when in the background, Notification messages are delivered to the notification tray.
Data Messages:
These are are always delivered to the application, regardless if it is in the foreground or in the background.
NOTE: The FCM data message alone will not bring your application in the foreground. You will need additional code that will do that upon reception of the data message.
I'm struggling on a Android app to redirect the app to a specific activity page whenever all the incoming push notification is clicked. I am new to android development and sorry for my programming.
Below are are android manifest.xml for push notification part. appreciated if there are any comment on this topic:-
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<permission
android:name="com.younginnovators.sjk.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<!-- VERY IMPORTANT! Don't forget this permission, or in-app billing won't work. -->
<uses-permission android:name="com.younginnovators.sjk.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<application
android:allowBackup="true"
android:icon="#mipmap/icon"
android:label="#string/app_name"
android:largeHeap="true"
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>
<!-- Push Notifications Receiver -->
<receiver
android:name=".backgroundservices.PushNotificationBroadcastReceiver"
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.younginnovators.sjk" />
</intent-filter>
</receiver>
<!-- /Push Notifications Receiver -->
<!-- Push Notifications Service -->
<service android:name=".backgroundservices.PushnotificationService" />
<!-- /Push Notifications Service -->
You can try something like this
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
Intent notificationIntent = new Intent(context, HomeActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
I want to develop a single activity android text messaging application that receives messages from a particular phone number. All other messages are to be sent to the inbox. For this purpose, I registered a BroadcastReceiver in the AndroidManifest.xml which checks for the incoming message's phone number and then aborts the broadcast if the number matches. The message is then stored in a sqlite database which is used to display messages in a ListActivity.
However, the issue I am facing is the broadcast is not received consistently by my app, sometimes it receives the intended message and sometimes it does not(goes to inbox). The message is received in th app as long as the app is opened, and a bit after it is closed. It is simply not consistent. I gave my app a higher priority (999) in the manifest.
My Manifest is below:
`
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:allowBackup="true">
<activity
android:launchMode="singleInstance"
android:name="org.trial.hiv.HIVActivity"
android:label="#string/title_activity_hiv"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="org.trial.hiv.SMSReceiver"
android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<service android:name="org.trial.hiv.SMSService" ></service>
<receiver android:name="org.trial.hiv.BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="org.trial.hiv.BootUpService" ></service>
</application>
`
And my SMSReceiver.java, which starts a service to perform necessary housekeeping tasks on the message received...
public class SMSReceiver extends BroadcastReceiver
{
public void onReceive(final Context context, Intent intent)
{
Intent smsServiceIntent = new Intent(context, SMSService.class);
smsServiceIntent.setClass(context, SMSService.class);
Bundle bundle = intent.getExtras();
Object pdus[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[pdus.length];
for (int n = 0; n<pdus.length; n++)`
{
smsMessage[n] = SmsMessage.createFromPdu((byte[]) pdus[n]);
}
String sender = smsMessage[0].getOriginatingAddress();
String body = smsMessage[0].getMessageBody();
if (sender.equalsIgnoreCase(activity.number))//incoming number is checked
{
this.abortBroadcast();
smsServiceIntent.putExtra("sender", sender);
smsServiceIntent.putExtra("body", body);
context.startService(smsServiceIntent);
}
}
}
I am using an smsService because I read that the BroadcastReceiver must not to any task for more than 10 seconds though I simply write the message to a SQLiteDatabase, I thought I still use a service.
Could someone point out where I am going wrong, or if I am missing out something critical. My requirement is to always receive all messages from a given number in my app, at any time.
After much debugging and understanding how BroadcastReceivers work in Android, I understand that the broadcast intent needs to be polled for, which I never did and hence the inconsistent behaviour... the following chage in code resolved my issue
do
{
bundle = intent.getExtras();
}
while (bundle == null);
in the onReceive() method of the BroadcastReceiver, and it resolved my issue. I could not find this documented anywhere, even in several SMS App tutorials.
Actually I am working on the notifications for an Android app.
My two main source of information are this tutorial and the android developer web site.
Let me quickly describe my app:
In my app I use web services (WS) which work with POST HTTP request.
For the Notification I use the GCM system.
My app uses the 'POST HTTP' request system above to be register on my server.
Actually my server does exactly the same job as the one in the tutorial (that means to register an account in the database with to two parameters and the register ID of the device, and send a message to the device with GCM)
Actually all of these steps work:
My app receive successfully gets register ID (gcm.register(SENDER_ID); work)
My app get successfully registered on my server
My server receives a successful message when I try to send a message from my device
{"multicast_id" : 6276079906208554309 , "success" : 1 , "failure" : 0 , "canonical_ids" : 0 , "results" : [{"message_id" : "0:1374826298092960%978fee92f9fd7ecd"}]}
The Problem:
I receive nothing on my device
What I did:
I try to do two versions of the application:
First I made an app using a part of the code of the tutorial, but with using the package com.google.android.gms.gcm.GoogleCloudMessaging instead of the com.google.android.gcm which are deprecated (and used in the tutorial), but I was unable to receive a message, so I try a second version …
This time I took the entire tutorial and just change the register function on the server to use mine, but like the first app, I receive nothing on my device. (I did this to try to understand how work the reception but it did not help me, and now I will forget this way)
Where do I need your help:
I need some/more explanation how to receive the message sent by my server.
My main activity uses the code describe on the android developer web site.
I create a broadcast class using the code on the android developer web site.
I don’t create any IntentService or service, maybe it is my error, but according what I read I understood that I don’t need one, like before with the deprecated GCMBaseIntentService
To conclude:
I really will appreciate some help to understand what I need to receive the message on my device, because actually I don’t know where I can found the information I need to be able to use this system.
Thanks.
PS: if you need some part of my code , just ask me.
EDIT
my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidhive.pushnotifications2"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.androidhive.pushnotifications2.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.androidhive.pushnotifications2.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- Main activity. -->
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<!-- Register Activity -->
<activity
android:name="com.androidhive.pushnotifications2.cop.RegisterActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Main Activity -->
<activity
android:name="com.androidhive.pushnotifications2.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name" >
</activity>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.androidhive.pushnotifications2" />
</intent-filter>
</receiver>
</application>
</manifest>
And my GcmBroadcastReceiver (who come from the tutorial)
the WakeLocker is the same as the tutorial too.
package com.androidhive.pushnotifications2;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import com.google.android.gms.gcm.GoogleCloudMessaging;
public class GcmBroadcastReceiver extends BroadcastReceiver {
static final String TAG = "GCMDemo";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
///
WakeLocker.acquire(context);
///
System.out.println("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server: " +
intent.getExtras().toString());
} else {
sendNotification("Received: " + intent.getExtras().toString());
}
WakeLocker.release();
setResultCode(Activity.RESULT_OK);
}
// Put the GCM message into a notification and post it.
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager)
ctx.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
new Intent(ctx, MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(ctx)
.setSmallIcon(R.drawable.common_signin_btn_icon_focus_light)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
I am using C2DM for "Push Notification" on Android. Every thing is okay.
My question is; can I get "if device has more than synchronized gmail accounts, which one is used for C2DM"?
Refer this link for C2DM and sample at this LINK. Now you device think where it is related to device.
In the below code the email id use is not device specific. C2DM uses email id just for interaction between server and C2DM not depending on device.
// Call when your application start
public void StartRegistrationNotification()
{
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "....#gmail.com");
this.startService(registrationIntent);
}
// change in Manifest File
<receiver android:name="com.ReceiverC2DM"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="yourpackagename" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="yourpackagename" />
</intent-filter>
</receiver>
<permission android:name="yourpackagename.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="yourpackagename.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive message -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />