My ultimate goal is to have an app on my Android tablet connect to an app on my desktop via USB. I don't want to require my users to enable USB debugging- I have seen several implementations (1, 2, 3 ...) which use adb to handle data transfer, but that is unsatisfactory for my use case.
I followed the USB Accessory guide, and tried to list devices with:
public void onResume() {
super.onResume();
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
log( "Devices:" + manager.getDeviceList().toString() );
...
but the device list is always empty. manager.getAccessoryList() returned null.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usb" android:versionCode="1" android:versionName="1.0">
<uses-sdk
android:minSdkVersion="12" android:targetSdkVersion="17" />
<uses-feature
android:name="android.hardware.usb.accessory" android:required="true" />
...
Later I tried lsusb on the device, in a terminal emulator and also in a cron'd script. It showed no devices connected. (I tried disabling USB debugging just in case- still nothing.)
Am I missing some permission for listing usb devices or do I need to configure my desktop to allow the UsbAccessory connection or what? If so, why would that prevent lsusb from showing the computer it's attached to?
The easiest way would be to enable USB tethering on the tablet and then use TCP to connect your client and server.
See https://support.google.com/android/answer/182134?hl=en
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
I have bought a new android 4.0.3 tablet- Micromax Funbook P300 to learn developing android applications.
I started with Wifi Direct, so that the tablet could be used as a remote for robotic platform.
To my disappointment the stock OS doesn't provide this function in the settings menu.
Is it possible to check if we can programatically start wifi direct feature?
If not can someone direct to some tutorials which addresses this?
Thanks.
The Android SDK contains a sample application for using the DirectWiFi mode:
WiFiDirectDemo - Wi-Fi Direct Demo
The used API itself is located in android.net.wifi.p2p
WiFi Direct should be supported by Android 4.0.3 (it has been around since Android API 14, or Android 4.0). It is possible that your tablet does not support WiFi Direct due to a hardware limitation, but I doubt it. You probably aren't seeing it in the settings because there is a custom Android skin running on the tablet that prevents you from seeing it, or maybe the WiFi Direct settings interface wasn't implemented until Android 4.1 or something.
Whatever the case, you can test it easily in the code.
First, put the proper permissions in your manifest.xml
http://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html#permissions
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.nsdchat"
...
<uses-permission
android:required="true"
android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission
android:required="true"
android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission
android:required="true"
android:name="android.permission.INTERNET"/>
...
Next, try initializing the Android WiFiP2pManager class to see if it is supported.
http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.html
public void onCreate(Bundle savedInstanceState) {
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
WifiP2pManager.Channel channel = manager.initialize(this, getMainLooper(), null);
}
Where I put null, you could pass a callback to check for failure. If it works, follow the rest of the Wi-Fi Direct guide to create your app.
He's not asking for a coded program example, so much as a way to programatically switch on the technology (ie one line of code). As far as I am aware there is no way to do this. It all has to be done from within your devices settings. While some devices allow Wi-Fi Direct to be switched on, other devices treat it the same as having regular Wi-Fi enabled - have you tried this? And have you checked if the P300 even supports Wi-Fi Direct?
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
I'm trying to receive data from a multicast address, but the call to MulticastSocket.receive() blocks until a timeout takes place.
I did some network sniffing and found out that my device (and the emulator) never send a MulticastSocket.joinGroup request.
I tried running the same Java code from my PC as a standalone application and it worked well. Could it be that the Android platform blocks IGMP join requests?
Has anyone succeeded with Multicast on Android before?
My manifest file contains the following permission:
I am running my application on 2.1 (Both emulator & device).
Any ideas anyone?
Thanks,
Lukas gives the best explanation and examples that I've seen on his blog: http://codeisland.org/2012/udp-multicast-on-android
In summary:
1. You need the permissions:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
2. You need a lock:
WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi != null){
WifiManager.MulticastLock lock = wifi.createMulticastLock("mylock");
lock.acquire();
}
3. You have to have a device that supports receiving multicast. Or you can follow his work around for rooted devices.
As it seems, there is no proper multicast support in the emulator.
Here's a bug report and related thread. It is being fixed for froyo.
You need to do something like this
WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE );
if(wifi != null)
{
MulticastLock mcLock = wifi.createMulticastLock("mylock");
mcLock.acquire();
}
Reference:
http://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html
I read all 2.1 devices not supporting IGMP stack.
IGMP was missing on different HTC, Samsung, and Motorola devices of all android version from 2.1 up to 3.2.
Link in which i read http://www.programmingmobile.com/2012/01/multicast-and-android-big-headache.html