Error calling getSupportFragmentManager() from a Broadcast receiver - java

I try to call a method that calls getSupportFragmentManager() however i get:
IllegalStateException: FragmentManager has not been attached to a host.
The broadcast receiver fires and the method which is in the activity which is currently in the UI fires as below but i get the error:
BottomSheet bottomSheet = new BottomSheet();
bottomSheet.show(getSupportFragmentManager(), "bottomButtons");
All i am attempting to do is call the bottomSheet from a service which i have to do via a broadcast receiver as i cant call getSupportFragmentManager from the service! How can i get the sheet to appear, triggered by an event in my service?

Fragments are part of the UI. BroadcastReceiver and Service are background components and do not have anything to do with UI. You cannot even call the method getSupportFragmentManager() from a BroadcastReceiver. This shouldn't even compile!
Only Activity components can do stuff with the UI.

To Call the method which displays my BottomSheet which is situated in the Activity that is currently displayed in the UI from a background service. I used MutableLiveData.
I initialised a global Boolean finished, in my service;
public static MutableLiveData<Boolean> finished = new MutableLiveData<Boolean>();
When the required event triggers in my Service i set the value of the live data variable to true. with
finished.setValue(true);
In the activity i need to display the BottomSheet i am observing this variable via:
finished.observe(this, new Observer<Boolean>(){
#Override
public void onChanged(Boolean aBoolean){
if(aBoolean){
//I call my Method here which displays my Bottom Sheet, this is the method that contains the getSupportFragmentManager().
}
}
});
I hope this can help anyone in my situation.

Related

how to put FirebaseAuth.AuthStateListener on continous listening mode so that when the state changes, i get a notification

We have put the Firebase auth listener in a specific activity in the Android app. It only works when that activity occurs.
auth.addAuthStateListener(new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
Log.i("firebase", "AuthState changed to null");
}
else {
Log.i("firebase", "AuthState changed to "+firebaseAuth.getCurrentUser().getUid());
}
}
});
From what I understood, the firebase auth listener listens all the time and is triggered as soon as the firebase auth state changes. However, this does not seem to be the case in our case. Do we have to put this code in every activity or is there any way to put this in a single place and it lets us know as soon as the firebase authentication status changes?
You can get that code out of the activity and put it into a separate (repository) class. You can save the auth state into a LiveData object that can be observed in all your activities. According to the result, you can take some actions in your activity.
If you understand Kotlin, I have created an app for learning purposes where I have implemented this mechanism:
https://github.com/alexmamo/FireApp
Another solution would be to have a single activity with several fragments. In this case, you need to attach the listener only once in the activity.

Android firebase onStart and onStop explanation

I've just started with firebase in android and i can't understand some things in onStart and in onStop.
Why is it necessary to have this code on stop method? Why do we need to remove listener ?
#Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop: ");
if(mAuthStateListener != null)
mAuth.removeAuthStateListener(mAuthStateListener);
}
And one more question what is the advantage of setting up mAuth listener in onStart method instead of onCreate ?
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
mAuth.addAuthStateListener(mAuthStateListener);
}
This is how they shoved in Firebase -> Authentication demo.
There is the need to remove listeners because the mAuth will keep of keeping track of all the listeners you added, in order to notify you when something happens.
When the activity stops you remove the listener from the list because well, the activity has stopped anyway, there is no need to listen for auth events when the activity is stopped, is there?
Why add the listener at onStart then?
Because according to the activity life cycle:
onStart and onStop correspond to each other, while onCreate and onDestroy correspond to each other.
If you add the listener in onCreate and remove at onStop, the listener will not be added back when the activity restarts, since onCreate is not called on restart. onStart is.

Kill app whenever it goes to background

I am creating an app. From MainActivity -> Fragment -> See Details Activity.
It is working fine.
But when I am going to background on See Details Activity, it is still running.
Why this activity or app is not getting destroyed. I want to kill the app whenever I will go to background.
Add this:
#Override public void onPause() { super.onPause(); // Always call the superclass method first
Finish();
}
Invoke finish() method before start Fragment

Android: How to enable button when service complete its task?

I have two buttons StartButton and StopButton on MainActivity.java . When I press StartButton a Service is created and StartButton get disable. On pressing StopButton Service get destroyed and StartButton get enable.
What I wanted to do is to enable my Start Button as Service completed its task; it returns any notification or trigger type event or message value on my MainActivity.java so my Start Button get enable.
Please give me any idea, concept or code to make it easy for me to understand.
To understand the communication between service and application take a look at the examples in the android developer docs.
You can enable and disable your buttons in the onServiceDisconnected() and onServiceConnected() methods.
Keep in mind that the service runs in the same thread as your app by default.
Have you tried,
MyButton.setClickable(false);
It will make the button disabled.
and
MyButton.setClickable(true);
It will enable the button.
However, if you want to hide or show the button, you can use,
MyButton.setVisibiity(VIEW.VISIBLE); and MyButton.setVisibiity(VIEW.INVISIBLE);
Edit- As you want to enable the button, once its task is completed, you could open the mainActivity with a flag value true, something like this,
Intent i= new Intent(getBaseContext(), myActivity.class);
i.putExtra("flag", true);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(i);
and in the mainActivity, check the value of flag,
Boolean flag;
flag = this.getIntent().getBooleanExtra("flag", false);
if(flag == true) {
MyButton.setClickable(true);
}
But for it, you should keep the value of flag initially to false.
and once you click the button, you could then set it as not clickable.
There can be many ways to achieve this. Let me tell you one with Broadcast Receiver. I hope you are aware of BroadcastReceiver Concepts.
Changes requires in your activity
1) Create a Broadcast receiver as inner class in your activity.
2) Register it with some action, suppose "MY_ACTION".(remember to unregister this receiver on onPause/onDestroy methods)
3) Suppose service completed its task, and you are into onReceive method of Broadcast receiver, now write your code to enable/disable button(i hope you know how to do it)
Changes requires in your Service
1) find out code where you think its task has completed.
2) Create an intent with same action ("MY_ACTION").
3) Broadcast message with sendBroadcast , intent as param. and you are done. :)
let me know if in any point you feel you are stuck ,

Close acivity 'used as dialog' on Android

I have an activity, which I used as a custom loading dialog (the dialog is pretty complex and has custom UI, which fits the customer colors schemes, etc.).
The loading dialog is created and shown from class, which is not derived from Activity class (this I am mentioning becuase the startActivityForResult() cannot be called):
private void showLoadingDialog()
{
Intent intent = new Intent( this, ActivityDialogLoading.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
isLoadingDialogShown = true;
}
The dialog is shown when long running asynchronous tasks are performed by the application on background.
Now when the background tasks if finished I want to close the loading dialog (The loading dialog has also the Cancel button, so client can interrupt the task, but this is other story).
I did not found a way to get the reference to the instance of the running ActivityDialogLoading class to call the finish() method...
The way I am using is a bit complicated - I override BroadcastReceiver so it takes the reference to the ActivityDialogLoading in its constructor. In OnResume() method of the ActivityDialogLoading I register as a receiver for broadcasted intent.
When I need to close the loading dialog i broadcast the intent... Is there a better way?
Saying the same with other words: What is the best way to close an activity when the close action is caused by some background event in application engine?

Categories