How can I receive a notification when the device loses network connectivity in android L (API 21)

后端 未结 3 1151
滥情空心
滥情空心 2020-12-24 07:53

I\'m using this code to be notified when the connection is lost in API 20 and down.

registerReceiver(getConnectivityStateBroadcastReceiver(), new IntentFilte         


        
相关标签:
3条回答
  • 2020-12-24 08:28

    OK, so I figure out how to do it but would appreciate confirmation that this solution is the right one.

    All I did is add a call to this code in the onCreate of my application class

    /**
     *
     */
    @SuppressLint("NewApi")
    private void registerConnectivityNetworkMonitorForAPI21AndUp() {
    
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            return;
        }
    
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    
        NetworkRequest.Builder builder = new NetworkRequest.Builder();
    
        connectivityManager.registerNetworkCallback(
                builder.build(),
                new ConnectivityManager.NetworkCallback() {
                    /**
                     * @param network
                     */
                    @Override
                    public void onAvailable(Network network) {
    
                        sendBroadcast(
                                getConnectivityIntent(false)
                        );
    
                    }
    
                    /**
                     * @param network
                     */
                    @Override
                    public void onLost(Network network) {
    
                        sendBroadcast(
                                getConnectivityIntent(true)
                        );
    
                    }
                }
    
        );
    
    }
    
     /**
     * @param noConnection
     * @return
     */
    private Intent getConnectivityIntent(boolean noConnection) {
    
        Intent intent = new Intent();
    
        intent.setAction("mypackage.CONNECTIVITY_CHANGE");
        intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, noConnection);
    
        return intent;
    
    }
    

    and in the IntentFilter that already monitoring my connectivity for API 20 and less I added this

    IntentFilter filter = new IntentFilter();
    
    filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    filter.addAction("mypackage.CONNECTIVITY_CHANGE");
    

    and now my already working broadcast receiver get notification about network changes in API 21 too.

    0 讨论(0)
  • 2020-12-24 08:36

    I'll paste my complete solution since I needed to look into many places in order to make it work:

    In Application class

    public void onCreate(){
    ...
    
    IntentFilter filter = new IntentFilter();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Timber.d("using registerNetworkCallback");
            createChangeConnectivityMonitor();
            filter.addAction(MY_CONNECTIVITY_CHANGE);
        } else {
            Timber.d("using old broadcast receiver");
            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        }
    
        registerReceiver(new SyncOnConnectivityReceiver(), filter);
     }
    
      @RequiresApi(Build.VERSION_CODES.N)
       private void createChangeConnectivityMonitor() {
        final Intent intent = new Intent(MY_CONNECTIVITY_CHANGE);
        ConnectivityManager connectivityManager = (ConnectivityManager) 
      getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            connectivityManager.registerNetworkCallback(
                   new NetworkRequest.Builder().build(), 
                   new ConnectivityManager.NetworkCallback() {
                        /**
                         * @param network
                         */
                        @Override
                        public void onAvailable(Network network) {
                            Timber.d("On available network");
                            sendBroadcast(intent);
                        }
    
                        /**
                         * @param network
                         */
                        @Override
                        public void onLost(Network network) {
                            Timber.d("On not available network");
                            sendBroadcast(intent);
                        }
                    });
        }
    
    }
    

    In my receiver:

    public class SyncOnConnectivityReceiver extends BroadcastReceiver {
    
    @Override
     public void onReceive(@Nullable final Context context, Intent intent) {
        Timber.d("triggering on connectivity change");
        if (context != null && isNetworkAvailable(context)) {
            Executors.newSingleThreadExecutor().submit(new Runnable() {
                @Override
                public void run() {
                    syncBusData(context);
                }
            });
        }
    }
    
    private boolean isNetworkAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            return networkInfo != null && networkInfo.isConnected();
        }
        return false;
    }
    
    private void syncData(Context context) {
    
    }
    }
    

    In AndroidManifiest.xml

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <receiver android:name="com.innofied.viapool.location.SyncOnConnectivityReceiver"/>
    
    0 讨论(0)
  • 2020-12-24 08:48

    Try this if you need

    • register to the network state changes
    • consider all network interfaces
    • want to be notified if network is available for any interface
    • that code supports API>20 (you can add also legacy API support easily)

    Declare the necessary variables in your class:

    private static final HashMap<Network, Boolean> mNetworkStates = new HashMap<>();
    private final Object mSyncNetworkState = new Object();
    private Boolean mNetworkState;
    

    Define your method which monitors the interface changes. mNetworkState shows always if at least one network interface is connected.

    private void registerNetworkStateInfo(@NonNull final Context context) throws Exception {
        final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkRequest.Builder builder = new NetworkRequest.Builder();
    
        if (connectivityManager != null) {
            connectivityManager.registerNetworkCallback(
                    builder.build(),
                    new ConnectivityManager.NetworkCallback() {
                        @Override
                        public void onAvailable(@NonNull Network network) {
                            mNetworkStates.put(network, true);
                            synchronized (mSyncNetworkState){
                                mNetworkState = true;
                            }
    
                            Log.d("Network state", "Network state: true");
                        }
    
                        @Override
                        public void onLost(@NonNull Network network) {
                            mNetworkStates.put(network, false);
                            synchronized (mSyncNetworkState){
                                mNetworkState = false;
                                Log.d("Network state", "Network state: false");
    
                                mNetworkStates.forEach(new BiConsumer<Network, Boolean>() {
                                    @Override
                                    public void accept(Network nextNetwork, Boolean state) {
                                        if (state.equals(true)) {
                                            mNetworkState= true;
                                            Log.d("Network state", "Network state: but true");
                                        }
                                    }
                                });
                            }
                        }
                    }
            );
        } else {
            synchronized (mSyncNetworkState){
                mNetworkState = false;
            }
            throw new Exception("Connectivity Manager is not available");
        }
    }
    

    Use your mNetworkState

    synchronized (mSyncNetworkState){
        if (!mNetworkState) {
            throw new Exception("No network available");
        }
    }
    
    0 讨论(0)
提交回复
热议问题