I have just implemented Parse push notifications into my app. I want to be able to show the push notification, but i don't want the app to open when the user presses the Push notification. Instead, i just want the notification to be dismissed.
i would imagine it would be handled by the ParsePushBroadcastReciever, but i can't find anything online which fits my purpose.
Here is my subclassed ParsepushBroadcastReciever:
public class Receiver extends ParsePushBroadcastReceiver {
#Override
public void onPushOpen(Context context, Intent intent) {
Log.e("Push", "Clicked");
Intent i = new Intent(context, HomeScreen.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
In order for you to programatically dismiss a notification you will need to call cancel() using a NotificationManager instance passing in the ID that was passed into notify() on the NotificationManager (since this is what actually pushes the notification into the notification pane). You can't do this using the Parse SDK alone since you will need to take control of the population of notifications yourself.
First you will need to setup a NotificationManager instance then when a notification is ready to be pushed you assign it a value that you can reference later when cancelling like this:
public class MyParsePushBroadcastReceiver extends ParsePushBroadcastReceiver {
NotificationManager mNotificationManager;
int notification_id = 0;
#Override
public void onPushOpen(Context context, Intent intent) {
Log.e("Push", "Clicked");
mNotificationManager.cancel(notification_id)
}
#Override
public void onReceive(Context context, Intent intent) {
mNotificationManager = (NotificationManager)context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
super.onReceive(context, intent);
...
}
#Override
protected Notification getNotification(Context context, Intent intent) {
Notification n = super.getNotification(context, intent);
notification_id = intent.getExtras().getInt("NOTIFICATION_TYPE");
mNotificationManager.notify(notification_id, n);
return null;
}
}
So you see by taking control of the NotificationManager (instead of passing it off to the Parse SDK to assign some unknown value) we can know exactly which values to use when calling cancel. I am letting the system build my Notification object (and I get it using super.getNotification()) but you are free to also use a Notification builder to create the notification yourself as well.
Related
I have been using parse for about 2 months for android and am very happy with it. I have built most of the app, just need to get push notifications finalized. I read the parse push guide and am able to receive and customize them.
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
ParseObject.registerSubclass(ParseFeedBack.class);
ParseObject.registerSubclass(ParseReportIssue.class);
ParseObject.registerSubclass(ParseOrder.class);
ParseObject.registerSubclass(ParseAddress.class);
Parse.enableLocalDatastore(getApplicationContext());
Parse.initialize(this, "ID", "ID");
ParseInstallation.getCurrentInstallation().saveInBackground();
}}
So the questions is
Do I leave ParseInstallation.getCurrentInstallation() in the application class itself? Or shift it out to the main activity and register over there since I also want to identify the user associated with it, hence ParseInstallation.put("userPointer", ParseUser.getCurrentUser) will need to be added on my main activity.
Does this function have to be called everytime the user opens the app or only the first time? In which case I will place the code in the registration page so its called only once.
What happens If user A uses user B's phone to login. In that case this code ParseInstallation.put("userPointer", ParseUser.getCurrentUser) will associate installation on B with user A as he had logged in last. So If i send a targeted push notification to user A, it will be received on his as well as User B phone.
In ParsePushBroadcastReceiver, I am overriding onPushRecieve, and building my notification over there. Im not placing any pending intent with the notification but instead overriding onPushOpen(). Is this recommended or should I just add a pending intent in the builder itself and leave onPushOpen() empty.
Google metioned that on October 15th. I noticed in manifest parse still uses C2DM. Have they released any blog about the changes they will implement?
.
public class MyPushReceiver extends ParsePushBroadcastReceiver {
final Integer PRIORITY_MAX=2;
NotificationCompat.Builder builder;
String message;
public MyPushReceiver() {
super();
}
#Override
protected void onPushReceive(Context context, Intent intent) {
super.onPushReceive(context, intent);
builder=new NotificationCompat.Builder(context);
try {
JSONObject jsonObject=new JSONObject(intent.getExtras().getString("com.parse.Data"));
message=jsonObject.getString("alert");
builder.setContentText(message);
builder.setContentTitle(jsonObject.getString("title"));
builder.setPriority(PRIORITY_MAX);
int mNotificationId = 001;
NotificationManager mNotifyMgr =
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, builder.build());
Log.d("PUSH ", jsonObject.toString());
Log.d("s", intent.toString());
}catch (JSONException e){
e.printStackTrace();
}
}
#Override
protected void onPushOpen(Context context, Intent intent) {
super.onPushOpen(context, intent);
Toast.makeText(context, "Opening push!", Toast.LENGTH_LONG).show();
Intent i=new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
I am using Parse to do push notifications and the issue I am running into is that while my application is running (either in the foreground or background) the phone's operating system does not show the push notification in the notification bar. What changes to my implementation do I need to make to see the push display on the notification bar?
My extended Application class has the following in onCreate()
// initialize Parse SDK
Parse.initialize(this, Constants.APPLICATION_ID_DEBUG, Constants.CLIENT_KEY_DEBUG);
ParsePush.subscribeInBackground(Constants.CHANNEL, new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Logger.i(TAG, "successfully subscribed to broadcast channel");
} else {
Logger.e(TAG, "failed to subscribe for push: " + e);
}
}
});
ParseInstallation.getCurrentInstallation().saveInBackground();
I have a sign in system for my app, so I am using the ID of the logged in user as the Channel to subscribe users to. So in the first Activity of my app I call the following code snippet in onCreate().
private void registerNotifications() {
List<String> arryChannel = new ArrayList<String>();
arryChannel.add(session.id);
ParseInstallation parseInstallation = ParseInstallation.getCurrentInstallation();
parseInstallation.put("channels", arryChannel);
parseInstallation.saveEventually();
}
I also have a custom receiver that is working. Each time a push is sent out, it is being received by the onPushReceive method, however, I want the push to display in the notification bar.
public class ParsePushReceiver extends ParsePushBroadcastReceiver {
private static final String TAG = ParsePushReceiver.class.getSimpleName();
#Override
public void onPushOpen(Context context, Intent intent) {
Log.i(TAG, "onPushOpen");
}
#Override
protected void onPushReceive(Context context, Intent intent) {
Log.i(TAG, "onPushReceive");
}
}
Thanks in advance!
Just remove the onPushReceive method and the default behaviour will remain (show the notification in the status bar.
You are getting this behaviour because if the application is running the Parse Push notification will call the method onPushReceive that does nothing.
I have figured this out. Although the answer provided by Sandra will make a push notification appear on the notification bar, it is not connected to Parse.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
This causes issues, because if you click on that notification the receiver you create extending ParsePushBroadcastReceiver will not register onPushOpen. My implementation for everything was correct, I only needed to add
super.onPushReceive(context, intent);
That will make the notification appear on the notification bar and also register clicks.
So make sure to make your receiver looks like this (at minimum)
public class ParsePushReceiver extends ParsePushBroadcastReceiver {
private static final String TAG = ParsePushReceiver.class.getSimpleName();
#Override
public void onPushOpen(Context context, Intent intent) {
Log.i(TAG, "onPushOpen");
}
#Override
protected void onPushReceive(Context context, Intent intent) {
Log.i(TAG, "onPushReceive");
**super.onPushReceive(context, intent);**
}
}
I have a subclassed BroadCastReceiver inside my main activity in an android application to deal with changing the GUI when a GCM comes in. All of this works fine.
The one thing that doesn't work is that if this gets called then the user has my app open on his device, and as such I want to clear the notification I entered into the notification center for this incoming GCM. If I put the cancelAll() and cancel(int) lines into my GCMIntentService, then it dismisses the notifications, but I cannot keep it there since I only want to dismiss this notification if the user has my app open. I used both the cancel() and cancelAll() to make sure that I wasn't somehow passing the wrong notification id from the IntentService (I have verified it is correct).
The problem is that there is no error and the notification in the notification center simply won't go away. I have verified that this method is getting called since I get the log entries in logcat.
I referenced this prior answer, but it doesn't work in my implementation for some reason: Starting and stopping a notification from broadcast receiver
My code inside my main activity:
private class NotificationBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v("Push", "Received Push Notification!");
//Now that the user has opened the app, cancel the notification in the notification center if it is still there
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final int NOTIFICATION_ID = intent.getIntExtra("notificationId",0);
Log.v("NOTIFICATION_ID",Integer.toString(NOTIFICATION_ID));
mNotificationManager.cancel(NOTIFICATION_ID);
mNotificationManager.cancelAll();
Log.v("Canceled Notifs","Canceled");
}
}
Any ideas why?
A potentially better option is, instead of posting the notification while the app is open, to first detect if the app is visible and, if it is, don't display the notification. You can do this using Intent broadcasts or an event bus like EventBus or Otto.
Example:
public class GCMReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is your receiver after gcm has been received
Intent appOpenCheck = new Intent("com.example.IS_APP_OPEN");
// put extras about your notification here...
context.sendOrderedBroadcast(appOpenCheck);
}
}
public class AppNotOpenReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is your receiver that will be hit if the app isn't open
// post your notification to the NotificationManager
}
}
Then, in AndroidManifext.xml:
<receiver
android:name=".AppNotOpenReceiver">
<intent-filter>
<action android:name="com.example.IS_APP_OPEN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Finally, in your Activity:
BroadcastReceiver appOpenAlert = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
abortBroadcast(); // prevents notification from going further
// this is your receiver that will be hit if the app is open
// update your ui
}
}
#Override
public void onStart() {
super.onStart();
IntentFilter notificationReceived = new IntentFilter();
notificationReceived.addAction("com.example.IS_APP_OPEN");
notificationReceived.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(appOpenAlert, notificationReceived);
}
#Override
public void onStop() {
unregisterReceiver(appOpenAlert);
super.onStop();
}
I am trying to display a notification in the Android notifications bar even if my application is closed.
I've tried searching, but I have had no luck finding help.
An example of this is a news application. Even if the phone screen is off or the news application is closed, it can still send a notification for recent news and have it appear in the notification bar.
How might I go about doing this in my own application?
You have to build a Service that handles your news and shows notifications when it knows that are new news (Service Doc).
The service will run in background even if your application is closed.
You need a BroadcastReciever to run the service in background after the boot phase is completed. (Start service after boot).
The service will build your notifications and send them through the NotificationManager.
EDIT: This article may suit your needs
The selected answer is still correct, but only for devices running Android 7 versions and below.
As of Android 8+, you can no longer have a service running in the background while your app is idle/closed.
So, it now depends on how you set up your notifications from your GCM/FCM server. Ensure to set it to the highest priority. If your app is in the background or just not active and you only send notification data, the system process your notification and send it to the Notification tray.
I used this answer to write a service, and as an exmaple you need to call ShowNotificationIntentService.startActionShow(getApplicationContext()) inside one of your activities:
import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
public class ShowNotificationIntentService extends IntentService {
private static final String ACTION_SHOW_NOTIFICATION = "my.app.service.action.show";
private static final String ACTION_HIDE_NOTIFICATION = "my.app.service.action.hide";
public ShowNotificationIntentService() {
super("ShowNotificationIntentService");
}
public static void startActionShow(Context context) {
Intent intent = new Intent(context, ShowNotificationIntentService.class);
intent.setAction(ACTION_SHOW_NOTIFICATION);
context.startService(intent);
}
public static void startActionHide(Context context) {
Intent intent = new Intent(context, ShowNotificationIntentService.class);
intent.setAction(ACTION_HIDE_NOTIFICATION);
context.startService(intent);
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_SHOW_NOTIFICATION.equals(action)) {
handleActionShow();
} else if (ACTION_HIDE_NOTIFICATION.equals(action)) {
handleActionHide();
}
}
}
private void handleActionShow() {
showStatusBarIcon(ShowNotificationIntentService.this);
}
private void handleActionHide() {
hideStatusBarIcon(ShowNotificationIntentService.this);
}
public static void showStatusBarIcon(Context ctx) {
Context context = ctx;
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx)
.setContentTitle(ctx.getString(R.string.notification_message))
.setSmallIcon(R.drawable.ic_notification_icon)
.setOngoing(true);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, STATUS_ICON_REQUEST_CODE, intent, 0);
builder.setContentIntent(pIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = builder.build();
notif.flags |= Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(STATUS_ICON_REQUEST_CODE, notif);
}
}
In my application, i have used C2DM. Here, when i receive a C2DM message/notification, i am trying to create a notification using notification manager. I can properly create notifications, but i am unable to increment the number of unread notifications(using Notification.number) when there are many unread notifications. Since i am creating notification object inside onReceive() function, its getting destroyed as soon as the control comes out of onReceive function. So, the statements
public class MyC2dmReceiver extends BroadcastReceiver{
private Context context;
#Override
public void onReceive(Context context1, Intent intent) {
this.context = context1;
if(intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(context, intent);
}
else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
handleMessage(context, intent);
}
}
private void handleMessage(Context context, Intent intent)
{
.....
.....
Notification notification =
new Notification(R.drawable.ic_launcher,intent.getStringExtra("payload"),
System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults = Notification.DEFAULT_ALL;
notification.number += 1;
}
}
have been of no use as it is creating a new notification object everytime. I can not make it(notification object) a static object also. If i make it a static object, even after all the unread notifications are viewed, the notification.number does not get reset. This is basically the problem. Could anybody help me?
Store your number of unread messages in a database, flat file, shared preference, or other persistent store. Read in that number when creating your new Notification.