Otto does not call to #Subscribe - android

I am working in a Hello Otto basic project in order to learn a bit how it works. This is my BusProvider over Otto 7.0.1. In MainActivity I have two buttons, after tap on the first one I post a string in the bus object. This is my BusProvider
public class BusProvider {
private BusProvider() {}
private static Bus bus;
public static Bus getInstance() {
if (bus == null){
bus = new Bus();
}
return bus;
}
}
MainActivity who will sent a String to Main2Activity using the bus class
public class MainActivity extends AppCompatActivity {
private Bus bus;
#Bind(R.id.myButton)Button mButton;
#Bind(R.id.button2)Button mButton2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setLibreries();
this.bus = BusProvider.getInstance();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
public void setLibreries(){
ButterKnife.bind(this);
}
#OnClick(R.id.myButton)
protected void buttonPressed1( ){
Toast.makeText(this, "click on the 1 button",Toast.LENGTH_SHORT).show();
BusProvider.getInstance().post("HELLO OTTO");
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
#OnClick(R.id.button2)
protected void buttonPressed(){
Toast.makeText(this, "click on the 2 button",Toast.LENGTH_SHORT).show();
}
}
Main2Activity how receives the String
public class Main2Activity extends AppCompatActivity {
private Bus bus;
#Bind(R.id.this_is_a_text_view) TextView myTextButter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
bus = BusProvider.getInstance();
ButterKnife.bind(this);
myTextButter.setText("HELLO");
}
#Override
protected void onResume() {
BusProvider.getInstance().register(this);
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void gettingStringPosted(String message){
Log.d("OTTO", "OTTO subscribe has been called "+message);
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
}
The problem is that the Toast with the message I am sending in MainActivity to Main2Activity
HELLO OTTO
is never showed.
What I am doing wrong?

The problem is that your Main2Activity has not been registered yet to Otto when your BusProvider.getInstance().post("HELLO OTTO"); line comes.
Here is how your code does:
Bus.post()
Bus.register()
This is how it should go:
Bus.register()
Bus.post()
You can't solve this by moving the line BusProvider.getInstance().post("HELLO OTTO"); under the startActivity() call because Activity.onResume() might not get called straight away so your register call (in onResume) could still happen after post call. I hope this makes sense to you.

This is just example of otto, to make sense how it is. Let's assume you have a service, and in it getting locations and sending to activities.
public class TrackingService extends Service {
Bus bus;
LocationListener mListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
bus.post(new MyLocation(location));
}
};
// Other service related methods..
}
And activity
#Override
protected void onResume() {
BusProvider.getInstance().register(this);
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void locationChanged(MyLocation location){
Toast.makeText(this, "you got new location", Toast.LENGTH_SHORT).show();
}
Thats just it.
BTW, and this is the what i mentioned for you in my comment
In MainActivity
Intent intent = new Intent(getBaseContext(), Main2Activity.class);
intent.putExtra("MY_INFO", "INFO");
startActivity(intent)
In Main2Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Intent intent = getIntent();
String info = intent.getStringExtra("MY_INFO");
}

Related

How Sign out to loginActivity when user inactive using common method for all activities in Android

In my application i want to sign out to loginActivity after 3 min when user inactive
i am currently use this code to do that but in my application there is more than 20 activities
so without pasting this bunch of code every activity i want common method to do that,
please help me
Here is the my code
public class HomeActivity extends AppCompatActivity {
private Handler handler;
private Runnable r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
handler = new Handler();
r = new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
finish();
Toast.makeText(HomeActivity.this, "Logged out after 3 minutes on inactivity.", Toast.LENGTH_SHORT).show();
}
};
startHandler();
}
public void stopHandler() {
handler.removeCallbacks(r);
}
public void startHandler() {
handler.postDelayed(r, 3 * 60 * 1000);
}
#Override
public void onUserInteraction() {
super.onUserInteraction();
stopHandler();
startHandler();
}
#Override
protected void onPause() {
stopHandler();
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
startHandler();
Log.d("onResume", "onResume_restartActivity");
}
#Override
protected void onDestroy() {
super.onDestroy();
stopHandler();
}
}
Define a class like
public class BaseActivity extends AppCompatActivity {
// Write logic of logout same as what you wrote in HomeActivity
}
Now extend this BaseActivity to each activities which meant to show after login. like
public class HomeActivity extends BaseActivity {
// Remove code related to logout from this class.
}
You can make a BaseActivity Class here you can implement your functionality.
And then extend this activity with all your Activities.
Also you can use Application Class to control over the app

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}

How to play music only in foreground

