I'm trying to receive propertly a message from FireBase when my app is in background but not working anithing. I've seen some Stackoverflow problems like mine but not working anything.
Could anyone help me to find the problem?
I need to do it when my app is in background but not working.
here AndoridManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.type.watch" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault"
tools:targetApi="ice_cream_sandwich">
<service
android:name=".MyfirebaseMessagingService" android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<uses-library
android:name="com.google.android.wearable"
android:required="true" />
<!--
Set to true if your app is Standalone, that is, it does not require the handheld
app to run.
-->
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
<!-- [START fcm_default_channel] -->
<!-- [START fcm_default_channel] -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id" />
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--<action android:name="android.intent.action.VIEW" />-->
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="gizmos"
android:scheme="example" />
</intent-filter>
</activity>
</application>
MyfirebaseMessagingService.java:
public class MyfirebaseMessagingService extends FirebaseMessagingService {
public static String TAG = "MyFirebaseMsgService";
private LocalBroadcastManager broadcaster;
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
broadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public void onDestroy() {
super.onDestroy();
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = getString(R.string.default_notification_channel_id);
CharSequence name = getString(R.string.default_notification_channel_id);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(channelId, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Intent home = new Intent(getApplicationContext(), MainActivity.class);
home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(home);
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
Intent intent = new Intent("Data");
intent.putExtra("messageFromCloud", remoteMessage.getNotification().getBody());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
broadcaster.sendBroadcast(intent);
if (intent.getExtras() != null)
{
RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
for (String key : intent.getExtras().keySet())
{
builder.addData(key, intent.getExtras().get(key).toString());
}
onMessageReceived(builder.build());
}
}
}
}
If you want use MainActivity as Activity ofNotification click activity then you need to code like:
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="gizmos"
android:scheme="example" />
</intent-filter>
</activity>
It will be automatically redirect to MainAcitivity on Notification click.
You need to mention The messaging file in manifest but this is not only the solution for open an activity through notification you need to write into intent in Messaging files.
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
For manifest write this code:
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<service
android:name=".MyFirebaseMessagingService"
android:permission=""
tools:ignore="ExportedService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
You need to declare it as service because notification is the part of service and run in application background when you application became closed.
Related
I am implementing push notification on Android with FirebaseMessagingService for an app that mainly lives in a webview.
The notifications arrives as expected when the app is in foreground, background and closed (wiped away).
Tapping a notification opens the deeplink provided in data.payload.link (after parsing the JSON in data.payload) when the app is in forground and background but not when closed.
In case the app is closed - the app gets started and shows up but the deeplink is not loaded like when the app is in foreground/background.
The payload I send to the Firebase API looks as follows:
admin
.messaging()
.send({
data: {
payload: JSON.stringify({
link: link || "",
}),
},
notification,
android: {
notification: {
click_action: "OPEN_DEEPLINK_FROM_PUSH_NOTIFICATION",
},
priority: "normal",
},
token: recipient,
})
The onMessageReceived() is implemented as follows:
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage == null) return;
Map<String, String> data = remoteMessage.getData();
String payload = (String) data.values().toArray()[0];
String link = null;
JSONObject jObject = null;
try {
jObject = new JSONObject(payload);
link = jObject.getString("link");
} catch (Exception e) {
Log.e(PUSH_NOTIFICATION, "ERROR: " + e.getMessage());
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(link));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody())
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, builder.build());
notificationId = ++notificationId;
}
The androidManifest.xml looks like:
<?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.myapp" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<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/Theme.AppCompat" >
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorNotification" />
<activity
android:name="com.myapp.app.mobile.MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|screenSize"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="OPEN_DEEPLINK_FROM_PUSH_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="app.myapp.com" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="app.myapp.com" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="app.myapp.ch" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="app.myapp.ch" />
</intent-filter>
</activity>
<service
android:name="com.myapp.app.mobile.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
Opening deeplinks when an app is not running is handled in onPageFinished() of my WebViewClient instance (what works for openening deeplinks eg. from email when the app is not running):
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
if(intent.getData() != null){
openDeeplink(intent);
}
}
I am wondering why this logic does not work in case of tapping a notification when the app was not running?
Any suggestions are welcome.
As firebese the docs describe here: https://firebase.google.com/docs/cloud-messaging/android/receive the data is delivered within the extras of the intent. This also applies for apps that are NOT running. I think the docs are not precise enough in this matter.
The following fix did the trick in this case:
public void onPageFinished(WebView view, String url) {
Intent intent = getIntent();
if(intent.getData() != null || intent.getExtras() != null){
openDeeplink(intent);
}
I am working on a project in which I have made app to default sms app and getting new message body and notification through Broadcast Receiver. It is showing toast that new message has been received and also read new message body.
But problems are
Problem 1:
The newly received sms is not retrieving from my default sms app inbox and not showing in my listview.
Problem 2:
I am not able to get each and every message from each conversation
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.e(TAG, "Intent recieved: " + intent.getAction());
if (intent.getAction() == SMS_RECEIVED) {
SmsMessage msg = null;
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > -1) {
Log.e(TAG, "Message recieved: " + messages[0].getMessageBody());
MyNotificationManager.getInstance(context).displayNotification(messages[0].getOriginatingAddress(), messages[0].getMessageBody());
}
}
}
}
Manifest File
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<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-sdk android:name="org.apache.http.legacy" android:required="false"/>
<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"
android:name="com.ughareja.whocaller.utils.App"
android:networkSecurityConfig="#xml/network_security_config"
android:largeHeap="true">
<activity android:name="com.ughareja.whocaller.activities.SplashActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id" />
<receiver android:name=".smsReciever.SmsListener"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".smsReciever.MmsReciever"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".smsReciever.ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".smsReciever.HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
Can you tell me How to save receive message ?
To receive, I suggest changing your manifest:
<receiver android:name=".smsReciever.SmsListener"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver android:name=".smsReciever.MmsReciever"
android:enabled="true"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
In addition, you will need to declare the following permissions:
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
You shouldn't be doing so much work on the receiver, send it to an intentReceiver instead:
#Override
public void onReceive(Context context, Intent intent) {
Timber.i("Intent received: " + intent.getAction());
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
Intent intentServiceIntent = new Intent(context, SMSIntentService.class);
intentServiceIntent.putExtras(bundle);
context.startService(intentServiceIntent);
//send broadcast to networkAvailableReceiver
Intent intentNetworkBroadcastReceiver = new Intent();
intentNetworkBroadcastReceiver.setAction("Youraction.CHECK_NETWORK_CONNECTIVITY");
context.sendBroadcast(intentNetworkBroadcastReceiver);
}
}
Here's what I use to parse out the message:
private fun parseOutMessages(intent : Intent?) {
val msgsAny : Array<Any>
var sender: String?
val msgBody: String
var bundle = Bundle()
if (intent != null) {
bundle = intent.extras as Bundle
}
try {
//parses out the message
val pdus = bundle.get("pdus") as Array<Any>
val msgs = Array<SmsMessage?>(pdus.size, {null})
for (i in msgs.indices) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val format = bundle.getString("format")
msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray, format)
} else {
msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
}
// Here you have the sender(phone number)
sender = msgs[i]?.originatingAddress
//is the message long enough to send?
var messageBodyLength = 0
if (msgs[i] != null) {
val message = msgs[i] as SmsMessage
messageBodyLength = message.messageBody.length
}
}
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
}
}
I'm developing a Android IM Chat app using PubNub and Backendless. I'm currently working on sending a Push Notification to user when they get a new chat message. I successfully integrated PubNub and GCM. So, I can send notification to the device using those two services. I followed this tutorial to get this done.
https://www.pubnub.com/blog/2015-06-24-sending-receiving-android-push-notifications-with-gcm-google-cloud-messaging/
But even though notification message is sending, it's not showing in the notification bar of the mobile phone as a push notification. Message come to the device with the tone. But no message is showing as notification bar. Can anyone please help me with the issue. Here is my code so far
This is my AndroidManifest file
<permission android:name="your.package.name.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="your.package.name.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<!--<receiver
android:name="your.package.name.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="your.package.name" />
</intent-filter>
</receiver>-->
<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" />
<category android:name="your.package.name" />
</intent-filter>
</receiver>
<!-- [START gcm_listener] -->
<service
android:name="your.package.name.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="your.package.name.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name="your.package.name.RegistrationIntentService"
android:exported="false">
</service>
</application>
This is my MainActivity Class ( Some Parts of the class)
[ Send Notification method ]
public void sendNotification() {
PnGcmMessage gcmMessage = new PnGcmMessage();
JSONObject jso = new JSONObject();
try {
jso.put("GCMSays", "hi");
} catch (JSONException e) { }
gcmMessage.setData(jso);
PnMessage message = new PnMessage(
pubnub,
"GCMPush",
callback,
gcmMessage);
try {
message.publish();
} catch (PubnubException e) {
e.printStackTrace();
}
}
This is GCMListenerService class
ublic class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
}
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
//.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
Can anyone please tell what is the wrong with this implementation. I can give you more code if you want.
Thanks in advance
I found the error I have been made when I was defining the sendNortification method. I have commented out the .setSmallIcon property in NotificationCompact which is a required notification content.
Thanks
I am trying to get started with Parse push notification on Android, but I could not find any way to implement my own BroadcastReceiver which would perform action in response to a push notification.
In their "getting started", they give a program sample where the receiver and the intent service is contained in the jar file (and not implemented in the code, so that I could try and play with it). A similar question has been asked here, but it's two years old and the answer has 11 downvotes.
There are a few other blog posts, e.g. as in here, but none of them work properly (the one in that link was two years old).
So please kindly suggest a step by step way to implement the same.
EDIT:
I tried the code as suggested by droidx. But it does not work. I am sending my AndroidManifest.xml (rest of the code is exactly as he suggested):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rahulserver.parsenotificationdemo" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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" />
<!--
IMPORTANT: Change "com.parse.starter.permission.C2D_MESSAGE" in the lines below
to match your app's package name + ".permission.C2D_MESSAGE".
-->
<permission android:protectionLevel="signature"
android:name="com.rahulserver.parsenotificationdemo.permission.C2D_MESSAGE" />
<uses-permission android:name="com.rahulserver.parsenotificationdemo.permission.C2D_MESSAGE" />
<application
android:name=".ParseNotification"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<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=".MyCustomParsePushReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</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" />
<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.rahulserver.parsenotificationdemo" />
</intent-filter>
</receiver>
</application>
</manifest>
Here's an example!
public class ParseCustomBroadcastReceiver extends ParsePushBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
JSONObject json = new JSONObject(intent.getExtras().getString("com.parse.Data"));
Log.d(TAG, json.getString("alert").toString());
final String notificationTitle = json.getString("title").toString();
final String notificationContent = json.getString("alert").toString();
final String uri = json.getString("uri");
Intent resultIntent = null;
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
resultIntent = new Intent(context, HomeScreen.class);
stackBuilder.addParentStack(HomeScreen.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
//Customize your notification - sample code
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_notification_icon)
.setContentTitle(notificationTitle)
.setContentText(notificationContent);
int mNotificationId = 001;
NotificationManager mNotifyMgr =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, builder.build());
} catch (JSONException e) {
Log.d(TAG, e.getMessage());
}
}
}
Following this guide, replace android name for the receiver to the path of your custom broadcastreceiver
<receiver
android:name=".receivers.ParseCustomBroadcastReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
In your application class, make sure to have subscribed to Parse Push like this
Parse.initialize(this, ParseUtils.PARSE_APPLICATION_ID_DEV, ParseUtils.PARSE_CLIENT_KEY_DEV);
ParseObject.registerSubclass(Article.class);
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d(TAG, "successfully subscribed to the broadcast channel.");
} else {
Log.e(TAG, "failed to subscribe for push", e);
}
}
});
Update:
The above broadcast receiver expects to send a json object notification from parse dashboard usually consists of three name value pairs:
{ "alert": "Alert message", "title": "Title", "uri": "bla bla" }
When you use only plain string for eg: hello world! in parse push dashboard, internally it goes as only alert tag. something like this : {"alert" : "hello world!, "title" = null/"", "uri" = null/""}
The broadcast receiver code above doesn't have this null checks, so it's caught in the catch with exception No title/uri.
So you can add some null checks based on what you are expecting from the push notification.
Something like this:
JSONObject json = new JSONObject(intent.getExtras().getString("com.parse.Data"));
Log.d(TAG, json.getString("alert").toString());
if (json.has("title")) {
notificationTitle = json.getString("title").toString();
}
if (json.has("alert")) {
notificationAlert = json.getString("alert").toString();
}
if(json.has("uri")) {
notificationURI = json.getString("uri");
}
Then set appropriate contentTitle and contentText in notification
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(notificationAlert)
.setContentText(notificationAlert);
Hope this helps!
I am using GCM for push notifications for my project, but am stuck at acquiring wake lock.
Log message:
09-03 17:04:05.003: V/GCMBroadcastReceiver(5772): onReceive:com.google.android.c2dm.intent.REGISTRATION
09-03 17:04:05.003: V/GCMBroadcastReceiver(5772): GCM IntentService class: example.pro.GCMIntentService
09-03 17:04:05.049: V/GCMBaseIntentService(5772): Acquiring wakelock
Below is my manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="example.pro"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="example.pro.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="example.pro.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name="com.thinkappz.advancedtictactoe.FriendPickerApplication"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<activity
android:name="com.thinkappz.advancedtictactoe.Splash"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.google.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
<activity
android:name="com.thinkappz.advancedtictactoe.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name=".MainActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.GcmMainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name=".GcmMainActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.NewGame"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.NewGame" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.Vs_Facebook"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.Vs_Facebook" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.RandomPlayer"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.RandomPlayer" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.Register"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.Register" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.RegisterActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.RegisterActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.SendRequest"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.SendRequest" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.PickFriendsActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.PickFriendsActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.getFinishedGames"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.getFinishedGames" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.thinkappz.advancedtictactoe.HomeScreen"
android:label="#string/app_name" >
<intent-filter>
<action android:name="example.pro.HomeScreen" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/app_id" />
<activity android:name="com.facebook.LoginActivity" />
<receiver
android:name="com.google.android.gcm.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="example.pro" />
</intent-filter>
</receiver>
<service android:name="com.thinkappz.advancedtictactoe.GCMIntentService" />
</application>
</manifest>
GCMIntentService----> This class file is inside com.thinkappz.advancedtictactoe package, but my R.java file is generated inside example.pro. I don't know why.
package com.thinkappz.advancedtictactoe;
import javax.management.Notification;
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
public GCMIntentService() {
super(SENDER_ID);
}
/**
* Method called on device registered
**/
#Override
protected void onRegistered(Context context, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
displayMessage(context, "Your device registred with GCM");
Log.d("NAME", GcmMainActivity.name);
ServerUtilities.register(context, GcmMainActivity.name,
GcmMainActivity.email, registrationId);
}
/**
* Method called on device un registred
* */
#Override
protected void onUnregistered(Context context, String registrationId) {
Log.i(TAG, "Device unregistered");
displayMessage(context, getString(R.string.gcm_unregistered));
ServerUtilities.unregister(context, registrationId);
}
/**
* Method called on Receiving a new message
* */
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("price");
displayMessage(context, message);
// notifies user
generateNotification(context, message);
}
/**
* Method called on receiving a deleted message
* */
#Override
protected void onDeletedMessages(Context context, int total) {
Log.i(TAG, "Received deleted messages notification");
String message = getString(R.string.gcm_deleted, total);
displayMessage(context, message);
// notifies user
generateNotification(context, message);
}
/**
* Method called on Error
* */
#Override
public void onError(Context context, String errorId) {
Log.i(TAG, "Received error: " + errorId);
displayMessage(context, getString(R.string.gcm_error, errorId));
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
displayMessage(context,
getString(R.string.gcm_recoverable_error, errorId));
return super.onRecoverableError(context, errorId);
}
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
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;
// Play default notification sound
notification.defaults |= Notification.DEFAULT_SOUND;
// notification.sound = Uri.parse("android.resource://" +
// context.getPackageName() + "your_sound_file_name.mp3");
// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}
}
I also tried <service android:name="example.pro.GCMIntentService" /> But then it is giving me an error while registering, saying that it can't instantiate service.
You are using the com.google.android.gcm.GCMBroadcastReceiver broadcast receiver from the Google GCM client library. This class expects the intent service to be in the main package of your app (example.pro) but your intent service is in a different package - com.thinkappz.advancedtictactoe. That's why the receiver can't find the service.
You should either move the GCMIntentService to the main package of your app, or override GCMBroadcastReceiver.