我正在使用Firebase开发一个Android聊天应用。除推送通知外,其他一切正常。我已经在Google上搜索并阅读了有关该问题的几乎所有帖子,但仍然没有找到解决方案!
问题:将应用重新安装到设备上!我收到通知(仅一次),然后,没有任何显示的通知。 Volley返回一条成功消息“每条成功消息的多播ID都相同,甚至每条成功消息的消息ID都相同”,想知道这与问题有关!请看下面的代码:
1)我的Web地址(应用服务器)上运行的我的PHP脚本:
<?php
define( 'API_ACCESS_KEY', 'AAAAeaFcZdA:APA91bFqhLc..............' );
$token = $_GET["token"];
$title = $_POST["title"];
$notification = $_POST["message"];
$msg =
[
'message' => $notification,
'title' => $title,
];
$fields =
[
'to' => $token,
'data' => $msg
];
$headers =
[
'Authorization: key=' . API_ACCESS_KEY,
'Content-Type: application/json'
];
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close( $ch );
echo $result;
?>
2)我的MessagingService(Firebase)获取通知,因为我收到第一个通知,所以我相信它的配置正确!
public class MessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Timber.i("From: " + remoteMessage.getFrom());
//Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Timber.i("Message data payload: " + remoteMessage.getData());
Map<String, String> data = remoteMessage.getData();
sendNotification(data);
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Timber.i("Message Notification Body: " + remoteMessage.getNotification().getBody());
Map<String, String> data = remoteMessage.getData();
sendNotification(data);
}
Map<String, String> data = remoteMessage.getData();
sendNotification(data);
}
@Override
public void onNewToken(@NonNull String token) {
Timber.i("MyToken: " + token);
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference usersdRef = database.getReference("users");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
usersdRef.child(user.getUid()).child("tokens").setValue(token);
}
}
private void sendNotification(Map<String, String> messageBody) {
String myTitle = messageBody.get("title");
final int not_nu = generateRandom();
Intent intent = new Intent(this, ChatMessageActivity.class);
intent.putExtra("username", myTitle);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
ChatUserModel.chatWith = myTitle;
PendingIntent pendingIntent = PendingIntent.getActivity(this, not_nu /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.marker)
.setContentTitle(messageBody.get("title"))
.setContentText(messageBody.get("message"))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(not_nu /* ID of notification */, notificationBuilder.build());
}
public int generateRandom() {
Random random = new Random();
return random.nextInt(9999 - 1000) + 1000;
}}
3)我将消息发送给其他用户的聊天活动。getOtherToken =我将向其发送消息的其他用户令牌ID
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String messageText = messageArea.getText().toString();
SimpleDateFormat sdf = new SimpleDateFormat("dd.MMM.yyyy", Locale.getDefault());
String currentDate = sdf.format(new Date());
String currentTime = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(new Date());
if (!messageText.equals("")) {
Map<String, String> map = new HashMap<String, String>();
map.put("message", messageText);
map.put("user", user.getDisplayName());
map.put("timetoshow", currentTime);
map.put("dateStamp", currentDate);
usersmRef.child(reference1).push().setValue(map);
usersmRef.child(reference2).push().setValue(map);
messageArea.setText("");
sendNotificationToappServer(getOtherToken, user.getDisplayName(), messageText);
Timber.i("GetOtherTOken: " + user.getDisplayName() + " | " + getOtherToken + " | " + messageText);
}
}
});
4)与上述相同的ChatActivity.java中的我的Volley方法,其中我向我的App Server发送字符串请求,这里的令牌是将接收消息的用户的令牌!
public void sendNotificationToappServer(String token, String title, String notification) {
String SERVER_ADDRESS = "https://www.mywebsite/notification.php?token=";
RequestQueue requestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
requestQueue = new RequestQueue(cache, network);
// Start the queue
requestQueue.start();
StringRequest stringRequest = new StringRequest(Request.Method.POST, SERVER_ADDRESS + token,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(ChatMessageActivity.this, response, Toast.LENGTH_LONG).show();
Timber.i("Volley: %s", response.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ChatMessageActivity.this, error.toString(), Toast.LENGTH_LONG).show();
Timber.i("Volley Error: " + error.toString());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("title", title);
params.put("message", notification);
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
requestQueue.add(stringRequest);
}
5)我的Volley Response在Android Studio中录制成功,这是第一次,它首次提供了推送通知,但此后直到重新安装为止!
除上述以外的任何要求!请告诉我。手指交叉!
我能够解决此问题!好吧,我发现问题是由于凌空造成的缓存管理。在发布新的队列请求之前,清除缓存将解决此问题!queue.getCache().clear();
[此外,我更喜欢在Volley中使用单例类。这是上面sendNotificationToappServer方法的更新代码:
public void sendNotificationToappServer(String token, String title, String notification) {
String SERVER_ADDRESS = "https://www.mywebsite/notification.php?token=";
// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(ChatMessageActivity.this).
getRequestQueue();
StringRequest stringRequest = new StringRequest(Request.Method.POST, SERVER_ADDRESS + token,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(ChatMessageActivity.this, response, Toast.LENGTH_LONG).show();
Timber.i("Volley: %s", response.toString());
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ChatMessageActivity.this, error.toString(), Toast.LENGTH_LONG).show();
Timber.i("Volley Error: " + error.toString());
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("title", title);
params.put("message", notification);
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
};
queue.getCache().clear();
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(stringRequest);
}
上面问题中的PHP代码非常有效!因此,如果您正在寻找用于一对一消息传递的Firebase Cloud消息传递App服务器的PHP脚本,那就去吧!