简体   繁体   中英

Access an application broadcast receiver from within an activity?

I have a broadcast set up as such in my manifest to monitor connection activity:

<application
    ... 
    <receiver
        android:name="com.blah.appname.NetworkChangeReceiver"
        android:label="NetworkChangeReceiver" >
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
        </intent-filter>
    </receiver>
    ...
</application>

Inside NetworkChangeReceiver is the onHandle() method. This is mainly just to show a Toast message, and do some logging, and works across the entire app.

public class NetworkChangeReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {
        // do stuff
    }

}

However, I also need to do special things in an individual activity based on the the loss of a connection.

How can I access the onReceive() method of the existing broadcast receiver from within an activity? I don't totally understand the internals of how the receiver is tied into the application from the manifest.

You create a broadcast receiver in your app to access it in your app. The broadcast receiver in your manifest must return within 10 seconds so generally the manifest version of the broadcast receiver will just start something with an intent and then return.

Here's a code example of adding a broadcast receiver to your app.

 BroadcastReciver yourReceiver;


 public void onStart() {
    super.onStart();
    setupGPS();
 }


private void setupGPS() {
    if (yourReceiver == null) {
        // INTENT FILTER FOR GPS MONITORING
        final IntentFilter theFilter = new IntentFilter();
        theFilter.addAction(ACTION_GPS);
        yourReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null) {
                    String s = intent.getAction();
                    if (s != null) {
                        if (s.equals(ACTION_GPS)) {
                            gpsCheck();
                        }
                    }
                }
            }
        };
        getActivity().registerReceiver(yourReceiver, theFilter);
    }
    gpsCheck();
}


private void gpsCheck() {
    if (view != null) {
        LinearLayout llTrackerEnableGPS = (LinearLayout) view
                .findViewById(R.id.llTrackerEnableGPS);
        if (llTrackerEnableGPS != null) {
            LocationManager locationManager = (LocationManager) fragmentActivity
                    .getSystemService(Context.LOCATION_SERVICE);
            boolean isGPSAvailable = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);
            llTrackerEnableGPS.setVisibility(isGPSAvailable ? View.GONE
                    : View.VISIBLE);
        }
    }
}



@Override
public void onPause() {
    super.onPause();
    if (yourReceiver != null) {
        final FragmentActivity a = getActivity();
        if (a != null) {
            a.unregisterReceiver(yourReceiver);
        }
    }
    yourReceiver = null;
}

So you want to do something in your activity based on what you receive in the onReceive of the BroadcastReceiver? Here is something that I did before:

You can use LocalBroadcast . See LocalBroadcast Manager . For how to implement is, there is a great example on how to use LocalBroadcastManager? .

LocalBroadcast Manager is a helper to register for and send broadcasts of Intents to local objects within your process. The data you are broadcasting won't leave your app, so don't need to worry about leaking private data.`

Your activity registers for this local broadcast. From the NetworkChangeReceiver you send a LocalBroadcast from within the onReceive (saying that hey, I received a message. Show it activity). Then inside your Activity you can listen to the broadcast. This way if the activity is in the forefront/is active, it will receive the broadcast otherwise it won't. So, whenever you receive that local broadcast, you may do the desired action if activity is open.

If you want to do for the whole app, then you can make all your activities extend an abstract activity. And inside this abstract activity class you can register it for this 'LocalBroadcast'. Other way is to register for LocalBroadcast inside all your activities (but then you'll have to manage how you'll show the message only once). This Broadcast is private to your app. So its secure as well.

Hope it helps. Same thing can be done from within the Service as well. This is just one of the ways to do it.

You need so called dynamic broadcast receiver.You don't need to register it in the manifest file, but right inside your activity.

NetworkChangeReceiver mReceiver = new NetworkChangeReceiver();

@Override
protected void onStart() {
    super.onStart();
    registerReceiver(mReceiver, new IntentFilter(android.net.conn.CONNECTIVITY_CHANGE));
}

@Override
protected void onStop() {
    unregisterReceiver(mReceiver);
    super.onStop();
}

Now you can add logic into onReceive() analysing connection state and adjusting the logic.

Alternatively, if you want to use some libraries, then you might want to look at open source TinyBus . It makes all this much simpler. In your activity you need to add just this.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    // wire connectivity events
    TinyBus.from(this).wire(new ConnectivityEvents());

}

@Subscribe
public void onConnectivityEvent(ConnectionChangedEvent event) {
    if (event.isConnected()) {
        // connected
    } else {
        // disconnected
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM