Broadcast Receiver calles twice - android

Trying to check Internet connection in my app.
There is a code of my manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
And there is a handle class:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() != null && intent.getAction().equals("android.net.conn.CONNECTIVITY_CHANGE"));
{
Log.d("myLogs", "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("myLogs", "Network " + ni.getTypeName() + " connected");
}
}
if (intent.getExtras().getBoolean(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
Log.d("myLogs", "There's no network connectivity");
}
}
}
}
In my Logcat i get a picture like a:
04-11 23:24:48.021: D/myLogs(10261): Network connectivity change
04-11 23:24:48.021: I/myLogs(10261): Network WIFI connected
04-11 23:24:48.202: D/myLogs(10261): Network connectivity change
04-11 23:24:48.202: I/myLogs(10261): Network WIFI connected
So, receiver called twice. Why? There is some problem with all types of connections.

You may also need to check to see if the intent being received is one of the Sticky events by checking isStickyBroadcast in your reciever. If that is true, then you may ignore it, and continue on. You get sticky broadcasts as soon as the receiver is registered.
http://developer.android.com/reference/android/content/BroadcastReceiver.html#isInitialStickyBroadcast%28%29

Explained in the docs:
"Changes to a device's connectivity can be very frequent—this broadcast is triggered every time you move between mobile data and Wi-Fi. As a result, it's good practice to monitor this broadcast only when you've previously suspended updates or downloads in order to resume them. It's generally sufficient to simply check for Internet connectivity before beginning an update and, should there be none, suspend further updates until connectivity is restored."
Edit:
Forgot to add...a broadcast receiver only to know if the device is connected is a bit of an hoverhead. From the same docs:
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;

Related

How do i track wifi connection state?

I am making an android app which will maintain login and logout details of person using wifi connection. Person gets logged in whenever connect to WIFI and logout if connection lost.
I want to track wifi log details of android device and store in database. Is there any solution?? please help!
Add this permission
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Use BroadcastReceiver.
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMan.getActiveNetworkInfo();
if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI)
Log.d("WifiReceiver", "Have Wifi Connection"); // here login
else
Log.d("WifiReceiver", "Don't have Wifi Connection"); // here logout
}
};
and add this in manifest file.
<receiver android:name=".WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>

Broadcast Receiver on Network State change for TYPE_ETHERNET on Android

I am writing an application, which needs to check Ethernet(RJ45) connectivity.
for this purpose am using a broadcast receiver, but it is only working for Connected State, and my application hangs when I disconnect the Ethernet (RJ45).
here is my Broadcast receiver code and manifest.
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
boolean isConnected ;
ConnectivityManager networkConnectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo = networkConnectivity.getActiveNetworkInfo();
if(networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET)
isConnected = true;
else
isConnected = false;
}
}
Manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<receiver
android:name=".NetworkChangeReceiver"
android:label="NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
As far as I know you should do a null-check for the active network info. It is stated on the API ref of the android that
public NetworkInfo getActiveNetworkInfo ()
Returns details about the currently active default data network. When connected, this network is the default route for outgoing connections. You should always check isConnected() before initiating network traffic. This may return null when there is no default network.
Please have a look at the below code.
String action = intent.getAction();
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
ConnectivityManager conMan = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMan.getActiveNetworkInfo();
if (netInfo != null) {
if (netInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
// is connected
}
}
}

what is a list of android internal broadcast?

