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

11,350

Solution 1

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);
        }
    }

Solution 2

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

Solution 3

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"/>

Solution 4

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?)

Solution 5

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>

Share:
11,350
Alex
Author by

Alex

Updated on July 25, 2022

Comments

  • Alex
    Alex almost 2 years

    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
       }
    }
    
  • danny117
    danny117 over 7 years
    I got a couple up votes on this in the past couple days. I wanted to point out that the main reason you start a service then an async task is so you can put up a cool nifty notification that says "Hey I'm uploading in the background" with a progress bar maybe even a cancel button. Just so the user knows your app is playing fair when it runs in the background.