Android - launch app from broadcast receiver - android

I want the broadcast receiver to launch my app this way:
If the app is not in the foreground or background, launch it as if it is launched from launcher.
If the app is in the background, bring it to the foreground with the state it was last in.
If the app is in the foreground, do nothing.
Here is my code:
#Override
public void onReceive(Context context, Intent intent) {
Intent launch_intent = new Intent("android.intent.action.MAIN");
launch_intent.setComponent(new ComponentName("com.example.helloworld","com.example.helloworld.MainActivity"));
launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launch_intent.addCategory(Intent.CATEGORY_LAUNCHER);
launch_intent.putExtra("some_data", "value");
context.startActivity(launch_intent);
}
MainActivity is my root activity. Like I said, if the app is already running, I just want it brought to the front without changing its state. If there is some activity on top of MainActivity, leave it as it is.
Most of the time the above code worked fine, but sometimes I noticed that the app was restarted (or the state was reset --- the root was back on top) when it was brought from the background.
What code should I be using? Any help is appreciated!

You don't need to write all that code. You can use a "launch Intent", as follows:
PackageManager pm = context.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("com.example.helloworld");
launchIntent.putExtra("some_data", "value");
context.startActivity(launchIntent);
However, your code should also work.
If you say this works most of the time, you might be seeing a nasty old Android bug in those cases. This occurs when you launch your app for the first time either directly from the installer, or via an IDE (Eclipse, Android Studio, etc.). You should always launch your app for the first time directly from the HOME screen or list of installed apps. For more information about this frustrating Android bug see https://stackoverflow.com/a/16447508/769265

Since you need behaviour like
1) If the app is not in the foreground or background, launch it as if it is launched from the launcher.
2) If the app is in the background, bring it to the foreground with the state it was last in.
3) If the app is in the foreground, do nothing.
Consider:
#Override
public void onReceive(Context context, Intent intent) {
Intent startIntent = context
.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName());
startIntent.setFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
);
context.startActivity(startIntent);
}

