我在Android应用中使用GCM通过设备发送通知。但该应用程序显示将收到所有通知。但我只是想显示“新”消息,因此旧消息应标记为“已读”或其他内容。
以下是我的GCM课程:
public class NotificationUtils {
private static String TAG = NotificationUtils.class.getSimpleName();
private Context mContext;
public NotificationUtils() {
}
public NotificationUtils(Context mContext) {
this.mContext = mContext;
}
public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent, null);
}
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
if (!TextUtils.isEmpty(imageUrl)) {
if (imageUrl != null && imageUrl.length() > 4 && Patterns.WEB_URL.matcher(imageUrl).matches()) {
Bitmap bitmap = getBitmapFromURL(imageUrl);
if (bitmap != null) {
showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
} else {
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
}
}
} else {
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
if(Config.appendNotificationMessages){
// store the notification in shared pref first
AppController.getInstance().getPrefManager().addNotification(message);
// get the notifications from shared preferences
String oldNotification = AppController.getInstance().getPrefManager().getNotifications();
List<String> messages = Arrays.asList(oldNotification.split("\\|"));
for (int i = messages.size() - 1; i >= 0; i--) {
inboxStyle.addLine(messages.get(i));
}
}else{
inboxStyle.addLine(message);
}
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.drawable.load_profilepic)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID, notification);
}
private void showBigNotification(Bitmap bitmap, NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
bigPictureStyle.setBigContentTitle(title);
bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
bigPictureStyle.bigPicture(bitmap);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(bigPictureStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.drawable.load_profilepic)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);
}
/**
* Downloading push notification image before displaying it in
* the notification tray
* */
public Bitmap getBitmapFromURL(String strURL) {
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// Playing notification sound
public void playNotificationSound() {
try {
Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + AppController.getInstance().getApplicationContext().getPackageName() + "/raw/notification");
Ringtone r = RingtoneManager.getRingtone(AppController.getInstance().getApplicationContext(), alarmSound);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Method checks if the app is in background or not
*/
public static boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
// Clears notification tray messages
public static void clearNotifications() {
NotificationManager notificationManager = (NotificationManager) AppController.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
public static long getTimeMilliSec(String timeStamp) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = format.parse(timeStamp);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
}
}
public class GcmIntentService extends IntentService {
private static final String TAG = GcmIntentService.class.getSimpleName();
public GcmIntentService() {
super(TAG);
}
public static final String KEY = "key";
public static final String TOPIC = "topic";
public static final String SUBSCRIBE = "subscribe";
public static final String UNSUBSCRIBE = "unsubscribe";
@Override
protected void onHandleIntent(Intent intent) {
String key = intent.getStringExtra(KEY);
switch (key) {
case SUBSCRIBE:
// subscribe to a topic
String topic = intent.getStringExtra(TOPIC);
subscribeToTopic(topic);
break;
case UNSUBSCRIBE:
break;
default:
// if key is specified, register with GCM
registerGCM();
}
}
/**
* Registering with GCM and obtaining the gcm registration id
*/
private void registerGCM() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.e(TAG, "GCM Registration Token: " + token);
// sending the registration id to our server
sendRegistrationToServer(token);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, true).apply();
} catch (Exception e) {
Log.e(TAG, "Failed to complete token refresh", e);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
private void sendRegistrationToServer(final String token) {
// checking for valid login session
User user = AppController.getInstance().getPrefManager().getUser();
if (user == null) {
// TODO
// user not found, redirecting him to login screen
return;
}
String endPoint = EndPoints.USER.replace("_ID_", user.getId());
Log.e(TAG, "endpoint: " + endPoint);
StringRequest strReq = new StringRequest(Request.Method.PUT,
endPoint, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.e(TAG, "response: " + response);
try {
JSONObject obj = new JSONObject(response);
// check for error
if (obj.getBoolean("error") == false) {
// broadcasting token sent to server
Intent registrationComplete = new Intent(Config.SENT_TOKEN_TO_SERVER);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(registrationComplete);
} else {
Toast.makeText(getApplicationContext(), "Unable to send gcm registration id to our sever. " + obj.getJSONObject("error").getString("message"), Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("gcm_registration_id", token);
Log.e(TAG, "params: " + params.toString());
return params;
}
};
//Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq);
}
/**
* Subscribe to a topic
*/
public static void subscribeToTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(AppController.getInstance().getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(AppController.getInstance().getApplicationContext());
String token = null;
try {
token = instanceID.getToken(AppController.getInstance().getApplicationContext().getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.subscribe(token, "/topics/" + topic, null);
Log.e(TAG, "Subscribed to topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(AppController.getInstance().getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void unsubscribeFromTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(getApplicationContext());
String token = null;
try {
token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.unsubscribe(token, "");
Log.e(TAG, "Unsubscribed from topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic unsubscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
public class MyGcmPushReceiver extends GcmListenerService {
private static final String TAG = MyGcmPushReceiver.class.getSimpleName();
private NotificationUtils notificationUtils;
/**
* Called when message is received.
*
* @param from SenderID of the sender.
* @param bundle Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
@Override
public void onMessageReceived(String from, Bundle bundle) {
String title = bundle.getString("title");
Boolean isBackground = Boolean.valueOf(bundle.getString("is_background"));
String flag = bundle.getString("flag");
String data = bundle.getString("data");
Log.d(TAG, "From: " + from);
Log.d(TAG, "title: " + title);
Log.d(TAG, "isBackground: " + isBackground);
Log.d(TAG, "flag: " + flag);
Log.d(TAG, "data: " + data);
if (flag == null)
return;
if(AppController.getInstance().getPrefManager().getUser() == null){
// user is not logged in, skipping push notification
Log.e(TAG, "user is not logged in, skipping push notification");
return;
}
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
switch (Integer.parseInt(flag)) {
case Config.PUSH_TYPE_CHATROOM:
// push notification belongs to a chat room
processChatRoomPush(title, isBackground, data);
break;
case Config.PUSH_TYPE_USER:
// push notification is specific to user
processUserMessage(title, isBackground, data);
break;
}
}
/**
* Processing chat room push message
* this message will be broadcasts to all the activities registered
* */
private void processChatRoomPush(String title, boolean isBackground, String data) {
if (!isBackground) {
try {
JSONObject datObj = new JSONObject(data);
String chatRoomId = datObj.getString("chat_room_id");
JSONObject mObj = datObj.getJSONObject("message");
Message message = new Message();
message.setMessage(mObj.getString("message"));
message.setId(mObj.getString("message_id"));
message.setCreatedAt(mObj.getString("created_at"));
JSONObject uObj = datObj.getJSONObject("user");
// skip the message if the message belongs to same user as
// the user would be having the same message when he was sending
// but it might differs in your scenario
if (uObj.getString("user_id").equals(AppController.getInstance().getPrefManager().getUser().getId())) {
Log.e(TAG, "Skipping the push message as it belongs to same user");
return;
}
User user = new User();
user.setId(uObj.getString("user_id"));
user.setEmail(uObj.getString("email"));
user.setName(uObj.getString("name"));
message.setUser(user);
// verifying whether the app is in background or foreground
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra("type", Config.PUSH_TYPE_CHATROOM);
pushNotification.putExtra("message", message);
pushNotification.putExtra("chat_room_id", chatRoomId);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils();
notificationUtils.playNotificationSound();
} else {
// app is in background. show the message in notification try
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("chat_room_id", chatRoomId);
showNotificationMessage(getApplicationContext(), title, user.getName() + " : " + message.getMessage(), message.getCreatedAt(), resultIntent);
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
} else {
// the push notification is silent, may be other operations needed
// like inserting it in to SQLite
}
}
/**
* Processing user specific push message
* It will be displayed with / without image in push notification tray
* */
private void processUserMessage(String title, boolean isBackground, String data) {
if (!isBackground) {
try {
JSONObject datObj = new JSONObject(data);
String imageUrl = datObj.getString("image");
JSONObject mObj = datObj.getJSONObject("message");
Message message = new Message();
message.setMessage(mObj.getString("message"));
message.setId(mObj.getString("message_id"));
message.setCreatedAt(mObj.getString("created_at"));
JSONObject uObj = datObj.getJSONObject("user");
User user = new User();
user.setId(uObj.getString("user_id"));
user.setEmail(uObj.getString("email"));
user.setName(uObj.getString("name"));
message.setUser(user);
// verifying whether the app is in background or foreground
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra("type", Config.PUSH_TYPE_USER);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils();
notificationUtils.playNotificationSound();
} else {
// app is in background. show the message in notification try
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
// check for push notification image attachment
if (TextUtils.isEmpty(imageUrl)) {
showNotificationMessage(getApplicationContext(), title, user.getName() + " : " + message.getMessage(), message.getCreatedAt(), resultIntent);
} else {
// push notification contains image
// show it with the image
showNotificationMessageWithBigImage(getApplicationContext(), title, message.getMessage(), message.getCreatedAt(), resultIntent, imageUrl);
}
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
} else {
// the push notification is silent, may be other operations needed
// like inserting it in to SQLite
}
}
/**
* Showing notification with text only
* */
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
/**
* Showing notification with text and image
* */
private void showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);
}
}
public class MyInstanceIDListenerService extends InstanceIDListenerService {
private static final String TAG = MyInstanceIDListenerService.class.getSimpleName();
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. This call is initiated by the
* InstanceID provider.
*/
@Override
public void onTokenRefresh() {
Log.e(TAG, "onTokenRefresh");
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
Intent intent = new Intent(this, GcmIntentService.class);
startService(intent);
}
}
那么,我怎样才能显示新通知,而不是所有收到的通知。