Broadcast receiver for checking internet connection in android app

后端 未结 21 3182
温柔的废话
温柔的废话 2020-11-21 22:28

I am developing an android broadcast receiver for checking internet connection.

The problem is that my broadcast receiver is being called two times. I want it to get

相关标签:
21条回答
  • 2020-11-21 22:32

    Here's a comfortable way to do it for activity, fragment or context. It will also auto-unregister if you do it for activity/fragment (in onDestroy), if you wish:

    abstract class ConnectionBroadcastReceiver : BroadcastReceiver() {
        companion object {
            @JvmStatic
            fun registerWithoutAutoUnregister(context: Context, connectionBroadcastReceiver: ConnectionBroadcastReceiver) {
                context.registerReceiver(connectionBroadcastReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
            }
    
            @JvmStatic
            fun registerToFragmentAndAutoUnregister(context: Context, fragment: Fragment, connectionBroadcastReceiver: ConnectionBroadcastReceiver) {
                val applicationContext = context.applicationContext
                registerWithoutAutoUnregister(applicationContext, connectionBroadcastReceiver)
                fragment.lifecycle.addObserver(object : LifecycleObserver {
                    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
                    fun onDestroy() {
                        applicationContext.unregisterReceiver(connectionBroadcastReceiver)
                    }
                })
            }
    
            @JvmStatic
            fun registerToActivityAndAutoUnregister(activity: AppCompatActivity, connectionBroadcastReceiver: ConnectionBroadcastReceiver) {
                registerWithoutAutoUnregister(activity, connectionBroadcastReceiver)
                activity.lifecycle.addObserver(object : LifecycleObserver {
                    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
                    fun onDestroy() {
                        activity.unregisterReceiver(connectionBroadcastReceiver)
                    }
                })
            }
    
            @JvmStatic
            fun hasInternetConnection(context: Context): Boolean {
                val info = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
                return !(info == null || !info.isConnectedOrConnecting)
            }
        }
    
        override fun onReceive(context: Context, intent: Intent) {
            val hasConnection = !intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)
    //        Log.d("AppLog", "conenctivity changed. hasConnection? $hasConnection")
            onConnectionChanged(hasConnection)
        }
    
        abstract fun onConnectionChanged(hasConnection: Boolean)
    }
    

    Usage in fragment:

        ConnectionBroadcastReceiver.registerToFragmentAndAutoUnregister(activity!!, this, object : ConnectionBroadcastReceiver() {
            override fun onConnectionChanged(hasConnection: Boolean) {
                // Log.d("AppLog", "onConnectionChanged:" + hasConnection)
            }
        })
    
    0 讨论(0)
  • 2020-11-21 22:33

    CONNECTIVITY_ACTION docs:

    Apps targeting Android 7.0 (API level 24) and higher do not receive this broadcast if they declare the broadcast receiver in their manifest. Apps will still receive broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.

    0 讨论(0)
  • 2020-11-21 22:36

    Complete answer here

    Menifest file

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    
    <receiver android:name=".NetworkStateReceiver">
        <intent-filter>
          <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
      </receiver>
    

    BroadecardReceiver class

    public class NetworkStateReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
         Log.d("app","Network connectivity change");
         if(intent.getExtras()!=null) {
            NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
            if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
                Log.i("app","Network "+ni.getTypeName()+" connected");
            } else if(intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
                Log.d("app","There's no network connectivity");
            }
       }
    }
    

    Registering receiver in MainActivity

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkReceiver, intentFilter);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        if (networkReceiver != null)
            unregisterReceiver(networkReceiver);
    }
    

    Enjoy!

    0 讨论(0)
  • 2020-11-21 22:37

    Try with this

    public class ConnectionBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        if (<Check internet connection available >) { 
            Toast.makeText(context, "connect to the internet", Toast.LENGTH_LONG).show();
    
            /*upload background upload service*/
            Intent serviceIntent = new Intent(context,<your service class>);
            context.startService(serviceIntent);
    
    
        }else{
            Toast.makeText(context, "Connection failed", Toast.LENGTH_LONG).show();
    
        }
        }
    }
    

    As soon as internet connection trigger, this (BroadcastReciever) will be loaded

    0 讨论(0)
  • 2020-11-21 22:38

    This only checks if the network interface is available, doesn't guarantee a particular network service is available, for example, there could be low signal or server downtime

      private boolean isNetworkInterfaceAvailable(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        }
    

    if you want to make a real connection to make sure your connection can gather data from a server or any url:

      private boolean isAbleToConnect(String url, int timeout) {
            try {
                URL myUrl = new URL(url);
                URLConnection connection = myUrl.openConnection();
                connection.setConnectTimeout(timeout);
                connection.connect();
                return true;
            } catch (Exception e) {
                Log.i("exception", "" + e.getMessage());
                return false;
            }
        }
    

    This function needs to be wrapped in a background thread :

    final String action = intent.getAction();
            if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                checkConnectivity(context);
            }
        }
    
    
        private void checkConnectivity(final Context context) {
            if (!isNetworkInterfaceAvailable(context)) {
                Toast.makeText(context, "You are OFFLINE!", Toast.LENGTH_SHORT).show();
                return;
            }
    
            final Handler handler = new Handler();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    final boolean isConnected = isAbleToConnect("http://www.google.com", 1000);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (isConnected)
                                Toast.makeText(context, "You are ONLINE!", Toast.LENGTH_SHORT).show();
                            else
                                Toast.makeText(context, "You are OFFLINE!", Toast.LENGTH_SHORT).show();
                        }
                    });
    
                }
            }).start();
    
        }
    

    Add required permissions:

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

    Add this line under application in manifest file:

    android:usesCleartextTraffic="true"
    

    Add receiver to manifest file:

    <receiver android:name=".ConnectivityChangeReceiver" >
                <intent-filter>
    
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                </intent-filter>
            </receiver>    
    

    Register/Unregister the BR in you Activity:

    @Override
        protected void onStart() {
            super.onStart();
            IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
            registerReceiver(connectivityChangeReceiver, filter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(connectivityChangeReceiver);
        }
    

    this is the entire Broadcast class :

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.os.Handler;
    import android.util.Log;
    import android.widget.Toast;
    
    import java.net.URL;
    import java.net.URLConnection;
    
    public class ConnectivityChangeReceiver extends BroadcastReceiver {
    
    
        @Override
        public void onReceive(final Context context, final Intent intent) {
    
            final String action = intent.getAction();
            if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                checkConnectivity(context);
            }
        }
    
    
        private void checkConnectivity(final Context context) {
            if (!isNetworkInterfaceAvailable(context)) {
                Toast.makeText(context, "You are OFFLINE!", Toast.LENGTH_SHORT).show();
                return;
            }
    
            final Handler handler = new Handler();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    final boolean isConnected = isAbleToConnect("http://www.google.com", 1000);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (isConnected)
                                Toast.makeText(context, "You are ONLINE!", Toast.LENGTH_SHORT).show();
                            else
                                Toast.makeText(context, "You are OFFLINE!", Toast.LENGTH_SHORT).show();
                        }
                    });
    
                }
            }).start();
    
        }
    
        //This only checks if the network interface is available, doesn't guarantee a particular network service is available, for example, there could be low signal or server downtime
        private boolean isNetworkInterfaceAvailable(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        }
    
        //This makes a real connection to an url and checks if you can connect to this url, this needs to be wrapped in a background thread
        private boolean isAbleToConnect(String url, int timeout) {
            try {
                URL myUrl = new URL(url);
                URLConnection connection = myUrl.openConnection();
                connection.setConnectTimeout(timeout);
                connection.connect();
                return true;
            } catch (Exception e) {
                Log.i("exception", "" + e.getMessage());
                return false;
            }
        }
    } 
    
    0 讨论(0)
  • 2020-11-21 22:40

    1) In manifest : - call receiver like below code

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.safal.checkinternet">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme"
            tools:ignore="AllowBackup,GoogleAppIndexingWarning">
            <receiver android:name=".NetworkChangeReceiver" >
                <intent-filter>
                    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                </intent-filter>
            </receiver>
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

    2) Make one Broad Cast Receiver Class: - In This class add code of Network Check

    package com.safal.checkinternet;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.util.Log;
    import android.widget.Toast;
    
    public class NetworkChangeReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (isOnline(context)){
                Toast.makeText(context, "Available", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(context, "Not Available", Toast.LENGTH_SHORT).show();
            }
        }
        public boolean isOnline(Context context) {
    
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            assert cm != null;
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return (netInfo != null && netInfo.isConnected());
        }    
    } 
    

    3) In your Activity call to Broad Cast Receiver : -

    package com.safal.checkinternet;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    //Call Broad cast Receiver 
            IntentFilter filter = new IntentFilter();
            filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            registerReceiver(new NetworkChangeReceiver(), filter);
        }
    }
    
    0 讨论(0)
提交回复
热议问题