Dynamic Broadcast Receiver in Fragment - android

Is it possible to dynamically register a broadcast receiver in a fragment to listen for connectivity state changes? If so how? If not, what are some workarounds for fragments?
EDIT: To register a BroadcastReceiver you need a Context. Since fragments live within activities, probably the best way to get a Context is to just use getActivity(). However, as gnorsilva explains below, there are certain special cases to look out for.

user853583 suggestion is a good one, but if you need access to a context inside a fragment you should use getActivity().getApplicationContext()
You should avoid passing an activity as a context whenever possible as this can introduce memory leaks - some object will hold on to that activity after its onDestroy() has been called and it won't be garbage collected.
Having said that, there are cases when you do need to pass an activity as a context - eg: for list adapters
Two more things though:
because a fragment is attached and detached from an activity, some times getActivity() returns null - you can call it safely inside certain lifecycle methods where you know an activity is alive eg: onResume()
if your fragment does not retain its instance i.e. is destroyed on orientation change, be sure to unregister your receiver in your fragment, for eg inside onPause() or onDestroy()

As far as I can see there is no way to register a BroadcastReceiver in a fragment. What do you need that broadcast receiver for? A nice solution is the one mentioned here

You can register a broadcast receiver like this :
getActivity().registerReceiver(...

Related

What is faster Communicating, sending broadcast VS calling activity method directly in Android?

In my app, I have to call an activity method from the fragment.
I know I can do this in two ways:
1. Via sending a broadcast to activity:
Intent intent = new Intent("FILTER");
intent.putExtra("EXTRA", 1);
sendBroadcast(intent);
2. Or Calling the activity method directly:
((MyActivity) getActivity()).method();
I would like to know which way is faster and safe to communicate. Any help would be appreciated.
Thank you.
Loosely Coupled Fragment?
I am not sure about the speed. But on the design perspective You should use an interface to communicate with an Activity rather calling Activity method directly from your Fragment. ie ((MyActivity) getActivity()).method();
Because using an interface makes your Fragment independent from your
Activity. Let's say in future you want to use your fragment in Some
other Activity then you will not have to change anything in your
Fragment.
Interface
public interface Somelistener {
public void someMethod();
}
Your Loosely coupled Fragment
YourFragment extends Fragment {
Somelistener listener;
public void onActivityCreated(Context context){
listener = (SomeLisner)context;
}
public void buttonClick()
{
listener.someMethod();
}
}
So if you are using in your MainActivity. No problem
MainActivity implements SomeListener{
#Override
public void someMethod()
{
// Activity method
}
}
In future you want to use Fragment in SomeOtherActivity. No problem
SomeOtherActivity implements SomeListener{
#Override
public void someMethod()
{
// somethother method
}
}
BroadcastReceiver Approach?
TBH I have seen this approach for Service-Activity Communication. Not for Activity - Fragment communication.
For communicating between Fragments and the Activity that contains it, there's actually a much better 3rd option.
The better option is to use an Interface as a callback method. This is described very well in this documentation: https://developer.android.com/training/basics/fragments/communicating
Using an interface is much more preferred over your two methods because it's both safer and more efficient.
For your first method of using Broadcast Receivers, this is actually a very inefficient solution due to Broadcast Receivers not being meant for a task like what you're after.
Let me quote you something from the Android documentation:
Warning: Limit how many broadcast receivers you set in your app. Having too many broadcast receivers can affect your app's performance and the battery life of users' devices. For more information about APIs you can use instead of the BroadcastReceiver class for scheduling background work, see Background Optimizations.
https://developer.android.com/guide/topics/manifest/receiver-element
So yes, Broadcast Receivers will have a bigger effect on your app's performance and the device's battery life over the other method you suggested and the method I suggested.
Additionally, don't forget that a Broadcast Receiver is meant to listen to broadcasts. The type of Broadcast Receiver you're using in your example is actually a Global Broadcast where you didn't explicitly limit it's "range", so any Broadcast Receiver could potentially "listen" in to your broadcast. In terms of security, using a Global Broadcast like this isn't safe either.
You also don't want other apps to potentially fire off a Broadcast that coincidentally coincides with your app's Broadcast Receiver, causing it to receive data not meant for it and crashing due to this accidental and coincidental naming.
Honestly, there's more potential issues of using a Broadcast Receiver in a way it's not meant for.
As for your second method of directly calling the Activity's method... this is actually very inefficient for managing code. You're basically tying the Fragment tightly together with that specific Activity.
However, Fragments, by design, makes it common to be swapped into other Activities or Fragments... you'll basically have to do multiple if statements and casts each time you want to run code from it's parent.
Also, keep in mind that if you later change code in MyActivity, it can cause problems for this fragment due to you forgetting how tightly bound it is to the Activity.
But if you use the more preferred Callback Interface approach, it's simply a middleman meant to deliver a "Hey, DO something for me" message. Quick and direct. It's also plays friendly with any Activity or Fragment you want to attach this Fragment to later since those Activities or Fragments simply have to implement the Interface and the callback bridge between both parent and child is formed.
It is better to use interface to communicate from fragment to activity rather than a Local broadcast.
Activity will implement the interface and fragment will call the methods.

Get activity instance from called activity

I have an activity containing some fragments. One of those fragments calls another activity. In this new activity I need to have an instance of the first activity. GetParent() returns null so I don't know how I can acomplish this...
MainActivity --contains--> Fragment1 --startActivity()--> SecondaryActivity
Is there some way to get the calling activity on the SecondaryActivity?
I don't think there is a good way of doing so.
It's really a bad practise to handle activity references like that, since android wouldn't be able to gc them when needed (orientation changes, lack of memory).
The best way is to pass all the data you need with Intent extras (intent that you use to start activity), and, if you need SecondActivity to return something, use Fragment1.startActivityForResult() for starting activity, and when done, use SecondActivity.setResult() to return desired result, you will need to override onActivityResult() to get the result (there are plenty tutorials about this).
If you absolutely need to hold references to something, you can use your own instance of Application class (don't forget to declare it in the manifest) to hold data for you while application is running.

Bind service to activity or fragment?

I am working on a music player app. I have a main activity which has multiple fragments, each displaying songs on the device album wise, artist wise etc..
I have a music service which handles all the playback and other stuff.
What I'm confused about is the binding of this service with various fragments I have.
Right now I'm binding the main activity and each fragment individually with the service and its working pretty much fine. But I was wondering if this is really the best practice? Is there any way to just bind the main activity with the service and then some how use it in its child fragments?
I maybe missing some very basic concept of activity or fragments or services. So someone please guide me in this regard.
I guess it's more of a conceptual question so any code isn't needed. But still if it's required then please let me know.
EDIT :
My question is: What would be a better way to bind a service with an activity with multiple child fragments(each of which would be using the service)?
Bind the Service to your activity and not the Fragment. The description of your application, one activity with multiple Fragment that are swapped in and out, makes this the most (and really only) practical approach.
When you bind a Service to an Activity you are tying its lifecycle to that of the Activity. See Bound Services. Each time you add or remove a Fragment in your activity that Fragment is created and destroyed. You do not want to try to link a service to this process because then you would have to create and destroy the service each time a new fragment is created or destroyed.
Instead bind to the host Activity. You can then interact with your host activity from your fragments with an interface to access the bound service or by Intent.
I think the cleaner architecture is to bind directly from the fragment. Regarding the problem outlined in Rarw's answer, you can bind to the service from your activity and from your fragments too. This way you are sure that the service will be there until the activity is not destroyed.
I can see two main advantages in connecting from the fragment:
Service connection is async, so inside the fragment you are never really sure that the service you are getting from the activity is not null. This will lead you at least to some null pointer checks and to some mechanism to refresh the fragment both when it's created and when the service connects (so you are sure you will display the data no matter which of the two happens first).
You do not depend on the particular activity your fragments lives in. To get the service from the activity I think you are doing a cast to the activity specific class. You could create an interface like BoundActivity with a method like getBoundService to obtain the service from it, but I think it's an overhead considering the advantage of point 1. And what if you have multiple services.
UPDATE
Here is a very simple project showing this.
https://github.com/ena1106/FragmentBoundServiceExample
You can access your activity from a fragment by getActivity()
you can tray using the event bus pattern with this library , eventbus publish/subscribe pattern.https://github.com/greenrobot/EventBus check the project site for more information.
you can send events from/to service to active or fragments
IF you need to get some data from your service to your fragment at the beginning of the fragment lifecycle, the onServiceConnected on activity could not be called yet, mainly when you rotate your device, and you'll get a NPE.
I think is a good idea let fragment make his own connections since the service is started with startService() and not with bindService().
I bind service in My Host Activity,and pass Ibinder's object by Bundle which is setted in arguments.
and my code may like this:
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
//put service in bundle
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
The only method I have found to be reliable is to use a loader in Fragment:
create a Loader in the fragment
use the context of the Loader (set to activity in initLoader at when the Fragment's onCreate is called)
bind the service in onStartLoading, using a ServiceConnection which calls forceLoad() as soon as the service is bound
optionally register callbacks in onStartLoading/onStopLoading
unbind the service in onStopLoading

Where is FragmentActivity#onDetachFragment?

Every time I attach a fragment to my activity, I want to register it to receive events from the activity. This is easy, because I can override FragmentActivity#onAttachFragment(Fragment). When the fragment is removed from the activity, I want to unregister it from receiving events. I expected there to be a onDetachFragment event that I could use in a similar manner, but I'm not finding it.
Is there another way to accomplish what I'm trying to do? I'd like to keep the registering/unregistering in the activity, as opposed to moving it to a base fragment class (where I could just use onAttach/onDetach).
its better to use the onStart(), onStop() method from your fragment. Just cast getActivity() to your calling activity class.

Android IntentFilter for Every New Activity?

Is it possible to register a global broadcast receiver that gets notified every time a new activity is started (either by startActivity, startActivityForResult, etc)? What would the IntentFilter be?
EDIT: Just to clarify, I don't mean across apps I mean within my own app
You could potentially create your own partial subclass of Activity where it overrides onCreate(), onStart(), etc and manually calls a static/singleton instance of your global receiver as appropriate. After that, just derive your own activities' implementations from that subclass.
However, I'm assuming the reason you want to do this is that the "receiver" actually contains or otherwise represents some globally available state or resource - if you can find a way to implement your application without having any global state (and just passing it along as payload for an activity call, for instance), that would be best.
No, there is no way to do that.

Categories

Resources