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.
Related
I have created Two App for NFC. 1. NFC Sender 2. NFC Receiver. NFC Sender sends simple text data to NFC Receiver App. But I am in a big problem here.
I am unable to read simple text from NFC. The text format I am sending using NFC is NdefRecord.
1. NFC Sender Activity code :
public class MainActivity extends AppCompatActivity {
private Button btnPay;
private LinearLayout llRootView;
private NfcAdapter mNfcAdapter;
private EditText edtAmount;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnPay = findViewById(R.id.btnPay);
llRootView = findViewById(R.id.rootView);
edtAmount = findViewById(R.id.etAmount);
btnPay.setOnClickListener(view -> {
hideKeyboard(MainActivity.this);
if (TextUtils.isEmpty(edtAmount.getText().toString().trim())) {
Snackbar.make(llRootView, "Please enter valid value.", Snackbar.LENGTH_SHORT).show();
return;
}
startNFC();
});
}
private void startNFC() {
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
//This will be called if the message is sent successfully
mNfcAdapter.setOnNdefPushCompleteCallback(event -> runOnUiThread(() ->
Toast.makeText(MainActivity.this, "Message sent.", Toast.LENGTH_SHORT)
.show()), this);
//This will refer back to createNdefMessage for what it will send
mNfcAdapter.setNdefPushMessageCallback(event -> new NdefMessage(createRecords()), this);
Snackbar.make(llRootView, "Please attach receiver device to back of your device.", Snackbar.LENGTH_INDEFINITE).show();
} else {
Toast.makeText(this, "NFC not available on this device",
Toast.LENGTH_SHORT).show();
}
}
private NdefRecord[] createRecords() {
//Api is high enough that we can use createMime, which is preferred.
NdefRecord record = NdefRecord.createMime("text/plain", edtAmount.getText().toString().trim().getBytes(StandardCharsets.UTF_8));
return new NdefRecord[]{
record
, NdefRecord.createApplicationRecord("com.example.nfcreceiver")
};
}
public static void hideKeyboard(Activity activity) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
//Find the currently focused view, so we can grab the correct window token from it.
View view = activity.getCurrentFocus();
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = new View(activity);
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
2. NFC Receiver Manifest :
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
3. NFC Receiver Activity Code :
public class MainActivity extends AppCompatActivity {
NfcAdapter mAdapter;
PendingIntent mPendingIntent;
TextView tvReceived, tvTagTech;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvReceived = findViewById(R.id.tvReceived);
tvTagTech = findViewById(R.id.tvTagList);
Initialization();
}
#Override
protected void onResume() {
super.onResume();
if (!WebConstant.isOnline()) {
Snackbar.make(tvReceived, R.string.str_no_internet_connection, Snackbar.LENGTH_LONG).show();
}
resolveIntent(getIntent());
if (mAdapter != null) {
if (!mAdapter.isEnabled()) {
Toast.makeText(this, "NFC Not Enabled", Toast.LENGTH_LONG).show();
}
mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
}
}
#Override
protected void onPause() {
super.onPause();
if (mAdapter != null) {
mAdapter.disableForegroundDispatch(this);
}
}
private void Initialization() {
mAdapter = NfcAdapter.getDefaultAdapter(this);
if (mAdapter == null) {
Toast.makeText(this, "NFC Not found", Toast.LENGTH_LONG).show();
// finish();
return;
}
mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
}
#Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
new Handler().postDelayed(() -> {
setIntent(intent);
}, 0);
}
private void resolveIntent(Intent intent) {
String action = intent.getAction();
Log.d("ActionType", action);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
getTagInfo(intent);
}
}
private void getTagInfo(Intent intent) {
sendToFirebase(intent);
}
private void sendToFirebase(Intent intent) {
String title, message;
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
NdefMessage[] messages = getNdefMessages(intent);
if (messages != null && messages.length > 0) {
title = "Success";
message = "Received NDEF Messages";
showAlert(title, message);
try {
String msg = new String(messages[0].getRecords()[0].getPayload(), StandardCharsets.UTF_8);
message = String.format("You received %sQAR", msg);
tvReceived.setText(message);
} catch (Exception e) {
e.printStackTrace();
title = "Error";
message = e.getLocalizedMessage();
showAlert(title, message);
}
} else {
title = "Failure";
message = "Received empty NDEF Messages";
showAlert(title, message);
}
} else {
title = "Failure";
message = "Received non NDEF Messages";
showAlert(title, message);
}
Map<String, Object> body = new HashMap<>();
body.put("Title", title);
body.put("Message", message);
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag != null) {
body.put("TagList", Arrays.toString(tag.getTechList()));
} else {
body.put("TagList", "");
}
RestClient.getInstance().push("NFCDetails", body, mResponse -> {
});
}
private NdefMessage[] getNdefMessages(Intent intent) {
Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
NdefMessage[] messages = new NdefMessage[rawMessages.length];
for (int i = 0; i < messages.length; i++) {
messages[i] = (NdefMessage) rawMessages[i];
}
return messages;
} else {
return null;
}
}
public void showAlert(String title, String message) {
AlertDialog dialog = new AlertDialog.Builder(this)
.create();
dialog.setTitle(title);
dialog.setMessage(message);
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK", (dialog1, which) -> dialog1.dismiss());
dialog.show();
}
}
Please Help me to solve this puzzle.
The tag technology I am receiving in the Receiver app is below :
[android.nfc.tech.IsoDep, android.nfc.tech.NfcA]
Android Beam was deprecated in Android 10
Therefore the Pixel phone does not have the capability to send or receive NDEF messages sent from other old Android phones via this method you are trying to use.
Update:
The IsoDep Tag you are seeing is most likely being generated by the secure element part of the NFC hardware in the device as part of the NFC wallet type functionality that can hold your contactless bank card details. You would read this as though you were reading a contactless bank cards with, using the right AID's and higher level protocols and standards (But if you have not loaded a credit/debit card in to Google Wallet, it won't respond to any of the standard AID's for credit/debit cards)
The only thing you could really read from at the IsoDep level is a randomly generated UID.
Android does allow you to do Host Card Emulation (HCE) which allows you to set the response to selected AID queries. There is an AID for NDef data, thus using HCE you could replicate the Android Beam type funtionality, but this is complicated.
The recommended way to send data between 2 devices is via Bluetooth or Wifi Direct
How can I use an app to detect when the otg cable is plugged in and when it's not?
Is there an intent for otg cables like the one below for usb devices: "android.hardware.usb.action.USB_DEVICE_ATTACHED"
I have created an app but it only detects a flash drive and not an otg cable:
public class MainActivity extends AppCompatActivity
{
private TextView mInfo;
private Logger mLogger;
private HashMap<UsbDevice, UsbDataBinder> mHashMap = new HashMap<UsbDevice, UsbDataBinder>();
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInfo = (TextView)findViewById(R.id.log);
mLogger = new Logger(this);
mLogger.setMode(Logger.MODE_TOAST);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
usbConnection();
}
private void usbConnection() {
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbAttachReceiver , filter);
filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbDetachReceiver , filter);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
showDevices();
}
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mUsbDetachReceiver);
unregisterReceiver(mUsbAttachReceiver);
unregisterReceiver(mUsbReceiver);
};
BroadcastReceiver mUsbDetachReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
// call your method that cleans up and closes communication with the device
UsbDataBinder binder = mHashMap.get(device);
if (binder != null) {
binder.onDestroy();
mHashMap.remove(device);
Toast.makeText(MainActivity.this, "Attached!", Toast.LENGTH_SHORT).show();
}
}
}
}
};
BroadcastReceiver mUsbAttachReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
showDevices();
Toast.makeText(MainActivity.this, "Detached!", Toast.LENGTH_SHORT).show();
}
}
};
private static final String ACTION_USB_PERMISSION = "com.android.example.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)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// call method to set up device communication
UsbDataBinder binder = new UsbDataBinder(mUsbManager, device);
mHashMap.put(device, binder);
Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_SHORT).show();
}
} else {
// Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
private void showDevices() {
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next();
mUsbManager.requestPermission(device, mPermissionIntent);
//your code
mLogger.log("usb", "name: " + device.getDeviceName() + ", " +
"ID: " + device.getDeviceId());
mInfo.append(device.getDeviceName() + "\n");
mInfo.append(device.getDeviceId() + "\n");
mInfo.append(device.getDeviceProtocol() + "\n");
mInfo.append(device.getProductId() + "\n");
mInfo.append(device.getVendorId() + "\n");
}
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
}
I never tried USB OTG, but from https://github.com/shakalaca/USB-OTG-Manager you can use
<intent-filter>
<action android:name="com.sonyericsson.hardware.action.USB_OTG_DEVICE_CONNECTED" />
<action android:name="com.sonyericsson.hardware.action.USB_OTG_DEVICE_DISCONNECTED" />
<action android:name="com.sonyericsson.hardware.action.USB_OTG_ERROR" />
<action android:name="com.sonyericsson.usbotg.ACTION_ERROR_OK" />
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
From the documentation:
USB OTG Manager
This software is originally designed for Sony Ericsson Xperia Arc S.
Since OTG is enabled in kernel, I'm wondering why I can't access my
memory stick. So I've created this little application for reading
books on my thumb disk, and happily ever after ! :D
Supported Phone:
* Sony Ericsson Xperia Arc S (4.0.2.A.042, 4.0.2.A.062)
* Sony Ericsson Xperia Mini Pro (4.0.2.A.042, 4.0.2.A.058)
* Samsung Galaxy Nexus
Supported USB Device:
* FAT USB memory stick
* Card Reader
related project: https://github.com/mik3y/usb-serial-for-android
you're on your own boat now.
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!!
My app should pair with a BLE without showing any pairing request dialog. I am setting pin in the code. But actually dialog is showing for a sec and then disappearing. Pairing is happening, but i don't want this dialog to be shown. Is there a method to do that?
Since the SDK version 19 this is more difficult. I found a way to bypass it using a subclass of BroadcastReceiver.
public class BluetoothPairingRequest extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
// convert broadcast intent into activity intent (same action string)
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
Intent pairingIntent = new Intent();
pairingIntent.setClass(context, MainActivity.class);
pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, type);
pairingIntent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (device != null) {
try {
device.setPin("1111".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
context.startActivity(pairingIntent);
}
}
}
Then you need register a bond receiver like this.
/**
* Lock used in synchronization purposes
*/
private final Object lock = new Object();
private String deviceAddress;
...
#Override
public void onCreate() {
super.onCreate();
...
final IntentFilter bondFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(bondStateBroadcastReceiver, bondFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
...
unregisterReceiver(bondStateBroadcastReceiver);
}
After this you can add this code when you want to initialize the bonding process.
...
BluetoothDevice newDevice = bluetoothAdapter.getRemoteDevice(device.getAddress());
deviceAddress = newDevice.getAddress();
createBond(newDevice);
...
The implementation of the createBond is here:
private final BroadcastReceiver bondStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// Obtain the device and check it this is the one that we are connected to
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!device.getAddress().equals(mDeviceAddress))
return;
// Read bond state
final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
if (bondState == BluetoothDevice.BOND_BONDING)
return;
requestCompleted = true;
// Notify waiting thread
synchronized (lock) {
lock.notifyAll();
}
}
};
private boolean createBond(final BluetoothDevice device) {
if (device.getBondState() == BluetoothDevice.BOND_BONDED)
return true;
boolean result;
requestCompleted = false;
sendLogBroadcast(LOG_LEVEL_VERBOSE, "Starting pairing...");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
result = device.createBond();
} else {
result = createBondApi18(device);
}
// We have to wait until device is bounded
try {
synchronized (lock) {
while (!requestCompleted) lock.wait();
}
} catch (final InterruptedException e) {
Log.e(TAG, "Sleeping interrupted", e);
}
return result;
}
private boolean createBondApi18(final BluetoothDevice device) {
/*
* There is a createBond() method in BluetoothDevice class but for now it's hidden. We will call it using reflections. It has been revealed in KitKat (Api19)
*/
try {
final Method createBond = device.getClass().getMethod("createBond");
if (createBond != null) {
return (Boolean) createBond.invoke(device);
}
} catch (final Exception e) {
Log.w(TAG, "An exception occurred while creating bond", e);
Log.e(TAG, e.toString());
}
return false;
}
Finally don't forget to add to your manifest these lines:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
And register the receiver:
<receiver android:name=".bluetooth.BluetoothPairingRequest">
<intent-filter>
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<action android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
</intent-filter>
</receiver>
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" />