How can I catch the event of wifi state changes - android

I am developing a Power Control Widget, in which I have an ImageButton that when pressed toggles the Wifi and also changes the button's src for visual confirmation. The problem is that I do not know how to detect when the Wifi has been disabled or enabled from other sources, like from the settings or from other power control widget, and change the button's src accordingly.
For example, if I have both my widget and the Android default Power Control Widget on the home screen and I disable the Wifi using my widget, then the Wifi button of the Android default Power Control Widget gets disabled as well, but if I disable the wifi using the stock Power Control Widget, my wifi button's src does not change and still indicates that the wifi is enabled.
Any ideas are appreciated as I can not find a solution to this.
EDIT:
Here is my BroadcastReceiver:
public void onReceive(Context context, Intent intent) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
int state = wifi.getWifiState();
switch(state) {
case WifiManager.WIFI_STATE_DISABLED:
remoteViews.setImageViewResource(R.id.widget_wifi, R.drawable.ic_widget_wifi_off);
break;
case WifiManager.WIFI_STATE_ENABLED:
remoteViews.setImageViewResource(R.id.widget_wifi, R.drawable.ic_widget_wifi_on);
break;
case WifiManager.WIFI_STATE_DISABLING:
remoteViews.setImageViewResource(R.id.widget_wifi, R.drawable.ic_widget_wifi_off);
break;
case WifiManager.WIFI_STATE_ENABLING:
remoteViews.setImageViewResource(R.id.widget_wifi, R.drawable.ic_widget_wifi_on);
break;
}
}
Also the AndroidManifest.xml:
<receiver
android:name="WidgetIntentReceiver"
android:label="widgetBroadcastReceiver" >
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
and the permissions:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>

Listen to System broadcasts such as ACCESS_NETWORK_STATE or ACCESS_WIFI_STATE by registering a BroadcastReceiver in your manifest.
To listen to these system broadcast you need permissions declared in your manifest. Refer to this documentation for the broadcasts actions and the corresponding permissions required.
I hope you know how to implement a broadcast receiver.

public boolean checkOnlineState() {
ConnectivityManager CManager =(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo NInfo = CManager.getActiveNetworkInfo();
if (NInfo != null && NInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}

Related

How to make the app's broadcast receiver keep listening without having a service running in the background

I'm trying to make an android application which listens to wifi change broadcast and do some action. But the problem is that it is not working when the process is killed. I found this question which says that it won't work without an activity
How to create BroadcastReceiver without Activity/Service?
So that is not an alternative. Hence I created an activity which is empty. I don't want to create a service which keeps running in the background. How can I make my application keep listening even when it is killed. I have registered the broadcast in the manifest.
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.background.service.BroadCastReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This is my class
public class BroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//do some action
}
}
Looks like you have it correct defining in the manifest with one exception. The broadcast receiver will trigger an ANR if it doesn't complete in 10 secs. http://developer.android.com/training/articles/perf-anr.html
in your broadcast receiver simply start a service.
public class ReceiverUpload extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, ServiceUploader.class));
}
}
Then in your service start an asynctask because you don't want to be on the UI thread for example you start the same service from an activity in your app.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// start asynctask to get off this thread
new MyBackGround().execute(startId);
return Service.START_REDELIVER_INTENT;
}
First thing to do in the asynctask is check for wifi
Below is excerpt from a function I call to check network if it returns false the asynctask just finishes if it's true it does network stuff which hey has to be in the background anyways so asynctask makes even more sense.
// check for network connection
ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connMgr == null) {
return false;
}
// check ok to process
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected()) {
return false;
}
boolean isWifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
if (!isWifi) {
return false;
}
return true;
Note in this example the startId passed to the asynctask is used to cancel OS redelivering the intent.
#Override
public void onPostExecute(Integer startId) {
if (startId != null) {
stopSelfResult(startId);
}
}
You already doing right with the Broadcast Receiver and declaring it the Manifest. That's all you need to do. No services running in the background are needed.
Just make sure you install and run the app at least once otherwise the broadcast receives won't be registered
The best that worked for me:
AndroidManifest
<receiver android:name="com.AEDesign.communication.WifiReceiver" >
<intent-filter android:priority="100">
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
BroadcastReceiver class
public class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info != null) {
if(info.isConnected()) {
// Do your work.
// e.g. To check the Network Name or other info:
WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
}
}
}
}
Permissions
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
best solution is to make a broadcast receiver , it will work
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ConnectivityManager connMgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final android.net.NetworkInfo wifi = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile = connMgr
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable() || mobile.isAvailable()) {
// Enjoy coding here
Log.d("Netowk Available ", "Flag No 1");
}
}}
in manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastreceiverforinternetconnection"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>
Normally, if app is killed and broadcast comes your app process will be started by system for you. There is absolutely no need to keep something alive or do any additional manipulations (otherwise why would you need BroadcastReceiver if you can just use Service?)
Updated answer 05/2022
The docs on Broadcasts and Broadcast limitations inform that from Android 7 (Android 8 made it even more stringent)
you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts
That means, for most use cases manifest-declared Broadcast won't work anymore and must be replaced with scheduled jobs or services. Be aware, the latter suffers from being killed by the OS for battery optimization.

