I have reviewed a lot of information on this issue, but no one can solved it.
On android 7.0 devices,when using NotificationManager to send more than 5 messages, all messages will be collapsed.
Please click on the image to see the message is collapsed.
When I click on this collapsed notification bar message, my app will be rebooted into the login activity even if my app is logged in and running in the foreground.This is terrible.If I click on a single notification bar message, then it will enter the activity normally.
How to set the notification bar message to not collapse or when I click on the collapsed notification bar message, do not restart the app.
this is my code:
Intent notifyIntent;
PendingIntent appIntent;
notifyIntent = new Intent(context, TestActivity.class);
notifyIntent.putExtra("content", contentJson);
appIntent = PendingIntent.getActivity(context,
noticeId, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "program").setAutoCancel(true)
.setSmallIcon(iconId)
.setContentTitle(notifyTitle)
.setDefaults(Notification.DEFAULT_ALL)
.setNumber(noticeId)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setGroupSummary(false)
.setContentIntent(appIntent);
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
builder.setColorized(true);
Notification myNoti = builder.build();
myNoti.flags = NotificationCompat.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL;
if (noticeId > 40) {
noticeId = 0;
notificationManager.cancelAll();
}
notificationManager.notify(noticeId, myNoti);
I set TestActivity
android:launchMode="singleTop"
I found the problem, not what I thought. App is not restarted.Only LoginActivity was recreated once and placed on the top of the stack.I am worried that other people have the same thoughts as me and think that the APP has been restarted,So I won’t change this question.I hope to help people who have this problem.I will put the solution below.
When you click on the collapsed notification bar message, assume your LoginAtivity has been recreated.You need to write the following code in the onCreate of LoginActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isTaskRoot()) {
finish();
return;
}
setContentView(R.layout.activity_main_menu);
}
isTaskRoot() will detect if this class is at the root of the stack.If not, then finish.
Note that if you have logic in onDestory, use isTaskToot() to determine,for example:
#Override
protected void onDestroy(){
super.onDestroy();
if (isTaskRoot()) {
//your code
}
}
Related
I have an app that elderly people use, and I need a really noticeble way for them to know that they received a new notification, so I want to display a dialog in the screen even though the App might be closed/Background
I created a class that extends Dialog to show a Dialog, and it works when I call it in any of my activities:
The error makes sense since FirebaseMessagingService is actually not one of my classes, but I do not know how to work around this, inputs are appreciated
Thanks
I may be a bit late but here is a complete solution, which will force the activity to auto open even if the application is closed or killed or in the background. This solution can even show the "Activity/Fragment" when the device is on sleep or screen lock.
Create an activity which will serve the notification and open automatically whenever notification received.
inside your
onMessageReceived
Do following code
if (remoteMessage.getData().size() > 0) {
sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
}
here your sendNotification() method is
private void sendNotification(String messageTitle,String messageBody) {
Intent intent = new Intent(this, DeliveryRecieved.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);
long[] pattern = {500,500,500,500,500};
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_dart_board)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setVibrate(pattern)
.setLights(Color.BLUE,1,1)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
getApplicationContext().startActivity(intent);
}
Notice the two important things
FLAG_ACTIVITY_NEW_TASK
and
getApplicationContext().startActivity(intent);
In your activity, if you want to un-lock device screen and bring the application back from device sleep mode do the following in your activity onCreate()
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
The last important thing is in firebase messaging system always use "data payload" because to invoke onMessageReceived() when the device is in background "data payload is required"
To show any dialogue you can code it in your activity's onCreateView() or anywhere;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final DeliveryRecieved c = this;
setContentView(R.layout.activity_jp_map);
mediaPlayer = MediaPlayer.create(this, R.raw.call_bell);
mediaPlayer.setLooping(true);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
String[] title = {"A","B"};
mediaPlayer.start();
new MaterialDialog.Builder(this)
.items(title)
.itemsCallbackMultiChoice(null, new MaterialDialog.ListCallbackMultiChoice() {
#Override
public boolean onSelection(MaterialDialog dialog, Integer[] which, CharSequence[] text) {
mediaPlayer.stop();
c.finish();
return true;
}
})
.title("NOTICES For Delivery")
.content("IMPORTANT NOTICE")
.positiveText("Accept")
.build().show();
}
Create your class which extends FirebaseMessagingService and write onMessageReceived method from which you can show notification dialog or what ever you like to do like :
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
}
}
create MyFirebaseMessagingService extends FirebaseMessagingService
with its entry in the AndroidManifest and with the method onMessageReceived.
send a data-message (not a notification / display message).
use context.startActivity() to launch an activity
customize the style of the activity to look like a dialog
see: Android Activity as a dialog
If you want to show dialog you have to either show it in activity by attaching window or by Redirecting to an Activity that will look like a Dialog. Or simply you can use Toast on a handler.
I have hooked up to Google Cloud Messaging and am displaying a notification when I receive something.
I want to "maximize" my app when the user clicks on the notification. I.e. show the latest activity related to my app. Or, if the app has not started, I want to start it's main activity.
It is imperative that I do not create a new instance of the last activity if the app is already open.
How can I achieve this?
I have seen a lot of similar questions, but all the answers seem to want to specify the activity class, which I don't know, since I don't know which activity was last shown.
Is there a solution to this seemingly simple task?
My code looks something like this at the moment:
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon)
.setContentTitle("foo")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0));
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
But it is not working.
When your opening an Activity while Notification is clicked just open the following Activity. i.e. your PendingIntent will open following Activity
Please read all the comments written in Activity so that you will know why this has been created
public class NotificationHandlerActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//deep linking - resuming app code
if (isTaskRoot()) {
// This Activity is the only Activity, so
// the app wasn't running. So start the app from the
// beginning (redirect to MainActivity)
} else {
// App was already running, so just finish, which will drop the user
// in to the activity that was at the top of the task stack
Intent intent = getIntent();
Uri data = intent.getData();
//you can put your extra's if any
finish();
}
}
}
My notification get restart when i click on it by Status bar
when i start my app it stream audio from server and show a notification until i don't clear it from status bar so my problem is when i click on my app notification it restart the activity and stop the streaming music..
so please suggests me solution for to stop restarting app again from notification and i want to show notification which stick on notification bar upto i exit from app
Also I want to Show pause and Play button on Notification so please help me that too
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nm=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent = new Intent(this,MainActivity.class);
PendingIntent pi= PendingIntent.getActivity(this, 0, in`enter code here`tent, 0);
String body = " Welcome to streaming ";
String title = "radio";
Notification n = new Notification(R.drawable.png, body, System.currentTimeMillis());
n.setLatestEventInfo(this , title, body, pi);
n.defaults=Notification.DEFAULT_ALL;
nm.notify(uniid,n);`
Add this in to your manifest file inside the activity which you are starting through notification, as if it is already running it won't be restarted again ..
android:launchMode="singleTop"
android:configChanges="orientation|keyboardHidden" // fixes orientation
Don't allow to destroy your application on back press :
#Override
public void onBackPressed()
{
moveTaskToBack(true);
//super.onBackPressed(); // comment this line else your app will be destroyed
}
I've found a lot of Stack Overflow posts about this issue but they all use the now deprecated Notification methods instead of using the Notification.Builder class.
I'm successfully creating status bar notifications, but when clicked nothing happens. A warning in LogCat shows up:
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy#412d6df0
Here is the code I'm using to build my Notification:
public class LunchNotificationBuilder {
private Notification notification;
public LunchNotificationBuilder(Lunch lunch, Context context) {
Builder builder = new Builder(context);
Calendar reminderTime = (Calendar)lunch.getReminderTime().clone();
builder.setWhen(reminderTime.getTimeInMillis());
builder.setTicker("Reminder for " + lunch.getTitle());
builder.setContentTitle("LunchBunch Notification");
builder.setContentText("Upcoming lunch at " + lunch.getTitle());
builder.setSmallIcon(R.drawable.ic_launcher);
Intent intent = new Intent(context, InviteDetails.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
builder.setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT));
this.notification = builder.getNotification();
}
public Notification getNotification() {
return this.notification;
}
}
The Lunch class is just a data structure I created, don't worry about that.
The Context being passed in is Application.getApplicationContext().
I'm setting the Intent.FLAG_ACTIVITY_NEW_TASK flag as suggested by the documentation, and the PendingIntent has the PendingIntent.FLAG_ONE_SHOT flag.
Another note: The activity I'm trying to launch (InviteDetails) works just fine when I explicitly call startActivity elsewhere in the code. Something about this PendingIntent business isn't working.
Turns out I don't know how to use Android. I was clicking the status bar at the top, not dragging down to see the full notification before clicking. my code was working. doh!
I have implemented C2DM in the application and everything seems to work properly when app is running. But in case app is not running and push message is received. On tap of push message in the notification panel a separate activity is called. This activity can be called PushMsgHandlerActivity. From this activity one can be redirected to other activity within the application. Say user clicks on a button in PushMsgHandlerActivity and is redirected to Activity A which is the launcher activity. From here, if user presses back button then would go to the view which was there before opening up the push message. If now the home button is kept pressed and we select the app from there then instead of starting launcher activity the app starts the PushMsgHandlerActivity again. The reason I suppose is since that's the activity that was started first for the application.
Anyways of starting launcher activity in this case.
Please note that this issue occurs only when push message is received and application is not running. Otherwise the app works and behaves properly.
If you never want the user to be returned to the PushMsgHandlerActivity, try turning off history for that Activity, as described here, by adding the flag android:noHistory="true" to your manifest file in the section for that activity. This should only bring the user to that Activity when you take them there (through clicking a push message).
Here is a simple example that seems to do what you want. It has two activities, a NotifyMainActivity which immediately starts a notification, and a HandleNotificationActivity which is called when you click the notification.
NotifyMainActivity:
public class NotifyMainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this,
HandleNotificationActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText,
contentIntent);
mNotificationManager.notify(1, notification);
}
}
HandleNotificationActivity:
public class HandleNotificationActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler);
}
public void startMain(View view) {
Intent i = new Intent(this, NotifyMainActivity.class);
startActivity(i);
finish();
}
}
handler.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="startMain"
android:text="Main" />
</LinearLayout>
I have tested by starting the main activity, which creates a notification. Then press the back button, go to your home screen. Click the notification, which starts the handler activity. Then click the Main button, and press back. It will not take you back to the handler since it called finish() on itself. I hope this example can clear things up a bit.