Manually starting 3G connection in Android, and keeping it on - android

How do you start the 3G data connection in Android at the same time WiFi is on? I tried
IConnectivityManager.setMobileDataEnabled(enabled); // via reflection
and it works in the emulator, but in my real phone (Droid 2), it briefly turns on then back off again.
From the shell (adb shell), ip link provides the details of the 3G connection:
15: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 3 link/ppp
However, it is only available when WiFi is off. When WiFi is on and I try to turn it on manually, it complains the ppp0 device doesn't exist.
bash-3.2# ip link set ppp0 up
ip link set ppp0 up
Cannot find device "ppp0"
When I try to list the device, I can't even find it
bash-3.2# ls /dev/ppp*
ls /dev/ppp*
/dev/ppp

As I understand it's not possible to get 3g and WiFi simultaneously connected without modifying Android platform source code (at least versions 2.3 and 4). The main problem is hardcoded priorities of connections defined in frameworks/base/core/res/res/values/config.xml:
<!-- This string array should be overridden by the device to present a list of network
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
<!-- An Array of "[Connection name],[ConnectivityManager connection type],
[associated radio-type],[priority] -->
<!-- ^^^^^^^^^^---------- Connection priority -->
<string-array translatable="false" name="networkAttributes">
<item>"wifi,1,1,1"</item>
<item>"mobile,0,0,0"</item>
<item>"mobile_mms,2,0,2"</item>
<item>"mobile_supl,3,0,2"</item>
<item>"mobile_hipri,5,0,3"</item>
</string-array>
This config.xml is then read by ConnectivityService which is subscribed to connect/disconnect events. And in connect handler it decides what it should do with other connections:
private void handleConnect(NetworkInfo info) {
//------------8-<--------------------------
// if this is a default net and other default is running
// kill the one not preferred
if (mNetAttributes[type].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
mNetAttributes[mActiveDefaultNetwork].mPriority >
// ^^^^^^^^^ --- From config.xml
mNetAttributes[type].mPriority) ||
// ^^^^^^^^^-------- From config.xml
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
teardown(thisNet);
return;
//------------8-<--------------------------

You could try keeping both active at the same time by modifying your connectivityservice,
but I'd advice against it, since it'll most likely destroy your battery life.
See here if you want to give it a try anyway (and make sure you have a backup, obviously)

If you're trying to connect to a specific machine you can try ConnectivityManager.requestRouteToHost.

Related

Changing Doze mode parameters programmatically

Question about changing the parameters of the transition to doze mode
I have a non-rooted Android 12 device
There are a number of parameters for changing the transition time in doze mode:
inactive_to
motion_inactive_to
light_after_inactive_to
If you change these parameters through the PC using ADB, then the parameters are set. For instance:
adb shell device_config put device_idle inactive_to 2592000000
The problem is that after a reboot, the settings are reset.
Tried to change them directly in the program
// val command = arrayOf("/system/bin/device_config", "put", "device_idle", "motion_inactive_to", "2592000000")
val command = arrayOf("/system/bin/settings", "put", "global", "device_idle_constants", "light_after_inactive_to", "2592000000")
Log.d("ADB", "Start ${command.joinToString(separator = " ")}")
val process = Runtime.getRuntime().exec(command)
val bufReader = BufferedReader(InputStreamReader(process.errorStream))
val log = StringBuilder()
var line: String?
line = bufReader.readLine()
while (line != null) {
log.append(line + "\n")
line = bufReader.readLine()
}
Log.d("ADB", "Command: $log")
But the first command is answered:
“cmd: Can't find service: "device_config"”
And the second command gives an error:
Permission Denial: getCurrentUser() from pid=28435, uid=10245 requires android.permission.INTERACT_ACROSS_USERS
After searching for information about the INTERACT_ACROSS_USERS permission, I understand that it is necessary for it to make the application system. And for this I need to root the device.
Is there any other way to change the parameters of doze mode or disable it altogether?
It's confusing that you can run a command with adb on a non-rooted device, but you can't directly in the program.
Is there any other way to change the parameters of doze mode or disable it altogether?
No. If there were, it would have been pointless to add Doze mode, as every developer would opt out of it.
It's confusing that you can run a command with adb on a non-rooted device, but you can't directly in the program.
Different users/processes having different privileges has been a common concept in operating systems for at least 30 years.

Connecting to WiFi network automatically in Android 5 and 6

Been struggling with connecting to WiFi network in Android 5 and 6 for a while and other similar questions don't seem to work for me. I could get the same code working in Android 4.4.2
Adding the code snippet below.
String networkSSID = getSsid();
String networkPass = getNetworkPass();
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";
conf.status = WifiConfiguration.Status.ENABLED;
conf.priority = 40;
conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
conf.preSharedKey = "\""+ networkPass +"\"";
int value = mWifiManager.addNetwork(conf);
Log.i(TAG_CHECK, "Connecting to : " + value);
boolean enabled = mWifiManager.enableNetwork(value, true);
Log.i(TAG_CHECK, "enabled to : " + enabled);
mWifiManager.reconnect();
And here is what I noticed.
mWifiManager.addNetwork(conf)
returns some (+) integer with Android 5(phone) and Android 6(tab).
But both don't connect unless I open the wifi settings (I don't have to do anything and just landing there connects) or I manually turn off and turn on Wifi from the top bar to automatically connect.
The listeners to detect connection to the network are in tact for both the versions to precisely know when the connection get established - confirming the above behaviour. Have attached a pic of the permissions granted below.
Any pointers as to what I am missing?
EDIT: Upon digging into WifiManager class, looks like the Access Point remains in WIFI_AP_STATE_DISABLED state. I should also highlight that everything worked as expected while trying on a different Android M phone.
EDIT2
I have the following observations.
1. The issue so far is specific to 1 android 6.0.1 Samsung tablet and 1 android 5.0.2 Micromax phone. It works just fine on 3 other android 6.0.1 phones, 1 android N phone and Android 4.4.2 phone.
2. The access point ends up in wifi_ap_disabled state in the problematic cases consistently. Both addNetwork and enableNetwork calls are affirmative.
3. These access points are not that of a router wifi but that of other phones that broadcast. The problematic phones can programatically connect to wifi hotspots (setup manually and not in the programatic way as I would like to) without any issue.
4. Mobile data enabled/disabled state or wifi state with a different connected network doesn't change the dynamics for both working and problematic phones.
This makes me think that it is a combination of phones/tabs (and not OS) and the access point broadcast configuration. Do you think I should be playing around with some config parameters?
Edit 3 - Important Update
So the wifimanager is obtained like below
WifiManager mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
I instantiate mWifiManager in a service (inside onCreate method) and use that later to scan and connect with inputs from front-end activity. While it doesn't work in the way as described earlier, using the same snippet seems to work when the enableNetwork call is done right in the onCreate method - working just as expected. It also works fine when called from front-end activity but only when I don't instantiate mWifiManager in the service.
Though I would expect only one reference to a system service - WifiManager i.e, I think the subsequent usage of that reference (or a different reference to WifiManager) gets a lower priority (or gets deprioritized by the previous reference) and hence doesn't get completely executed leaving the access point in disabled state and requiring manual intervention to help complete the execution by WifiManager and other wifi system services.
Also, I notice the same in Android 5.0.2 phone, the asynchronous enableNetwork does get executed, but it takes some time to execute it.
My questions
1. It is no more a question about the correctness of the code. Services in general have lesser priority compared to front-end threads So, is there is way I could prioritise the enableNetwork call so that it gets immediately executed?
2. What happens in case of multiple references to WifiManager?
I believe if you add a disconnect() it will do what you want. I've added a check here because addNetwork() can fail to add your network. For Android 6.0+, you can't add a network if it exists already but if this fails you can try getting the network id then connecting. (For instance, it will be there if added (and saved) if you re-install) I also do not add quotes to SSID in Lollipop (ver 21)+.
int value = mWifiManager.addNetwork(conf);
// need to check the result if successful
if (value == -1) {
return; // network not added successfully
}
Log.i(TAG_CHECK, "Connecting to : " + value);
mWifiManager.disconnect(); // add a disconnect
boolean enabled = mWifiManager.enableNetwork(value, true);
Log.i(TAG_CHECK, "enabled to : " + enabled);
mWifiManager.reconnect();

