Fragment's BroadcastReceiver onCreate method does not get called - android

I have a simple Fragment within my Activity in which I enable and disable Bluetooth adapter and I want to listen to Bluetooth Adapter state changes with a BroadcastReceiver from within the Fragment. The reason is that I want to directly change the Fragment's UI elements upon Bluetooth state change. This is my code:
public class FragmentBT extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
IntentFilter iFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(BtStateChangedReceiver, iFilter);
}
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(BtStateChangedReceiver);
}
public BroadcastReceiver BtStateChangedReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
... change UI based on the extra data from intent ...
}
}
}
When I enable or disable BT in my device using Action Buttons in my Fragment's ActionBar, the BT goes on and off, but my receiver never gets called. I never get into the receiver's onReceive method. I realize this is a pretty common question here, but I tried the sollutions from several but neither worked (and all are incorporated into my current code).
Thank you for any advice!

Try this:
getActivity().registerReceiver(BtStateChangedReceiver, iFilter);
getActivity().unregisterReceiver(BtStateChangedReceiver);
The docs say that 'LocalBroadcastManager' is used to 'register for and send broadcasts of Intents to local objects within your process'.

Related

How to send message from BroadcastReceiver to activity or fragment

I have a receiver, it does call details saving task like storing incoming call, outgoing call etc.. all these details goes to sqlite DB. If my activity is not running, then its fine.
Sometime, when my activity is running, i get some incoming call. the receiver runs & stores data to DB. UI wont get refreshed because it never knows about change in DB.
Here i need to manually tell from receiver that, if activity is running refresh screen. How to implement this process in android.
I'm slightly confused in this part
You can use a LocalBroadcastManager to send a local broadcast to your Activity (more efficient and more secure than using a global broadcast):
Intent intent = new Intent(action);
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(context);
mgr.sendBroadcast(intent);
http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
Your Activity would have to register a BroadcastReceiver in onStart and unregister it in onStop:
private BroadcastReceiver mBroadcastReceiver;
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do your thing
}
};
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this);
mgr.registerReceiver(mBroadcastReceiver, new IntentFilter(action));
in onStop:
mgr.unregisterReceiver(mBroadcastReceiver)
Now that's the official Android way to do it. I most certainly prefer to use an event/message bus like Otto or EventBus (https://github.com/greenrobot/EventBus). You can use those to broadcast messages/events across different components in your app. The advantage is you don't need access to a Context (like you do when using Broadcasts), it's faster and it forces the developer to object oriented programming (since the events are always objects). Once you start using an event bus you'll never look back to local broadcasts and you'll replace many of the sometimes messy observer / listener patterns used across your app.
You can create a BroadcastReceiver inside an activity. Register it in onResume() and unregister it in onPause(). Whenever your other receiver receives a broadcast, send a broadcast to this receiver too. If the activity is running(i.e. on front), the broadcast will be received. Do whatever you want in its onReceive().
Example:
BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Do stuff
}
};
Also override methods:
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(br);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter("intent_filter"));//Use any string for IntentFilter you like
}
You can update fragments from activiy by creating methods inside fragment and access them from Fragment object inside activity.

send action from receiver to activity?

I am using broadcast receiver in my app to detect incomming call and it works fine. But problem is I can not send action to activity. I mean.. I want do something in activity not in receiver. I read many tutorial but they all are performing action in receiver. Any idea ?
You can declare a BroadcastReceiver as inner class of the Activity. In this case you can directly call activity's methods:
public class MyActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activityMethod();
}
};
private final IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
#Override
protected void onStart() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onPause();
unregisterReceiver(receiver);
}
private void activityMethod() {
}
}
You can start the Activity using an Intent and put a command code in the Intent extra fields. In your Activity you can then decide the behaviour based on the command code or resort to a default behaviour if none is present.
You can start an activity from your receiver via the normal means:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, YourActivity.class);
startActivity(i);
}
Note though that the user is going to expect that the phone application starts up since they are receiving a phone call. It is very likely a bad idea to hijack the phone call by dumping your own activity on top of the stock dialer app.

Destroying Activity or application itself from another application

I have two applications. One is a receiver and its starting my application. It works fine. Now i want destroy my application from the receiver itself. Is that possible ? Please note that these are my own application
It is possible but the activity has to finish itself using the finish()-method.
You can register an activity to a receiver using registerReceiver(..) and handle your logic in your activity. Don't forget to unregisterReceiver(...) inside the OnDestroy.
Example:
BroadcastReceiver mReceiver;
#Overrride
public void onCreate(Bundle savedInstanceState){
IntentFilter filter = new IntentFilter();
filter.addAction(...);
mReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// implement logic
finish();
}
}
registerReceiver(mReceiver, filter);
}
you cant directly control the lifecycle of one activity from another actvity
alternates to this could be :
you can set a timer in the new activity, if you want to end it after a certain amount of time, and call finish()' inrun()`
you can finish() the new activity on some events with EventListeners

