FLAG_ACTIVITY_REORDER_TO_FRONT not working on some devices - android

So here is what I am trying to achieve here... We have two android APKs installed on the device... Each APK can force itself to be on the foreground (This is not an app the general public will use so it's okay...)
So we launch task a with activity a.
We then launch task b with activity b.
Then activity a & task a wants to go to foreground (This can happen at any time)
At some point later, activity a and task a wants to go to foreground
So we had this code working using the following code:
Intent i = new Intent(Variables.context, HomeActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
Great!
However, on a phone running 4.2.2 (and maybe others too) we noticed that the behavior was not as expected. The following two things can happen.
Let's assume activity a & task a is in the foreground, but want to make activity b and task b come to the foreground it does not work.
However if no task was in the foreground and the home launcher is focused, then activity b and task b gets popped to the foreground as expected.
Here is an example of one of my manifest from one of the applications:
<activity
android:name="some.app.id.goes.here"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have tried adding this line of code:
android:launchMode="singleTop"
and it still does not work.
Is there anything I am missing?
A few notes:
Activity A can be ANY application, not just our developed application which rules out activity A from stopping this from happening. We had the same results using Google chrome / Google maps / Google play store.
We do not override onNewIntent

Well, what a pain this was...
Here is the workaround I had to make...
private void generateNotificationToPopActivityToTop(final int id, Context context, String message) {
Intent notificationIntent = new Intent(context, HomeActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getString(R.string.app_name))
.setFullScreenIntent(intent, true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, mBuilder.build());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mNotificationManager.cancel(id);
}
}, 1000);
}

Related

Android: How to show/skip the Splash Screen as needed when opening an app through a notification?

(Note: My app's targetSdk and compileSdk are set to 29, so I can't take advantage of the new SplashScreen API)
I have a very simple app with two activities:
SplashActivity - Default activity opened with the launcher icon. Shows a splash screen, loads some stuff, and when complete, calls startActivity() to start the Main Activity and then calls finish() to finish itself.
Main Activity - It just posts a notification. When pressing that notification, the app should be brought to the foreground.
What do I mean by "the app should be brought to the foreground"? To be clear:
If MainActivity already exists (either in the background or foreground), open that same instance.
If MainActivity was destroyed (the user previously pressed Back), then open the SplashActivity. The splash activity will redirect you itself to MainActivity.
In fact, this is exactly the default behavior of the launcher icon.
However, I can't get my app to behave this way when the notification is pressed. Either it's always opening the SplashScreen, or it's always opening the MainActivity directly and skipping the Splash Screen.
Ideally, I would like to do this:
Intent intent;
if (MainActivity already exists) {
// Bring that instance of MainActivity to the foreground
intent = new Intent(this, MainActivity.class);
} else {
// No UI activity exists for the app. Start from the Splash Screen.
intent = new Intent(this, SplashActivity.class);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
...
// later
notificationBuilder.setContentIntent(pendingIntent);
But I'm pretty sure I shouldn't be checking for the existence of MainActivity myself. I should be using a combination of Intent Flags and activity launch modes.
in the manifest you should add the following to your main activity
android:launchMode="singleTask"
then my notification looks as follows
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context, MainActivity.NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(text)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(text));
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
Intent goToAppIntent = context.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName())
.setPackage(null)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent piGoToApp = PendingIntent.getActivity(context, 0, goToAppIntent, 0);
mBuilder.addAction(0,"go to app",piGoToApp);
mBuilder.setContentIntent(piGoToApp);
let me know if it helps

Confuse about activity launch

Notification.Builder builder = new Notification.Builder(getContext());
builder.setAutoCancel(true);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("abc");
builder.setContentText("abc");
builder.setContentIntent(PendingIntent.getActivity(getContext(), 0,
new Intent(getContext(), MainActivity.class).replaceExtras(bundle).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP),
PendingIntent.FLAG_UPDATE_CURRENT));
builder.setDefaults(Notification.DEFAULT_SOUND);
NotificationManager manager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
first way to set launch mode.
<activity
android:name=".activity.mainActivity.MainActivity"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode="singleTask"/>
second way to set launch mode.
Google offical document.
FLAG_ACTIVITY_NEW_TASK
Start the Activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent().
This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.
activity stack a,b,MainActivity
Why onNewIntent() not invoked in first way.
Why activity(a,b) not cleaned in first way.
by using android:launchMode="singleTask"
"singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
by using FLAG_ACTIVITY_NEW_TASK It set, this activity will become the start of a new task on this history stack.

Change android status bar notification every day

