How to receive USB connection status broadcast? - android

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!!

Related

Bluetooth:onReceive() and registerReceiver() these method never been called

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 );
}
}
};
}

Having Bluetooth problems with my app

I'm developing an app for a project. It uses bluetooth. I followed the steps for for setting up bluetooth from google's developer page. I reached the phase where i enable discoverability. The problem is that I want to display the devices in a listview , and they don't show up. Maybe someone can point out my clumsiness as i can't see the problem.
public class MainActivity extends AppCompatActivity {
private final static int REQUEST_ENABLE_BT = 1;
Set<BluetoothDevice> pairedDevices;
ArrayAdapter<String> deviceAdapter;
ArrayList<String> list;
ListView listView;
BroadcastReceiver mReceiver;
Intent discoverableIntent;
IntentFilter intentFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.devices);
list = new ArrayList<>();
deviceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(deviceAdapter);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null)
Toast.makeText(this, "Bluetooth is not supported!", Toast.LENGTH_SHORT).show();
else {
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
if (bluetoothAdapter != null) {
pairedDevices = bluetoothAdapter.getBondedDevices();
}
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
deviceAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceAdapter.add(device.getName() + "\n" + device.getAddress());
Log.d("BT", device.getName() + "\n" + device.getAddress());
}
}
};
intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, intentFilter);
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
bluetoothAdapter.startDiscovery();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.szili.bluetoothclient.MainActivity">
<ListView
android:id="#+id/devices"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.szili.bluetoothclient">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<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>
<!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
You forgot to scan devices:
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
To start discovering devices, simply call startDiscovery()
From: http://developer.android.com/intl/es/guide/topics/connectivity/bluetooth.html
After some research I was able to figure out what the problem was. Basically with Android Marshmallow i needed to give Location permission to my app else it couldn't scan for nearby devices.

Testing an app by faking NFC tag scan