#Override
public void onReceive(Context context, Intent intent) {
Intent launch_intent = new Intent(context, MainActivity.class);
launch_intent.setComponent(new ComponentName("com.example.helloworld","com.example.helloworld.MainActivity");
launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP |INTENT.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launch_intent.putExtra("some_data", "value");
launch_intent.addCategory(Intent.CATEGORY_LAUNCHER);
context.startActivity(launch_intent);
}
It's this simple but unless you know the proper way when you try to get the extra data from your intent you will usually get a java null pointer exception.
Use the onNewIntent() method to receive the extra data. If you want to know how comment below.
Edit:
Try the following. But what I don't understand is the first code which I gave you should work on its own. It has always worked for me. Have you made sure that you have copied the first code I gave you and pasted it without making any changes?
Edit2:
If that doesn't work try setting the flag to clearTaskOnLaunch instead of INTENT.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

Assuming you already know BroadcastReceiver, you just have to do the launching like you usually do on onReceive : Therefore it will look like this
#Override
public void onReceive(Context context, Intent intent) {
Intent launch_intent = new Intent("android.intent.action.MAIN");
launch_intent.putExtra("some_data", "value");
tiapp.startActivity(launch_intent);
}
If it is launched before, it will just resume that Activity, if not, it will start a new

Related

Prevent app from being launched at boot if manually launched by user

I've set my application to be launched at system startup and it does so. The problem is that it takes about ~30 seconds between the homescreen showing up and my app to be launched. This may be a problem if the user doesn't wait.
My idea is to prevent the app from being re-launched when the system broadcasts the message IF it is already running.
So, basically, I'm looking for either solution:
Decrease wait time between system start and app start AND / OR;
Prevent app from being launched when the message is received if it is already running.
The first topic is something I want to achieve regardless, but I don't control when android will fire the message. If I could achieve both, it would be great, but I'd settle for the second option.
I don't think it's necessary to show this, but I've set everything in the Manifest (i.e BOOT_COMPLETED) and this is my code, where MyNamedActivity is my main activity (working code):
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) && AppController.getUsuarioLogado() == null) {
Intent i = new Intent(context, MyNamedActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Note: Removing addFlags line causes the app to cash.

startActivity() doesn't work when app is in background (In this special case)

I'm trying to bring my app from background to foreground. In onHandleIntent() of my custom IntentService class, I have:
Intent intent = new Intent();
intent.setClass(getApplicationContext(), MainActivity.class); // Also tried with "this" instead of getApplicationContext()
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
Now this code works at first sight but I found a scenario where it doesn't work. If you have the app opened and you put it to background via home button and execute startActivity() within ~5 second, there will be a delay before your app will come to foreground. This is a known implementation and you can find the topic discussed on stackoverflow. In this scenario, the app succeeded in coming from background to foreground.
If you repeat the same experiment above, but instead of waiting for the app to come to foreground, go browse (scroll, swipe, etc) around your phone (I was browsing around the google playstore). The result is that startActivity() will get called but the app will not come to the foreground.
I'm not asking for a solution but more of an explanation on why this is happening. Is this intended behavior?
Use the context of your class.
For instance :
Intent intent= new Intent(context, other.class)
Instead of getapplicationContext()
Use the code :
private void startMenuActivity() {
Intent i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
the below code works for me,
val login = Intent(applicationContext, SignInActivity::class.java)
login.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
login.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
applicationContext.startActivity(login)

Android - Determine if the app is started or brought to the front from notification click

My app issues notifications. By clicking the notification, the app needs to be launched or brought to the front. Here is the intent for the notification:
Intent launch_intent = new Intent("android.intent.action.MAIN");
launch_intent.setComponent(new ComponentName("com.example.helloworld","com.example.helloworld.MainActivity"));
launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launch_intent.addCategory(Intent.CATEGORY_LAUNCHER);
launch_intent.putExtra("some_data", "value");
And in my app I want to determine if it's launched or brought to the front by the notification click, so I use putExtra there. Then in MainActivity's onResume I check the intent data. This works fine is the app is launched by the notification click.
However, if the app is brought to the front by the notification click, in MainActivity's onResume there is no intent data.
I think the reason is: MainActivity is the root activity, and it's the splash screen. There could be any number of activities on top of it when the app is brought to the front. And when it's brought to the front, I want to keep its state.
What is the right way of doing this?
Override onNewIntent() in your activity and check the value there. If you want future calls to getIntent() to return this new intent, you can call setIntent() and pass the new intent.
Try in onNewIntent() method
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String value = intent.getStringExtra("some_data");
}

How do I bring my activity to the front using broadcastReceiver onReceive()?

All of this has to do with my own app.
I have two cases. First, my activity is on top, and everything works fine. My service broadcasts info and my activity updates its GUI.
My problem is that I don't know how to bring my activity to the front if its not already there. Ideally, all the activities in front of it would be closed and this one be brought to the front. How do i do this?
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//what code do I put here to bring this activity to the front and close all other activities on top of it?
}
};
Here is how I solved the problem with the help of the post bellow.
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setClass(MyClass.this, MyClass.class);
startActivity(i);
First of all there isn't a direct command to bring an activity to front such as myActivity.bringToFront. Instead you will have to let android do it for you through the intents mechanism.
So if you want to bring an activity to front you will have to call startActivity and pass an intent with the correct flags. For example the flag FLAG_ACTIVITY_CLEAR_TOP will do your job. However there is a catch, you cannot set this flag if you use startActivity from within a broadcast receiver or a service. So in your case I think that you should use the flag FLAG_ACTIVITY_NEW_TASK.
Here is an example:
Intent i = null;
i = new Intent(context, My_activity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Hope this helps...

Some questions about android broadcastReceiver && context.startActivity()

#Override
public void onReceive(Context context, Intent intent) {
Log.i("TEST", "user is present");
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
I want to start my app's MainActivity at once after receiving the intent , but the MainActivity starts about 3 seconds later after I see the log "user is present" , not start at once.
And I need it to start at once for better user experiences.
I wonder wether there is a way can let the MainActivity starts faster ?
PS: when I use a button in another activity to start the MainActivity, it starts immediately, could it be that the method "context.startActivity(i)" in BroadcastReceiver is more slowly ?
There are flags that you can add to the Intent object that can help you achieve your goal. Also when the user is present, this is only after the device has been unlocked (hint).
UPDATE
Apparently the Intent Flag is no longer in the API, bummer. However; Using the KeyguardManager you can achieve this as part of the solution to your problem.

Categories

Resources