BroadcastReceiver is not working (detect if wifi is connected)

I'm trying to use a BroadcastReceiver to detect if wifi is connected and simply display a toast when the status changes (wifi disonnect/reconnect/turn off) but it doesn't seem to be working. Any ideas?
ConnectionChangeReceiver class:
public class ConnectionChangeReceiver extends BroadcastReceiver
{
#Override
public void onReceive( Context context, Intent intent )
{
ConnectivityManager connMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final boolean isWifiConn = networkInfo.isConnected();
Log.d("debug", "Wifi connected: " + isWifiConn);
Toast toast = Toast.makeText(context, "Wifi connected: " + isWifiConn, Toast.LENGTH_LONG);
toast.show();
}
}
Manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<receiver android:name="ConnectionChangeReceiver" android:label="NetworkConnection">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
I go in the app, and disconnect wifi, reconnect, no toast. I disable wifi, no toast. re-enable it, no toast. I suspect that there's something wrong with the broadcast receiver.
Thanks in advance.
I got it working.
My problem was in the Manifest. I was putting my receiver block outside the application tag. Once I moved it inside, it worked perfectly.

Difference between CONNECTION_STATE_CHANGED and STATE_CHANGED

What's the difference between Action CONNECTION_STATE_CHANGED and STATE_CHANGED in Android Bluetooth Receiver ?
else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED .equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
if (state == BluetoothAdapter.STATE_CONNECTED) {
//nothing
} else {
}
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_OFF) {
}
}
According to the docs the difference is the following:
ACTION_CONNECTION_STATE_CHANGED
Intent used to broadcast the change in connection state of the local Bluetooth adapter to a profile of the remote device.
ACTION_STATE_CHANGED
The state of the local Bluetooth adapter has been changed. For example, Bluetooth has been turned on or off.
In other words one Intent is for changes in the connection state and the other one for state changes of the Bluetooth adapter itself.
EDIT:
To detect if a device moves in and out of range you need to use the following intents:
ACTION_ACL_CONNECTED: link to documentation
ACTION_ACL_DISCONNECTED: link to documentation
For both of those you need the normal BLUETOOTH permission and the BLUETOOTH_ADMIN permission:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
The intent filter for your BroadcastReceiver would look something like this:
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
</intent-filter>
Here is the general documentation about BluetoothDevice.

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.

Invoking an activity from Broadcast Receiver

i am a beginner in android and i am developing an application where BrocastReceiver starts whenever the user makes a call... i am trying to monitor the network status inside the broadcast receiver... and i am trying to start the activity when the user hangs up the phone... but unfortunately it is giving me an error...please let me know how to do this...
My broadcast receiver starts properly when the user make a call... but i do not know how to monitor the network inside the BroadcastReceiver when the user is on call.. and invoke the activity from the BroadcastReceiver when the user hangs up the phone...
Please let me know how to achieve this... Thanks in advance.. :-)
my code...
BroadcastReceiver Code
public class MoniterNetworkStatus extends BroadcastReceiver{
private ConnectivityManager connectivityManager;
private NetworkInfo info;
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Monitering Network Status !!!", Toast.LENGTH_LONG).show();
boolean networkStatus = false;
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Intent activityIntent = new Intent(context, NetworkStatusActivity.class);
// I am monitoring the network status as long as user is on call...
while(telephonyManager.getCallState()!= TelephonyManager.CALL_STATE_IDLE){
info = connectivityManager.getActiveNetworkInfo();
if(info == null){
networkStatus = false;
}else if(info.getType() == ConnectivityManager.TYPE_MOBILE){
networkStatus = info.isConnected();
}else{
networkStatus = false;
}
}
//Putting the network details in to the activity.
activityIntent.putExtra("operatorName", telephonyManager.getNetworkOperatorName());
activityIntent.putExtra("networkStatus", networkStatus);
// starting the activity
context.startActivity(activityIntent);
abortBroadcast();
}
}
My Manifest File
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- <uses-permission android:name="android.permission.INTERNET"/> -->
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity android:name="com.abc.activity.NetworkStatusActivity"></activity>
<receiver android:name="com.abc.broadcastreceiver.MoniterNetworkStatus"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.ANSWER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
My broadcast receiver starts properly when the user make a call... but i do not know how to monitor the network when the user is on call.. and invoke the activity when the user hangs up the phone...
Please let me know how to achieve this... Thanks in advance.. :-)
You need to register another receiver to accept ACTION_PHONE_STATE_CHANGED. This may be a duplicate of Detecting outgoing call and call hangup event in android

Categories

Resources