I have a BroadcastReceiver implementation that receives network connection events. its declared in the AndroidManifest.xml and is called by Android automatically when network events occur.
BroadcastReceiver:
public class ConnectivityChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "action: " + intent.getAction());
Log.v(TAG, "component: " + intent.getComponent());
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<receiver
android:name=".ConnectivityChangeReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>
I'd like to use Google's MVP sample architecture described here for my app:
https://github.com/googlesamples/android-architecture/tree/todo-mvp/
Using the above architecture, just wondering:
Where should my BroadcastReceiver be placed?
If my BroadcastReceiver needs to write to the database, whats the best way of doing this?
If my BroadcastReceiver needs to update the UI, whats the best way of doing this?
Android BroadcastReceiver is a dormant component of android that listens to system-wide broadcast events or intents. When any of these events occur it brings the application into action by either creating a status bar notification or performing a task.
You should register and unregister your broadcast in onResume() and onPause() methods. if you register in onStart() and unregister it in onStop().
Step 1. Open your project where you want to implement this. Step 2. Open your BroadcastReceiver class from where you pass data to activity inside your onReceive() you need to start intent and pass data inside intent and start sendBroadcast() as shown bellow.
BroadcastReceiver
should be delivered to the presenter.Based on statement 1, presenter holds reference to the Interactor
/Contract
/Use case
that should handle db operations.
BroadcastReceiver
--event--> Presenter
--> Interactor
---> Repository
Based on statement 1, again the presenter should consume the event and make call to the View.
BroadcastReceiver
--event--> Presenter
--> (maybe do some stuff, business logic) ---> View
Here is what I have, a minimal example snippet that sums up what I said:
private class NetworkBroadcastReceiver23 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//... redacted code.../
boolean connected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
mPresenter.onConnectionChanged(activeNetworkInfo,connected);
}
}
Place the receiver in the activity, because from there you stream events to the presenter. This will ease testing the presenter for connection change. It's hard to achieve separation of concern for platform events, I wanted to keep my layers free from android sdk components and classes. Another way, that was pointed by Alex Shutov, is mixing MVP and Observer pattern if you go with considering BroadcastReceiver as external entity, rather than event source.
Yes, I agree that you can improve the method by getting rid of the NetworkInfo
param.
In MVP design pattern Model has all entities for connection with outer world (for example, Repository for fetching data and persisting it locally). Broadcast receiver is a input for external events, which, eventually, will modify model. Good comparison is a 'Input port' in Hexagonal architecture.
Presenter defines the way of displaying data from model, but all business logic, including reaction to another system or user events is supposed to be inside model.
View and Presenter can be changed dynamically depending on mode program running in, say, you want to use another version of UI, or more simplistic UI behaviour, but all logic must remain the same, including reaction to external events. That is why BroadcastReceiver should be placed inside model.
You should NEVER place Broadcast receiver into Activity, because Activity is a system container for (View), at least if you follow MVP pattern. In case your project is quite complex consider abstracting from BroadcastReceiver by some 'ExternalInput' interface, which can be easily mocked during testing and use it inside Model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With