Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
   }
}
like image 875
Alex Avatar asked Nov 26 '14 10:11

Alex


People also ask

Does broadcast receiver run in background?

A broadcast receiver will always get notified of a broadcast, regardless of the status of your application. It doesn't matter if your application is currently running, in the background or not running at all.

What are the life cycle methods of broadcast receiver?

When a broadcast message arrives for the receiver, Android calls its onReceive() method and passes it the Intent object containing the message. The broadcast receiver is considered to be active only while it is executing this method. When onReceive() returns, it is inactive.

How do I restrict broadcasting the current app?

setAction(packageName + "<MY_ACTION>"); context. sendBroadcast(intent); Since the application package would remain unique for all apps on android, this would safely limit the Broadcast to your own app and you can register BroadcastReceivers in AndroidManifest. xml.


5 Answers

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);
        }
    }
like image 92
danny117 Avatar answered Oct 17 '22 17:10

danny117


You already doing right with the Broadcast Receiver and declaring it the Manifest. That's all you need to do. No services running in the background are needed.

Just make sure you install and run the app at least once otherwise the broadcast receives won't be registered

like image 45
João Alves Avatar answered Oct 17 '22 17:10

João Alves


The best that worked for me:

AndroidManifest

<receiver android:name="com.AEDesign.communication.WifiReceiver" >
  <intent-filter android:priority="100">
    <action android:name="android.net.wifi.STATE_CHANGE" />
  </intent-filter>
</receiver>

BroadcastReceiver class

public class WifiReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

  NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
  if(info != null) {
     if(info.isConnected()) {
        // Do your work. 

        // e.g. To check the Network Name or other info:
   WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        String ssid = wifiInfo.getSSID();
     }
  }
 }
 }           

Permissions

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
like image 29
Elango Avatar answered Oct 17 '22 16:10

Elango


best solution is to make a broadcast receiver , it will work

public class NetworkChangeReceiver extends BroadcastReceiver {

@Override
public void onReceive(final Context context, final Intent intent) {
    final ConnectivityManager connMgr = (ConnectivityManager) context
            .getSystemService(Context.CONNECTIVITY_SERVICE);

    final android.net.NetworkInfo wifi = connMgr
            .getNetworkInfo(ConnectivityManager.TYPE_WIFI);

    final android.net.NetworkInfo mobile = connMgr
            .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

    if (wifi.isAvailable() || mobile.isAvailable()) {
        // Enjoy coding here 

        Log.d("Netowk Available ", "Flag No 1");
    }
}}

in manifest.xml

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastreceiverforinternetconnection"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <receiver android:name=".NetworkChangeReceiver" >
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
        </intent-filter>
    </receiver>
</application>

like image 26
lalit vasan Avatar answered Oct 17 '22 18:10

lalit vasan


Normally, if app is killed and broadcast comes your app process will be started by system for you. There is absolutely no need to keep something alive or do any additional manipulations (otherwise why would you need BroadcastReceiver if you can just use Service?)

like image 33
Dmitry Zaytsev Avatar answered Oct 17 '22 16:10

Dmitry Zaytsev