Go to previous activity from BroadcastReceiver? - java

I need to close the current activity from a broadcast receiver. I'm not sure how to call finish from it, maybe there is a way to simulate a "Back" key keypress. Any implementation will be fine as long as it does the job.
#Override
public void onReceive(Context context, Intent intent) {
// How can I finish the current activity here?
}

At your broadcast receiver write:
YourCurrentActivityName.this.finish();
Or you can terminate the front activity with this.finish(); so the last open in stuck comes to front.
Update:
Code for first case:
Use of broadcast receiver to terminate activity at back stack:
public class ActivityFirstName extends Activity {
private BroadcastReceiver mFinishReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// other code
if (mFinishReceiver == null) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.ACTION_TERMINATE");// a string to identify your action
mFinishReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// How can I finish the current activity here?
if ("com.example.ACTION_TERMINATE".equals(intent.getAction())) {
ActivityFirstName.this.finish();
}
}
};
registerReceiver(mFinishReceiver, intentFilter);
}
// other code
}
#Override
protected void onDestroy() {
super.onDestroy();
if (isFinishing()) {
if (mFinishReceiver != null) {
unregisterReceiver(mFinishReceiver);
}
}
}
}
And the front/current running activity, the sender of the broadcast:
public class ActivitySecondName extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
// code code code
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Perform action on click
terminateBackActivities();
}
});
}
private void terminateBackActivities() {
Intent i = new Intent("com.example.ACTION_TERMINATE"); // the two action strings MUST be same
// i.putExtra(...); // to send extra data
sendBroadcast(i);
}
}

You can simply call this.finish();

Assuming from your comment that the BroadcastReceiver is not an internal class of the activity, here is what you should do: Rather than having the broadcast receiver in a separate class, define it inside your activity like so:
private BroadcastReceiver mFinishReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
YourActivity.this.finish();
}
};
Then, you will want to register the receiver in onResume() as such:
#Override
public void onResume(){
super.onResume();
registerReceiver(mFinishReceiver, new IntentFilter(yourIntentAction));
}
You will also want to unregister this receiver in onPause() so you don't leak it:
#Override
public void onPause(){
super.onPause();
unregisterReceiver(mFinishReceiver);
}
Then you can remove the other receiver that had its own separate class and also remove its definition in the manifest. The above example will ensure that you can always call finish() with no issues because the receiver is only registered when the activity is running, as it is internal to the activity's class.
EDIT: Change the methods to onCreate() and onDestroy() rather than onPause() and onDestroy(), according to madlymad's comment.

The ActivityManager class can give you the current foreground activity (even if it's not from your app). The getRunningTasks methods will give you a list of the running tasks, the first element of the list being the most recent launched activity.Unfortunately,this method will just give you an object of type RecentTaskInfo , not the activity itself, so there is no way to call its finish() method,I believe :/
On the other hand, if you want to close the current activity from your app, you can implement a static variable on a personal class that each activiy would set in their onResume() method. This way you will always know what activity is the current one. But I guess it's not what you are looking for.
Edit: The getRunningTasks is just intended for debug purposes, as says the doc..

As suggested by other answers you can simply call finish() on the activity in the broadcast receiver code or you can even trigger a back button press key event yourself.
this.dispatchKeyEvent(new Keyevent(ACTION_DOWN, KEYCODE_BACK));

Not sure about whether this is helpfull to you or not but its help me once and i think thats a same case here so i am answering for you.
Whenever the broadcast receiver get call, you can navigate to any activity by clicking on that broadcast message.
Just like:
#Override
public void onReceive(Context context, Intent intent) {
// My Notification Code
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
int icon = R.drawable.app_icon;
//System.out.println("The ID Number is: "+Long.parseLong(intent.getData().getSchemeSpecificPart()) );
contentText = intent.getStringExtra("MyMessage");
System.out.println("The Message is: "+intent.getStringExtra("MyMessage"));
CharSequence text = "Your tax amount due period";
CharSequence contentTitle = "Tax Toolbox";
long when = System.currentTimeMillis();
intent = new Intent(context, MenuPageActivity.class); // here i am calling activity
intent.putExtra("sixMonth", "sixMonth");
intent.putExtra("messageSixMonth", contentText);
PendingIntent contentIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new Notification(icon,text,when);
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate; // To vibrate the Device
notification.ledARGB = Color.RED;
notification.ledOffMS = 300;
notification.ledOnMS = 300;
notification.defaults |= Notification.DEFAULT_LIGHTS;
//notification.flags |= Notification.FLAG_SHOW_LIGHTS;
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
notificationManager.notify(com.project.TaxToolbox.NotificationConstants.NOTIFICATION_ID_SIX_MONTH, notification);
}
Now, on the onCreate() of that activity you have to identify whether it is call by Notification or not.
As like:
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
System.out.println("The Extra for twoMonth is: "+getIntent().hasExtra("twoMonth"));
System.out.println("The Extra for sixMonth is: "+getIntent().hasExtra("sixMonth"));
System.out.println("The Extra for EveryMonth is: "+getIntent().hasExtra("everyMonth"));
if(getIntent().hasExtra("sixMonth")){
notificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SIX_MONTH);
final AlertDialog alert3 = new AlertDialog.Builder(MenuPageActivity.this).create();
alert3.setTitle("Tax Toolbox");
alert3.setMessage(getIntent().getExtras().getString("messageSixMonth"));
alert3.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alert3.setIcon(R.drawable.app_icon);
alert3.show();
// here you can do anything more or close the activity.
}
Not sure but might be helpfull to you.
Feel free to comments if it help you.

