Android O - detect connection changes in the background

First: I know that it is ConnectivityManager.CONNECTIVITY_ACTIONoutdated, and I know how to use it connectivityManager.registerNetworkCallback. Also, if you read about JobScheduler, but I'm not quite sure if I understood correctly.

My problem is that I want to execute some code when the phone is connected / disconnected to / from the network. This should happen when the application is also in the background. Starting with the Android OI, you will need to show a notification if I want to start the service in the background, which I want to avoid.
I tried to get information about when the phone connects / disconnects using the API JobScheduler/JobService, but it only gets the completed time when I plan it. It seems to me that I cannot run the code when such an event occurs. Is there any way to achieve this? Maybe I just need to change the code a bit?

My JobService:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ConnectivityBackgroundServiceAPI21 extends JobService {

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        LogFactory.writeMessage(this, LOG_TAG, "Job was started");
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        if (activeNetwork == null) {
            LogFactory.writeMessage(this, LOG_TAG, "No active network.");
        }else{
            // Here is some logic consuming whether the device is connected to a network (and to which type)
        }
        LogFactory.writeMessage(this, LOG_TAG, "Job is done. ");
        return false;
    }
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
    LogFactory.writeMessage(this, LOG_TAG, "Job was stopped");
    return true;
}

I start the service as follows:

JobScheduler jobScheduler = (JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
ComponentName service = new ComponentName(context, ConnectivityBackgroundServiceAPI21.class);
JobInfo.Builder builder = new JobInfo.Builder(1, service).setPersisted(true)
    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).setRequiresCharging(false);
jobScheduler.schedule(builder.build());
            jobScheduler.schedule(builder.build()); //It runs when I call this - but doesn't re-run if the network changes

Manifesto (Abstract):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <application>
        <service
            android:name=".services.ConnectivityBackgroundServiceAPI21"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE" />
    </application>
</manifest>

I guess this should be an easy solution, but I cannot find it.

+4
2

: firebase JobDispatcher ( @cutiko). :

public class ConnectivityJob extends JobService{

    @Override
    public boolean onStartJob(JobParameters job) {
        LogFactory.writeMessage(this, LOG_TAG, "Job created");
        connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.registerNetworkCallback(new NetworkRequest.Builder().build(), networkCallback = new ConnectivityManager.NetworkCallback(){
                // -Snip-
            });
        }else{
            registerReceiver(connectivityChange = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    handleConnectivityChange(!intent.hasExtra("noConnectivity"), intent.getIntExtra("networkType", -1));
                }
            }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        }

        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        if (activeNetwork == null) {
            LogFactory.writeMessage(this, LOG_TAG, "No active network.");
        }else{
            // Some logic..
        }
        LogFactory.writeMessage(this, LOG_TAG, "Done with onStartJob");
        return true;
    }


    @Override
    public boolean onStopJob(JobParameters job) {
        if(networkCallback != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)connectivityManager.unregisterNetworkCallback(networkCallback);
        else if(connectivityChange != null)unregisterReceiver(connectivityChange);
        return true;
    }

    private void handleConnectivityChange(NetworkInfo networkInfo){
        // Calls handleConnectivityChange(boolean connected, int type)
    }

    private void handleConnectivityChange(boolean connected, int type){
        // Calls handleConnectivityChange(boolean connected, ConnectionType connectionType)
    }

    private void handleConnectivityChange(boolean connected, ConnectionType connectionType){
        // Logic based on the new connection
    }

    private enum ConnectionType{
        MOBILE,WIFI,VPN,OTHER;
    }
}

( ):

   Job job = dispatcher.newJobBuilder().setService(ConnectivityJob.class)
            .setTag("connectivity-job").setLifetime(Lifetime.FOREVER).setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
            .setRecurring(true).setReplaceCurrent(true).setTrigger(Trigger.executionWindow(0, 0)).build();

: . . , :

  • , , startForeground (, ) stopForeground , , Android
  • , startService
  • : , , (, ).
  • onTaskRemoved , , . , , onTaskRemoved, .

, , . . , (, ?), ( , !).


, :

  • Android 7.0 CONNECTIVITY_ACTION , , . , , , , ( ). , connectivityManager.registerNetworkCallback
  • Android 8.0 , , , .

:

    • .
  • JobService
    • , , . , .

:

  • connectivityManager.registerNetworkCallback(NetworkInfo, PendingIntent) , PendingIntent , ;
    • , 1 , .

VPNService, (, , ), , , VPNService . , .
, 8.0 , , ( JobService), . ( , , , "XX ", ). | - , .

+4

Ch4t4r

public class JobServicio extends JobService {
String LOG_TAG ="EPA";
ConnectivityManager.NetworkCallback networkCallback;
BroadcastReceiver connectivityChange;
ConnectivityManager connectivityManager;
@Override
public boolean onStartJob(JobParameters job) {
    Log.i(LOG_TAG, "Job created");
    connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        connectivityManager.registerNetworkCallback(new NetworkRequest.Builder().build(), networkCallback = new ConnectivityManager.NetworkCallback(){
            // -Snip-
        });
    }else{
        registerReceiver(connectivityChange = new BroadcastReceiver() { //this is not necesary if you declare the receiver in manifest and you using android <=6.0.1
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "recepcion", Toast.LENGTH_SHORT).show();
                handleConnectivityChange(!intent.hasExtra("noConnectivity"), intent.getIntExtra("networkType", -1));
            }
        }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    }


    Log.i(LOG_TAG, "Done with onStartJob");
    return true;
}
@Override
public boolean onStopJob(JobParameters job) {
    if(networkCallback != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)connectivityManager.unregisterNetworkCallback(networkCallback);
    else if(connectivityChange != null)unregisterReceiver(connectivityChange);
    return true;
}
private void handleConnectivityChange(NetworkInfo networkInfo){
    // Calls handleConnectivityChange(boolean connected, int type)
}
private void handleConnectivityChange(boolean connected, int type){
    // Calls handleConnectivityChange(boolean connected, ConnectionType connectionType)
    Toast.makeText(this, "erga", Toast.LENGTH_SHORT).show();
}
private void handleConnectivityChange(boolean connected, ConnectionType connectionType){
    // Logic based on the new connection
}
private enum ConnectionType{
    MOBILE,WIFI,VPN,OTHER;
}
     ConnectivityManager.NetworkCallback x = new ConnectivityManager.NetworkCallback() { //this networkcallback work wonderfull

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
public void onAvailable(Network network) {
        Log.d(TAG, "requestNetwork onAvailable()");
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
    //do something
        }
        else {
        //This method was deprecated in API level 23
        ConnectivityManager.setProcessDefaultNetwork(network);

    }
    }
      @Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
    Log.d(TAG, ""+network+"|"+networkCapabilities);
}

@Override
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
    Log.d(TAG, "requestNetwork onLinkPropertiesChanged()");
}

@Override
public void onLosing(Network network, int maxMsToLive) {
    Log.d(TAG, "requestNetwork onLosing()");
}

@Override
public void onLost(Network network) {
}
    }
    }

_

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            Job job = dispatcher.newJobBuilder().setService(Updater.class)
                    .setTag("connectivity-job").setLifetime(Lifetime.FOREVER).setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
                    .setRecurring(true).setReplaceCurrent(true).setTrigger(Trigger.executionWindow(0, 0)).build();
            dispatcher.mustSchedule(job);
        }

...

    <service
        android:name=".Updater"
        android:permission="android.permission.BIND_JOB_SERVICE"
        android:exported="true"/>
0

Source: https://habr.com/ru/post/1685487/


All Articles