Can I turn on WiFi-Direct from code? on API-16 (Android 4.2.2)

I am developing an application with NFC and wifi direct. I get the MAC address using NFC and the Wifi Direct to transfer data. I call discoverpeers() and could get success. But there is no callback WIFI_P2P_PEERS_CHANGED_ACTION, the callback comes only when I go to settings and the select wifidirect.
This was discussed in the other question
Can I turn on WiFi-Direct from code? on Android API-14 (ICS)
"I'd like to add that WiFi direct on JB and above (at least on AOSP) is not active all the time - it only appears to be. If you look at listeners for WiFi direct, it turns itself off after some time. It turns itself back on if you open the wifi direct menu, however. You might have to have the host do a peer search or initialize itself in order to be able to be found. Likely a battery saving trick. I have also found that it's blocking, since as it accepts a connection, the entire system will lock up and fail to connect sometimes. (The system invitation) – Mgamerz "
Can anyone suggest the solution for the problem WIFI_P2P_PEERS_CHANGED_ACTION callback is not got and can get only when manually go to settings->wifi->tap on wifidirect
I used two devices Samsung galaxy nexus and nexus 7 both running on 4.2.2
There is no available API to enable wifiP2P but you can invoke method "enableP2p" from android settings 4.0.1
WifiP2pManager manager = (WifiP2pManager) getActivity().getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(getActivity(), getActivity().getMainLooper(), null);
try {
Method method1 = manager.getClass().getMethod("enableP2p", Channel.class);
method1.invoke(manager, channel);
//Toast.makeText(getActivity(), "method found",
// Toast.LENGTH_SHORT).show();
} catch (Exception e) {
//Toast.makeText(getActivity(), "method did not found",
// Toast.LENGTH_SHORT).show();
}
To disable wifiP2P use this method
Method method1 = manager.getClass().getMethod("disableP2p", Channel.class);
Not from code. The user has to. That's why the demo has the link to wifi settings in the action bar.
When you call manager.discoverPeers(channel, new WifiP2pManager.ActionListener()
define onFailure and look at the reasonCode. If it's 0, then either the Wifi or WiFi direct is off.
If you look at the WiFi Direct demo app, the WifiDirectBroadcast Reciever, this piece of code looks at whether p2p is enabled specifically
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
// UI update to indicate wifi p2p status.
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
// Wifi Direct mode is enabled
activity.setIsWifiP2pEnabled(true);
} else {
activity.setIsWifiP2pEnabled(false);
activity.resetData();
}
Then when discover peers is called it looks at the variable set by setIsWifiP2pEnabled
thanks user3093354. to continue with your solution, in order to disable the p2p you have to invoke:
Method method1 = manager.getClass().getMethod("disableP2p", Channel.class);
//Try this it may be help you
WifiManager wifiManager = (WifiManager)this.getSystemService(this.WIFI_SERVICE);
wifiManager.setWifiEnabled(true); //True - to enable WIFI connectivity .
//False -disable WIFI connectivity.
//add this permissions in Manifest file :
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
You can load the wifi driver from a command prompt with the desired concurrency level if you are rooted:
/system/bin/insmod /system/lib/modules/wlan.ko con_mode=3
These are the values:
typedef enum
{
VOS_STA_MODE=0,
VOS_STA_SAP_MODE=1,
VOS_P2P_CLIENT_MODE,
VOS_P2P_GO_MODE,
VOS_MONITOR_MODE,
VOS_FTM_MODE = 5,
VOS_IBSS_MODE,
VOS_P2P_DEVICE_MODE,
VOS_MAX_NO_OF_MODE
} tVOS_CON_MODE;
This is for an Atheros card.

