我正在构建一个不需要服务器设置的 android firebase 聊天应用程序,我已经为它构建了一切,并找到了一些关于如何做我现在遇到问题的 YouTube 教程,我我正在尝试让应用程序本身向其发送消息的设备发送推送通知,我正在使用 Volley 发送通知,我面临的问题是另一台设备没有收到或显示通知,你能告诉我我做错了什么以及如何解决吗?
build.gradle
implementation 'com.google.firebase:firebase-auth:20.0.4'
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation platform('com.google.firebase:firebase-bom:27.0.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-messaging:20.0.1'
implementation 'com.android.volley:volley:1.1.1'
AndroidManifest
<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="com.google.android.c2dm.permission.RECEIVE" />
...
<service
android:name=".MyFirebaseMessagingService"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
MyFirebaseInstanceIDService
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "mFirebaseIIDService";
@Override
public void onTokenRefresh() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String token = FirebaseInstanceId.getInstance().getToken();
FirebaseInstallations.getInstance().getToken(false)
.addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
@Override
public void onComplete(@NonNull Task<InstallationTokenResult> task) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
FirebaseMessaging.getInstance().subscribeToTopic(user.getUid());
Log.i("TAG", "onTokenRefresh completed with token: " + task.getResult().getToken());
}
});
}
}
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID = "admin_channel";
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(85-65);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setupChannels(notificationManager);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
notificationManager.notify(notificationID, notificationBuilder.build());
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager){
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to device notification";
NotificationChannel adminChannel;
adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
adminChannel.setDescription(adminChannelDescription);
adminChannel.enableLights(true);
adminChannel.setLightColor(Color.RED);
adminChannel.enableVibration(true);
if (notificationManager != null) {
notificationManager.createNotificationChannel(adminChannel);
}
}
}
消息活动
final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
final private String serverKey = "key=MY_KEY";
final private String contentType = "application/json";
final String TAG = "NOTIFICATION TAG";
...
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String msg = msg_editText.getText().toString();
if (!msg.equals("")) {
sendMessage(fuser.getUid(), userid, msg);
JSONObject notification = getStructure(fuser.getUid(), userid, msg);
sendNotification(notification);
}
msg_editText.setText("");
}
});
...
private JSONObject getStructure(String senderId, String receiverId, String msg) {
JSONObject notification = new JSONObject();
JSONObject notificationBody = new JSONObject();
try {
notificationBody.put("title", "App Test");
notificationBody.put("message", "This is a test notification from the app");
notification.put("to", "/topics/" + receiverId);
notification.put("data", notificationBody);
} catch (JSONException e) {
e.printStackTrace();
}
return notification;
}
...
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(TAG, "onResponse: " + response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MessageActivity.this, "Request error", Toast.LENGTH_SHORT).show();
Log.i(TAG, "onErrorResponse: Didn't work");
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Authorization", serverKey);
params.put("Content-Type", contentType);
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
MySingleton
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private Context ctx;
public MySingleton(Context ctx) {
this.ctx = ctx;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}