Issue
My app is internet-based. I need to show an alert dialog when there is no internet while my app is running. So I've created a BroadcastReceiver
and registered it in MainActivity. I can show no internet with toast properly on top of every activity or fragment, but the alert dialog is only shown in MainActivity. When I'm in another activity or fragment and the network is disconnected it doesn't show an alert dialog in my current activity but shows an alert dialog in MainActivity, it seems like context it's getting is the context of MainActivity. My code is here NetworkUtil.java
as utility class.
//NetworkUtil.java
public class NetworkUtil {
public static final int TYPE_WIFI = 1;
public static final int TYPE_MOBILE = 2;
public static final int TYPE_NOT_CONNECTED = 0;
public static final int NETWORK_STATUS_NOT_CONNECTED = 0;
public static final int NETWORK_STATUS_WIFI = 1;
public static final int NETWORK_STATUS_MOBILE = 2;
public static int getConnectivityStatus(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork) {
if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
return TYPE_WIFI;
if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
return TYPE_MOBILE;
}
return TYPE_NOT_CONNECTED;
}
public static int getConnectivityStatusString(Context context) {
int conn = NetworkUtil.getConnectivityStatus(context);
int status = 0;
if (conn == NetworkUtil.TYPE_WIFI) {
status = NETWORK_STATUS_WIFI;
} else if (conn == NetworkUtil.TYPE_MOBILE) {
status = NETWORK_STATUS_MOBILE;
} else if (conn == NetworkUtil.TYPE_NOT_CONNECTED) {
status = NETWORK_STATUS_NOT_CONNECTED;
}
return status;
}
}
My BroadcastReceiver
CheckConnectivity
public class CheckConnectivity extends BroadcastReceiver{
@Override
public void onReceive(final Context context, final Intent intent) {
int status = NetworkUtil.getConnectivityStatusString(context);
if ("android.net.conn.CONNECTIVITY_CHANGE".equals(intent.getAction())) {
if (status == NetworkUtil.NETWORK_STATUS_NOT_CONNECTED) {
new SweetAlertDialog(context, SweetAlertDialog.ERROR_TYPE)
.setTitleText("Oops...")
.setContentText("No internet! Check your network connection")
.show();
Toast.makeText(context, "Internet Connection Lost", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Internet Connected", Toast.LENGTH_LONG).show();
}
}
}
}
MainActivity
where BroadcastReceiver is registered.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BroadcastReceiver networkChangeReceiver=new CheckConnectivity();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkChangeReceiver, intentFilter);
}
}
Solution
Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver in their manifest. Apps will still receive CONNECTIVITY_ACTION broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.
So, below is the full solution for all the devices.
Create a common class to check whether device is connected to network state or not.
class ConnectivityHelper() {
companion object {
fun isConnectedToNetwork(): Boolean {
val connectivityManager: ConnectivityManager =
CenceApplication.cenceAppContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
if (networkInfo != null) {
return networkInfo.isConnected
}
return false
}
}
}
Now to check for devices below than Nougat: 1. You need to setup broadcast receiver in manifest 2. Listen to changes 3. Notify to your base activity.
Note: Base activity is common activity, which is extended by all other activities in the app, and base activity is extended by AppCompatActivity()
In Manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<receiver
android:name=".Utility.NetworkChangeReceiver"
android:label="NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
Broadcast receiver class:
class NetworkChangeReceiver : BroadcastReceiver() {
companion object {
lateinit var networkChangeListener: NetworkChangeListener
}
override fun onReceive(context: Context?, intent: Intent?) {
networkChangeListener.networkStateChanged(ConnectivityHelper.isConnectedToNetwork())
}
}
Create an interface to notify in base activity:
interface NetworkChangeListener {
fun networkStateChanged(boolean: Boolean)
}
Initialise interface in Application:
class YourApplication:Application() {
companion object {
lateinit var appContext: Context
}
override fun onCreate() {
super.onCreate()
appContext = this
}
fun initializeNetworkListener(listener:NetworkChangeListener){
NetworkChangeReceiver.networkChangeListener = listener
}
}
BasActivity, which implements interface and with the help of MutableLivedata notifies any activity/fragment if network goes off:
class BaseActivity : AppCompatActivity(), NetworkChangeListener {
private var networkLiveData: MutableLiveData<Boolean> = MutableLiveData()
private lateinit var snackbar: Snackbar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupNetworkState()
}
private fun setupNetworkState() {
networkLiveData.postValue(checkNetworkState())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val connectivityManager: ConnectivityManager =
this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network?) {
super.onAvailable(network)
networkLiveData.postValue(checkNetworkState())
}
override fun onLost(network: Network?) {
super.onLost(network)
networkLiveData.postValue(checkNetworkState())
}
})
} else {
(application as YourApplication).initializeNetworkListener(this@BaseActivity)
}
}
override fun networkStateChanged(boolean: Boolean) {
networkLiveData.postValue(boolean)
}
fun getNetworkStateUpdate(): MutableLiveData<Boolean> {
return networkLiveData
}
fun checkNetworkState(): Boolean {
return ConnectivityHelper.isConnectedToNetwork()
}
Now final step in **your any activity/fragment****: In **onCreate() method,
getNetworkStateUpdate().observe(this, object : Observer<Boolean> {
val snackbar = Snackbar
.make(
mIndMainParentLayout, "You're Offline",
Snackbar.LENGTH_INDEFINITE
)
override fun onChanged(t: Boolean?) {
if (!t!!) {
snackbar.show()
} else {
snackbar.dismiss()
}
}
})
Answered By - Rishabh Jain
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.