I have an android application, when user installs it and when this app is to be run i want to be able to start an service if the device has internet access.
this is my mainfest.xml content for service and my broadcast
<receiver android:name="com.google.audiancelistening.WifiChangedBrodcast" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
For this solution when wifi is turned on this broadcast executes successfully,
but i want start it in first of my application so i added below code in my activity:
if(isInternetOn()){
Intent inten = new Intent(getApplicationContext(), ConnectionService.class);
getApplicationContext().startService(inten);
writeToSDFile();
android.os.Process.killProcess(android.os.Process.myPid());
} else{
writeToSDFile();
android.os.Process.killProcess(android.os.Process.myPid());
}
isInternetOn() method is an method that check internet access like below:
public final boolean isInternetOn() {
ConnectivityManager connec = null;
connec = (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if ( connec != null){
NetworkInfo result = connec.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (result != null && result.isConnectedOrConnecting());
return true;
}
return false;
}
but when my activity execute and internet for first is access this can not be able to run successfully and when i turn off and on my wifi service is start and work successfully.
:(
i dont know what is my solution but i dont have any exception.

open app when connect with wifi

How can I open my application when an user enters a zone that has wi-fi? Is this possible? Suppose my application is onPause() state (means My Device's homescreen). now when device connected with wifi. it will automatically open my application.
Try add broadcast receiver and listen network changes, when wi-fi connected start your activity. Something like this solution
public class ConnectivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifi = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mobile = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (((null != wifi)&&(wifi.isAvailable())) || ((null != mobile)&&(mobile.isAvailable()))){
Intent uplIntent = new Intent(context, YourActivity.class);
uplIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(uplIntent);
}
}
}
And add to manifest
<receiver android:name=".receiver.ConnectivityReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
What I can imagine is an overwriting of the onPause() Method like this:
#Override
public void onPause() {
String conn_context = Context.WIFI_SERVICE;
final WifiManager wifi = (WifiManager) getSystemService(conn_context);
if (wifi.isWifiEnabled())
{
super.onResume();
}
else
{
super.onPause();
}
}
But you must also figure a way to handle the real onPause event.
Maybe doable with the Tasker app from Play Store (not free though). Or you can create a Service (http://developer.android.com/guide/components/services.html) that will have code outlined in the other answers and then launch your app (Activity) when wifi is available.

Wifi Connect-Disconnect Listener

Which listener does my class have to implement inorder to automatically check code if the wifi connects/disconnects?
I'm able to manually check for wifi connection/disconnection but each time I need to connect/disconnect WIFI from android settings and then run my program for the result.
My current code is as simple as:
WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()==true)
{
tv.setText("You are connected");
}
else
{
tv.setText("You are NOT connected");
}
Actually you're checking for whether Wi-Fi is enabled, that doesn't necessarily mean that it's connected. It just means that Wi-Fi mode on the phone is enabled and able to connect to Wi-Fi networks.
This is how I'm listening for actual Wi-Fi connections in my Broadcast Receiver:
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMan.getActiveNetworkInfo();
if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI)
Log.d("WifiReceiver", "Have Wifi Connection");
else
Log.d("WifiReceiver", "Don't have Wifi Connection");
}
};
In order to access the active network info you need to add the following uses-permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
And the following intent receiver (or you could add this programmatically...)
<!-- Receive Wi-Fi connection state changes -->
<receiver android:name=".WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
EDIT: In Lollipop, Job Scheduling may help if you're looking to perform an action when the user connects to an unmetered network connection. Take a look: http://developer.android.com/about/versions/android-5.0.html#Power
EDIT 2: Another consideration is that my answer doesn't check that you have a connection to the internet. You could be connected to a Wi-Fi network which requires you to sign in. Here's a useful "IsOnline()" check: https://stackoverflow.com/a/27312494/1140744
Create your own class that extends BroadcastReceiver...
public class MyNetworkMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Process the Intent here
}
}
In AndroidManifest.xml
<receiver
android:name=".MyNetworkMonitor" >
<intent-filter>
<action android:name="android.net.wifi.STATE_CHANGE" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
See WIFI_STATE_CHANGED_ACTION and CONNECTIVITY_ACTION for an explanation of using the Intent.
Check out these two pages of javadoc:
ConnectivityManager
WiFiManager
Notice that each one defines broadcast actions. If you need to learn more about registering broadcast receivers, check this out:
Programmatically register a broadcast receiver
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()) {
tv.setText("You are connected");
} else {
tv.setText("You are NOT connected");
}
}
};
And in your manifest you could do something like this (if you would prefer to NOT register the receiver in code):
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".WiFiReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.net.ConnectivityManager.CONNECTIVITY_ACTION" />
</intent-filter>
</receiver>
</application>
EDIT:
I should add that it would be better to register this broadcast receiver in your code rather than in the manifest if you only need to receive the broadcast while the app is running. By specifying it in the manifest your process will be notified of a connection change even when it was not previously running.
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 android.content.BroadcastReceiver} with android.content.Context#registerReceiver Context.registerReceiver() and that context is still valid.
I agree with #tanner-perrien's answer, and for 2020, Kotlin represent:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerReceiver(wifiBroadcastReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}
private val wifiBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
Log.d("TUT", "Wifi is ${wifiManager.isWifiEnabled}")
}
}
override fun onDestroy() {
unregisterReceiver(wifiBroadcastReceiver)
super.onDestroy()
}
}
But might want to move with the times: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Activity:
lateinit var connec: ConnectivityManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
connec = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkRequestWiFi = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()
connec.registerNetworkCallback(networkRequestWiFi, networkCallbackWiFi)
}
private var networkCallbackWiFi = object : ConnectivityManager.NetworkCallback() {
override fun onLost(network: Network?) {
Log.d("TUT", "WiFi disconnected")
}
override fun onAvailable(network: Network?) {
Log.d("TUT", "WiFi connected")
}
}
override fun onDestroy() {
connec.unregisterNetworkCallback(networkCallbackWiFi)
super.onDestroy()
}
In AndroidManifest.xml add following permission.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Create new Receiver class.
public class ConnectionChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetInfo != null
&& activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
Toast.makeText(context, "Wifi Connected!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Wifi Not Connected!", Toast.LENGTH_SHORT).show();
}
}
And add that receiver class to AndroidManifest.xml file.
<receiver android:name="ConnectionChangeReceiver"
android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
In response to sabsab. To hook into the Connectivity Change broadcast receiver I utilized warbi's answer and added a class with static methods.
public class WifiHelper
{
private static boolean isConnectedToWifi;
private static WifiConnectionChange sListener;
public interface WifiConnectionChange {
void wifiConnected(boolean connected);
}
/**
* Only used by Connectivity_Change broadcast receiver
* #param connected
*/
public static void setWifiConnected(boolean connected) {
isConnectedToWifi = connected;
if (sListener!=null)
{
sListener.wifiConnected(connected);
sListener = null;
}
}
public static void setWifiListener(WifiConnectionChange listener) {
sListener = listener;
}
}
Then I made changes to the receiver class on the first answer shown above.
public class ConnectivityReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMan.getActiveNetworkInfo();
if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI)
{
Log.d("WifiReceiver", "Have Wifi Connection");
WifiHelper.setWifiConnected(true);
} else
{
Log.d("WifiReceiver", "Don't have Wifi Connection");
WifiHelper.setWifiConnected(false);
}
}
}
Finally, in your activity you can add a listener to utilize this callback.
wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
wasWifiEnabled = (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED || wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING);
WifiHelper.setWifiListener(new WifiHelper.WifiConnectionChange()
{
#Override
public void wifiConnected(boolean connected)
{
//Do logic here
}
});
Notice the listener is removed after the callback fires, this is because it's a static listener. Anyhow this implementation works for me and is one way to hook into your activity, or anywhere gives it's static.
There's also WifiManager.NETWORK_STATE_CHANGED_ACTION:
Broadcast intent action indicating that the state of Wi-Fi connectivity
has changed. An extra provides the new state in the form of a
NetworkInfo object. No network-related permissions are required to subscribe to this broadcast.
Then there is getState(), which has states like CONNECTING/DISCONNECTING, for example, which CONNECTIVITY_ACTION doesn't. Also, CONNECTING means there's no Internet. CONNECTED means there is Internet: https://android.googlesource.com/platform/frameworks/base/+/android10-release/core/java/android/net/NetworkInfo.java#122. Or there's getDetailedState(), which includes "infinity".
Though, NetworkInfo has been deprecated since API 29, so there's that too. But for me seems better than to use CONNECTIVITY_ACTION on supported devices, because of many and accurate states.

Categories

Resources