I have trouble to play music across all activity, I had implement service and handle onPause to stop the music when going to background (not visible to user).
The problem is when i navigate to another activity, the onPause method is called that make my music stop. How to fix this issue? I need to play my music across all my activity in foreground only and dont wan to play it when the application in the background. Appeciate anyone know how to solve this.
This is my base activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startIntent = new Intent(getApplicationContext(), MusicService.class);
if(binder==null){
bindService(startIntent,this, Context.BIND_AUTO_CREATE);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(binder.getMyService()!=null){
stopService(startIntent);
unbindService(this);
}
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onPause() {
super.onPause();
if(binder!=null) {
binder.getMyService().pauseMusic();
}
}
#Override
protected void onResume() {
super.onResume();
if(binder!=null){
binder.getMyService().resumeMusic();
}
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MusicService.Binder) service;
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
this is my mainactivity extends base activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startIntent = new Intent(MainActivity.this, MusicService.class);
startService(startIntent);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
public void how(View view) {
Intent intent = new Intent(this, AboutActivity.class);
this.startActivity(intent);
}
You could implement code that will track current activity in your app. (Good example: How to get current activity)
And stop music only when "current activity" is null.
PS: depending on your implementation of tracking current activity you might want to check current activity not onPause() right away but with some delay .
Don't stop the audio play in onPause() as Harin Kaklotar suggested. You can use his method of onDestroy() or you can have it in an asynchronous task and turn off the sound by using surfaceDestroyed(). You can refer the android documentation of AudioManager if you need anything else of the sort.
https://developer.android.com/reference/android/media/AudioManager.html
Hope I Helped :D
UPDATE
You can create a system to check if your app is in the foreground or background. This involves counting how many activities are paused. Add this to all your activities:
#Override
protected void onPause() {
super.onPause();
MainActivity.Pause++;
}
#Override
protected void onResume() {
super.onResume();
MainActivity.Pause--;
}
And in your MainActivty,
if (Pause == NUMBER_OF_ACTIVITIES) {
//PAUSE MUSIC HERE
}
You have to use ActivityLifecycleCallbacks to tell if you app is in the foreground or background.
For example:
public class DummyActivityLifecycleCallbacks implements ActivityLifecycleCallbacks {
#Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
#Override public void onActivityStarted(Activity activity) { }
#Override public void onActivityResumed(Activity activity) { }
#Override public void onActivityPaused(Activity activity) { }
#Override public void onActivityStopped(Activity activity) { }
#Override public void onActivityDestroyed(Activity activity) { }
#Override public void onActivitySaveInstanceState(Activity activity, Bundle savedInstanceState) { }
}
public class OnApplicationForegroundBackgroundEnterCallbacks extends DummyActivityLifecycleCallbacks {
private Listener listener;
private int activityStartStopCounter = 0;
public interface Listener {
public void onEnterForeground();
public void onEnterBackground();
}
public OnApplicationForegroundBackgroundEnterCallbacks(Listener listener) {
this.listener = listener;
}
#Override public void onActivityStarted(Activity activity) {
if(++activityStartStopCounter == 1) listener.onEnterForeground();
}
#Override public void onActivityStopped(Activity activity) {
if(--activityStartStopCounter == 0) listener.onEnterBackground();
}
}
Then in Application.onCreate call:
registerActivityLifecycleCallbacks(new OnApplicationForegroundBackgroundEnterCallbacks(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());
}
});

Handler Callbacks not removed in onPause of Activity

I have two activities(MainActivity,Sample) which extend to a custom activity(BaseActivity) i have created. I have created a handler which runs a runnable every 5 seconds in BaseActivity. In BaseActivity i have overridden onpause and onresume methods to start and stop handler whenever needed. When i remove the callbacks of handler in onPause of BaseActivity, the handler stops but won't stop in onpause of MainActivity. Below is the code.
public class BaseActivity extends Activity{
public int mInterval = 5000;
public Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("Oncreate baseactivity");
mHandler = new Handler();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
Log.d("MyApp", "every 5 secs");
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
#Override
protected void onPause() {
super.onPause();
System.out.println("OnPause baseactivity");
//stopRepeatingTask();
}
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
#Override
protected void onResume() {
super.onResume();
System.out.println("Onresume baseactivity");
startRepeatingTask();
}
}
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void newpage(View v){
startActivity(new Intent(this,Sample.class));
}
#Override
protected void onPause() {
super.onPause();
System.out.println("onpause mainactivity");
stopRepeatingTask();
}
}
public class Sample extends BaseActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.txt);
tv.setText("sample activity");
}
}
The Onpause of both BaseActivity and mainActivity are called but the handler still runs if the app is closed. I hope am clear.
I think to start thread we should use start() method,
and write onPause method of MainActivity in BaseActivity Itself and remove in MainActivity(i mean stopRepeating Task).
I hope it works.

Categories

Resources