I am opening a link in my app and once back is pressed I want to show HomePage to retain user for some more time. I have been trying to acheive this but unable to do so. I get homeLauncher activity as my top as well as baseActivity.
DeepLink Tap > Open desired Activity > user presses back button > Check if its last activity but not homeActivity > If yes, Navigate user to homeActivity.
Tried following code:
#Override
public void onBackPressed() {
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 && taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())){
//// This is last activity
}
else{
//// There are more activities in stack
}
super.onBackPressed();
}
I have also tried isTaskRoot but result is same. It doesn't give right answer.Please help
Use isTaskRoot() method. (From a h9kdroid comment - here)
#Override
public void onBackPressed() {
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(isTaskRoot()){
//// This is last activity
} else{
//// There are more activities in stack
}
super.onBackPressed();
}
You could simply use the ActivityManager it keeps track of which activity is and is not here is a piece of code I stumbled on that I use always:
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 &&
taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
Log.i(TAG, "This is last activity in the stack");
}
Quoting From ActivityManager.RunningTaskInfo
Information you can retrieve about a particular task that is currently
"running" in the system. Note that a running task does not mean the
given task actually has a process it is actively running in; it simply
means that the user has gone to it and never closed it, but currently
the system may have killed its process and is only holding on to its
last state in order to restart it when the user returns.
String getLastOpenClass ;// Global
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
getLastOpenClass=taskInfo.get(0).topActivity.getClassName();
if(getLastOpenClass.equals("Your_Class_Name"))
{
}else{
}
Give permission
<uses-permission android:name="android.permission.GET_TASKS" />
The ActivityManager keeps a record of the runnings task and the topmost task .
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 && taskList.get(0).topActivity.getClassName().equals(this.getClass().getName()))
{
Log.i(TAG, "This is Last activity in the stack");
}
Courtesy How to check if an activity is the last one in the activity stack for an application?
Please Check How can I get the current foreground activity package name
http://developer.android.com/intl/es/reference/android/app/ActivityManager.html#getRunningTasks%28int%29
Please note that the below solution will only work on API14+.
Create a custom application class;
public class App extends Application {
private int created;
#Override
public void onCreate() {
registerActivityLifecycleCallbacks(new Callbacks());
}
public int getCreated() {
return created;
}
private class Callbacks implements ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
created++;
}
#Override
public void onActivityDestroyed(Activity activity) {
created--;
}
}
}
Register it in your AndroidManifest.xml in the application element;
<application name=".App"/>
And in your activity opened through a deep link use the following piece of code;
#Override
public void onBackPressed() {
if (((App) getApplicationContext()).getCreated() == 1) {
// start your home activity
}
super.onBackPressed();
}
I wrote this off the top of my head so I haven't had a chance to test it, but theoretically it should work.
Specify parent activity for desired Activity, like :
<activity
android:name=".DesiredActivity"
android:parentActivityName="com.packagename.HomePage" >
<!-- The meta-data element is needed for versions lower than 4.1 -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.packagename.HomePage" />
</activity>
With the parent activity declared, you can use the NavUtils APIs to
synthesize a new back stack by identifying which activity is the
appropriate parent for each activity.
override onBackPressed as :
#Override
public void onBackPressed() {
Intent intent = NavUtils.getParentActivityIntent(this);
startActivity(intent);
super.onBackPressed();
}
Android developer's site has a very good resource for same problem. Please refer to link http://developer.android.com/training/implementing-navigation/temporal.html#SynthesizeBackStack
Related
I periodically bring activity to the foreground. Code is below
public void moveToFront( ) {
runOnUiThread(new Runnable() {
#Override
public void run() {
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
Log.e(TAG,"moveToFront ..recentTasks.size = "+recentTasks.size());
for (int i = 0; i < recentTasks.size(); i++)
{
Log.e( TAG, "Application executed : "
+recentTasks.get(i).baseActivity.toShortString()
+ "\t\t ID: "+recentTasks.get(i).id+"");
// bring to front
if (recentTasks.get(i).baseActivity.toShortString().indexOf("MainActivity") > -1) {
Log.e(TAG, "Moving to front");
activityManager.moveTaskToFront(recentTasks.get(i).id, ActivityManager.MOVE_TASK_WITH_HOME);
return;
}
}
}
});
There are several scenarios where 'activityManager.getRunningTasks' method doesn't return taskinfo of my activity (this method is also deprecated), hence my code doesn't push activity to foreground.
1) I reviewed ActivityManager.getRunningTasks is deprecated android but I could not understand how to embed it in my above code (or how to map its fields to parameters of'activitymanager.moveTaskToFront so that I can push my activity to foreground)
2)Also, how to address the situation if above code is called from outside activity (say service) and Android has killed my activity (for low memory)
Set android:launchMode="singleTop" for the activity you need to bring to foreground in AndroidManifest.xml file. singleTop means, there will be only one instance of activity running at any time. So when your activity is in backgroud or killed, it will be brought to front and if it is in foreground, it will be left as such.
In moveToFront() method just open the activity with Intent as
Intent intent = new Intent(context, activity.class)
startActivity(intent)
In the app having background service running, periodical it will trigger some event that app needs to show an activity.
The issue is if that activity is already on top how to not open another one.
The following snippet whenever the event is triggered, the showAlertActivity() will try to open the activity (it is not just a alert).
Any way to check if there is one has been opened? Thanks!
public void showAlertActivity(String title, String msg……) {
// this does not work, throws a exception
//“ava.lang.SecurityException: Permission Denial: getTasks() from pid=24139, uid=10048 requires android.permission.GET_TASKS”
ActivityManager mngr = (ActivityManager) mContext.getSystemService( Activity.ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
for (ActivityManager.RunningTaskInfo info: taskList) {
Log.d(“+++ info.numActivities:" + info.numActivities +", info.topActivity.getClassName():"+info.topActivity.getClassName()+", info.baseActivity:"+info.baseActivity.getClassName());
}
Intent intent = new Intent(mContext, TheAlertActivity.class);
dialogIntent.putExtra(Constants.LAYOUT_RESOURCE_ID, R.layout.alert_form);
dialogIntent.putExtra(Constants.TILTLE, title);
dialogIntent.putExtra(Constants.TEXT, msg);
……
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
Add something along the lines of this to your Activity you want to check and isOpen will tell you if it is currently on top.
public static boolean isOpen = false;
private static int countOpen = 0;
public void onStart() {
super.onStart();
countOpen++;
isOpen = countOpen > 0;
}
public void onStop() {
super.onStop();
countOpen--;
isOpen = countOpen > 0;
}
The count is added to secure the boolean being correct even if you open the activity for some reason in front of itself and the system sometimes calling the new activities onStart() before the old activities onStop().
I want to detect and count when Activity goes from background to foreground (when activity is visible, increase count).I tried to use flag in onPause() and onResume() like this:
void onPause(){
flag = true;
}
void onResume(){
if(flag){
//save to shared reference.
saveCount(getCount(count) + 1);
flag = false;
}
}
It works when user press home key and relaunches the app, but when I transfer Activity then goes back, it still increases the count, because it calls onPause(). How to prevent that? Or is there anyway to count this?
Use this method to check wheter app is brought to background:
private boolean isApplicationBroughtToBackground(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
It requires the GET_TASKS permission:
<uses-permission android:name="android.permission.GET_TASKS" />
My app is consisted of many activities and a BraodcastReceiver. I want to restart an activity if it is on foreground when my app receives the broadcast Intent.How can I implement it?
use Intent.FLAG_ACTIVITY_REORDER_TO_FRONT to launch activity to be brought to the front of its task's history stack if it is already running and if not then start as new one. to make confirm if Activity is running or not use ActivityManager
#Override
public void onReceive(Context context, Intent intent) {
//start activity
if(isRunning(context)){
Intent i = new Intent(context,Your_Activity_Name.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
context.startActivity(i);
}
else{
// Activity not available in activity stack
}
}
public boolean isRunning(Context ctx) {
ActivityManager activityManager = (ActivityManager)
ctx.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks =
activityManager.getRunningTasks(Integer.MAX_VALUE);
for (RunningTaskInfo task : tasks) {
if (ctx.getPackageName().equalsIgnoreCase(
task.baseActivity.getPackageName()))
return true;
}
return false;
}
and also set android:noHistory AndroidManifest.xml to store Activity in activity stack no longer visible on screen :
<activity
android:noHistory="false"
android:name=".Your_Activity" />
Make the activity singleTop and just send the intent.
I want to detect and count when Activity goes from background to foreground (when activity is visible, increase count).I tried to use flag in onPause() and onResume() like this:
void onPause(){
flag = true;
}
void onResume(){
if(flag){
//save to shared reference.
saveCount(getCount(count) + 1);
flag = false;
}
}
It works when user press home key and relaunches the app, but when I transfer Activity then goes back, it still increases the count, because it calls onPause(). How to prevent that? Or is there anyway to count this?
Use this method to check wheter app is brought to background:
private boolean isApplicationBroughtToBackground(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
It requires the GET_TASKS permission:
<uses-permission android:name="android.permission.GET_TASKS" />