ConnectivityManager.CONNECTIVITY_ACTION verouderd

In Android N wordt op de officiële website vermeld dat “Apps die gericht zijn op Android N geen CONNECTIVITY_ACTION-uitzendingen ontvangen”. En er wordt ook vermeld dat JobSchedulerals alternatief kan worden gebruikt. Maar de JobSchedulerbiedt niet precies hetzelfde gedrag als de uitzending van CONNECTIVITY_ACTION.

In mijn Android-applicatie gebruikte ik deze uitzending om de netwerkstatus van het apparaat te weten. Ik wilde weten of deze status CONNECTINGof CONNECTEDwas met behulp van CONNECTIVITY_ACTIONuitzending en het was het meest geschikt voor mijn vereiste.

Nu het verouderd is, kan iemand mij de alternatieve benadering voorstellen om de huidige netwerkstatus te krijgen?


Antwoord 1, autoriteit 100%

Wat zal worden afgeschaft, is de mogelijkheid voor een app op de achtergrond om statuswijzigingen van de netwerkverbinding te ontvangen.

Zoals David Wasserzei dat je nog steeds op de hoogte kunt worden gehouden van connectiviteitswijzigingen als de app-component is geïnstantieerd (niet vernietigd ) en je hebt uw ontvanger programmatisch geregistreerdmet zijn context, in plaats van dit in het manifest te doen.

Of u kunt in plaats daarvan NetworkCallbackgebruiken. In het bijzonder moet u negeren onAvailablevoor wijzigingen in verbonden status.

Laat me snel een fragment opstellen:

public class ConnectionStateMonitor extends NetworkCallback {
   final NetworkRequest networkRequest;
   public ConnectionStateMonitor() {
       networkRequest = new NetworkRequest.Builder()
           .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
           .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
           .build();
   }
   public void enable(Context context) {
       ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
       connectivityManager.registerNetworkCallback(networkRequest, this);
   }
   // Likewise, you can have a disable method that simply calls ConnectivityManager.unregisterNetworkCallback(NetworkCallback) too.
   @Override
   public void onAvailable(Network network) {
       // Do what you need to do here
   }
}

Antwoord 2, autoriteit 42%

Ik zal Sayem'santwoord updaten voor het oplossen van pluisproblemen die aan mij worden getoond.

class ConnectionLiveData(val context: Context) : LiveData<Boolean>() {
    private var connectivityManager: ConnectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    private lateinit var connectivityManagerCallback: ConnectivityManager.NetworkCallback
    private val networkRequestBuilder: NetworkRequest.Builder = NetworkRequest.Builder()
        .addTransportType(android.net.NetworkCapabilities.TRANSPORT_CELLULAR)
        .addTransportType(android.net.NetworkCapabilities.TRANSPORT_WIFI)
    override fun onActive() {
        super.onActive()
        updateConnection()
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(getConnectivityMarshmallowManagerCallback())
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> marshmallowNetworkAvailableRequest()
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> lollipopNetworkAvailableRequest()
            else -> {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    context.registerReceiver(networkReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")) // android.net.ConnectivityManager.CONNECTIVITY_ACTION
                }
            }
        }
    }
    override fun onInactive() {
        super.onInactive()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.unregisterNetworkCallback(connectivityManagerCallback)
        } else {
            context.unregisterReceiver(networkReceiver)
        }
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private fun lollipopNetworkAvailableRequest() {
        connectivityManager.registerNetworkCallback(networkRequestBuilder.build(), getConnectivityLollipopManagerCallback())
    }
    @TargetApi(Build.VERSION_CODES.M)
    private fun marshmallowNetworkAvailableRequest() {
    connectivityManager.registerNetworkCallback(networkRequestBuilder.build(), getConnectivityMarshmallowManagerCallback())
    }
    private fun getConnectivityLollipopManagerCallback(): ConnectivityManager.NetworkCallback {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
               override fun onAvailable(network: Network?) {
                   postValue(true)
               }
               override fun onLost(network: Network?) {
                   postValue(false)
               }
           }
           return connectivityManagerCallback
       } else {
           throw IllegalAccessError("Accessing wrong API version")
       }
    }
    private fun getConnectivityMarshmallowManagerCallback(): ConnectivityManager.NetworkCallback {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
          connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onCapabilitiesChanged(network: Network?, networkCapabilities: NetworkCapabilities?) {
                networkCapabilities?.let { capabilities ->
                    if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                        postValue(true)
                    }
                }
            }
            override fun onLost(network: Network?) {
                postValue(false)
            }
         }
         return connectivityManagerCallback
       } else {
         throw IllegalAccessError("Accessing wrong API version")
       }
    }
    private val networkReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            updateConnection()
        }
    }
    private fun updateConnection() {
        val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
        postValue(activeNetwork?.isConnected == true)
    }
}

