How to know if activity is at the top of stack - android

How could I know if an activity is the top of stack? I thought about using onResume/onPause, but this is not exactly, as it would fail once the app goes to background.
The fact is that I'm sending a broadcast receiver that is received for all activities (I have a BaseActivity that is extended by all activities and that registers to the broadcast). So, only the activity that is at the top of the stack must react to the broadcast. If I use the isResumed() then it would work always but when the app goes to background. Any idea?
Thanks in advance!

in base activity you register the broadcast Receiver and in receiver function you call one abstract function which one is implemented by all child activities.
The activity which is on top will automatically receive that function call.
Edit sample code:
public abstract class BaseActivity extends AppCompatActivity {
private static final String NOTIFICATION_ARRIVED = "arrived";
public abstract void receivedFunction(Intent intent);
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
displayToast(" received in Base");
receivedFunction(intent);
}
};
public void displayToast(String s) {
Toast.makeText(this,s,Toast.LENGTH_SHORT).show();
}
#Override
public void onResume() {
super.onResume();
registerReceiver(mMessageReceiver, new IntentFilter(BaseActivity.NOTIFICATION_ARRIVED));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(mMessageReceiver);
}
}
public class MainActivity extends BaseActivity {
#Override
public void receivedFunction(Intent intent) {
displayToast(" received in child");
}
// do whetever you want . if you ovveride onpause and onResume then call super as well
}
or any other child
public class MainActivity2 extends BaseActivity {
#Override
public void receivedFunction(Intent intent) {
displayToast(" received in child");
}
// do whetever you want . if you ovveride onpause and onResume then call super as well
}
// to broadcast
Intent intent = new Intent(BaseActivity.NOTIFICATION_ARRIVED);
sendBroadcast(intent);

Related

Passing events from a non-activity class to an Activity class

I have an activity class A for the layout and a non-activity class B for Location Request; the class B triggers some events like onConnectionSuspended and i want to get these back in the classe A. How can i do that ?
Thank you for the previous answers, i worked on it but i add some details.
I want to separate the Activity code from the GoogleApi.Connection code. To do that i made a non-activity class (maybe a service is better ?) with Connection code (see the structure code below).
1) Is it a good idea ?
2) If it is not, what is better to do (maybe put all in the same Activity ?) ?
3) If it is yes, i don't think that i can put some "Toast" in the connections events of my non-activity code so how can i get back the connections events in the Activity to display some messages ?
Thank you for the answers
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
public class SATlocation implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
As an alternative to broadcast receivers, if you have access to your class B instance from your Activity, you can also create an interface for listening to those events.
public interface LocationRequestEventListener {
void onConnectionSuspended();
...
}
public class SomeActivity extends Activity implements LocationRequestEventListener {
private ClassB classB;
#Override
public void onCreate() {
...
classB.setListener(this);
}
...
#Override
void onConnectionSuspended() {
//react to the event here
}
}
public class ClassB {
private LocationRequestListener listener;
....
public void setListener(LocationRequestListener listener) {
this.listener = listener;
}
private void connectionSuspended() {
// suppose this is where your class fire the event of interest
if (listener != null) {
listener.onConnectionSuspended();
}
}
}
use Local broadcast receiver add receiver in your activity as below
private BroadcastReceiver onNotice = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// intent can contain anydata
}
}
inside onresume register receiver as below
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(MyIntentService.ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, intentFilter);
}
unRegister receiver in onPause
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}
In your location service add following code to send local broadcast
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

How to run function with broadcastreceiver in Android?

