How to make the app's broadcast receiver keep listening without having a service running in the background

Alex picture Alex · Nov 26, 2014 · Viewed 11.1k times · Source

I'm trying to make an android application which listens to wifi change broadcast and do some action. But the problem is that it is not working when the process is killed. I found this question which says that it won't work without an activity
How to create BroadcastReceiver without Activity/Service?

So that is not an alternative. Hence I created an activity which is empty. I don't want to create a service which keeps running in the background. How can I make my application keep listening even when it is killed. I have registered the broadcast in the manifest.

<activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name="com.background.service.BroadCastReceiver">  
        <intent-filter>
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>  
    </receiver>

This is my class

public class BroadCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    //do some action
   }
}

Answer

danny117 picture danny117 · Dec 8, 2014

Looks like you have it correct defining in the manifest with one exception. The broadcast receiver will trigger an ANR if it doesn't complete in 10 secs. http://developer.android.com/training/articles/perf-anr.html

in your broadcast receiver simply start a service.

public class ReceiverUpload extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    context.startService(new Intent(context, ServiceUploader.class));
}
}

Then in your service start an asynctask because you don't want to be on the UI thread for example you start the same service from an activity in your app.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // start asynctask to get off this thread
    new MyBackGround().execute(startId);
    return Service.START_REDELIVER_INTENT;
}

First thing to do in the asynctask is check for wifi

Below is excerpt from a function I call to check network if it returns false the asynctask just finishes if it's true it does network stuff which hey has to be in the background anyways so asynctask makes even more sense.

// check for network connection
        ConnectivityManager connMgr = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connMgr == null) {
            return false;
        }

        // check ok to process
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo == null || !networkInfo.isConnected()) {
            return false;
        }

        boolean isWifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
        if (!isWifi) {

                return false;

        }

        return true;

Note in this example the startId passed to the asynctask is used to cancel OS redelivering the intent.

 @Override
    public void onPostExecute(Integer startId) {
        if (startId != null) {
            stopSelfResult(startId);
        }
    }