En hetzelfde gebruik:

   val connectionLiveData = ConnectionLiveData(context)
    connectionLiveData.observe(this, Observer { isConnected ->
           isConnected?.let {
             // do job
           }
    })

Trouwens, bedankt Sayem voor je oplossing.


Antwoord 3, autoriteit 27%

In de documentatie voor Android N staat:

Apps die Android N targeten, ontvangen geen CONNECTIVITY_ACTION
uitzendingen, zelfs als ze manifest-items hebben om om kennisgeving te vragen
van deze evenementen. Apps die op de voorgrond draaien, kunnen nog steeds luisteren naar
CONNECTIVITY_CHANGE op hun hoofdthread als ze om een ​​melding vragen
met een BroadcastReceiver.

Dit betekent dat je nog steeds een BroadcastReceiverkunt registreren als je app op de voorgrond draait, om veranderingen in de netwerkconnectiviteit te detecteren.


Antwoord 4, autoriteit 6%

Ik kwam een ​​paar dagen geleden hetzelfde probleem tegen en besloot deze bibliotheek te gebruiken Android-Job

Deze bibliotheek gebruikt JobSchedular, GcmNetworkManageren BroadcastReceiver, afhankelijk van op welke Android-versie de app draait.

Een baan starten is vrij eenvoudig

new JobRequest.Builder(DemoSyncJob.TAG)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(false)
            .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) // this is what gets the job done
            .build()
            .schedule();

Antwoord 5, autoriteit 4%

Ik heb een Kotlin-implementatie geschreven die is gebaseerd op Sayam’s antwoordmaar zonder LiveData. Ik besloot de (op dit moment) nieuwste API-methode te gebruiken (ConnectivityManager#registerDefaultNetworkCallback) die gericht is op Android Nougat.

/**
 * Observes network connectivity by consulting the [ConnectivityManager].
 * Observing can run infinitely or automatically be stopped after the first response is received.
 */
class ConnectivityObserver @JvmOverloads constructor(
        val context: Context,
        val onConnectionAvailable: () -> Unit,
        val onConnectionLost: () -> Unit = {},
        val shouldStopAfterFirstResponse: Boolean = false
) {
    private val connectivityManager
        get() = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    @Suppress("DEPRECATION")
    private val intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
    private val broadCastReceiver = object : BroadcastReceiver() {
        @Suppress("DEPRECATION")
        override fun onReceive(context: Context?, intent: Intent?) {
            if (ConnectivityManager.CONNECTIVITY_ACTION != intent?.action) {
                return
            }
            val networkInfo = connectivityManager.activeNetworkInfo
            if (networkInfo != null && networkInfo.isConnectedOrConnecting) {
                onConnectionAvailable.invoke()
            } else {
                onConnectionLost.invoke()
            }
            if (shouldStopAfterFirstResponse) {
                stop()
            }
        }
    }
    private lateinit var networkCallback: ConnectivityManager.NetworkCallback
    init {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            networkCallback = object : ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network) {
                    super.onAvailable(network)
                    onConnectionAvailable.invoke()
                    if (shouldStopAfterFirstResponse) {
                        stop()
                    }
                }
                override fun onLost(network: Network?) {
                    super.onLost(network)
                    onConnectionLost.invoke()
                    if (shouldStopAfterFirstResponse) {
                        stop()
                    }
                }
            }
        }
    }
    fun start() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            // Decouple from component lifecycle, use application context.
            // See: https://developer.android.com/reference/android/content/Context.html#getApplicationContext()
            context.applicationContext.registerReceiver(broadCastReceiver, intentFilter)
        } else {
            connectivityManager.registerDefaultNetworkCallback(networkCallback)
        }
    }
    fun stop() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            context.applicationContext.unregisterReceiver(broadCastReceiver)
        } else {
            connectivityManager.unregisterNetworkCallback(networkCallback)
        }
    }
}

Gebruik:

val onConnectionAvailable = TODO()
val connectivityObserver = ConnectivityObserver(context, onConnectionAvailable)
connectivityObserver.start()
connectivityObserver.stop()