Create a common Activity class and extend this common class from all activities, that way you can have a centralized code. Have a register the broadcast receiver in onStart of the activity and unregister in onStop that way only one activity, the one which is visible will be registered for the broadcast intent.
Sample code:
public class BaseActivity extends Activity {
/*
* (non-Javadoc)
*
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(receiver, new IntentFilter(YOUR_INTENT_FILTER));
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onStop()
*/
protected void onStop(){
unregisterReceiver(receiver);
}
/*
* (non-Javadoc)
*
* #see android.app.Activity#onStart()
*/
protected void onStart(){
super.onStart();
registerReceiver(receiver, new IntentFilter(YOUR_INTENT_FILTER));
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
/*
* (non-Javadoc)
*
* #see
* android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
#Override
public void onReceive(Context context, Intent intent) {
onBackPressed();//on back pressed simply calls finish()
}
};
} // End of BaseActivity
// End of File

Try using:
Intent i = new Intent(context,intent.getClass());

Follow the instructions from gezdy on How to get current foreground activity context in android? to ensure you can get a reference to the current activity from anywhere in your application.
From there you can call .finish() to close the current activity.

Place finish(); after u completed all the tasks in onReceive() of BroadcastReceiver class as below:
#Override
public void onReceive(Context context, Intent intent) {
// Do all the tasks onReceive of BroadCast Receiver
finish(); // This finishes the current activity here....
}

Related

From where value of intent is coming on which I am calling getAction() function? (This is overridden method of BroadcastReceiver class)

I have created a broadcast receiver class Which is working fine. I am confused about from where the value of intent comes in onReceive method.
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(wifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action))
{
int state=intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,-1);
if(state==WifiP2pManager.WIFI_P2P_STATE_ENABLED){
Toast.makeText(context,"Wifi is ON",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(context,"Wifi is OFF",Toast.LENGTH_SHORT).show();
}
}
}
Main Activity code where I have made an Intent Filter, where I have added an action.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_device);
wifiP2pManager = (WifiP2pManager)
getSystemService(Context.WIFI_P2P_SERVICE);
channel = wifiP2pManager.initialize(this,getMainLooper(),null);
broadcastReceiver = new WiFiDirectBroadcastReceiver(wifiP2pManager, channel, this);
intentFilter = new IntentFilter();
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
}
If your BroadcastReceiver works, then you must have initialized wifiP2pManager and called a function on the object. When tbe state changes an intent is being broadcasted. With the receiver you subscribe to those intents.
You can read in more detail about the WifiP2pManager in the Android documentation Wi-Fi Direct (peer-to-peer or P2P) overview

How to destroy/kill a service?

I have my application running a service for shake detect, however in my MainActivity, I have button for log out user, in which I must log out and terminate the service that detects the shake event.
my method for log out in my MainActivity is:
public void signOutAndFinish(){
//Stop Shakeservice
Intent intent = new Intent(this, ShakeService.class);
stopService(intent);
//Go to login activity
Intent iLoginView = new Intent(this, LoginActivity.class);
startActivity(iLoginView);
}
however if I shake my device after logging out, the service recognizes the shake, it is as if it will not kill it immediately:
Intent intent = new Intent(this, ShakeService.class);
stopService(intent);
The code in the method onDestroy is:
#Override
public void onDestroy() {
super.onDestroy();
}
How can I terminate the service so that when I log out the service dies?
Thanks for your help!
You can send a broadcast back your activity in the onDestroy() method of your service and then do the logout.
Here is some sample code of the above idea:
This for your service:
#Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data","Notice for logout!");
sendBroadcast(intent);
}
And this is for your activity:
private BroadcastReceiver br = new MyBroadcastReceiver();
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter("com.example.broadcast.MY_NOTIFICATION");
registerReceiver(br, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(br);
}
// An inner class at your activity
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "MyBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
YourActivity.this.finish();
// or do anything you require to finish the logout...
}
}
however if I shake my device after logging out, the service recognizes the shake
Then presumably you did not clean up your Sensor stuff in the service's onDestroy() method.
How can I terminate the service so that when I log out the service dies?
You are doing that now. However, if you set up something in the service, such as listening to events from SensorManager, you need to clean that up, typically in onDestroy() of the service.

Android service running but overlay activity flicks and disappears

Background info: I'm trying to create a service. I create it in my main activity. I know the service is running because the notification is showing. So the service doesn't stop at any point.
What i want to happen: when the screen is locked/turned off i want a certain activity to be displayed for when the screen is turned back on.
What is happening: first, When the screen is turned back on the main activity shows and then the activity i want shows over that. I dont want the main activity to show at all when the screen is turned on .
Then i changed a few things: and now the desired activity flickers on the main screen and then vanishes. It seems very unreliable and only comes a few times.
That should be enough info, here is the code so far (specifically onReceive())
public class OverlayService extends Service{
//IN THIS CLASS CHECK WHETHER LOCK BUTTON WAS PRESSED OR IF PHONE WHEN TO SLEEP.. UPON AWAKENING START THE OVERLAY ACTIVITY...
private BroadcastReceiver mReceiver;
private boolean isShowing = false;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private WindowManager windowManager;
WindowManager.LayoutParams params;
#Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//Register receiver for determining screen off and if user is present
mReceiver = new OverlayStateReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mReceiver, filter);
makeNotification();
}
void makeNotification() {
Notification notification = new NotificationCompat.Builder(this)
//TODO change icon
.setSmallIcon(R.drawable.test)
.setContentTitle("App")
.setContentText("service is running...")
.setPriority(Notification.PRIORITY_LOW)
.build();
startForeground(1, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public class OverlayStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.i("app", "load view");
showOverlayActivity(context);
}
}
}
private void showOverlayActivity(Context context) {
Intent intent = new Intent(context, OverlayActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
#Override
public void onDestroy() {
//unregister receiver when the service is destroy
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
//TODO remove view if it is showing and the service is destroy
super.onDestroy();
}
}

BroadcastReceiver fires only once

I have activity where I have EditText for user to enter certain data. After user writes some text and clicks button, he is waiting for a response from BroadcastReceiver. The problem is that everything works for the first time and user receive response but if user doesn't exit activity and clicks the button again, BroadcastReceiver is not firing anymore. If user closes activity and opens it again, BroadcastReceiver is again working but only for the first time.
This is a little bit confusing. Here is my code:
public void onCreate(Bundle savedInstanceState) {
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent in) {
switch (getResultCode()) {
case Activity.RESULT_OK:
mStatus = true;
break;
}
}
};
getActivity().registerReceiver(mReceiver,
new IntentFilter(FLAG));
}
When user clicks button:
Intent in = new Intent(FLAG);
PendingIntent pIn = PendingIntent.getBroadcast(context, 1, in, 0);
SmsManager.getDefault().sendTextMessage("123456789", null, "text", pIn, null);
while(!mStatus){
}
mStatus = false;
Unregister receiver:
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mReceiver);
}
What do you think? Why it works only when activity is started and button is clicked for the first time?
Try this instead:
public void onPause() {
super.onPause();
// getActivity().unregisterReceiver(mReceiver);
}
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(mReceiver);
}
Explanation: you should manage the receiver either in onCreate() / onDestroy() or onResume() / onPause() (corresponding lifecycle events).
Edit: make this change also (second line sets flag argument):
Intent in = new Intent(FLAG);
PendingIntent pIn = PendingIntent.getBroadcast(context, 1, in, PendingIntent.FLAG_UPDATE_CURRENT);
SmsManager.getDefault().sendTextMessage("123456789", null, "text", pIn, null);
Not sure if this will fix it because I don't know what the 0 would mean that you were using for the flag value. FLAG_UPDATE_CURRENT seems correct though.
Edit 2:
while(!mStatus){
}
You should never do that!

Orientation change and Notification

I want to implement the following scenario:
When a user presses the Home key a Notification is displayed in the Status bar and the App is normally hidden. When user taps the Notification App is normally restored.
Here is my code for this:
private int NOTIFICATION = R.string.local_service_started;
private NotificationManager mNM;
private void showNotification() {
CharSequence text = getText(R.string.local_service_started);
Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, JingleCartoucheActivity.class), 0);
notification.setLatestEventInfo(this, getText(R.string.local_service_label), text, contentIntent);
mNM.notify(NOTIFICATION, notification);
}
#Override
public void onPause() {
super.onPause();
if (!isFinishing()) {
showNotification();
}
}
#Override
public void onResume() {
super.onResume();
mNM.cancel(NOTIFICATION);
}
All of this is working well except for one thing:
When the App is run and the user rotates the phone, the notification is created and immediately destroyed. Is there a way to detect the phone orientation change in onPause() and not show this Notification?
You can get the current orientation using the getResources().getConfiguration().orientation. At the onCreate you store the orientation value and then you can compare it later. Be sure to store the value into a static variable, since when you rotate the phone, the activity is destroyed and so are it's values.
When the user rotate the screen the activity is destroyed and recreated , If you want to display the notification after orientation change make a static flag in onDestroy method and check it in the onCreate method to display the notification like
public void onDestroy() {
Flag = 1;
}
and
public static int Flag = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(Flag == 1) {
showNotification();
}
else {
.......//
}
}

Categories

Resources