I am new to Android, working on Near Field Communication for reading data from NFC tags. Neither I have NFC supported Android mobile nor NFC tags to test the application I created.
I found the below two posts which says about faking NFC tag scans by triggering an Intent.
Possibility for Fake NFC(Near Field Communication) Launch
Need To Fake an NFC Tag Being Scanned In Android
I changed my code according to the first post, where on click of a button I am triggering the required Intent in the 1st activity. Whereas I have created one more activity capable of handling that same intent. The reading of NFC tag and handling data is based on a button click on the 2nd activity.
The problem is: Whenever I am triggering the fake NFC tag scan intent from the 1st activity, it is throwing an error "No Activity found to handle Intent { act=android.nfc.action.NDEF_DISCOVERED (has extras) }".
The Manifest file goes like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.expensemanager.saubhattacharya">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc" android:required="false" />
<application
android:allowBackup="true"
android:icon="#mipmap/icon1"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Set_Monthly_Target"
android:label="#string/title_activity_set__monthly__target"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.expensemanager.saubhattacharya.MainActivity" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*" />
</intent-filter>
</activity>
<activity
android:name=".Add_Daily_Expense"
android:label="#string/add_daily_expense_activity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.expensemanager.saubhattacharya.MainActivity" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*" />
</intent-filter>
</activity>
</application>
</manifest>
The intent trigger code snippet from the 1st activity is below:
public void scan_tag (View view)
{
final Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED);
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, "Custom Messages");
startActivity(intent);
}
The code snippet from the 2nd activity, which handles the above trigger is below:
public class Add_Daily_Expense extends AppCompatActivity {
Button read_data;
TextView show_data;
Tag detected_tag;
NfcAdapter nfcAdapter;
IntentFilter[] intentFilters;
public static final String MIME_TEXT_PLAIN = "text/plain";
public static final String MIME_IMAGE_ALL = "image/*";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add__daily__expense);
final PackageManager pm = this.getPackageManager();
show_data = (TextView) findViewById(R.id.show_data);
nfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
read_data = (Button) findViewById(R.id.read_nfc);
read_data.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
try {
AlertDialog.Builder builder = new AlertDialog.Builder(Add_Daily_Expense.this);
builder.setMessage("NFC feature is not available on this device!")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "NFC feature is available on this device!", Toast.LENGTH_SHORT).show();
HandleIntent(getIntent());
}
}
});
}
public void HandleIntent(Intent intent)
{
String action = intent.getAction();
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
{
detected_tag = getIntent().getParcelableExtra(nfcAdapter.EXTRA_TAG);
NDefReaderTask NDefReader = new NDefReaderTask();
NDefReader.execute();
}
}
public void onResume()
{
super.onResume();
if(nfcAdapter != null)
setupForeGroundDispatch(this, nfcAdapter);
}
public void onPause()
{
super.onPause();
if(nfcAdapter != null)
stopForeGroundDispatch(this, nfcAdapter);
}
public void onNewIntent(Intent intent)
{
HandleIntent(intent);
}
public void setupForeGroundDispatch (final Activity activity, NfcAdapter nfcAdapter)
{
Intent new_intent = new Intent(getApplicationContext(),Add_Daily_Expense.class);
new_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),0,new_intent,0);
intentFilters = new IntentFilter[1];
String[][] techList = new String[][]{};
intentFilters[0] = new IntentFilter();
intentFilters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
intentFilters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
intentFilters[0].addDataType(MIME_TEXT_PLAIN);
intentFilters[0].addDataType(MIME_IMAGE_ALL);
}
catch(IntentFilter.MalformedMimeTypeException me)
{
me.printStackTrace();
}
nfcAdapter.enableForegroundDispatch(activity, pendingIntent, intentFilters, techList);
}
public void stopForeGroundDispatch (final Activity activity, NfcAdapter nfcAdapter)
{
nfcAdapter.disableForegroundDispatch(activity);
}
public class NDefReaderTask extends AsyncTask <Tag, Void, String>
{
#Override
protected String doInBackground(Tag... params)
{
try
{
detected_tag = params[0];
Ndef ndef = Ndef.get(detected_tag);
ndef.connect();
if(ndef != null)
{
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for(NdefRecord ndefRecord : records)
{
if((ndefRecord.getTnf() == NdefRecord.TNF_ABSOLUTE_URI) || (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN))
{
byte[] payload = ndefRecord.getPayload();
String encoding1 = "UTF-8";
String encoding2 = "UTF-16";
String textEncoding = ((payload[0] & 128) == 0) ? encoding1 : encoding2;
int languageCodeLength = payload[0] & 0063;
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
}
}
ndef.close();
}
catch (UnsupportedEncodingException UE)
{
UE.printStackTrace();
}
catch (IOException IE)
{
IE.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute()
{
}
protected void onPostExecute(String result)
{
if(result != null)
{
show_data.setText(result);
}
}
}
}
My question is: What is wrong I am doing here? Is there any other way to test my app by faking the NFC tag scan?
You specify a MIME type filter for the NDEF_DISCOVERED intent filter:
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*" />
Consequently, the fake NFC intent needs to contain one of these MIME types to match the intent filter. You can add the type information to the intent using the setType() method:
public void scan_tag (View view) {
final Intent intent = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED);
intent.setType("text/plain");
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, ...);
startActivity(intent);
}
Also note that the above code won't add a tag handle to the NFC intent. Hence, you can't obtain a Tag object with
detected_tag = getIntent().getParcelableExtra(nfcAdapter.EXTRA_TAG);
Consequently, you also can't obtain an instance of the Ndef connection class using
Ndef ndef = Ndef.get(detected_tag);
You might want to look into the following questions/answers regarding mock tag objects:
How to mock a Android NFC Tag object for unit testing
Is there a way to create an ACTION_NDEF_DISCOVERED intent from code
How to simulate the tag touch from other application
Finally, be aware that there are several other issues in your code.

Remove USB Accessory permission dialog

