BroadcastReceiver
and Activity
. In order to avoid some risks like leak memory, data losing,... you must manage the background threads well.There are many external libraries that helpful to us with this problem, for example: EventBus. It's is a powerful library and easy to implement. And this is publisher/subscriber pattern description:
In this post, you are going to learn how to use the EventBus library by building a simple Android application that displays the "connecting Internet" status of the device. Because changes in the connecting status are system events, the app is going to have an
Activity
that needs to receive information from a BroadcastReceiver
- the perfect scenario for using an event bus.
This post is part of a series called Android TOP useful libraries
Creating new project
app/build.gradle
:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'de.greenrobot:eventbus:2.4.0' //EventBus dependency
}
Because of checking Internet connection, you must add ACCESS_NETWORK_STATE
permission to your AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Create a BroadcastReceiver class
NetworkState.java
In the package info.devexchanges.eventbus;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class NetworkState {
public static int TYPE_WIFI = 1;
public static int TYPE_MOBILE = 2;
public static int TYPE_NOT_CONNECTED = 0;
public static int getConnectivityStatus(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) {
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
return TYPE_WIFI;
if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
return TYPE_MOBILE;
}
return TYPE_NOT_CONNECTED;
}
public static String getConnectivityStatusString(Context context) {
int conn = getConnectivityStatus(context);
String status = null;
if (conn == TYPE_WIFI) {
status = "Wifi enabled";
} else if (conn == TYPE_MOBILE) {
status = "Mobile data enabled";
} else if (conn == TYPE_NOT_CONNECTED) {
status = "Not connected to Internet";
}
return status;
}
}
BroadcastReceiver
class, we must declare an EventBus
instance first:
private final EventBus eventBus = EventBus.getDefault();
Posting message with EventBus
is very simple, just call post()
method, your data will be ready in background thread and you can get it anytime later. This is full code for the BroadcastReceiver
file:NetworkReceiver.java
package info.devexchanges.eventbus;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import de.greenrobot.event.EventBus;
public class NetworkReceiver extends BroadcastReceiver {
private final EventBus eventBus = EventBus.getDefault();
@Override
public void onReceive(Context context, Intent intent) {
String status = NetworkState.getConnectivityStatusString(context);
// Get current time
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
String formattedDate = df.format(c.getTime());
String eventData = "@" + formattedDate + ": device network state: " + status;
// Post the event with this line
eventBus.post(eventData);
}
}
Creating an Activity to display data
BroadcastReceiver
class, in this Activity
, you must initialize the EventBus
singleton like above (use getDefault()
method).To allow a class to subscribe to events on the bus, the
register()
method is invoked. In our Activity
, we call it in the onCreate()
method.Similarly, to stop receiving events, the
unregister()
method is called. We call this method in the onDestroy()
method to make sure all resources are freed.The most important method is
onEvent()
, every class that intends to receive events from the event bus should contain this method. The name of this method is important, because the EventBus library uses the Java Reflection API to access this method. In this example, I only update network status to a TextView
.Full code of this
Activity
:
MainActivity.java
Never forget to registering your
package info.devexchanges.eventbus;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
import de.greenrobot.event.EventBus;
public class MainActivity extends AppCompatActivity {
private EventBus eventBus = EventBus.getDefault();
private LinearLayout linearLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linearLayout = (LinearLayout)findViewById(R.id.layout);
eventBus.register(this);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
super.onDestroy();
eventBus.unregister(this);
}
public void onEvent(String event) {
LayoutParams lparams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(this);
tv.setLayoutParams(lparams);
tv.setText(event);
linearLayout.addView(tv);
}
}
BroadcastReceiver
in AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.devexchanges.eventbus">
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NetworkReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>
</manifest>
Running this application, you will see this output: