I have 2 kinds of notification builders in my MyFirebaseMessagingService.java, one passes string called 'lecture_date' and opens Lectures_graph.class while the other one passes string called 'web_url' and opens webview_base.class when clicked.
What i want to achieve : fully working FCM notifications even when app is killed, notifications must open activity (with extras) once they are clicked.
How far i am : I can receive notifications to open Lectures_graph.class with intent extras, everything loads and works just fine. Even if i receive notifications for webview_base.class activity, nothing happens when i click on notification.
There might be one thing that points to problem - Logcat often tells me this :
E/FirebaseMessaging: Notification pending intent canceled
Im using PHP to send out notifications (that code is 100% correct and working), code below shows represents the idea of JSON sent out for webview_base.class activity. To send out notifications for Lectures_graph.class activity, i just have to swap click_action from "OPEN_ACTIVITY_WEBVIEW" to "OPEN_ACTIVITY_LECTURES" and change the data payload. PHP for webview_base.class activity sends away such data :
$msg = array
(
'body' => 'test body',
'title' => "test title",
'click_action' => 'OPEN_ACTIVITY_WEBVIEW',
'channelId' => "newsfeed",
'vibrate' => 1,
'sound' => 1
);
//sends notifications via topics
$fields = array
(
"data" => [
'web_url' => $_POST['notification_url']
],
'notification' => $msg,
'to' => '/topics/test'
);
This is my whole manifest file from Android studio :
<?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="secret">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<application
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme.CustomTheme"
android:usesCleartextTraffic="true"
tools:targetApi="m">
<activity
android:name=".systems.webview_activity.webview_base"
android:configChanges="orientation|screenSize">
<intent-filter>
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="file" />
<data android:mimeType="\*/\*" />
<data android:pathPattern=".*\\.kdb" />
<data android:host="*" />
//even if this method worked with Lectures_graph activity
//it doesnt work with this one
<action android:name="OPEN_ACTIVITY_WEBVIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".systems.lectures.Lectures_graph"
android:configChanges="keyboardHidden|screenSize"
android:label="#string/title_lectures_graph"
>
<intent-filter>
//this intent filter provides correct response
//to click_action which is provided in my PHP file
<action android:name="OPEN_ACTIVITY_LECTURES" />
<action android:name = "android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".SplashScreen"
android:configChanges="keyboardHidden|orientation|screenSize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NoInternetConnection"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name="secret.systems.about.about_app"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="#style/FullscreenTheme" />
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
<service
android:name="secret.services.MyFirebaseMessagingService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
MyFirebaseMessagingService.java:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
//get key/value from notification
String lectureDate = remoteMessage.getData().get("lecture_date");
String web_url = remoteMessage.getData().get("web_url");
if(lectureDate != null)sendLecturesNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), lectureDate);
else if(web_url != null) sendNotificationWithURL(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), web_url);
else Log.e(TAG, "Message.notification is empty!");
}
}
#Override
public void onNewToken(#NonNull String token) {
Log.d(TAG, "Refreshed token: " + token);
}
private void sendLecturesNotification(String title,String messageBody, String date) {
Intent intent;
intent = new Intent(this, Lectures_graph.class).putExtra("lecture_date", date).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.lectures_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Lectures notification built with date:"+date);
}
private void sendNotificationWithURL(String title, String messageBody, String web_url) {
Intent intent;
intent = new Intent(this, webview_base.class).putExtra("web_url", web_url).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.newsfeed_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Webview notification built with URL:"+web_url);
}
}
a while ago i was getting an error in logcat that said something like "default FCM channel is not defined", but im not quite sure thats the problem.
Even if i searched across the whole web, i would like to see better solutions/suggestions for notification (with its payload) handling when app is killed.
So i fixed my nightmare and here is how :
Since i cant open more than one specific activity from notifications, why could i just open my apps main class and handle extra variable from there ?
Instead of having for each wanted activity
<intent-filter>
<action android:name="OPEN_ACTIVITY_???????" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
i made this :
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="OPEN_APP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
I added extra variable to notifications payload (examle : 'activity' => 'webview') and renamed click_action in my PHP code. I handled all payloads in MainActivity.class and called wanted android activity from there. MainActivity code :
Bundle extras = getIntent().getExtras();
if(extras == null) {
Log.e("MainActivity", "No Activities passed in notification extras");
} else {
//get opening activity from notification payload
String activity = extras.getString("activity");
if( activity != null){
switch (activity){
//webview activity
case "webview":
//gets url for webview
String web_url = extras.getString("web_url");
if(web_url != null){
finish();
startActivity(new Intent(this, webview_base.class).putExtra("web_url", web_url));
}
break;
//lectures activity
case "lectures":
//gets lecture date
String lecture_date = extras.getString("lecture_date");
if(lecture_date != null){
finish();
startActivity(new Intent(this, Lectures_graph.class).putExtra("lecture_date", lecture_date));
}
break;
}
}
}
Hope this helps someone, someday..
Cheers.
Related
As long as I don't turn the phone off (even if the application is closed), the forward notification that I have created with the alarm manager in my android-java mobile application does not have a problem. But when I restart the phone before the notification time comes, it doesn't work even if it's time for my notification. Can you please help? Thanks.
MY ALARM SERVICE CLASS
package com.gokhankopuz.kopuzfilo.services;
public class AlarmService {
private Context context = null;
private long timeInMillis = 0L;
private String notificationTitle, notificationDesc = "";
public AlarmService(Context context, long timeInMillis, String notificationTitle, String notificationDesc) {
this.context = context;
this.timeInMillis = timeInMillis;
this.notificationTitle = notificationTitle;
this.notificationDesc = notificationDesc;
}
public void setAlarm() {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, getPendingIntent());
}
private PendingIntent getPendingIntent() {
#SuppressLint("UnspecifiedImmutableFlag")
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, (int) timeInMillis, getIntent(), PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
private Intent getIntent() {
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("notificationTitle", notificationTitle);
intent.putExtra("notificationDesc", notificationDesc);
return intent;
}
}
MY ALARM RECEIVER CLASS
package com.gokhankopuz.kopuzfilo.receivers;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
buildNotification(context, intent);
}
private void buildNotification(Context context, Intent intent) {
String notificationTitle = intent.getStringExtra("notificationTitle");
String notificationDesc = intent.getStringExtra("notificationDesc");
Notify.build(context)
.setImportance(Notify.NotifyImportance.HIGH)
.setTitle(notificationTitle)
.setContent(notificationDesc)
.setColor(R.color.app_background)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false)
.show();
}
}
MY 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.gokhankopuz.kopuzfilo">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
tools:ignore="CoarseFineLocation" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.KopuzFilo"
tools:ignore="AllowBackup">
<activity
android:name=".activities.NavigationActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true" />
<activity
android:name=".activities.MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize|keyboardHidden"
android:windowSoftInputMode="stateVisible|adjustPan" />
<activity
android:name=".activities.SplashActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".receivers.AlarmReceiver" />
</application>
</manifest>
I added the following permissions to my manifest file but it didn't work
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
This is the expected behavior. If you turn off your device, all alarms are deleted. So, to workaround this issue, you must register for boot complete broadcast and re-schedule your alarm.
You can find more details on how to do it in the following question/answer:
does Alarm Manager persist even after reboot?
I think you can try use work manager, which will be executed by system.
WorkManager is the recommended solution for persistent work. Work is persistent when it remains scheduled through app restarts and system reboots. Because most background processing is best accomplished through persistent work, WorkManager is the primary recommended API for background processing.
I implemented FCM Push Notifications. The main problem is when app is closed, notifications not arrive when this happen on device.
I tried a lot of thigs for that works; when notification sent the server response with "success", but I never received.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String CHANNEL_NAME = "FCM";
private static final String CHANNEL_DESC = "Firebase Cloud Messaging";
final String TAG = "MyFirebaseMsgService";
private String id = "";
private String title = "";
private String message = "";
private String type = "";
private String module = "";
private String fcm_notification = "";
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("newToken", s);
getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG, "Message Body" + remoteMessage.getNotification().getBody());
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
id = remoteMessage.getData().get("id");
title = remoteMessage.getData().get("title");
message = remoteMessage.getData().get("message");
type = remoteMessage.getData().get("type");
fcm_notification = "Y";
}
sendNotification(remoteMessage.getNotification().getBody(), id, title, message, type, fcm_notification);
}
private void sendNotification(String body, String user_id, String title, String message, String type, String fcm_notification) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("fcm_notification", fcm_notification);
intent.putExtra("title", title);
intent.putExtra("message", message);
intent.putExtra("type", type);
intent.putExtra("id", user_id);
int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "");
notificationBuilder.setSmallIcon(R.drawable.ic_launcher_background)
.setContentText(body)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setColor(getResources().getColor(R.color.colorAccent))
.setLights(Color.RED, 1000, 300)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setSmallIcon(R.mipmap.ic_launcher);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
getString(R.string.notification_channel_id), CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT
);
channel.setDescription(CHANNEL_DESC);
channel.setShowBadge(true);
channel.canShowBadge();
channel.enableLights(true);
channel.setLightColor(Color.RED);
channel.enableVibration(true);
channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500});
assert notificationManager != null;
notificationManager.createNotificationChannel(channel);
}
assert notificationManager != null;
notificationManager.notify(0, notificationBuilder.build());
}
public static String getToken(Context context) {
return context.getSharedPreferences("_", MODE_PRIVATE).getString("fb", "empty");
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.TestNotification"
android:targetSandboxVersion="1">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".Utils.App"
android:allowBackup="true"
android:icon="#drawable/kl_logo"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true">
<service
android:name=".Utils.ForegroundService"
android:enabled="true"
android:exported="true"/>
<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=".Utils.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/notification_channel_id" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#mipmap/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
</application>
</manifest>
Try adding enabled="true" and INTERNAL_SERVICE permission to your message service
I am new to Android and programming and I am creating an app that receives messages from FCM and its work normally while the app in the Background, so I have added a FirebaseMessagingService class that receives the notifications in onMessageReceived method and followed out google docs but still the notification does not work while the app in the foreground state, I have followed every step and can't figure out where is the problem in my code as the Logs does not help me and I don't receive any bug expect this one which I don't know if its the source if the problem:
Error while parsing timestamp in GCM event java.lang.NumberFormatException: s == null
Here is my MyFirebaseMessagingService class
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import com.app.muhammadgamal.swapy.R;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String click_Action = remoteMessage.getNotification().getClickAction();
String messageTitle = remoteMessage.getNotification().getTitle();
String messageBody = remoteMessage.getNotification().getBody();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, getString(R.string.default_notification_channel_id))
.setSmallIcon(R.drawable.ic_main_logo)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
Intent intent = new Intent(click_Action);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
int mNotificationID = (int)System.currentTimeMillis();
NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
manager.notify(mNotificationID,mBuilder.build());
}
}
and my Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.app.muhammadgamal.swapy">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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:allowBackup="true"
android:icon="#drawable/ic_main_logo"
android:label="#string/app_name"
android:roundIcon="#drawable/ic_main_logo"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".Activities.SignInActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Activities.SignUpActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Activities.ProfileActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Activities.NavDrawerActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Activities.SwapCreationActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity android:name=".Activities.ReceivedSwapRequest">
<intent-filter>
<action android:name="com.app.muhammadgamal.swapy.Activities.ReceivedSwapRequest_NOTIFICATION_TASK"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
<service
android:name=".Notifications.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
and my index function
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Notifications/{receiver_user_id}/{notification_id}')
.onWrite((data, context) =>
{
const receiver_user_id = context.params.receiver_user_id;
const notification_id = context.params.notification_id;
console.log('We have a notification to send to :' , receiver_user_id);
if (!data.after.val())
{
console.log('A notification has been deleted :' , notification_id);
return null;
}
const DeviceToken = admin.database().ref(`/Users/${receiver_user_id}/device_token`).once('value');
return DeviceToken.then(result =>
{
const token_id = result.val();
const payload =
{
notification:
{
title: "New Swap Request",
body: `you have a new Swap Request, Please Check.`,
click_action: "com.app.muhammadgamal.swapy.Activities.ReceivedSwapRequest_NOTIFICATION_TASK"
}
};
return admin.messaging().sendToDevice(token_id, payload)
.then(response =>
{
return console.log('This was a notification feature.');
});
});
});
I discovered the problem, It was that I am using Android O and didn't set the Channel ID for the notification which is a must if you want to receive it on Android 8.0 or higher
so here is the solution code
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) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, 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);
}
}
I solved it but I no longer have the source code..sorry
I don't receive the notifications on my Android device. The messagge was sent successfully to the GCM servers. I tried them all. Can someone help me? This is the code:
GCMIntentService.java
public class GCMIntentService extends IntentService {
static SharedPreferences prefs;
static Editor editor;
Context context;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public static final String TAG = "GCM Intent Service";
public static final int NOTIFICATION_ID = 1;
public GCMIntentService() {
super(Configuration.SENDER_ID);
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
String msg = intent.getStringExtra("message");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.
MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server: " +
extras.toString());
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// This loop represents the service doing some work.
for (int i=0; i<5; i++) {
Log.i(TAG, "Working... " + (i+1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
// Post notification of received message.
//sendNotification("Received: " + extras.toString());
sendNotification(msg);
Log.i(TAG, "Received: " + extras.toString());
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
editor.putInt("lastViewVisited", 1).commit();
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getText(R.string.app_name).toString())
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(intent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="<MY-PACKAGE>"
android:versionCode="9"
android:versionName="2.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- GCM -->
<permission android:name="<MY-PACKAGE>.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="<MY-PACKAGE>.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<!-- GCM -->
<receiver android:name="<MY-PACKAGE>.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="<MY-PACKAGE>" />
</intent-filter>
</receiver>
<service android:name="<MY-PACKAGE>.GCMIntentService" android:enabled="true" />
<activity
android:name="<MY-PACKAGE>.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="<MY-PACKAGE>.PreferenceFragment"
android:label="Preferenze">
</activity>
</application>
</manifest>
GcmBroadcastReceiver.java
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GCMIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Try:
Check if you are using the browser api key to send the message from web server to android devices.
I am trying to capture download complete events, but my BroadcastReceiver is not receiving them. Here is the receiver:
public class DownloadListenerService extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
System.out.println("got here");
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
String downloadPath = intent.getStringExtra(DownloadManager.COLUMN_URI);
editor.putString("downloadPath", downloadPath);
editor.commit();
}
}
}
Here is the manifest:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name="com.example.alreadydownloaded.DownloadListenerService"
android:exported="true">
<intent-filter>
<action android:enabled="true" android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
</application>
Anyone see what's wrong?
Use full package name for you receiver like com.example.DownloadListenerService
Add android:exported="true" BroadcastReceiver can receive messages from sources outside its application.
Change the name of the Action in the intent-filter to android.intent.action.DOWNLOAD_COMPLETE
<receiver
android:name="com.example.DownloadListenerService"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.INTERNET" />
The receiver only will be triggered if was registered from your application using registerReceiver(#Nullable BroadcastReceiver receiver,IntentFilter filter);
Code to enqueue Download :
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("https://www.google.com/images/srpr/logo4w.png"));
dm.enqueue(request);
I think the action name in your XML is wrong. The docs state that the correct one is: android.intent.action.DOWNLOAD_COMPLETE not DownloadManager.ACTION_DOWNLOAD_COMPLETE - you need to use the constant, not the Java form.
<receiver android:name=".DownloadListenerService" >
<intent-filter>
<action android:enabled="true" android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
<receiver
android:name=".BroadCast_Service.Download_BroadCast"
android:exported="true">
<intent-filter android:priority="1099">
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
I think you are calling DownloadManger service from the IntentService/Service. If so remove it from there and put it into activity.
add permission in android manifest
<uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
If the download is based on your app then you need to send a broadcast?
Intent i = new Intent();
i.setAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
sendBroadcast(i);