I have a function in activity I want to run this function with broadcastreceiver. How can I make this?
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
}
}
This is my broadcastreceiver class I want to run function which is in my activty please tell me with some code how to do this.
If the method you want to execute needs your activity instance, then you can register the broadcast receiver inside your activity, so it can access your activity's state and functions.
In your Activity "onCreate" method:
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Your Intent action here");
intentFilter.addAction("Another action you want to receive");
final BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
theFunctionYouWantToExecute();
}
};
registerReceiver(myReceiver, intentFilter);
And in your "onDestroy" method:
unregisterReceiver(myReceiver);
Keep in mind that in this case your broadcast receiver has full access to your activity state, BUT it's lifecycle will be conditioned to the activity lifecycle.
Another option you have is to declare your activity method as static, so you can execute it in any part of your application.
You can declare an interface in Myclass and implement it in your MainActivity
public class Myclass extends BroadcastReceiver{
public interface MyClassInterface {
void onMyClassReceive();
}
private MyClassInterface mListener;
public Myclass(MyClassInterface mMyClassInterface) {
mListener = mMyClassInterface;
}
#Override
public void onReceive(Context context, Intent intent) {
mListener.onMyClassReceive();
}
}
Then in your MainActivity:
public class MainActivity implements Myclass.MyClassInterface {
private mMyClass Myclass = new Myclass(this);
#Override
public void onMyClassReceive() {
// Do stuff when Myclass.onMyClassReceive() is called,
// which will be called when Myclass.onReceive() is called.
}
}
You are almost there. Just create your method in the Activity and using Activity's instance call that method. Remember that your method inside your Activity should be not private.
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
new YourActivity().yourFunction();
}
}
If you want to create a static method inside your Activity then
public class Myclass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
YourActivity.yourFunction();
}
}
To trigger the Broadcast, you have to pass an Intent. If you want to trigger it from any Activity then
Intent intent = new Intent();
this.sendBroadcast(intent);
If you want to trigger the Broadcast from a Fragment then
Intent intent = new Intent();
getActivity().sendBroadcast(intent);
I know it's quote naif, but you could call a static method in your activity.
In your activity you declare the method like this:
public static <return_type> yourMethod(<input_objs>){
....
Your code
....
}
In the receiver you can use this function just calling:
YourActivityClass.yourMethod(<input_objs>);
I hope it helped.

do something inside mainActivity whenever a push notification is received

In my app, whenever I receive a push notification, I will perform a check if my mainActivity is visible to the user to do something...
I have a static boolean value that is set true inside onResume of mainActivity, and false inside it's onPause.
What should I do inside the onMessage
#Override
protected void onMessage(Context context, Intent intent)
{
if(mainActivity == visible)
//do something inside mainactivity.. change text inside edittext
else
//do something else
}
any insights ?
I'm not a fan of keeping static references to activities. I think they're a can of worms ready to explode on you. So you'll suggest an alternative to #TeRRo answer:
on your global BroadcastReceiver onMessage you'll send a LocalBroadcast that your activity will be listening to. Like this:
private static final String ACTION_PUSH_RECEIVED = "com.myapp.mypackage.action.pushReceived";
public static final IntentFilter BROADCAST_INTENT_FILTER = new IntentFilter(ACTION_PUSH_RECEIVED);
#Override
protected void onMessage(Context context, Intent intent) {
Intent i = new Intent(ACTION_PUSH_RECEIVED);
i.putExtra( ... add any extra data you want... )
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
}
and now we make the activity listen to it:
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(context)
.registerReceiver(mBroadcastReceiver, BroadcastReceiverClass.BROADCAST_INTENT_FILTER);
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(context)
.unregisterReceiver(mBroadcastReceiver);
super.onPause();
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
// read any data you might need from intent and do your action here
}
}
To avoid this, you should manage activities references. Add the name of the application in the manifest file:
<application
android:name=".MyApp"
....
</application>
Your application class :
public class MyApp extends Application {
public void onCreate() {
super.onCreate();
}
private Activity mCurrentActivity = null;
public Activity getCurrentActivity(){
return mCurrentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity){
this.mCurrentActivity = mCurrentActivity;
}
}
Create a new Activity :
public class MyBaseActivity extends Activity {
protected MyApp mMyApp;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMyApp = (MyApp)this.getApplicationContext();
}
protected void onResume() {
super.onResume();
mMyApp.setCurrentActivity(this);
}
protected void onPause() {
clearReferences();
super.onPause();
}
protected void onDestroy() {
clearReferences();
super.onDestroy();
}
private void clearReferences(){
Activity currActivity = mMyApp.getCurrentActivity();
if (currActivity != null && currActivity.equals(this))
mMyApp.setCurrentActivity(null);
}
}
So, now instead of extending Activity class for your activities, just extend MyBaseActivity. Now, you can get your current activity from application or Activity context like that :
Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
Or why don't you use the Local broadcasts when you receive the push notification, and receive it in your activity, and do respective changes or actions.
And if they are UI intensive tasks, bind your activity to a service, and receive the push notification and perform the action in this service and use the result in the activity.