of:

val onConnectionAvailable = TODO()
val onConnectionLost = TODO()
ConnectivityObserver(context, 
    onConnectionAvailable, 
    onConnectionLost, 
    shouldStopAfterFirstResponse = true
).start()

Vergeet niet de machtiging ACCESS_NETWORK_STATEtoe te voegen aan uw AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Ik kijk ernaar uit om nuttige opmerkingen en verbeteringen van u te lezen.


Antwoord 6, autoriteit 2%

Apps die Android N (Nougat) targeten, ontvangen geen CONNECTIVITY_ACTION-uitzendingen die zijn gedefinieerd in het manifest (zie Svelte).

Mogelijke oplossingen:

Zie ook Android O – Verbindingsverandering op de achtergrond detecteren


Antwoord 7

Hier is mijn oplossing in Java! van Android LOLLIPOP tot Android S en hoger

@RequiresApi (api = Build.VERSION_CODES.LOLLIPOP)
public final class NetworkWatcher extends LiveData<Boolean> {
//    Variables
private final Context context;
private final ConnectivityManager connectivityManager;
private ConnectivityManager.NetworkCallback networkCallback;
private NetworkRequest networkRequest;
private NetworkWatcher.NetworkStateWatcherReceiver networkStateWatcherReceiver;
//    Constructors
public NetworkWatcher(@NonNull Context context){
    this.context = context;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        this.connectivityManager = context.getSystemService(ConnectivityManager.class);
        this.networkCallback = new ConnectivityManager.NetworkCallback(){
            @Override
            public void onLost(@NonNull Network network) {
                NetworkWatcher.super.postValue(false);
            }
            @Override
            public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
                NetworkWatcher.super.postValue(
                        networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                                networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                );
            }
        };
        this.networkRequest = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                .build();
    } else {
        this.networkStateWatcherReceiver = new NetworkStateWatcherReceiver();
        this.networkStateWatcherReceiver.setOnNetworkChangedListener(NetworkWatcher.super::postValue);
    }
}
//    Override methods
@Override
protected void onActive() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
            this.connectivityManager.registerBestMatchingNetworkCallback(this.networkRequest, this.networkCallback, null);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            this.connectivityManager.registerDefaultNetworkCallback(this.networkCallback);
        } else {
            this.connectivityManager.registerNetworkCallback(this.networkRequest, this.networkCallback);
        }
    } else {
        this.context.registerReceiver(
                this.networkStateWatcherReceiver,
                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        );
    }
}
@Override
protected void onInactive() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        this.connectivityManager.unregisterNetworkCallback(this.networkCallback);
    } else {
        this.context.unregisterReceiver(this.networkStateWatcherReceiver);
    }
}
//    Inner method classes
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
private static final class NetworkStateWatcherReceiver extends BroadcastReceiver {
    //        Variables
    private NetworkStateWatcherReceiver.OnNetworkChangedListener onNetworkChangedListener;
    //        Constructors
    public NetworkStateWatcherReceiver() {
    }
    //        Override methods
@Override
    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
        if (this.onNetworkChangedListener != null) {
            boolean isConnected = this.isConnected(context);
            this.onNetworkChangedListener.onNetworkChangedListener(isConnected);
        }
    }
    //        Methods
    private boolean isConnected(@NonNull Context context){
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        return networkInfo != null && networkInfo.isConnected();
    }
    public void setOnNetworkChangedListener(@Nullable OnNetworkChangedListener onNetworkChangedListener) {
        this.onNetworkChangedListener = onNetworkChangedListener;
    }
    //        Inner interfaces
private interface OnNetworkChangedListener{
        void onNetworkChangedListener(boolean isConnected);
    }
}
}

Gebruik het in je hoofdactiviteit binnen de onCreate-methode

new NetworkWatcher(this).observe(this, aBoolean -> {
        if (aBoolean){
            // Internet connection available
        } else {
           // No internet connection
        }
    });

Antwoord 8

Je kunt gemakkelijk de bibliotheek com.github.vladan29:internet_checker:1.0.3 gebruiken.
Met die bibliotheek hoef je geen reactief programmeren te kennen en na te denken over het verwijderen van waarnemers. Slechts een paar regels code zorgen voor een continue en veilige controle van de internetverbinding.

