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.
Related
I was searching by myself but failed. Can I start an application like Google translator in the background? Here below-listed program runs the Translator very well, but at the same time, my app goes to the background. I would like to have my app foreground while the Translator is started in the background. Many thanks in advance!
Intent app_to_launch = getPackageManager().
getLaunchIntentForPackage("com.google.android.apps.translate");
if (app_to_launch != null) {
startActivity(app_to_launch);
}
Updated:
Following the subject. One thing is observed. Here below-listed code is working fine:
Intent app_to_launch = getPackageManager().getLaunchIntentForPackage("com.google.android.apps.translate");
if (app_to_launch != null) {
startActivity(app_to_launch);
}
try{Thread.sleep(1000);}catch (Exception e){};
Intent intent = new Intent(MainActivity.this, WordsStatus.class);
startActivity(intent);
But if I remove the 1 sec pause (Thread.sleep) there is no sign that the Google translator has been run. It seems like the launching of the second Intend (my application starting) suppresses the first launch (Google translator starting). If I restore the 1-sec pause everything works as it should be.
Sure just do this:
Intent app_to_launch = getPackageManager().getLaunchIntentForPackage("com.package.of.background.app");
if (app_to_launch != null) {
startActivity(app_to_launch);
}
Intent app_to_launch = getPackageManager().getLaunchIntentForPackage("com.package.of.forground.app");
if (app_to_launch != null) {
startActivity(app_to_launch);
}
(The second app launch doesn't need to use the package manager, you can use anyone of starting an Activity, i.e. if you want to start your own app's internal activity, then just use the normal approach startActivity(new Intent(this, MyActivity.class))
That will start two apps, and the second one starting will move the first one second in the stack.
Note that apps don't really "run in the background" any app that isn't showing on the screen is usually in the paused state, (it may have started a background service to do some work though).
I am trying to create an app that communicates with USB flash drive. I would like to have the user prompted and asked if they wish to open the app once the intent "android.hardware.usb.action.USB_DEVICE_ATTACHED" is received.
Currently, I have the onRecieve() set up so that it launches the main activity
#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);
}
I would like to have the user prompted for permission first, a good example of what I would like to achieve is ES File Explorer Like this
I would like to have the user prompted and asked if they wish to open the app once the intent "android.hardware.usb.action.USB_DEVICE_ATTACHED" is received.
The screen you want to show has to from your app so in fact is has already started, even if the user perceives it differently.
What you can do is start an activity when this broadcast is received (you need to be in activity context to be able to show stuff on the screen). Make the activity's background transparent and have it show a dialog on top that handles the user's input. From there you either start the next activity, or not.
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
My app, running in background, at some point displays activity to purposefully interrupt user's flow. My activity starts a new task, which appears in "Recent Tasks" lists while being in foreground. Is there any way it could be prevented? Setting android:excludeFromRecents does not work - activity is not presented anymore in "Recent Tasks" only after is has been paused.
Manifest looks like:
<activity
android:name="com.example.recenttasks.MainActivity"
android:excludeFromRecents="true">
</activity>
and activity is started this way:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
The key thing you mentioned is
appears in "Recent Tasks" lists while being in foreground
I think you can't change that behavior. I just tested on my app and the same thing happens. If I press the "recent tasks" button while having my activity in the foreground, it appears listed there. The moment I move out of it to another activity or to my phone's main screen, the activity is not listed anymore.
I also tested this on the built-in DeskClock app that comes with recent Android versions and the same behavior is present there when a new alarm is triggered. Note that the AlarmAlertFullscreen activity of that app has the same parameters you mentioned in your question.
I'm not sure you can circumvent this or why you would need to in the first place since the activity is not listed anymore once it loses the focus.
you are defined it in manifest that is enough but it is not coming..
ok..try add this flag also to your Intnet and start the Activity..
intnet.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Should the user be able to return to it? (Meaning if it shows and user clicks recents, have they lost their chance to see the hidden activity or should it still be there?)
If they cannot return to it anyway then the best action would be to finish() the activity onPause(). This will mean that as long as you have used android:excludeFromRecents and android:noHistory="true", there will be no item in recents.
If however you do wish to return to the 'interruption' activity (but do not want a recents entry) you could consider still finishing the activity onPause - but also recording a preference flag (something like IS_INTERSTITIAL). Your other activities can then check this preference in onResume and, if it is true, send an Intent to restart the Interstitial instead - To the user it will just appear they are resuming the app in the same state as they left it (interstitial)
Edit: If the screen needs to stay (rather than be re-instantiated) it may be possible to use a DialogFragment, although then you must worry about configuration changes. There is one hack you could try (explained in this answer) -
Set your label empty By using android:label="" your recent task is excluded. however this is a definite hack which may produce inconsistent results (as I haven't tested it to be sure)
I have an application that uses Urban Airship for push notification. When a notification arrives and the user clicks on it, activity A in my application should open and do something.
I've installed the BroadcastReceiver as is shown in the docs, and it's almost working.
When my app is in the foreground I don't let the user see the notification at all, and just handle it automatically.
When my app is not running at all, the activity opens up just fine.
When my app is in the background (which always happens when A is the top activity), a second instance of Activity A is created.
This is, of course, a problem. I don't want two A activities, I just want one of them. Here's the relevant BroadcastReceiver code:
#Override
public void onReceive(Context ctx, Intent intent)
{
Log.i(tag, "Push notification received: " + intent.toString());
String action = intent.getAction();
int notificationId = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, -1);
if(action.equals(PushManager.ACTION_NOTIFICATION_OPENED))
{
Intent intentActivity = new Intent(ctx, ActivityA.class);
intentActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
UAirship.shared().getApplicationContext().startActivity((intentActivity);
}
}
UPDATE:
I tried to bypass this bug by calling System.exit(0) when the user presses Back on Activity A. The process ended, but then it was restarted immediately! My BroadcastReceiver is not called again in the second instance. What's happening?
UPDATE 2:
#codeMagic asked for more information about the app and activity A.
This app lets its user review certain items and comment on them. Activity A is started when the app is launched. If the user's session isn't valid any more, a Login activity is started. Once the user logs in, activity A becomes active again. A only has a "No items to review" message and a "Try now" button.
When the user logs in, the server starts sending push notifications whenever a new item is available for review. When the app gets the notification, activity A accesses the server and gets the next item to review. The item is shown in activity B. Once the review is submitted to the server, activity B finishes and activity A is again the top activity.
The server knows when a user is reviewing an item (because activity A fetched it), and doesn't send push notifications until the review is submitted - meaning a notification can't come if the user isn't logged in or if the user is viewing activity B.
While I agree there is a subtle race condition here, it is not causing the problem I'm seeing - in testing I am 100% positive there's no race condition - the push notification is only sent after Activity A becomes active again.
The solution was to add a launchMode='singleTask' to the activity in AndroidManifest.xml . As a result, instead of a new activity, onNewIntent of the same activity instance is called.
You can use one of several Intent Flags. FLAG_ACTIVITY_REORDER_TO_FRONT being one of them. This will bring the Activity to the front of the stack if it is already in the stack and if not then it will create a new instance. I believe you will still need FLAG_ACTIVITY_NEW_TASK if you aren't calling it from an Activity
Intent.FLAG_ACTIVITY_CLEAR_TOP should also work. But this will clear any other Activities on the stack. It just depends on what other functionality you need. Look through the Intent Flags and see which of these will work best for you
There are multiple scenarios when this could happen. One of them can be handled this way. Please see my answer here: https://stackoverflow.com/a/44117025/2959575
Ok, two notes on this :
You can register a broadcast receiver via the manifest so it is independent of any parts of your app. and use a Singleton pattern (keep a static reference to your activity somewhere in your app) that way you can check if their is an activity viewing or not and process accordingly.
// your activity A
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
myActivityReference = this;
}
public void onPause() {
super.onPause();
if (isFinishing()) {
myActivityReference = null;
}
}
or you can keep everything as it is and use activity lunching modes flags in your manifest such as singleTop, singleInstance ... etc. take a look here android activity lunch modes