EventBot: subscribing activity is not reached by Event - android

Problem:
For some communication scenarios I am using EventBus.
I have got an event that is already successfully fired and subscribed by different components in my app.
Now I need an activity to subscribe that event. Unfortunately it is not reached.
Question:
How can I achieve that the activity does subscribe the event correctly, either? Is the problem with registering the activity?
Note:
I have found that post that suggests to use onStart() and onStop() events.
my activity class:
public class MachineActivity extends AppCompatActivity{
(...)
#Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void characteristicsChangeByUser(IntentChangeByUser intentChangeByUser) {
// Do something here.
}
(...)
}
EventBus class:
public class IntentChangeByUser {
int position;
int value;
public IntentChangeByUser(int position, int value){
this.position = position;
this.value = value;
}
public int getPosition() {
return position;
}
public int getValue() {
return value;
}
}

Could be because you have the wrong way to unregister then EventBus in onStop().
Change to this:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
Then make sure in your Subscriber Activity, there is received Event:
#Subscribe(threadMode = ThreadMode.MAIN)
public void characteristicsChangeByUser(IntentChangeByUser intentChangeByUser) {
// Do something here.
Log.d("Activity", "IntentChangeByUser Event received");
}

Related

Event Bus not received

I'm trying to pass an event with Otto Event Bus from the SplashActivity to LoginActivity which is 2 o 3 activities later with:
SplashActivity
#Override
public void onStart() {
super.onStart();
BusProvider.getInstance().register(this);
if(UtilityManager.isAppOpenedFromNotificationTap(this)){
BusProvider.getInstance().post(new AppOpenedFromNotificationClickEvent());
}
}
#Override
public void onStop() {
super.onStop();
BusProvider.getInstance().unregister(this);
}
And I am getting value with:
LoginActivity
#Override
public void onStart() {
super.onStart();
BusProvider.getInstance().register(this);
}
#Override
public void onStop() {
super.onStop();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void onAppOpenedFromNotificationEvent(AppOpenedFromNotificationClickEvent event) {
Log.e("LOGIN", "ARRIVED" );
appOpenedFromNotification = true;
}
These Log that I put inside subscribe is never showed. What the problem?
Use a sticky event
for sending
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
for receiving
// UI updates must run on MainThread
#Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}

Doing something when returning to an Activity from Background

I want to execute a function only when returning to the Application from the background.
I have included the method in onResume, and this does it to a certain extent. Problem is since onResume is fired even on creating the Activity and when returning to the activity from another activity (Ex: From pressing the back button), and the function is executed there as well.
How to avoid this and execute the function only when returning from background?
Ps: My application already has multiple places using startActivity so changing to startActivityForResult is a tedious task.
Also all my Activities are extending from a common BaseAppCompactActivity class and it's where my method is located, so this will apply to the whole application.
Edit 2:
My BaseAppCompactActivity is as below with LifecycleObserver implemented now. This doesn't seem to work though.
public class BaseAppCompactActivity extends AppCompatActivity implements LifecycleObserver {
private String TAG = BaseAppCompactActivity.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
#Override
protected void onPause() {
super.onPause();
stopService();
}
#Override
protected void onPostResume() {
super.onPostResume();
startService();
}
// #Override
// protected void onResume() {
// super.onResume();
//// updateLastAccessedDate();
// }
private void startService() {
startService(new Intent(this, BusinessCacheService.class));
}
private void stopService() {
stopService(new Intent(this, BusinessCacheService.class));
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
private void updateLastAccessedDate() {
//Do something
}
}
Although its a duplicate . Here is a Java implementation i am sharing for sake of help ..
public class MyApplication extends MultiDexApplication implements LifecycleObserver {
private boolean previouslyInBackground;
#Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onAppBackgrounded() {
previouslyInBackground=true;
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
void onAppForegrounded() {
if(previouslyInBackground){
// Do your stuff Here
}
previouslyInBackground=false;
}
}
Add the Gradle dependency from Lifecycle-aware components Documentation
You can use startActivityForResult instead of startActivity.
Then you can catch the returning inside onActivityResult method.
first set a global boolean variable like this:-
boolean isPaused = false;
now set a methods in your activity :-
#Override
protected void onUserLeaveHint() {
isPaused = true;
super.onUserLeaveHint();
}
or in your onResume method:-
#Override
protected void onResume() {
if(isPaused){
isPaused = false;
}
super.onResume();
}
Do like this
add these variable in your main activity
public static boolean isAppWentToBg = true;
public static boolean isWindowFocused = false;
public static boolean isBackPressed = false;
and also add these methods
private void applicationWillEnterForeground() {
if (isAppWentToBg) {
isAppWentToBg = false;
// Toast.makeText(getApplicationContext(), "App is in foreground", Toast.LENGTH_SHORT).show();
}
}
public void applicationdidenterbackground() {
if (!isWindowFocused) {
isAppWentToBg = true;
// Toast.makeText(getApplicationContext(), "App is Going to Background", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed() {
isBackPressed = true;
Log.d(TAG, "onBackPressed " + isBackPressed + "" + this.getLocalClassName());
super.onBackPressed();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
isWindowFocused = hasFocus;
if (isBackPressed && !hasFocus) {
isBackPressed = false;
isWindowFocused = true;
}
super.onWindowFocusChanged(hasFocus);
}
#Override
protected void onStart() {
Log.d(TAG, "onStart isAppWentToBg " + isAppWentToBg);
applicationWillEnterForeground();
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop ");
applicationdidenterbackground();
}
What I would suggest is create a new boolean variable which say if that is created for the first time in resume and work on it.
Boolean isForeGround = true;
#Override
public void onPause() {
super.onPause();
isForeGround = false;
}
#Override
public void onResume() {
super.onPause();
if(!isForeGround){
isForeGround = true;
// write your code here
}
}

Eventbus onMessageEvent not getting called

I have implemented EventBus in my project but I am not getting all of my events
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EventBus.getDefault().post(new MessageEvent());
EventBus.getDefault().post(new MessageEvent2());
}
});
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event)
{
Toast.makeText(this, "MainActivity called", Toast.LENGTH_SHORT).show();
};
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}
Here i created 2 event inside onClick();
And this is my AnotherActivity where i have another #Subscribe
public class AnotherActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_another);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent2 event2)
{
Toast.makeText(this, "AnotherActivity called", Toast.LENGTH_SHORT).show();//Not getting called
};
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}
I dont know why my second toast is not getting called, i have done every thing correctly.
What i suspect is the AnotherActivity is not created yet so my event is not called is that is so what is use of EventBus then?
What i suspect is the AnotherActivity is not created yet so my event
is not called is that is so
Yes, if the event happened in past and the component(activity) is not active/created then the event will not be received.
what is use of EventBus then?
You can use Sticky Event to listen to past events in newly created activity
so use postSticky
EventBus.getDefault().postSticky(new MessageEvent2());
and add sticky = true in subscribe annotation
#Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent2 event2){
Toast.makeText(this, "AnotherActivity called", Toast.LENGTH_SHORT).show();//Not getting called
};
or you can receive them manually
MessageEvent2 msg2 = EventBus.getDefault().getStickyEvent(MessageEvent2.class);
// you can also remove it using
// EventBus.getDefault().removeStickyEvent(msg2);
or remove it from history as well
MessageEvent2 msg2 = EventBus.getDefault().removeStickyEvent(MessageEvent2.class);
if(msg2!=null){//do something}

UI is not updated when OnEvent is being called in Android Event Bus

Here I used #Subscribe annotation but my calender_text is not updated.But calender_text.setText("Test") properly working in side the oncreate method.What can be the issue?
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Date event) {
// your implementation
date = event.getSelected_date();
calender_text.setText("Test");
Toast.makeText(getActivity(), event.getSelected_date(), Toast.LENGTH_SHORT).show();
}
You need to register EventBus in onStart() method
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
You need to unregister EventBus in onStop() method
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}