Je kunt alle benodigde instructies vinden op: https:// github.com/vladan29/internet_checker/blob/master/README.md#internet_checker


Antwoord 9

Niets bijzonders hierin. Ik heb zojuist het bovenstaande antwoord naar java omgezet omdat er geen antwoorden zijn met java.

 public class ConnectivityWatcher extends LiveData<Boolean> {
    private static final String TAG = "ConnectivityWatcher";
    private final ConnectivityManager connectivityManager;
    private ConnectivityManager.NetworkCallback connectivityManagerCallback;
    private final NetworkRequest.Builder networkRequestBuilder;
    @NotNull
    private final Context context;
    protected void onActive() {
        super.onActive();
        this.updateConnection();
        if (Build.VERSION.SDK_INT >= 24) {
            try {
                this.connectivityManager.registerDefaultNetworkCallback(this.getConnectivityMarshmallowManagerCallback());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else if (Build.VERSION.SDK_INT >= 23) {
            try {
                this.marshmallowNetworkAvailableRequest();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else if (Build.VERSION.SDK_INT >= 21) {
            try {
                this.lollipopNetworkAvailableRequest();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    protected void onInactive() {
        super.onInactive();
        Log.e(TAG, "onInactive: I am inActive ");
        if (Build.VERSION.SDK_INT >= 21) {
            connectivityManager.unregisterNetworkCallback(connectivityManagerCallback);
        }
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void lollipopNetworkAvailableRequest() throws IllegalAccessException {
        this.connectivityManager.registerNetworkCallback(this.networkRequestBuilder.build(), this.getConnectivityLollipopManagerCallback());
    }
    @TargetApi(Build.VERSION_CODES.M)
    private void marshmallowNetworkAvailableRequest() throws IllegalAccessException {
        this.connectivityManager.registerNetworkCallback(this.networkRequestBuilder.build(), this.getConnectivityMarshmallowManagerCallback());
    }
    private ConnectivityManager.NetworkCallback getConnectivityLollipopManagerCallback() throws IllegalAccessException {
        if (Build.VERSION.SDK_INT >= 21) {
            this.connectivityManagerCallback = new ConnectivityManager.NetworkCallback() {
                public void onAvailable(@NotNull Network network) {
                    postValue(true);
                }
                public void onLost(@NotNull Network network) {
                    postValue(false);
                }
            };
            return this.connectivityManagerCallback;
        } else {
            throw new IllegalAccessException();
        }
    }
    private ConnectivityManager.NetworkCallback getConnectivityMarshmallowManagerCallback() throws IllegalAccessException {
        if (Build.VERSION.SDK_INT >= 23) {
            this.connectivityManagerCallback = new ConnectivityManager.NetworkCallback() {
                public void onCapabilitiesChanged(@NotNull Network network, @NotNull NetworkCapabilities networkCapabilities) {
                    if (connectivityManager != null) {
                        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
                        if (capabilities != null) {
                            if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                                postValue(true);
                            }
                        }
                    }
                }
                public void onLost(@NotNull Network network) {
                    postValue(false);
                }
            };
            return this.connectivityManagerCallback;
        } else {
            throw new IllegalAccessException();
        }
    }
    private void updateConnection() {
        boolean isConnected;
        NetworkInfo activeNetwork = this.connectivityManager.getActiveNetworkInfo();
        if (activeNetwork != null) {
            isConnected = activeNetwork.isConnected();
        } else {
            isConnected = false;
        }
        this.postValue(isConnected);
    }
    @NotNull
    public final Context getContext() {
        return this.context;
    }
    public ConnectivityWatcher(@NotNull Context context) {
        this.context = context;
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            throw new NullPointerException("null cannot be cast to non-null type android.net.ConnectivityManager");
        } else {
            this.connectivityManager = cm;
            this.networkRequestBuilder = (new NetworkRequest.Builder()).addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addTransportType(NetworkCapabilities.TRANSPORT_WIFI).addTransportType(NetworkCapabilities.TRANSPORT_VPN);
        }
    }
}

Antwoord 10

Hoewel het negeren van onAvailable(Network network)soms werkt, kan het zijn dat wanneer onAvailable() wordt aangeroepen, het nieuwe netwerk nog niet volledig functioneel is. Ik heb uiteindelijk het volgende gebruikt volgens dit document https://developer.android. com/reference/android/net/ConnectivityManager.OnNetworkActiveListener

connectivityManager.addDefaultNetworkActiveListener()

Other episodes