I want to create a constant notification on status bar (like current battery percents - it's always there), but the icon will be changed every day on 00:00.
In addition, I want this notification will alert automatically after rebooting the device and not only after the user opens the application.
I created the notification in MainActivity, but I don't know how to make it alert after rebooting and also I don't know how to change it every day at mid-night.
I tried to create AlarmService and broadcast reciever but it run every 5 seconds and it's far too much so I deleted it.
My current code is:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notificationTitle))
.setContentText(....)
.setLargeIcon(largeIconBitmap)
.setSmallIcon(getResources().getIdentifier("icon_status_" + myHelper.getCurrentImageNumber(),"drawable", getPackageName())); // change the icon at mid-night. 'getCurrentImageNumber' should get me the right icon number
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mylHelper.myRequestCode, notification);
Right now I see a notification, but the icon doesn't change and it does not alarm after reboot. I saw some answers in stackoverflow but nothing helped me.
I wont give you all the code, you will need to learn by doing.
Here is what you should do:
1 Use a Service to launch your notification and maintain the logic to updating it. If the notification already exists you can update the existing one or programmatically dismiss it and replace with a new one.
2 Register a broadcast receiver in AndroidManifest.xml with multiple intent filters to launch your service.
<receiver android:name=".myReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3 Create class which extends the broadcast receiver class and use and launch the above service.

Activity strange behavior when started from Android Notification

I am experiencing a strange behavior with my android application when dealing with a notification that is created from a BroadcastReceiver when a C2DM message arrives on the mobile device. The flow I am executing to experience this behavior is the following one:
Start my application, DashboardActivity is displayed;
Close application either by pressing home button or back button;
Receive the push message and create the notification;
Click the notification item and the activity BookingOfferActivity is launched;
Close the BookingOfferActivity either by pressing home or back button or calling finish()
Long press home button and select my application from recent applications
BookingOffcerActivity is displayed instead of DashboardActivity
The BookingOfferActivity is being launched from the notification using the following code:
Intent notificationIntent = new Intent(context, BookingOfferActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Bundle b = new Bundle();
b.putSerializable("booking", booking);
notificationIntent.putExtras(b);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AppUtil.getNextPushIndexBooking(), notification);
BookingOfferActivity is defined in the AndroidManifest this way:
<activity android:name=".activity.BookingOfferActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" />
and my DashboardActivity is defined like this:
<activity android:name=".activity.DashboardActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The reason I am calling it a strange behavior is that I would like to start DashboardActivity whenever my application is started or restarted by the user, not by the notification item. So after closing, finishing or destroying BookingOfferActivity and reopening by application by accessing recent opened application (long press on home button) or accessing the launcher icon on the application list, I would like to see the Dashboard.
I create a question similar to this one but I didnt provide too much details, so I closed the other one and opened this one with more data.
Many thanks for any guidance on how to solve this problem
T
I'm not sure, but I suppose that in your scenario second activity just go to the top of activity stack and will be shown until application wont be killed. We have approximately same problem and solv it in easy way: Notification start main(first) activity with extra "go to second immediately". in onCreate of first activity check this extra and start second activity if needed. With this solution you should be careful with pressing back button - if you dont want to show first activity in case of "notification start" you should care about it in onResume of first activity

how to awake already running app after c2dm message on android

is there a way to awake already running app from the notification bar after c2dm message?
i have this app that is registered with c2dm servers that receives push notifications from my server to do some processing. so after i receive c2dm message from my server, it displays the status bar notification to the user, user expands the notifications and clicks on my app, brings it up.
all is good but if this app was already running before (stared from the icon) this would load another instance of my app into memory. also some of the things are crashing in it. i already changed the android:launchMode="singleTop" on all my activities, i tried using intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) in my notification and no luck. i always end up with 2 apps running.
any help is appreciated
here my static function that i use to create a notification after i receive the c2dm message:
public static void notifyStart(Context context, String notificationText) {
//notification
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
int icon = R.drawable.icon_notify;
CharSequence tickerText = notificationText;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 400;
notification.ledOffMS = 400;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_SOUND;
CharSequence contentTitle = "App Name";
CharSequence contentText = notificationText;
Intent notificationIntent = new Intent(context, home.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(1350, notification);
}
and here is my home activity:
<activity android:name=".home"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
guys, i am very sorry but it was my fault :| couple of days ago i decided to change the name of the package of my app and forgot to remove the old app from the phone. i didn't realize that it would cause two separate installations on my phone, the task manager displays only app name so it did look like there were two instances of the same app, in fact there was one instance of each ;) sorry about trouble and appreciate your willingness to help :)
Android documentation says:
As shown in the table below, the modes fall into two main groups, with "standard" and "singleTop" activities on one side, and "singleTask" and "singleInstance" activities on the other. An activity with the "standard" or "singleTop" launch mode can be instantiated multiple times. The instances can belong to any task and can be located anywhere in the activity stack. Typically, they're launched into the task that called startActivity() (unless the Intent object contains a FLAG_ACTIVITY_NEW_TASK instruction, in which case a different task is chosen — see the taskAffinity attribute).
In contrast, "singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
so it seems (though I haven't checked) that singleInstance is what you're looking for.
see: http://bit.ly/gH8SBb

Categories

Resources