Reputation: 13
I'm encountering an issue where notifications are not being received on devices running Android 14 (API level 34) after updating my project, but they fail to appear on Android 14 devices.
Manifest permissions:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<queries>
<intent>
<action
android:name="android.media.action.IMAGE_CAPTURE"
android:exported="true" />
</intent>
</queries>
<application
android:name=".Utils.App"
android:allowBackup="false"
android:exported="true"
android:icon="@drawable/app_logo"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@drawable/app_logo"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:replace="android:allowBackup">
<uses-library
android:name="org.apache.http.legacy"
android:exported="true"
android:required="false" />
<service
android:name=".Utils.ForegroundService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="dataSync" />
<service
android:name=".Utils.BackgroundService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="dataSync"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:exported="true"
android:value="@string/google_maps_key" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action
android:name="android.intent.action.MAIN"
android:exported="true" />
<category
android:name="android.intent.category.LAUNCHER"
android:exported="true" />
</intent-filter>
</activity>
<service
android:name=".Utils.MyFirebaseMessagingService"
android:enabled="true"
android:exported="false"
android:stopWithTask="false">
<intent-filter>
<action
android:name="com.google.firebase.MESSAGING_EVENT"
android:exported="true" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:exported="true"
android:value="@string/notification_channel_id" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:exported="true"
android:resource="@mipmap/ic_launcher_foreground" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:exported="true"
android:resource="@mipmap/ic_launcher_foreground" />
<meta-data
android:name="com.google.android.gms.wallet.api.enabled"
android:exported="true"
android:value="true" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:exported="true"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
Notification code
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String CHANNEL_ID = "default_channel";
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 fcm_notification = "";
private String uid = "";
private String stuName = "", clsSec = "", imgUrl_old = "", imgUrl_new = "", enrollmentNo = "", cls = "", sec = "", conType = "", component = "", period = "";
@Override
public void onNewToken(@NonNull String s) {
super.onNewToken(s);
Log.e("newToken", s);
}
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.e("Message Body", Objects.requireNonNull(Objects.requireNonNull(remoteMessage.getNotification()).getBody()));
Log.e("Message data payload: ", remoteMessage.getData().toString());
Log.e("From: ", Objects.requireNonNull(remoteMessage.getFrom()));
if (!remoteMessage.getData().isEmpty()) {
try {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
id = remoteMessage.getData().get("id");
uid = remoteMessage.getData().get("uid");
title = remoteMessage.getData().get("title");
message = remoteMessage.getData().get("message");
type = remoteMessage.getData().get("type");
fcm_notification = "Y";
stuName = remoteMessage.getData().get("stuName");
clsSec = remoteMessage.getData().get("clsSec");
imgUrl_old = remoteMessage.getData().get("oldImg");
imgUrl_new = remoteMessage.getData().get("newImg");
enrollmentNo = remoteMessage.getData().get("enrollmentNo");
cls = remoteMessage.getData().get("cls");
sec = remoteMessage.getData().get("sec");
conType = remoteMessage.getData().get("conType");
component = remoteMessage.getData().get("component");
period = remoteMessage.getData().get("period");
} catch (Exception e) {
e.printStackTrace();
}
}
sendNotification(remoteMessage.getNotification().getBody(), id, uid, title, message, type, fcm_notification, stuName, clsSec, imgUrl_old, imgUrl_new, enrollmentNo, cls, sec, conType, component, period);
}
private void sendNotification(String body, String user_id, String uid, String title, String message, String type, String fcm_notification, String stuName, String clsSec, String imgUrl_old, String imgUrl_new, String enrollmentNo, String cls, String sec, String conType, String component, String period) {
try {
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);
intent.putExtra("uid", uid);
intent.putExtra("stuName", stuName);
intent.putExtra("clsSec", clsSec);
intent.putExtra("imgUrl_old", imgUrl_old);
intent.putExtra("imgUrl_new", imgUrl_new);
intent.putExtra("enrollmentNo", enrollmentNo);
intent.putExtra("cls", cls);
intent.putExtra("sec", sec);
intent.putExtra("conType", conType);
intent.putExtra("component", component);
intent.putExtra("period", period);
int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
PendingIntent pendingIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent, PendingIntent.FLAG_MUTABLE);
} else {
pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
}
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
notificationBuilder.setSmallIcon(R.drawable.app_logo)
.setContentText(body)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.app_logo))
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setLights(Color.RED, 1000, 300)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSmallIcon(R.drawable.app_logo);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(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());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Requesting notification permission in MainActivity
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_NOTIFICATION_PERMISSION = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, REQUEST_NOTIFICATION_PERMISSION);
} else {
// Permission already granted
showNotification();
}
} else {
// For devices below Android 13, no need to request the permission
showNotification();
}
}
private void showNotification() {
// Code to show your notification
Toast.makeText(this, "Notification permission granted", Toast.LENGTH_SHORT).show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_NOTIFICATION_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
showNotification();
} else {
// Permission denied
Toast.makeText(this, "Notification permission denied", Toast.LENGTH_SHORT).show();
}
}
}
}
Background service
public class BackgroundService extends Service {
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForegroundService();
return super.onStartCommand(intent, flags, startId);
}
private void startForegroundService() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Create Notification Channel
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
startForeground(NOTIF_ID, new NotificationCompat.Builder(this, NOTIF_CHANNEL_ID)
.setOngoing(true)
.setSmallIcon(R.drawable.app_logo)
.setContentTitle(getString(R.string.app_name))
.setContentText("Service is running in the background")
.setContentIntent(pendingIntent)
.build());
}
}
Foreground Service
public class ForegroundService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.app_logo)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(CHANNEL_ID, "Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
Questions:
I have tried multiple options with the help of Google and ChatGPT, but it remains unresolved.
Upvotes: 0
Views: 2040
Reputation: 1
Ensure you are requesting the POST_NOTIFICATIONS permission properly in your MainActivity. Your existing code for this seems correct, but make sure it is being executed.
or Update PendingIntent Flags: Ensure that you are using the appropriate flags for PendingIntent. Specifically, use PendingIntent.FLAG_UPDATE_CURRENT or other suitable flags depending on your needs.
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent, PendingIntent.FLAG_MUTABLE);
} else {
pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Upvotes: 0