Android DHCP enabled disabled check

I wanted to know if there is any way to check programmatically in android phone whether DHCP is enabled or disabled. (Assuming its possible to disable DHCP through some way or dhcpd is not running)
You can do the following to know if Android is currently using static IP adresses or DHCP attributed ones :
try {
if ( Settings.System.getInt(getContentResolver(),
Settings.System.WIFI_USE_STATIC_IP) == 0 )
/* Static ip addresses mode is not enabled */
;
} catch (SettingNotFoundException e) {
/* Do something smart here */
}
However, note that this method seems now deprecated and that it does not work across all devices (AVD for example).

USB_DEVICE_ATTACHED Intent not firing

Has anyone out there been able to get the android.hardware.usb.action.USB_DEVICE_ATTACHED" to work?
Ok so i'm trying to use the new usb host mode features to detect when a usb device is attached. For my purposes i want to be notified any time a device is attached. I was not able to see it happen. I'm using a broadcast reciever that i know works (when i have it listen for other things such as the home button being pressed. No matter what i try i can't seem to get the intent to fire.... So to make things simpler i decided to forget about my project and attempt to use google's own sample code and see if i could at least make that work. I don't have one of the missle launcher but i figured i could at least get it the USB_Device_Attached to fire. No go. I adapted the code to work for other devices. First i tried adjusting the device filter xml.
I added my device (a keyboard):
<usb-device vendor-id="1050" product-id="0010" />
I got the vendor and product from an lsusb command. When the device is attached the logcat shows that the device is found
D/EventHub( 144): No input device configuration file found for device 'Yubico Yubico Yubikey II'.
I/EventHub( 144): New device: id=43, fd=219, path='/dev/input/event8', name='Yubico Yubico Yubikey II', classes=0x80000003, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false
I/InputReader( 144): Device added: id=43, name='Yubico Yubico Yubikey II', sources=0x00000101
I/ActivityManager( 144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=2/1/1 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=47}
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN
I/EventHub( 144): Removed device: path=/dev/input/event8 name=Yubico Yubico Yubikey II id=43 fd=219 classes=0x80000003
I/InputReader( 144): Device removed: id=43, name='Yubico Yubico Yubikey II', sources=0x00000101
I/ActivityManager( 144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=48}
D/dalvikvm( 144): GC_EXPLICIT freed 78K, 26% free 14717K/19719K, paused 3ms+3ms
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN
The xoom does find the keyboard and it is usable from the device (i can use it in the browser to type letters). And the intent sort of fires (but it only fires the android.intent.action.MAIN) i don't ever get the DEVICE_ATTACHED Intent. The log entry comes from the sample code:
Log.d(TAG, "intent: " + intent.getAction().toString());
In the resume function. After more digging and removing any reference to usb i found that every app i make get's the resume called when a keyboard is attached/detached (hence the intent: android.intent.action.MAIN log entry).
Right now the only thing i can figure is that it's a bug in the android source.
By the way i'm using a wifi xoom with os 3.1.
I also had the same problem. I finally figured out that in the device filter xml we should add following line.
<usb-device vendor-id-"xxxxx" product-id="yyyyy">
the xxxxx and yyyyy should be decimal numbers. NOT HEX CODES. Then it all works as advertised!
I know it is late but I hope it helps.
So I found a solution to my problem and I've learned a lot hopefully it can help someone else.
So first off HID devices do not kick off any intent. Nor do they show up in the mUsbManager.getDeviceList() list. Other things however do. I gave a usb memory stick a go and what do you know the device is listed in the device list. I also found out that the device returned does not have the a class,subclass, or protocol. Debugging revealed that the parent interface did however have the proper class/subclass/and protocol.
Also if you must have a device filter. I ended up with a class=0008 (USB STORAGE) to work for my purposes. I'm guessing other classes would work as well.
So now on to figuring out intents. Turns out that the intent must be attached to a launcher activity. My attempts to attach it to a service or receiver will not bear any fruits. So now that I'm getting intents to fire I now see notifications popup when I attach my device (usb memory stick) it asks me to set my app as the default for that device. Perfect now my app gets run every time I attach that device. Note that you will be prompted for each unique device. But only once. It seems to be registered much like default programs.
Well, I think that about sums up what I found. too bad you can't get notified when an keyboard/mouse gets attached. Oh and one more thing. There are not any problems with the tiamat kernel, running it right now and no problems.
I recently discovered a solution to a similar issue.
As someone has already noted, HID devices do not kick off an intent, which I think was your issue.
However, a related issue is that, if your program is set to run when a USB device is connected, then even once your application is running, you can't capture the USB_DEVICE_ATTACHED action. Instead, the system sees that intent, and says "oh that means this application wants to run (as declared in your manifest) and then it sends you the android.intent.action.MAIN action instead of the USB_DEVICE_ATTACHED action, and it calls onResume(). Even if your app is running. So as far as I can tell, you CAN'T capture the USB_DEVICE_ATTACHED intent if your manifest declares that your app will run when USB devices are attached. You just have to put some code in onResume() to check to see if USB is connected. Even if your program is running, onResume will get called again when a USB device is attached.
I note my solution in more detail here: Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED
Enumerating devices
If your application is interested in inspecting all of the USB devices currently connected while your application is running, it can enumerate devices on the bus. Use the getDeviceList() method to get a hash map of all the USB devices that are connected. The hash map is keyed by the USB device's name if you want to obtain a device from the map.
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
If desired, you can also just obtain an iterator from the hash map and process each device one by one:
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next()
//your code
}
I had the same problem. My ultimate solution was to use the old fashioned polling technique. Here is a fairly minimal class which solves the problem to my satisfaction.
package com.YourCompancy.YourProduct;
import android.app.*;
import android.content.*;
import android.hardware.usb.*;
import java.util.*;
import android.util.*;
import android.os.*;
public class UsbDeviceWatcher extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED))
{
UsbDevice d = (UsbDevice)
intent.getExtras().get(UsbManager.EXTRA_DEVICE);
DeviceConnect(d, false);
}
}
public void DeviceConnect(UsbDevice device, boolean Attached)
{
if (Attached)
{
// Some suggestions ...
// play sound effect
// notify consumer software
// determine if interested in device
// etc
Log.i("usb", "device attached");
} else
{
Log.i("usb", "device detached");
}
}
public UsbManager manager;
public Handler handler;
public UsbDeviceWatcher(Context context, Handler handle)
{
this.handler = handle;
manager = (UsbManager)
context.getSystemService(Context.USB_SERVICE);
IntentFilter dev = new IntentFilter();
dev.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
context.registerReceiver(this, dev);
final UsbDeviceWatcher _this = this;
Thread thread = new Thread(new Runnable()
{
public void run()
{
LinkedList<UsbDevice> seen = new LinkedList<UsbDevice>();
LinkedList<UsbDevice> attached = new LinkedList<UsbDevice>();
//there is a need for multithread support here
// so the thread can watch for an exit condition
while (true)
{
HashMap<String, UsbDevice>
D = manager.getDeviceList();
for (UsbDevice d : D.values())
{
if (!seen.contains(d))
{
if (!attached.contains(d))
{
final UsbDevice dev = d;
handler.post(new Runnable(){
public void run()
{
DeviceConnect(dev, true);
}
});
}
seen.add(d);
}
}
for (UsbDevice d : seen)
{
if (!D.values().contains(d)) seen.remove(d);
}
try
{
Thread.sleep(500);
} catch (InterruptedException exception)
{
return;
}
}
}
});
thread.start();
}
}
Another workaround is to use
new FileObserver("/dev/input") {
#Override public void onEvent(int event, String path) {
//gets called on input device insert / remove
}
};
which will work for some usb devices (keyboard, mouse)
I have my app set as launchMode="singleTop" and in that mode it seems like the getIntent().getAction() is always equal to the action that first started the app.
So if you start the app manually and then plug in a device (even after switching away from that app), you will receive android.intent.action.MAIN.
If you kill the app and then plug in the device, you will always get android.hardware.usb.action.USB_DEVICE_ATTACHED, even from switching away and back to your app, or even for rotating the device.
I actually weirdly receive intents when unplugging the USB device, which I don't think is documented - but of course I receive USB_DEVICE_ATTACHED when my device is detached.
Without singleTop, it does kind of work as expected, but then you get another stupid extra activity if your app is already open and you plug in the device.
Once again Android's API is buggy, overly complicated and difficult to use.
OK more work, more failure, but some progress.
I found out more from the sdk documentation. it appears that you have to have the device filter in order to use the intents. so I decided to try using a class filter instead of the vendor/product ids. I figure that it would be more general and hopefully catch the hid device. I used 03h as the class id , I tried various formats, I tried the subclasses, I even used lsusb to discover, class, subclass, and protocol of my device. these didn't seem to help at all. so I went further in to the sdk documentation and decided to try enumerating all of the devices to see what the os saw the class/subclass/protocol integers. I copied the code pasted it into the click listener and adding log.v statements. nothing shows in the logcat .
it looks, like the us system isn't seeing any device (even though the device actually works.) now this is very indicitive of the USB device connected intent not firing. now I must say that I am using a custom kernel in my xoom (tiamat). I thought this might have something to do with the problem a while ago, so I reverted to stock 3.1. and still now progress. now this was a while ago, before I tried enumerating, so now I will revert agaian and keep working with stock until I am sure the kernel is not the issue. I'll check back In when I found out more. success or failure. ofcourse if anyone else unterstands this better than me please chime in.
one last note I'm a big worried about the whole otg host mode when I saw this in the documentation.. notice that the coe is identical even thought it references two methods of enumeration. probably just a copy writers mistake, but still worry some in light of all this failure.
This is what I did to detect USB/Media Connect.
Manifest file
<receiver
android:name=".UsbReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<data android:scheme="file"/>
</intent-filter>
</receiver>
I didn't do anything in the activity nor my receiver.
looks like this line is doing the stuff.
<data android:scheme="file"/>
Connect Usb Keyboard WONT fire USB_DEVICE_ATTACHED.
Instead, the System will fire Intent.ACTION_CONFIGURATION_CHANGED. However, as there is a configuration change, system will restart the Activity. You wont catch the action with the Activity restarted. In this case, you need to add android:configChanges="keyboard|keyboardHidden" in your Android Manifest so that the Activity wont be restarted once a external keyboard is connected.
From my testing, Android can fire an intent when an HID device is connected. (The MissileLauncher sample application does just that. See the sample source code for more info.)
The Missile Launcher (Dream Cheeky USB Missle Launcher) HID Device has its subclass and protocol set to 0x00. For more info see: http://www.mattcutts.com/blog/playing-with-a-usb-missile-launcher/
The caveat is that Android does not throw an intent for mouse and keyboard devices specifically (maybe more). I can however detect HID devices that have their InterfaceClass = 0x03, InterfaceSubClass = 0x00, InterfaceProtocol = 0x00. For my application, my HID device is an embedded controller so setting the subclass and protocol is not an issue.

Categories

Resources