I am working on an application which uses USB accessory.When I attach device to arduino it asks for usb permission and it has checkbox in dialog "use by default".When I checked and press ok then it should save permission and do not ask me again but it is asking for permission every time I attach USB.I want to save permission is there any way to save this?
My Code loooks like
#Override
public void onResume() {
super.onResume();
if (mInputStream != null && mOutputStream != null) {
// streams were not null");
return;
}
// streams were null");
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
}
And Android manifest file looks
<activity
android:name="pkg.sarvajal.soochakdroid.Main"
android:label="#string/Home"
android:theme="#android:style/Theme.Translucent.NoTitleBar.Fullscreen"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
Accessory filter is like
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Manufacturer" model="Model" version="1.0" />
<usb-device vendor-id="0x0403" product-id="0x0403" />
</resources>
My BroadcastReceiver code
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
//UsbAccessory accessory = UsbManager.getAccessory(intent);
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
Flag_USB_Attached = true;
Flag_Count_USB_Attached = 0;
Flag_Count_USB_Restart_App = 0;
openAccessory(accessory);
String strdatetime =responce_date();
//sendSMS_background(phoneNumber, "USB Cable Connected at "+strdatetime);
} else {
// USB permission denied
}
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
//UsbAccessory accessory = UsbManager.getAccessory(intent);
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null && accessory.equals(mAccessory)) {
// accessory detached
Flag_USB_Attached = false;
Flag_Count_USB_Attached = 0;
closeAccessory();
String strdatetime =responce_date();
//sendSMS_background(phoneNumber, "Communication Stopped! \n USB Cable Disconnected at "+strdatetime);
//SMS_USB();
}
}
}
And Settingup accessory code
/ Setting up accessory
private void setupAccessory() {
//mUsbManager = UsbManager.getInstance(this);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
if (getLastNonConfigurationInstance() != null) {
mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
openAccessory(mAccessory);
}
}
// Opening Accessory Mode
private void openAccessory(UsbAccessory accessory) {
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "OpenAccessoryTest");
thread.start();
// Accessory opened
} else {
// failed to open accessory
}
}
// close Accessory
private void closeAccessory() {
try {
// T.cancel();
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
According to the Android USB host documentation, your application has permission to access the device until the device is disconnected. This question provides a solution to suppress the permission dialog. Create an intent filter in your manifest file and provide the device information in an xml file. This would enable enumerating the device using a broadcast receiver.
Another reference is this question. The latter is meant for rooted devices and I haven't tried it personally.
Edit:
Manifest File: I register my Broadcast Receiver in the manifest file.
<receiver android:name="MyReceiver">
<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" />
</receiver>
For the sake of convenience, I have my Broadcast Receiver in a separate class:
public class PmrtReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)){
Toast.makeText(context, "Device Detected",Toast.LENGTH_LONG).show();
} else if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)){
Toast.makeText(context, "Device Detached",Toast.LENGTH_LONG).show();
}
}
};
I did not have to do anything else to suppress the permission dialog.
Look into the USB Missile Launcher example from the Android Samples. Your device filtr should be something like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" />
</resources>
You have the VID and PID as hexadecimal numbers.

Putting an android device in USB Host Mode?

For my application I need to make the android device act as the USB Host. It needs to send and receive data from USB connected devices. I have gone through USB Host in Android Developers Site, and developed sample code as follows:
Main.java
public class UsbDemoProjActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "button click", 30).show();
Intent it = new Intent(UsbDemoProjActivity.this,Second.class);
startActivity(it);
}
});
}
}
Second.java:
public class Second extends Activity{
UsbDevice device;
UsbManager mUsbManager;
PendingIntent mPermissionIntent;
private static String ACTION_USB_PERMISSION ="com.android.example.USB_PERMISSION";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("111111111");
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
ACTION_USB_PERMISSION ="com.android.example.USB_PERMISSION";
System.out.println("2222222222");
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
device = deviceList.get("deviceName");
System.out.println("33333333333");
mPermissionIntent = PendingIntent.getBroadcast(this, 0,
new Intent(ACTION_USB_PERMISSION), 0);
System.out.println("444444444444");
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
System.out.println("555555555555");
registerReceiver(mUsbReceiver, filter);
System.out.println("66666666666");
mUsbManager.requestPermission(device, mPermissionIntent);
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println("7777777777777");
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
System.out.println("88888888888");
UsbDevice device = (UsbDevice)intent.getParcelableExtra(
UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
System.out.println("99999999999999");
//call method to set up device communication
}
} else {
//Log.d(TAG, "permission denied for device " + device);
System.out.println("permission denied for device" + device);
}
}
}
}
};
}
However, when I click on button in Main.java page it is showing an error as:
Unfortunately USBDemoProj has been stopped
and in logcat displaying error as per the below image but here the system.output() lines are displaying which are declared in Second.java class. Can anyone please help me what is the error in my app?
Also, am I using the correct method in my sample code to access devices in USB Host Mode? Can anyone suggest me a better way?
I'm using a slickdev library to talk to my serial device, so I'm not sure about your code. It's not onDataReceived()? That might just be the library's function but...
our manifests should both have this in it:
<uses-feature android:name="android.hardware.usb.host" android:required="true"></uses-feature>
and in the
<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" />

Categories

Resources