Modify UI from BroadcastReceiver

I need some way to detect when the network connection has been lost.
So a switch between mobile and wifi doesn't really matter it's just to detect at runtime when the connection has been lost.
I now have found some code which works fine for me.
public class ConnectivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(ConnectivityReceiver.class.getSimpleName(), "action: "
+ intent.getAction());
}
}
I want to check inside the onReceive() method wheter or not a connection is still available or not.
The thing is, that I want to show a message to the user, if it has been lost. So what's the best way of passing back to my Activity, that the connection has been lost?
If you want to track network connection state only when activity is on screen you can place your ConnectivityReceiver as inner nested class in Activity. In this case you should register it in onResume method and unregister it in onPause. It will look like this:
public class MyActivity extends Activity {
private class ConnectivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(ConnectivityReceiver.class.getSimpleName(), "action: "
+ intent.getAction());
}
}
private final BroadcastReceiver receiver = new ConnectivityReceiver();
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
}
}
You can have an inner Class which extends BroadcastReceiver and you can dynamically register it. From the innterclass(precisely onRecieve() method) you can access your Activity.

Communication between C2DM BroadcastReceiver and multiple activities

I have an Android application which uses C2DM services (aka push).
I have a separate class which implements the registration process and which receives the data (and extends BroadcastReceiver).
I want to communicate this data to the activity which currently is in the foreground. The activity currently in the foreground may differ depending on user action.
What's the best way to communicate in between the receiver and the current activity?
Thanks.
I solved this problem by sending out a new broadcast from the C2DMReceiver class, which looked something like this.
The C2DMReceiver class:
public class C2DMReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(context, intent);
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
handleMessage(context, intent);
}
}
private void handleRegistration(Context context, Intent intent) {
// handle registration
}
private void handleMessage(Context context, Intent intent) {
Intent i = new Intent("push");
i.putExtras(intent);
// context.sendOrderedBroadcast(i, null);
context.sendBroadcast(i);
}
}
Another class I called PushReceiver. This is the class that will extend BroadcastReceiver and receive the broadcast sent by C2DMReceiver.
public class PushReceiver extends BroadcastReceiver {
public PushReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
// do stuff
abortBroadcast();
}
public static class PushFilter extends IntentFilter {
private static final int DEFAULT_PUSH_PRIORITY = 1;
public PushFilter() {
this(DEFAULT_PUSH_PRIORITY);
}
public PushFilter(int priority) {
super("push");
setPriority(priority);
}
}
}
And the activity class, in this case called MyActivity. This should work well if you are using a base activity class that all other activities extend. That way every activity registers the receiver. By doing the register/unregister in onResume/onPause, you should be able to guarantee that only the current activity receives the broadcast. If not, you can send an ordered broadcast from C2DMReceiver and use priority in the PushFilter.
public class MyActivity extends Activity {
private PushReceiver pushReceiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// your onCreate method
pushReceiver = new PushReceiver();
}
public void onResume() {
super.onResume();
// your onResume method
registerReceiver(pushReceiver, new PushReceiver.PushFilter());
}
public void onPause() {
super.onPause();
// your onPause method
unregisterReceiver(pushReceiver);
}
}
In my case, I wrote the PushReceiver constructor to take a View and then "did stuff" with the view in the onReceive method. Without knowing more about what your trying to do, I can't elaborate on this, but hopefully this can provide a decent template to work from.

Categories

Resources