I´m working on some application which uses Media Transfer Protocol to read Photos from a Camera connected to my Android Tablets USB host (Android 3.1, Acer Iconia Tab A500).
I found some tutorials describing how to work with USB and I got copying from USB camera to SD-Card already working.
There is only one problem I have: All the tutorials wait for USB_DEVICE_ATTACHED-Intent and then open a UsbDeviceConnection for communicating with the device that is sent within the intents Bundle.
So I would like to be able to manually start an activity which accesses USB - WITHOUT receiving this intent.
The Problem now is, that I cannot open an USBConnection like this
UsbDeviceConnection usbDeviceConnection = usbManager.openDevice(usbDevice);
It simply returns null.
If I re-plugin the device and select my Activity as Intent receiver, it works fine.
I think this must be because of the IntentReceiver having some exclusive permissions on the USB device.
My Manifest looks like this:
<activity
android:name=".ImageActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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>
So one example: What if a user has set Galery as default for USB devices. How can I access the USB device in this case?
I have found the USB Host mode API guide documentation to be highly useful in this area.
http://developer.android.com/guide/topics/connectivity/usb/host.html#discovering-d
The most important note is that if you have NOT received a UsbDevice from an activity, then you will need to request permission to communicate with it. This process is described in the link provided.
Related
I want to connect the Android device as a USB Device to an STM32 board which acts as a host device.
My application code for Android looks like:
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usb_connection">
<uses-feature android:name="android.hardware.usb.accessory" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
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>
</manifest>
So when I am trying to get the connected USB device details, the USB Device list is always null :
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Map<String,UsbDevice> deviceList = manager.getDeviceList();
Again, I also tried to get the accessory list, the USB accessory list is also null.
UsbAccessory[] accessoryList = manager.getAccessoryList();
Then tried ADB commands to connect the device. I have created a Desktop application in JAVA to run ADB command and its working fine. But when I tried run ADB command from my Android App, it's giving java.io.IOException: Error running exec(). Command: [ ADB, pull , ...] Working Directory: null Environment: null.
STM32 firmware is written in C.
Please help me I am stuck for a long time.
Hey here is my library for Android Accessory mode activation on Stm32(with cube Mx and HAL verified on series f4 and f1) and USB class for bulk communication:
https://github.com/once2go/Stm32-Android-Accessory
What are you trying to do on the STM32 side? You need to first connect to the Android device over USB and determine (on the STM32 side) whether the Android device is in AOA mode (by checking the Vendor and Product ID). If it's not, you need to send some USB requests that will toggle it (I've included the STM32 USBH library call name):
USBH_GetProtocol Version
USBH_SetString 0 manufacturer name
USBH_SetString 1 model name
USBH_SetString 2 description
USBH_SetString 3 version
USBH_SetString 4 URI
USBH_SetString 5 serial number
Start Accessory
You can see that process explained in more detail here:
https://source.android.com/devices/accessories/aoa#attempt-to-start-in-accessory-mode
Once you've done that, you'll disconnect from the USB device (it will reset the connection) and you'll need to redo the enumeration process. This time, the Vendor and Product ID should be that of an AOA device (0x18D1 & 0x2D00/1). Now you can just connect to it and use a fairly standard USBH_CDC communication process, with a few caveats. When you try to find the interface (in your interface init function), your subclass is 0xFF and your protocol is going to be 0x00).
It took me a while to get everything communicating properly, so having a usb logic analyzer is a really handy tool to make sure things are communicating properly.
Here are some other resources for getting the Android device to communicate once the STM32 is doing things correctly.
https://source.android.com/devices/accessories/aoa2
https://developer.android.com/guide/topics/connectivity/usb/accessory.html#manifest
Background :I have tried finding help on stackoverflow, android developers, and various other resources on web. This is my last hope.
I am new to communication and starting with implementation of USB. Following are my questions:
1) When I connect my phone to windows PC, which one is host?
Suppose I want to create an application that can send data, am I making my phone host?
2) For the case (Windows PC and Android phone), the other one would be a peripheral or a device? are they same?
3) From android developers website and a windows forum about USB, I understand that there are certain steps that need to be followed, and it's like
- Create an instance of USBManager.
- Create get list of devices
- Choose a device from which you want to establish connection
- Create an interface
- get endpoint from that interface.
- Create instance of DeviceConnections and call bulkTransfer method and send data.
But when I tried above steps, I get device == null.
I don't even know if my understanding for above communication method is correct.
Can someone please help me understand and establish basic communication between a PC and a android phone and send at least "hello world".
Big thank you for even reading such a long question.
Here is code sample of what I have done. here devicelist returns null.
public class MainActivity extends AppCompatActivity {
android.widget.Button usbButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final CustomUSBManager cmanager = new CustomUSBManager();
//1) //Create instance of USB Manager using getSystemService
final UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
//2) //Create a list of devices
HashMap<String,UsbDevice> deviceList = manager.getDeviceList();
Log.d("Devicelist = ", String.valueOf(deviceList.get(0)));
//3) //Get a specific device from the list
//-----------------------------------------------------------------
Here is my manifest file.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.neeraj.usbcommunication1">
<uses-feature android:name="android.hardware.usb.host"></uses-feature>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
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>
</manifest>
final UsbDevice device = deviceList.get(0); //getting first device
This will not work the way you want. The UsbManager.getDeviceList() is meant to be used with Android devices with an USB port (for example a tablet). However, you connect an Android device acting as a device to your PC acting as a host.
If you want to communicate between Android USB device and some USB host you need to use the accessory mode (https://developer.android.com/guide/topics/connectivity/usb/). But this mode requires special driver support on the USB host side (which is your PC).
Also note that getDeviceList() makes no sense in Accessory mode. This is because the connected accessory is a USB host, not a USB device.
Read more about this in this post: Android to PC USB Read/Write
Note that my answer is based on this answer: https://stackoverflow.com/a/14099963/5457878
Final intention here is to have a device in 'kiosk mod'.
They say you don't need NFC nor rooting to achieve application becoming device owner. I've yet to see a full example of this method but lets try:
adb shell dpm set-device-owner <package>/.<ReceiverImplementation>
should do... So I do so, and get:
java.lang.SecurityException:
Neither user 2000 nor current process has android.permission.BIND_DEVICE_ADMIN.
Following code, therefore, returns false.
((DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE))
.isDeviceOwnerApp(getApplicationContext().getPackageName())
This STO question poses a similar question but doesn't specify an actual failure..
Manifest file and the rest of the source is mostly inspired from this google sample
<manifest
package="com.example.android.deviceowner"
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0">
<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>
<receiver
android:name=".DeviceOwnerReceiver"
android:description="#string/app_name"
android:label="#string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/device_owner_receiver"/>
<intent-filter>
<action android:name="android.app.action.ACTION_DEVICE_ADMIN_ENABLED"/>
</intent-filter>
</receiver>
</application>
</manifest>
Device I am trying to do this currently is LG G Pad.
Your manifest file seems correct.
You should be aware that it may come from the state of your system when you are executing this command. Many points should be checked before running the dpm command successfully :
Make sure your app is already installed, like any other casual app
Make sure that no account is already set for the current user (make sure no account is set in Settings > Accounts) before its use.
there shouldn't be an existing device owner already registered
The best thing to do (That's what I did when experimenting indeed) is to completely factory-reboot your phone and avoid most configuration steps (except the mandatories steps "configure Wi-Fi", and "Name"), and do not associate any Google account.
Once provisioned, you are sure to be in a clean state.
Then,
Activate Debugging
install your app with your IDE (or with pm install...)
run the command adb shell dpm set-device-owner ...
I've written an article explaining most of these steps on my blog, take a look at it, it may be useful in your case.
I am not sure if this is going to help you, but if not you, maybe someone else will use this solution. I had a very similar problem with Samsung Tab A. I could not set the ownership to my application. Always while running:
adb shell dpm set-device-owner cy.com.myapp/.AdminReceiver
I was getting:
java.lang.SecurityException: Neither user 2000 nor current process has
com.sec.enterprise.permission.MDM_PROXY_ADMIN_INTERNAL.
After long search I finally found that I needed to add to my manifest permissions special permissions of Samsung:
<uses-permission android:name="com.samsung.accessory.permission.ACCESSORY_FRAMEWORK" />
That did the trick and now my app can go to the kiosk mode on demand. Possibly you are looking at a similar problem - maybe there is one or more permission setting that you need to set for your LG.
My solution worked for a non-rooted device (and obviously without any account added - fresh after factory reset).
I'm working on an android app that uses NFC to open an activity. So we wrote a NFC tag with specific MIME-Type, like in the API example, so only my app can open the data in it. It was working just fine on Android 2.3.3 to Android 4.0.4.
Now, after I upgraded my Samsung Galaxy Nexus to Android 4.1 Jelly Bean the NFC tag isn't opening my app anymore. The funny thing is that the phone recognizing the mime type of the tag when it shows it in the default android nfc reader.
So the question is... why the app isn't opened by the NFC tag in Android 4.1 Jelly Bean?
The Intent code in my AndroidMenifest.XML:
<activity
android:name=".ActivityToOpenWithNfcTag"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.android.barcodeScanner" />
</intent-filter>
</activity>
If I use the "text/plain" mime type in the tag and the app it works, but I need my unique mime type.
Please help!
Thanks.
I had the same exact problem and I figure out that in Jelly Bean, it converts the mimetype to all lower cases. I see that in your mimetype tag it has an uppercase "S".
So try this instead:
mimeType = "application/com.android.barcodescanner"
Hope this helps :)
In JellyBean, NDEF detection and parsing from tags has been improved and become stricter. Probably your NDEF message is somehow invalid. Check for example the payload length value inside the NDEF message and compare that with the total NDEF message length as stored on the tag.
I am attempting to leverage the USB host capability on the Samsung Galaxy Tablet. I purchased the attachment dongle from samsung (http://www.samsung.com/us/mobile/galaxy-tab-accessories/EPL-1PL0BEGSTA). When I first connected a usb device via this dongle, I had a high power error from the Galaxy Tablet -- FYI use an externally powered USB hub and you can bipass this.
Now that the device itself is acknowledging the existance of a USB peripheral when I attach it, I attempted to use Android's android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager; library. I saw that there are two methods for recognizing a USB device, registering a broadcast receiver to listen for the intents via
IntentFilter usbIntentFilter = new IntentFilter();
usbIntentFilter.addAction("android.hardware.usb.action.USB_DEVICE_ATTACHED");
usbIntentFilter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED");
registerReceiver(mUsbReceiver,usbIntentFilter);
This is not firing any intents when I attach any devices, strange...ok. So I went on to try the next method: explicitly querying for a device list via the UsbManager -- this was accomplished as follows:
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
int count = deviceList.size();
Iterator<UsbDevice> iterator = deviceList.values().iterator();
if(iterator.hasNext()){
UsbDevice deviceVal = iterator.next();
testTxtView1.setText("set device " + deviceVal);
}
This would presumably grab the one (only one USB device currently supported per Google Documentation) USB device that is currently connected. To test this I would call the above code upon a button click and display the device results. For some reason, I am getting a device from the device list every time, whether a USB dongle is connected or not. Furthermore, the device is the same every time regardless of the USB dongle (or lack thereof). The output is as follows:
device usbDevice[mName=/dev/bus/usb/001/002,mVendorId=1256,mProductId=27033,mClass=0,mSubClass=0,mProtocol=0,mInterfaces=[Landroid.os.Parcelable;#406ff4d8]
^^ the #406ff4d8 value changes every time I query this code (I just put a single instance of it up)
I have searched everywhere and have not been able to find any similar problems or solutions that may apply to my situation. I have tried implementing google's USB examples (which is exactly what I have essentially, I ripped theirs) and am running into these problems.
I should also mention the makeup of my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.mit.ll.drm4000"
android:versionCode="1"
android:versionName="1.0">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".DRM4000Activity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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>
</application>
and device filter:
(I removed criteria on the device filter but have also tried inserting specific information about the device I am looking for...both to no avail.)
Any help regarding this problem would be much appreciated!
Another update: The device I complained about always being enumerated on the device list
device usbDevice[mName=/dev/bus/usb/001/002,mVendorId=1256,mProductId=27033,mClass=0,mSubClass=0,mProtocol=0,mInterfaces=[Landroid.os.Parcelable;#406ff4d8]
must be the android side usb port or something...because I started attaching a bunch of different devices to my code and found that (similar to this link:
USB_DEVICE_ATTACHED Intent not firing) HID devices, arduino devices..and sadly... my USB device do not appear to fire an intent or get enumerated by the USB hub. I tried with a USB flash drive and it DID enumerate it and worked...however it shows up as the SECOND device on the list, the first being the ever-present usbDevice listed above. Intents do fire with it though.
Does anyone know a workaround to making intents fire with HID devices and other USB devices except the select few android seems to do now?
SOO unfortunately it looks like the Samsung Galaxy Tablet just does not play nicely with the UsbManager and about half of the USB devices in the world. The kernel in Samsung seems to fire intents for storage devices and the like, but not for HID and other random devices (such as arduino, and my usb sensor, and HID devices as well.) It seems to be a bug in samsung kernel. Interestingly, the HID devices WORK on the tablet, but are not enumerated on the UsbManager. I have found several links of the same problem, and it seems like a kernel patch (or the acer tablet) are the only ways around this atm. hopefully samsung will fix in the future. Here is a link to a guy who did a kernel patch if rebuilding the kernel is your thing and you really need to get UsbManager working. I have not tested but plan to eventually, and will leave a comment on my thoughts.
http://forum.xda-developers.com/showthread.php?t=1233072
I am facing same problem but you can use one method deviceName(), after enumerating device you can store device name in a string using device.getdeviceName() method.
you will get exact device name appart from full information of device.
Samsung has removed the USB API from the Android Kernal
i think you should define the device you want to recognize in resource/xml/device_filter.xml.
you can referring the android api.
There may be another (nasty) reason why you can't see your HID device.
UsbHostManager.beginUsbDeviceAdded() "Called from JNI in monitorUsbHostBus() to report new USB devices". This method calls a private method isBlackListed() which will unconditionally filter out all HUB's, and HID's with subclass BOOT.
This may be the reason why you don't see HID devices when you do a getDeviceList()
If anyone has a workaround to this, I think that there are a fair amount of users out there who would appreciate see this.
I have had succesfully attached my Arduino Uno to my samsung galaxy tab 10 P7500.
If you have a problem connecting it, It is because the tablet deny permission for the usb devices that doesn't have external power.
Try to power your device externally using 5 or 3.3 Volt AC/DC Adaptor, for the first time, if you find your device attached and fire the intent, unplug the power adaptor, and your device would operate without external power, the tablet itself would give the power through USB OTG