我遇到一个问题,即更新我的项目后,运行 Android 14(API 级别 34) 的设备上未收到通知,但通知无法显示在 Android 14 设备上。
清单权限:
<?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>
通知代码
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();
}
}
}
在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();
}
}
}
}
后台服务
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());
}
}
前台服务
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);
}
}
}
问题:
我在 Google 和 ChatGPT 的帮助下尝试了多种选项,但仍未解决。
确保您在 MainActivity 中正确请求 POST_NOTIFICATIONS 权限。您现有的代码似乎是正确的,但请确保它正在执行。
或 更新 PendingIntent 标志: 确保您对 PendingIntent 使用适当的标志。具体来说,根据您的需要使用 PendingIntent.FLAG_UPDATE_CURRENT 或其他合适的标志。
PendingIntent 待定意图; 如果(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ endingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, 意图, PendingIntent.FLAG_MUTABLE); } 别的 { endingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, 意图, PendingIntent.FLAG_UPDATE_CURRENT); }