Android Best Practice on Updating the UI from BroadcastReceiver to a certain activity

When i have a broadcastReceiver say android.intent.action.MEDIA_BUTTON and i want to update the current activity's UI without creating a new activity, is there any good practice on this one?
What i know (might not be correct)
1) I can put the BroadcastReceiver in the same class as the activity and call the updateUI function after certain activity
2) Create a ContentObserver?
3) Communicate to a service created by the activity, use aidl. (I dont know how to get the current service if its registered from an activity)
4) Create a custom filter on the broadcastReceiver located on the same class as the activity, and use context.sendBroadcast(msg of custom filter) and in the custom filter call updateUI (same as one but more generic?)
The final flow is it would come from a BroadcastReceiver and ends up updating the UI without renewing the activity (unless the activity is dead?)
Kindly provide links/source code on your how you tackle this kind of problem. Thanks a lot in advance :)
The easiest way to provide this functionality is to put the broadcast receiver in you Activity and bind / unbind it using registerReceiver and unregisterreceiver:
public class MyActivity extends Activity {
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
MyActivity.this.receivedBroadcast(intent);
}
};
#Override
public void onResume() {
super.onResume();
IntentFilter iff = new IntentFilter();
iff.addAction("android.intent.action.MEDIA_BUTTON");
// Put whatever message you want to receive as the action
this.registerReceiver(this.mBroadcastReceiver,iff);
}
#Override
public void onPause() {
super.onPause();
this.unregisterReceiver(this.mBroadcastReceiver);
}
private void receivedBroadcast(Intent i) {
// Put your receive handling code here
}
}
Depending on the intent you wish to receive, you may need to add the appropriate permissions to your AndroidManifest.xml file.
What I recently had to do to change a Button's text after receiving data from a LocalBroadcastManager is to store the value in a private field and then do the UI stuff in my onResume() method.
public class myClass extends Activity {
private String myString;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// register to receive data
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, new IntentFilter("myAction"));
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// get the extra data included in the intent
myString = intent.getStringExtra("myString");
}
};
#Override
public void onResume() {
super.onResume();
System.out.println("onResume");
// do something to the UI
myButton.setText(myString != null ? myString : "Default");
}
}

App will not launch from drawer after phone is removed from car dock

I am creating a replacement Car Home app for Android 2.0+ devices. The app needs to launch when the phone is inserted into the car dock, as well as terminate when it is removed from the dock. It also needs to be able to be launched from the app drawer.
I'm having a problem right now where once the phone is inserted and removed from the dock, I can no longer launch the app from the app drawer because every time I launch the app my BroadcastReceiver picks up a DOCK_EVENT action for some reason. I created a test project that only registers my BroadcastReceiver, and the same thing happens.
Here's the code for the BroadcastReceiver:
public class CarDockBroadcastReceiver extends BroadcastReceiver {
/**
* #see android.content.BroadcastReceiver#onReceive(Context,Intent)
*/
#Override
public void onReceive(Context context, Intent intent) {
// TODO Put your code here
if(intent.getExtras().containsKey("android.intent.extra.DOCK_STATE")){
int state = intent.getExtras().getInt("android.intent.extra.DOCK_STATE",1);
if(state == 0){
Log.i("Dock", "Removed from dock!");
((Activity)context).finish();
}
}
}
}
My main Activity is as follows:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
CarDockBroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
IntentFilter filter = new IntentFilter("android.intent.action.DOCK_EVENT");
receiver = new CarDockBroadcastReceiver();
registerReceiver(receiver, filter);
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(receiver);
super.onDestroy();
}
}
The main Activity has an intent filter for action.MAIN, category.LAUNCHER, category.DEFAULT, and category.CAR_DOCK. Any ideas on why this is happening?
Intent.ACTION_DOCK_EVENT is a sticky broadcast. This means that when you register a receiver for it, you will immediately get the last-broadcast Intent for that action, then all subsequent broadcasts until it is unregistered. There is nothing much you can do about it, other than finding a way of dealing with the situation.
BTW, I recommend using Intent.ACTION_DOCK_EVENT rather than "android.intent.action.DOCK_EVENT" in your IntentFilter. This way, if for some goofy reason they change the actual string, your code does not need to change.

Categories

Resources