I am trying to detect wifi, mobile data, bluetooth and location state changes using broadcastreceiver. this is how i do it:
StateChangeReceiver stateChangeReceiver = new StateChangeReceiver();
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
ConnectivityManager conManager = (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
LocationManager locationManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
#Override
protected void onStart() {
super.onStart();
IntentFilter bluetooth = new IntentFilter(bluetoothAdapter.ACTION_STATE_CHANGED);
IntentFilter wifi = new IntentFilter(wifiManager.WIFI_STATE_CHANGED_ACTION);
IntentFilter gps = new IntentFilter(locationManager.PROVIDERS_CHANGED_ACTION);
IntentFilter data = new IntentFilter(conManager.CONNECTIVITY_ACTION);
registerReceiver(stateChangeReceiver, bluetooth);
registerReceiver(stateChangeReceiver, wifi);
registerReceiver(stateChangeReceiver , gps);
registerReceiver(stateChangeReceiver , data);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(stateChangeReceiver);
}
private class StateChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive (Context context, Intent intent) {
if (intent.getAction().equals(wifiManager.WIFI_STATE_CHANGED_ACTION)) {
WifiStateChanged(intent);
} else if(intent.getAction().equals(bluetoothAdapter.ACTION_STATE_CHANGED)) {
BluetoothStateChanged(intent);
} else if(intent.getAction().equals(locationManager.PROVIDERS_CHANGED_ACTION)) {
GpsSwitchStateChanged(context , intent);
} else if(intent.getAction().equals(conManager.CONNECTIVITY_ACTION)) {
DataStateChanged(intent);
}
}
};
private void WifiStateChanged (Intent intent){
int wifiStateExtra = intent.getIntExtra(wifiManager.EXTRA_WIFI_STATE, wifiManager.WIFI_STATE_UNKNOWN);
if (wifiStateExtra == wifiManager.WIFI_STATE_ENABLED)
((ImageView) launcher.findViewById(R.id.wifi_button)).setImageResource(R.drawable.ic_wifi_orange_24dp);
else if (wifiStateExtra == wifiManager.WIFI_STATE_DISABLED)
((ImageView) launcher.findViewById(R.id.wifi_button)).setImageResource(R.drawable.ic_wifi_white_24dp);
};
private void DataStateChanged (Intent intent) {
NetworkInfo netInfo = conManager.getActiveNetworkInfo();
if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_MOBILE)
((ImageView) launcher.findViewById(R.id.data_button)).setImageResource(R.drawable.ic_data_orange_24dp);
else
((ImageView) launcher.findViewById(R.id.data_button)).setImageResource(R.drawable.ic_data_white_24dp);
};
private void BluetoothStateChanged (Intent intent){
String action = intent.getAction();
if (bluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if(intent.getIntExtra(bluetoothAdapter.EXTRA_STATE, -1) == bluetoothAdapter.STATE_ON)
((ImageView) launcher.findViewById(R.id.bluetooth_button)).setImageResource(R.drawable.ic_bluetooth_orange_24dp);
else if(intent.getIntExtra(bluetoothAdapter.EXTRA_STATE, -1) == bluetoothAdapter.STATE_OFF)
((ImageView) launcher.findViewById(R.id.bluetooth_button)).setImageResource(R.drawable.ic_bluetooth_white_64dp);
}
};
private void GpsSwitchStateChanged (Context context,Intent intent){
int locationMode=0;
try
{
locationMode = android.provider.Settings.Secure.getInt(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE);
} catch (android.provider.Settings.SettingNotFoundException e)
{
e.printStackTrace();
}
if (locationMode == android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY
|| locationMode == android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
||locationMode == android.provider.Settings.Secure.LOCATION_MODE_BATTERY_SAVING )
((ImageView) launcher.findViewById(R.id.location_button)).setImageResource(R.drawable.ic_location_orange_24dp);
else if (locationMode == android.provider.Settings.Secure.LOCATION_MODE_OFF) {
((ImageView) launcher.findViewById(R.id.location_button)).setImageResource(R.drawable.ic_location_white_24dp);
}
};
I also added permission that i though was needed:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
But the only changes that are tracking is wifi state changes and the rest doesn't fire the StateChangeReceiver. I am pretty confused why it's not working?
Try registering only one BroadcastReceiver with an unique IntentFilter with all actions. For example:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(bluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(wifiManager.WIFI_STATE_CHANGED_ACTION);
intentFilter.addAction(locationManager.PROVIDERS_CHANGED_ACTION);
intentFilter.addAction(conManager.CONNECTIVITY_ACTION);
registerReceiver(stateChangeReceiver, intentFilter);
With this way you simulate a declaration of BroadcastReceiver like in Manifest:
<receiver
android:name="YourReceiver">
<intent-filter>
<action android:name="action1"/>
<action android:name="action2"/>
</intent-filter>
</receiver>
Another solution is to create one BroadcastReceiver for each action, as I see you have one method for each action to parse it. It't not crazy to create 4 BroadcastReceivers and do the logic of each action inside its BroadcastReceiver.
You are calling registerReceiver multiple times which cause only last line to execute try using
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
intentFilter.addAction(LocationManager.PROVIDERS_CHANGED_ACTION);
intentFilter.addAction(ConnectionManager.CONNECTIVITY_ACTION);
registerReceiver(mReceiver, intentFilter);
You can listen actions in only one receiver and can extract as per action
eg:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
.....
} else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
...
}
}
};
Related
I am beginner in android. I just want to know what is Broadcast receiver (with an example if possible) and it's on onReceive() method. and how we can use that receiver to check the Internet connection.
So should I use the same to check the Internet connection or just create a static method in Main class and access it in other classes?
Okay so i'm not the best programmer but this should work.
this is for a fragment but you should easily be able to change it for an
activity.
first make 3 variables:
Context _mContext;
BroadcastReceiver br = null;
IntentFilter filter;
in your onCreate() paste this:
BroadcastReceiver br = new MyBroadCastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
_mContext = getActivity().getApplicationContext()
_mContext.registerReceiver(br, filter);
with this you register your fragment to the broadcastreceiver class MyBroadCastReceiver.
Now make a MyBroadCastReceiver class and paste this:
public class MyBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
switch(extraWifiState) {
case: WifiManager.WIFI_STATE_DISABLED:
//do something
break;
case WifiManager.WIFI_STATE_ENABLED:
//do something
break;
case: WifiManager.WIFI_STATE_ENABLING:
//do something
break;
case: WifiManager.WIFI_STATE_DISABLING:
//do something
break;
case: WifiManager.WIFI_STATE_UNKNOWN:
//do something with data if you desire so, I found it unreliable until now so i've done nothing with it
}
}
}`
Go back to your fragment and paste this somewhere at the bottom:
#Override
public void onPause() {
try {
if (br == null) {
Log.d("Receiver", "Can't unregister a receiver which was never registered");
} else {
getActivity().getApplicationContext().unregisterReceiver(br);
br = null;
}
} catch(Exception err) {
Log.e(err.getClass().getName(), err.getMessage(), err);
Log.e("Receiver not registered", "Couldn't get context");
}
super.onPause();
}
#Override
public void onResume() {
if(br != null) {
Log.d("Receiver", "Can't register receiver which already has been registered");
} else {
try {
br = new MyBroadCastReceiver();
filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(CONNECTIVITY_SERVICE);
_mContext = getActivity().getApplicationContext();
_mContext.registerReceiver(br, filter);
} catch(Exception err) {
Log.e(err.getClass().getName(), err.getMessage(), err);
}
}
super.onResume();
}
You should be able to call register/unregister the broadcast like this anywhere.
I hope this is enough
<receiver
android:name=".InternetConnectorBroadcastReceiver"
android:enabled="true">
<intent-filter>
<!-- Intent filters for broadcast receiver -->
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
public class InternetConnectionBroadcastReceiver extends BroadcastReceiver {
public InternetConnectorBroadcastReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
}
}
I am developing an application for a Bluetooth client side, and inside this application has a listview that will list out all the connected devices. First, the application will check for the availability of the Bluetooth and then try to connect to another device(Server) , beside that, I initialised the intent filter in the manifest file.
Below is my code :
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> listAdapter;
ListView listView;
BluetoothAdapter mBluetoothAdapter;
Set<BluetoothDevice> bondedDevices;
private BluetoothSocket socket;
Intent discoverableIntent;
private BluetoothDevice remoteDevice;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED"))
{
Log.i("Connect", "Connecting.>>>>");
unregisterReceiver(this);
remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String Temp1 = remoteDevice.getName();
String Temp2 = remoteDevice.getAddress();
listAdapter.add(Temp1 + Temp2);
listView.setAdapter(listAdapter);
new Thread(reader).start();
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
IntentFilter intentFilter = new IntentFilter("com.example.jackpowell.bluetoothclient.ACTION_ACL_CONNECTED");
registerReceiver(mReceiver,intentFilter);
startDiscovery();
}
private void startDiscovery() {
mBluetoothAdapter.cancelDiscovery();
mBluetoothAdapter.startDiscovery();
}
public void init() {
listView = (ListView)findViewById(R.id.listView);
listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,0);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Bluetooth is not supported in this device", Toast.LENGTH_SHORT).show();
finish();
} else {
if (!mBluetoothAdapter.isEnabled()) {
turnOnBluetooth();
}
}
bondedDevices = mBluetoothAdapter.getBondedDevices();
discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivity(discoverableIntent);
}
private Runnable reader = new Runnable() {
#Override
public void run() {
try {
Log.i("Connect","Connecting...........");
android.util.Log.e("TrackingFlow", "Found: " + remoteDevice.getName());
UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a19-03002011c456");
socket = remoteDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
} catch (Exception e) {
e.printStackTrace();
}
}
};
private void turnOnBluetooth() {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
my manifest:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<receiver android:name="bluetoothclient">
<intent-filter>
<action android:name="android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED" />
</intent-filter>
</receiver>
The problem now is onReceive() and registerReceiver() these method never been called, or maybe it already called, I just dont get it. If these method were called, the log cat should be displaying the log command. Why are these method never been called? thank you in advance!
The action name is "android.bluetooth.device.action.ACL_CONNECTED" (to use in manifest) or BluetoothDevice.ACTION_ACL_CONNECTED (to use in code, for intent filter). Action names in your code seem wrong.
Note, to register receiver in manifest the receiver name should be public class based on BroadcastReceiver, not sure what is the "bluetoothclient" meaning in the code above (you didn't show the receiver code).
Usually you don't need both manifest receiver and intent filter receiver in activity, one may be sufficient. The main difference is that manifest receiver can be independent from activity life cycle and receive even when activity is not running.
Try to listen also for ACTION_FOUND (per documentation after startDiscovery you'll receive BluetoothDevice.ACTION_FOUND) and others and try to reduce into minimal example. You need also check result of startDiscovery() which can return false on failure.
Here is slightly modified sample from Discovering devices section:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// Register for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
registerReceiver(mReceiver, filter);
...
if(!mBluetoothAdapter.startDiscovery()){
Log.e("Bluetooth", "discovery error");
}
}
// Create a BroadcastReceiver for bluetooth actions
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("Bluetooth", "got action " + action);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
Log.i("Bluetooth", "got device " + deviceName );
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
...
// Don't forget to unregister the ACTION_FOUND receiver.
unregisterReceiver(mReceiver);
}
Also note, per this question/answer, on some devices discovery does not always work as expected and there is a need for workarounds.
By the way, did you check the logcat for other errors, for example denied permissions etc.? You may try to enable location and add location permission.
Here is a working sample to display all devices:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testbluetooth"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<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>
</application>
</manifest>
MainActivity.java
package com.example.testbluetooth;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView textView;
StringBuilder text = new StringBuilder();
private void addLine(String line)
{
Log.i(getClass().getSimpleName(), line);
text.append("[bluetooth] ").append(line).append('\n');
if(textView!=null)
textView.setText(text);
}
BluetoothAdapter mBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
FrameLayout content = new FrameLayout(this);
textView = new TextView(this);
content.addView(textView, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addLine("onCreate");
setContentView(content);
// Register for broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
registerReceiver(mReceiver, filter);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
for(BluetoothDevice pairedDevice : mBluetoothAdapter.getBondedDevices())
{
addLine("got paired device " + pairedDevice.getName());
}
if(!mBluetoothAdapter.startDiscovery()){
addLine("ERROR: discovery error");
}
else
{
addLine("starting discovery");
}
}
// Create a BroadcastReceiver for bluetooth actions
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
addLine("got action " + action);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String deviceName = device.getName();
//String deviceHardwareAddress = device.getAddress(); // MAC address
addLine("got device " + deviceName );
}
}
};
}
I am trying to detect USB connection in my app, that is, whether or not USB is connected to device.
It's being tested on Marshmallow 6.0.1 (sdk23)
But I'm unable to receive the broadcast actions ACTION_USB_DEVICE_ATTACHED or ACTION_USB_DEVICE_DETACHED..
I tried using both the dynamic way and the AndroidManifest.xml way, neither worked..
Here's my code:
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gokulnc.blah_blah"
android:installLocation="auto"
android:versionCode="15"
android:versionName="1.5.1">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<android:uses-permission android:name="android.permission.USB_PERMISSION" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:vmSafeMode="false">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/DrawerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<receiver android:name="mUsbReceiver">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</receiver>
</activity>
</application>
</manifest>
MainActivity.java :
public class MainActivity extends AppCompatActivity {
BroadcastReceiver mUsbReceiver;
public void onCreate(Bundle savedInstanceState) {
.....
setBroadcastReceivers();
}
void setBroadcastReceivers() {
//Reference: http://www.codepool.biz/how-to-monitor-usb-events-on-android.html
mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
updateUSBstatus();
Log.d(LOG_TAG, "USB Connected..");
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
updateUSBstatus();
}
Log.d(LOG_TAG, "USB Disconnected..");
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver , filter);
Log.d(LOG_TAG, "mUsbReceiver Registered");
}
#Override
public void onResume() {
super.onResume();
Log.d(LOG_TAG, "App Resumed..");
//Refernce: https://stackoverflow.com/questions/18015656/cant-receive-broadcast-intent-of-usbmanager-action-usb-device-attached-usbmanag
Intent intent = getIntent();
if (intent != null) {
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
Toast.makeText(getApplicationContext(), "Attached", Toast.LENGTH_SHORT).show();
} else if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
Toast.makeText(getApplicationContext(), "Detached", Toast.LENGTH_SHORT).show();
}
}
}
}
I also checked this answer: Can't receive broadcast Intent of UsbManager.ACTION_USB_DEVICE_ATTACHED/UsbManager.ACTION_USB_DEVICE_DETACHED, but it didn't help..
Can someone please point out where I'm wrong??
Maybe the reason it doesn't work is that since Android 6.0, the default USB mode is Charging and, maybe ACTION_USB_DEVICE_ATTACHED doesn't get fired up when connected in that mode..
Instead, now I have another solution:
String usbStateChangeAction = "android.hardware.usb.action.USB_STATE";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if(action.equalsIgnoreCase(usbStateChangeAction)) { //Check if change in USB state
if(intent.getExtras().getBoolean("connected")) {
// USB was connected
} else {
// USB was disconnected
}
}
}
That is, the broadcast android.hardware.usb.action.USB_STATE is sent whenever there is a toggle in the USB state.
Unlike android.hardware.usb.action.USB_DEVICE_ATTACHED which is broadcasted only when something like a MTP mode is enable, android.hardware.usb.action.USB_STATE is broadcasted whenever it detects an USB connection that's capable of connecting to a host (say computer), irrespective of its current USB Mode like Charging, MTP or whatever.. (it's called USB config to be more precise)
Here the perfect steps to check that external usb connection occur or not in android activity. Just Follow the steps one by one.
In Android Manifest file:
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
Inside your USB checking Activity Tag:
<activity android:name=".USBEnabled">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
</activity>
Inside your connectivity checking USBEnabled class :
public class USBEnabled extends AppCompatActivity {
private static final String TAG = "UsbHost";
TextView mDeviceText;
Button mConnectButton;
UsbManager mUsbManager;
UsbDevice mDevice;
PendingIntent mPermissionIntent;
private static final int REQUEST_TYPE = 0x80;
private static final int REQUEST = 0x06;
private static final int REQ_VALUE = 0x200;
private static final int REQ_INDEX = 0x00;
private static final int LENGTH = 64;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_usbenabled);
mDeviceText = (TextView) findViewById(R.id.text_status);
mConnectButton = (Button) findViewById(R.id.button_connect);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
#Override
protected void onRestart() {
super.onRestart();
recreate();
}
#Override
protected void onResume() {
super.onResume();
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
updateDeviceList();
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
}
public void onConnectClick(View v) {
if (mDevice == null) {
return;
}
mUsbManager.requestPermission(mDevice, mPermissionIntent);
}
private static final String ACTION_USB_PERMISSION = "com.android.recipes.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
&& device != null) {
getDeviceStatus(device);
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
};
private void getDeviceStatus(UsbDevice device) {
UsbDeviceConnection connection = mUsbManager.openDevice(device);
byte[] buffer = new byte[LENGTH];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, LENGTH, 2000);
connection.close();
}
private void updateDeviceList() {
HashMap<String, UsbDevice> connectedDevices = mUsbManager
.getDeviceList();
if (connectedDevices.isEmpty()) {
mDevice = null;
mDeviceText.setText("No Devices Currently Connected");
mConnectButton.setEnabled(false);
} else {
for (UsbDevice device : connectedDevices.values()) {
mDevice = device;
}
mDeviceText.setText("USB Device connected");
mConnectButton.setEnabled(true);
}
}}
Inside your class xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/button_connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onConnectClick"
android:text="Connect" />
<TextView
android:id="#+id/text_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
<TextView
android:id="#+id/text_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
</LinearLayout>
Now create a new resource directory called xml and create new xml file called device_filter.xml with the following code.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device />
</resources>
Debug and run the application, it will show external usb device connectivity status without any error. I hope you will get output for your scenario.
Enjoy!!
I can`t run startDiscovery (for BlueTooth) from Service.
Service run from sleep by WakefulBroadcastReceiver (by timer).
Source code of Service:
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "LocationService";
private BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service onCreate");
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mBTReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
BTscanner();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (btAdapter != null) {
btAdapter.cancelDiscovery();
}
unregisterReceiver(mBTReceiver);
}
private void BTscanner() {
Log.e(TAG, "==BT: Run BTscanner");
btAdapter.cancelDiscovery();
btAdapter.startDiscovery();
Log.e(TAG, "==BT: End BTscanner");
}
private final BroadcastReceiver mBTReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.e(TAG, "==BT: Started");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.e(TAG, "==BT: Finished");
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e(TAG, "==BT: " + device.getAddress());
}
}
};
}
In log i see:
Service onStartCommand
==BT: Run BTscanner
==BT: End BTscanner
but don`t see:
==BT: Started
==BT: Finished
and list of discovered devices.
In Manifest all permissions installed:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
and service enabled in application field of Manifest:
<service
android:name=".LocationService"
android:enabled="true"
android:exported="true" />
What did I do wrong?
Tnx.
Are you sure that your receiver has not been unregistered in the onDestroy method before having the time to handle any action? I would put a break point in it to see what's happenning in there?
I think, I found a solution.
There were problems when I install and run the application with active Bluetooth on smartphone.
After installing application and manual deactivate/activate Bluetooth device all works fine.
Maybe it was some sort of a hardware failure.
Then reinstall the application twice, and the problem is not repeated.
I have problems with the wifi broadcast receiver. It doesn't receive anything, onReceive is never called. Here's my code:
public final class WifiChangeReceiver extends BroadcastReceiver {
boolean portableHotspot = true;
#Override
public void onReceive(final Context context, Intent intent) {
boolean alreadyPresent = false;
String action = intent.getAction();
if(action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
WifiManager w = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> l = w.getScanResults();
myApp myApp = (myApp)context.getApplicationContext();
List<ScanResult> previousScan = new ArrayList<ScanResult>();
previousScan = myApp.getPreviousScan();
System.out.print("previousScan " + previousScan + "\n");
for (ScanResult r : l) {
if(r.SSID.equals("\""+"TinyBox"+"\"")) {
if(previousScan!=null) {
for (ScanResult previousScanElement : previousScan) {
if(previousScanElement.SSID.contains("\""+"TinyBox"+"\"")) {
alreadyPresent = true;
break;
}
}
}
if (!alreadyPresent) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Methods.connectToNetwork(context);
}
}, 5000);
alreadyPresent = false;
}
}
}
myApp.setPreviousScan(l);
ConnectivityManager conMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo i = conMgr.getActiveNetworkInfo();
//Se non connesso a nessuna rete, allora tiro su TinyBox.
if (i == null) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i = conMgr.getActiveNetworkInfo();
if (i == null) {
boolean portableHotspot = false;
final SQLiteDatabase db = DatabaseManager.getInstance(context).getWritableDatabase();
Cursor c = HotSpotActivation.getHotSpotState(db);
if (c.getCount() > 0) {
String activation = c.getString(c.getColumnIndex(HotSpotActivation.CHECK_STATE));
if (activation.equals("ON")) {
portableHotspot = true;
}
else {
portableHotspot = false;
}
}
if (portableHotspot) {
Methods.setWirelessHotSpot(context.getApplicationContext());
}
}
}
else {
}
}
else if(action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
int iTemp = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
checkState(iTemp);
}
else if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
DetailedState state=
((NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)).getDetailedState();
changeState(state, context);
}
}
private void changeState(DetailedState aState, Context context) {
if (aState == DetailedState.SCANNING) {
Log.d("wifiSupplicanState", "SCANNING");
}
else if (aState == DetailedState.CONNECTING) {
Log.d("wifiSupplicanState", "CONNECTING");
}
else if(aState == DetailedState.OBTAINING_IPADDR) {
Log.d("wifiSupplicanState", "OBTAINING_IPADDR");
}
else if (aState == DetailedState.CONNECTED) {
Log.d("wifiSupplicanState", "CONNECTED");
}
else if (aState == DetailedState.DISCONNECTING) {
Log.d("wifiSupplicanState", "DISCONNECTING");
}
else if (aState == DetailedState.DISCONNECTED) {
myApp myApp = (myApp)context.getApplicationContext();
portableHotspot = myApp.getPortableHotspot();
if (portableHotspot) {
Methods.setWirelessHotSpot(context.getApplicationContext());
}
}
else if (aState == DetailedState.FAILED) {
}
}
public void checkState(int aInt) {
if (aInt == WifiManager.WIFI_STATE_ENABLING) {
Log.d("WifiManager", "WIFI_STATE_ENABLING");
}
else if (aInt== WifiManager.WIFI_STATE_ENABLED) {
Log.d("WifiManager", "WIFI_STATE_ENABLED");
}
else if (aInt == WifiManager.WIFI_STATE_DISABLING) {
Log.d("WifiManager", "WIFI_STATE_DISABLING");
}
else if (aInt == WifiManager.WIFI_STATE_DISABLED) {
Log.d("WifiManager", "WIFI_STATE_DISABLED");
}
}
}
and the manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<receiver android:name="sample.broadcastreceivers.WifiChangeReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"></action>
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"></action>
<action android:name="android.net.wifi.STATE_CHANGE"></action>
<action android:name="android.net.wifi.SCAN_RESULTS"></action>
</intent-filter>
</receiver>
It works (on Receive is called) only if I go to the wifi settings menu, the one in which networks are listed, without pushing anything, just opening it. Immediatly after I enter that menu I start to receive from the broadcast receiver and all works fine, without any reason.
Where is the problem? It's like an Android bug. I'm quite sure the same code worked sometimes ago. Thanks
Check your AndroidManifest: you declare
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
?