I launch a new activity "ActivityB" when keypad is locked.(ActivityA has been backgrounded before the keypad is locked).
ActivityB times out after 30 secs and supposed to close itself, so I called finish after 30 secs, though is not visible, after I unlock I see 2 seperate apps/activities in background.
So I used Intent.ACTION_USER_PRESENT broadcastreceiver to finish activityB, still it doesnt work.
Manifest.xml
<receiver
android:name="com.example.reciever.UnlockReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
UnlockReceiver:
public class UnlockReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent intent) {
if (ActivityB.b != null) {
ActivityB.b .finish();
}
}
}
ActivityB:
private Activity b;
onCreate() {
b= this;
}
ActivityB is started as we receive push:
Intent pushIntent = new Intent(context.getApplicationContext(), ActivityB.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
I see the onReceive called fine when I unlock the device, but it doesn't finsih ActivityB in the background. Hence I see 2 of the same apps in background
you may have an intent in activity a which is creating the activity b;
The issue was fixed after I set the below property in manifest file
android:launchMode="singleTop"
Related
I have MainActivity declared with following HOME, DEFAULT category, and MAIN Action. I also do select the app as default launcher. When I click back press it closes MainActivity as expected. But if I leave MainActivity running and restart the device, I cannot get out of MainActivity! Pressing onBackPress() in which I call finish(), pauses the activity as expected. But then I see onCreate called(), onResume() and MainActivity is back up like a clown! What I can do? This only happens after restart of device when activity is left running.
I'm doing everything I can to get rid of this activity including inside
onBackPressed(){
ActivityCompat.finishAffinity(MainActivity.this);
finish();
}
I have seen suggestion to FLAG_ACTIVITY_CLEAR_TOP but its the OS that starts the Activity in the first place, not me.
I cannot leave the app at all!
Add this code in your onBackPressed() method.
Intent intentExit = new Intent(Intent.ACTION_MAIN);
intentExit.addCategory(Intent.CATEGORY_HOME);
intentExit.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentExit);
finish();
This is just an idea, don't know whether it will work perfectly
Try creating a broadcast receiver
Get the event of phone restart
Close the app
In Manifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
BootCompleteReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP);
i.putExtra("close_activity",true);
context.startActivity(i);
}
}
MainActivity.java add this block
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent.getBooleanExtra("close_activity",false)){
this.finish();
}
}
References:
Android BroadcastReceiver, auto run service after reboot of device
Close application from broadcast receiver
I'm sorry I know when we mix BroadcastReceivers with activity life-cycle we cause the brain to have lots of errors and malfunction. I need help my brain stopped and my question is simple.
Is there a way to have BroadcastReceiver class that detect an activity going onPause() method ? if yes then how would that class be?
the only thing i can think of it on your activity send a costume broadcast intent that one of your receivers.
e.g:
action:
public static final String CUSTOM_INTENT = "example.com.intent.action.ActivityGoingOnPause";
activity onPause:
protected void onPause() {
Intent i = new Intent();
i.setAction(CUSTOM_INTENT);
context.sendBroadcast(i);
}
manifest:
<receiver android:name=".YourReceiver" android:enabled="true">
<intent-filter>
<action android:name="example.com.intent.action.ActivityGoingOnPause"></action>
</intent-filter>
</receiver>
reciver:
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(YourActivity.CUSTOM_INTENT)) {
//do your thing
}
}
}
Hope this helps
Set a global variable like isActivityPaused in onPause and unset it in onResume of the activity and then check that variable and decide whether to send broadcast or not.
BACKGROUND
I have a task (i.e. app) with multiple activities.
QUESTION
How do I bring a task to the front w/o re-ordering the activity stack for that task?
USER SCENARIO
When the device boots (i.e. after android.intent.action.BOOT_COMPLETED broadcast is received) my app starts, call this task 1, and displays activity A (code below). As the user interacts with task 1, he/she opens activity B on the stack (activity B is now currently displayed on screen). Next the user taps the home key and opens some other task, call it task 2, then locks the screen. The user unlocks the screen, and the android.intent.action.USER_PRESENT intent is broadcast and received by my app (see manifest snippet below). My executes the startActivity() call in my IntentReceiver class as expected, but instead of just bringing the task to the foreground it creates a new task, call it task 3.
CHANGES I'VE TRIED
If I modify or change the Intent.FLAG_ACTIVITY_NEW_TASK to any other intent then I get this error message:
Calling startActivity() from outside of an Activity context requires
the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
...so it looks like I have to use Intent.FLAG_ACTIVITY_NEW_TASK.
If I change the main activity's lauchMode to "singleTask" the correct task is brought to the foreground (i.e. no new task is created), but the activity stack is reordered such that activity_A is on top of the stack.
At this point I am at a loss as to how to bring an existing task to the foreground w/o re-ordering the activity stack while listening for the android.intent.action.USER_PRESENT intent, any help would be appreciated.
BTW, This app is being delivered on to a group of employees, not the general public, on company owned android devices.
CODE SNIPPETS
To start the app I setup a broadcast receiver in my manifest file.
<application
:
<activity
android:label="#string/app_name"
android:launchMode="singleTop"
android:name=".activities.activity_A" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
:
<receiver
android:enabled="true"
android:name=".utilities.IntentReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
In my IntentReceiver class, I start my main activity...
public class IntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, activity_A.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Here's a slightly hackish implementation that works for me:
Create a simple BringToFront activity that simply finish() itself on its onCreate():
public class BringToFront extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
}
}
In your BroadcastReceiver, start the BringToFront activity above instead of your activity_A if the action is USER_PRESENT:
#Override
public void onReceive(Context context, Intent intent) {
Class<? extends Activity> activityClass = activity_A.class;
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
activityClass = BringToFront.class;
}
Intent i = new Intent(context, activityClass);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
This works because the BringToFront activity has the same taskAffinity as your activity_A and starting it will make the system bring the existing task to the foreground. The BringToFront activity then immediately exit, bringing the last activity on your task (activity_B in your scenario) to the front.
It's worth noting that on API level 11 (Honeycomb), a moveTaskToFront() method is added to the system's ActivityManager service that might probably be the better way to achieve what you want.
Ok, I was able to get this to work by adding a static global variable in my main activity (activity_A). In onCreate I set isRunning = true, and onDestory = false. Then in my IntentReceiver class I check the isRunning to determine which activity to start:
:
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
if (GlobalVariables.isRunning) {
activityClass = BringToFront.class;
} else {
activityClass = activity_A.class;
}
} else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
activityClass = activity_A.class;
}
:
I want to start a system application activity in a broadcast onReceive() method, but it cannot be run. I need help!
My Manifest.xml
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
My java:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent b_intent = new Intent();
b_intent.setComponent(new ComponentName("com.android.email", "com.android.email.activity.Welcome"));
b_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(b_intent);
}
}
But this email application can not be run. There is only black color on the screen.
Thanks!
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent()
i.setClassName("com.android.email", "com.android.email.activity.Welcome");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i); }
Launching system or third party apps from your app should be done through implicit intents. Hard-coding the package names and component names is not reliable and may not work all the time.
Morever, this particular activity, I guess, is not allowed to be called from other apps (my assumption, I might be wrong)
I'm just trying this little sample project, all it does:
Activity one has a Button that sends a Broadcast. Activity two displays a toast when received.
Below is the code, the Broadcast is never received. What do I do wrong?
Sending the Broadcast
public class SendBroadcast extends Activity {
public static String BROADCAST_ACTION = "com.unitedcoders.android.broadcasttest.SHOWTOAST";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void sendBroadcast(View v){
Intent broadcast = new Intent();
broadcast.setAction(BROADCAST_ACTION);
sendBroadcast(broadcast);
}
}
Receiving it
public class ToastDisplay extends Activity {
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT);
}
};
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(SendBroadcast.BROADCAST_ACTION);
registerReceiver(receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
}
Manifest
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".SendBroadcast" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ToastDisplay">
<intent-filter>
<action android:name="com.unitedcoders.android.broadcasttest.SHOWTOAST"></action>
</intent-filter>
</activity>
</application>
What do I do wrong?
The source code of ToastDisplay is OK (mine is similar and works), but it will only receive something, if it is currently in foreground (you register receiver in onResume). But it can not receive anything if a different activity (in this case SendBroadcast activity) is shown.
Instead you probably want to startActivity ToastDisplay from the first activity?
BroadcastReceiver and Activity make sense in a different use case. In my application I need to receive notifications from a background GPS tracking service and show them in the activity (if the activity is in the foreground).
There is no need to register the receiver in the manifest. It would be even harmful in my use case - my receiver manipulates the UI of the activity and the UI would not be available during onReceive if the activity is not currently shown. Instead I register and unregister the receiver for activity in onResume and onPause as described in
BroadcastReceiver documentation:
You can either dynamically register an instance of this class with Context.registerReceiver() or statically publish an implementation through the tag in your AndroidManifest.xml.
Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT);
makes the toast, but doesnt show it.
You have to do Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT).show();
Extends the ToastDisplay class with BroadcastReceiver and register the receiver in the manifest file,and dont register your broadcast receiver in onResume() .
<application
....
<receiver android:name=".ToastDisplay">
<intent-filter>
<action android:name="com.unitedcoders.android.broadcasttest.SHOWTOAST"/>
</intent-filter>
</receiver>
</application>
if you want to register in activity then register in the onCreate() method e.g:
onCreate(){
sentSmsBroadcastCome = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "SMS SENT!!", Toast.LENGTH_SHORT).show();
}
};
IntentFilter filterSend = new IntentFilter();
filterSend.addAction("m.sent");
registerReceiver(sentSmsBroadcastCome, filterSend);
}
You need to define the receiver as a class in the manifest and it will receive the intent:
<application
....
<receiver android:name=".ToastReceiver">
<intent-filter>
<action android:name="com.unitedcoders.android.broadcasttest.SHOWTOAST"/>
</intent-filter>
</receiver>
</application>
And you don't need to create the class manually inside ToastDisplay.
In the code you provided, you must be inside ToastDisplay activity to actually receive the Intent.
I think your problem is that you send the broadcast before the other activity start ! so the other activity will not receive anything .
The best practice to test your code is to sendbroadcast from thread or from a service so the activity is opened and its registered the receiver and the background process sends a message.
start the ToastDisplay activity from the sender activity ( I didn't test that but it may work probably )
You forget to write .show() at the end, which is used to show the toast message.
Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT).show();
It is a common mistake that programmer does, but i am sure after this you won't repeat the mistake again... :D
Your also have to register the receiver in onCreate(), like this:
IntentFilter filter = new IntentFilter();
filter.addAction("csinald.meg");
registerReceiver(receiver, filter);