Android. Otto Bus doesn't fire event from onActivityResult() method of Fragment to Activity

I have BaseActivity with register() and unregister() methods:
public class BaseActivity extends AppCompatActivity{
...
#Override
protected void onResume() {
super.onResume();
// Register ourselves so that we can provide the initial value.
BusProvider.getInstance().register(this);
}
#Override
protected void onPause() {
super.onPause();
// Always unregister when an object no longer should be on the bus.
BusProvider.getInstance().unregister(this);
}
protected void setFragment(Fragment fragment){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(ROOT_CONTAINER_ID, fragment);
if(!isFinishing()) {
transaction.commitAllowingStateLoss();
}
}
}
I have ChildActivity which fire DoneEvent to FrDetails fragment and it works fine.
public class ChildActivity extends BaseActivity implements View.OnClickListener{
private ImageView btnDone;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
btnDone = (ImageView) toolbarView.findViewById(R.id.btnDone);
btnDone.setOnClickListener(this);
setFragment(FrDetails.newInstance());
}
#Override
public void onClick(View v) {
int viewId = v.getId();
switch (viewId){
case R.id.btnDone:
BusProvider.getInstance().post(new DoneEvent());
break;
default:
break;
}
}
#Subscribe
public void onDataFilled(DataFilledEvent event) {
Log.e("Data filled", "Yessss");
}
}
But DataFilledEvent doesn't fire to ChildActivity from onActivityResult method of FrDetails fragment. I've called register() and unregister() methods in FrBase fragment. FrDetails fragment is child for FrBase fragment.
public abstract class FrBase extends Fragment {
...
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
}
This is my FrDetails class:
import com.squareup.otto.Subscribe;
public class FrDetails extends FrBase implements View.OnClickListener{
...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View baseView = inflater.inflate(R.layout.one_fragment, null);
button = (Button) baseView.findViewById(R.id.btn1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//WORK FINE HERE!
BusProvider.getInstance().post(new DataFilledEvent());
}
});
button2 = (Button) baseView.findViewById(R.id.btn2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getBaseActivity(), ThirdActivity.class);
startActivityForResult(intent, SELECT_YEAR);
}
});
}
#Subscribe
public void onDone(DoneEvent event) {
//WORKS FINE HERE!
Toast.makeText(getActivity(), "Done", Toast.LENGTH_SHORT).show();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Log is called correctly
Log.e("OK", "log");
//DOENS'T WORK HERE!
BusProvider.getInstance().post(new DataFilledEvent());
}
}
Why BusProvider.getInstance().post(new DataFilledEvent()); doesn't fire event from onActivityResult() to ChildActivity? But it works if we fire event by click on button in FrDetails fragment.
Thanks in advance.
Based on the documentation on onActivityResult() (relevant snippet only):
You will receive this call immediately before onResume() when your activity is re-starting.
In other words, the event is fired before your activity has registered itself with the bus, because registration happens in onResume().
If you want to be able to fire and receive events at an earlier stage in the activity's life cycle, you should change registration (and unregistration) accordingly.
Alternatively, you may be able to get away with simply registering in onActivityResult() also. I haven't looked at Otto's code for a while, but I imagine that registering an already registered event handler will not result in the handler receiving events more than once. Do note that in this case you'll have to take into account the fact that your activity may not be in a state you expect it to be. That is, it will be somewhere inbetween onActivityResult() and onResume().
What you probably want to do is post the event as a runnable. By the time its executed, onStart|onResume where you register your eventbus should be executed.
new Handler().post(new Runnable() {
#Override
public void run() {
BusProvider.getInstance().post(new DataFilledEvent());
}
});

Categories

Resources