I am developing an application that communicates with an Embedded Device via the Android Devices USB Host port. I noticed that when the screen is locked USB Host port is disabled and no communication occurs.
How can I prevent the USB Host port from turning off so that communication can occur when the screen is locked?
------------- USB Host ---------------
| Android | <------------------> | Device |
------------- ---------------
Note: I can have root access on the Android system if necessary.
Thanks for the tip Chris Stratton. Using a PARTIAL_WAKE_LOCK the screen can turn off yet the CPU remains running. This is suitable for my application.
I created a quick app to test this:
public class MainActivity extends Activity {
PowerManager pm;
PowerManager.WakeLock wl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
}
#Override
protected void onStart() {
super.onStart();
if (wl != null) {
wl.acquire();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (wl != null) {
wl.release();
}
}
I tested it by connecting a mouse to the USB Host. When the screen was locked the mouse did not turn off as I would like.
Another option I came across which I have not tried. You may be able to adjust the system resource which controls the power management of the USB device. You probably need root access for this.
Changing the default idle-delay time
------------------------------------
The default autosuspend idle-delay time (in seconds) is controlled by
a module parameter in usbcore. You can specify the value when usbcore
is loaded. For example, to set it to 5 seconds instead of 2 you would
do:
modprobe usbcore autosuspend=5
Equivalently, you could add to a configuration file in /etc/modprobe.d
a line saying:
options usbcore autosuspend=5
Some distributions load the usbcore module very early during the boot
process, by means of a program or script running from an initramfs
image. To alter the parameter value you would have to rebuild that
image.
If usbcore is compiled into the kernel rather than built as a loadable
module, you can add
usbcore.autosuspend=5
to the kernel's boot command line.
Finally, the parameter value can be changed while the system is
running. If you do:
echo 5 >/sys/module/usbcore/parameters/autosuspend
then each new USB device will have its autosuspend idle-delay
initialized to 5. (The idle-delay values for already existing devices
will not be affected.)
Setting the initial default idle-delay to -1 will prevent any
autosuspend of any USB device. This has the benefit of allowing you
then to enable autosuspend for selected devices.
Source:
https://android.googlesource.com/kernel/common/+/android-3.10/Documentation/usb/power-management.txt
Related
We have written a test app to try and debug a issue with a 3rd party by reproducing the issues with our own source code.
The app has a feature to allow us to set times for when the devices switches off then on. This is to comply with green power saving policies.
The app switches the device off fine, but on switch on, we hear a 'click' at the expected time, but the display remains off. We wrote a test app and found this works well on other Android devices, but on the problem device we get the same - just the sound of the power relay clicking on, but nothing else.
We are wondering if this is something to do with a system setting on the devices that controls this behaviour.
The code to switch on is as follows:
public void wakeupTimer(){
new CountDownTimer(wakeupTime * 1000, 1000) {
public void onTick(long millisUntilFinished) {
textTimer.setText("0:"+checkDigit(wakeupTime));
wakeupTime--;
}
public void onFinish() {
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(( PowerManager.FULL_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE
| PowerManager.ACQUIRE_CAUSES_WAKEUP), "commandandcontrol:TAG");
wakeLock.acquire();
finish();
}
}.start();
}
I'm building an Android media player application that I intend to use to play media (videos, pictures, etc.) on a TV while connected via an HDMI cable.
I want to have the media player app pause when the TV's power status is OFF and want it to play when the TV is turned ON.
How do I detect the TV's power status within my Android application when my Android device is connected to the TV via HDMI?
Both the TV and the Android device have support for HDMI-CEC. The device in question is an ODROID C2. I've seen this functionality on the KODI Android application which has a feature to pause the video when the HDMI-CEC status is OFF, I'm looking to implement this within my app as well.
Any help is appreciated. Thanks in advance!
EDIT: Progress below
I tried reading the status of the HDMI connection from within this file /sys/devices/virtual/switch/hdmi/state. However, this file holds int 1 no matter whether the power status of the connected screen / TV is ON or OFF.
2nd Progress update
I'm still working on this. Will not give up, and once I'm done I will surely post the answer here.
You can listen for changes in HDMI status (0 for unplugged and 1 for plugged) by registering for ACTION_HDMI_AUDIO_PLUG. It reports with status 0 when tv is switched off, switches to any other display medium or HDMI is removed. To read into its technicality, you can check out how hot plug detection works in HDMI. Overall, your app can at all times monitor whether the display can currently play your content or not. I have myself implemented this in a solution (on X96 mini android box & amazon fire-stick) where I needed to ensure that the content was actually being played because it included paid content. Also, I have attached the sample code file.
Note: This solution will only work when android device is HDMI source not sink!
Here's the documentation link too- https://developer.android.com/reference/android/media/AudioManager#ACTION_HDMI_AUDIO_PLUG
private BroadcastReceiver eventReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// pause video
String action = intent.getAction();
switch (action) {
case ACTION_HDMI_AUDIO_PLUG :
// EXTRA_AUDIO_PLUG_STATE: 0 - UNPLUG, 1 - PLUG
Toast.makeText(getApplicationContext(),"HDMI PLUGGED OR UNPLUGGED",Toast.LENGTH_LONG).show();
Log.d("MainActivity", "ACTION_HDMI_AUDIO_PLUG " + intent.getIntExtra(EXTRA_AUDIO_PLUG_STATE, -1));
((TextView)(findViewById(R.id.textView))).setText(((TextView)(findViewById(R.id.textView))).getText().toString().concat("At "+System.nanoTime()+": "+intent.getIntExtra(EXTRA_AUDIO_PLUG_STATE, -1) +"\n"));
break;
}
}
};
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(eventReceiver);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_HDMI_AUDIO_PLUG);
registerReceiver(eventReceiver, filter);
}
In Some TV's, You need to monitor that (sys/class/amhdmitx/amhdmitx0/hpd_state) folder for changes by 500 ms Interval. because it'll change from 1 to 0 and again from 0 to 1 within 1 seconds.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 3 years ago.
Improve this question
I'm Developing an Android Application where it requireds 3 things:-
To keep the App up an running for specific time and then phone will be off (Working Fine)
When phone get charging from outlet, I want phone to power up automatically without hitting any power button. (Not Working with wall Socket, but working when connected to USB cable via Laptop).
After boot my app should start working Automatically (Working Fine)
You Must know :-
My phone is Moto E (rooted) and want 2nd step to be done. Tried some codes but that does not work on moto E.
When Connected with USB it gives 2 as response and when connected with Wall socket charger it says 1
Any help will be Appreciated
P.S :- Auto Boot working with USB cable connected with Laptop but not with Socket Charger
Update-1: 1- Found fastboot oem off-mode-charge 0 working with Nexus 7 but not on Moto e.
2- Moto e boots when connected to Router (USB Dongle Port)
At last I got the solution, you can achieve this by deleting system/bin/charge_only_mode file. Please do that at your own risk and before deleting have backup of that file. I got the desired result that was boot when its connected to wall charger and now its working fine.
All the best!
Moto e4 and Pixel 2 XL:
Get your device into the bootloader (fastboot) and run the following command from a computer connected over USB with Android Tools:
fastboot oem off-mode-charge 0
I was able to get it to work by updating the init.rc file
I found the on charger trigger and added the following lines below it:
setprop ro.bootmode "normal"
setprop sys.powerctl "reboot"
The entire trigger block ends up looking like this
on charger
class_start charger
setprop ro.bootmode "normal"
setprop sys.powerctl "reboot"
You then need to repack and flash the boot image created after the updates.
Connect the device over USB
Power on device and get to bootloader mode
adb reboot bootloader
To flash boot image execute the following command while in fastboot
fastboot flash boot new-boot.img
Note: This fix will cause the device to reboot when its plugged in even when shutting it off using the power button or software shutdown.
Source: https://forum.xda-developers.com/showthread.php?p=77766638#post77766638
You can see the commit that contains these changes for my project here:
https://github.com/darran-kelinske-fivestars/mkbootimg_tools/commit/c8633a2ec2e1924272fd16a8ed7fa7414bb65544#diff-d0007d763b44198f7c22e2c19609d5bbR606
I also tried replacing charge_only_mode with a sh script that rebooted the phone but only got a red circle with the M (on a Motorola Bionic). Changing the script to the below got it working...Now I get the red circle with the M for a few seconds, then a blank screen, the another red circle with the M, and it boots on up.
#!/system/bin/sh
su -c "/system/bin/reboot -n outofcharge"
On my device Lenovo K7000-Plus, the file need to be modified is kpoc_charger located at /system/bin.
Ipod file not working on my phone which using Android 6.0 ROM, but kpoc_charger works pefectly.
Regards
Hadi
For Lenovo A2010 phone,following worked:
Use file manager phone app from playstore like Total commander(on rooted phone) to goto folder /system/bin/
Copy file kpoc_charger and paste it there as kpoc_charger.bak
Now edit the original file kpoc_charger using total-commander, replace all lines with following code:
#!/system/bin/sh
/system/bin/reboot
Save it, goto properties and change UID:0 root, GID:2000 shell and permission as 755 (same as properties of other files in /system/bin folder).
Now shutdown phone and plug to charger.
Bazinga!!!! battery icon shows for a sec but phone sucessfully boots into os.
When phone get charging from outlet, I want phone to power up
automatically without hitting any power button. (Not Working with wall
Socket, but working when connected to USB cable via Laptop).
You can only achieve this by modifying your phone's OS files. Basically there is boot script/binary at /system/bin/chargemon which you can replace with a script that does nothing. Do it at your own risk because this may result in the device being damaged permanently. Also, Manufacturer warranty will become void.
I found another way for this (thanks to DavidThompson256 http://forum.xda-developers.com/showthread.php?t=1187631)
First make sure your phone is rooted (which I found iRoot very good for this), then install RootExplorer.apk (or similar) on your phone.
Try to edit "/system/bin/playlpm" and replace its content with following commands: (do not forget to make a backup first).
#!/system/bin/sh
/system/bin/reboot
(I know the content is in binary, simply remove them and write those two lines and save the file)
NOTE: When you modify that file, no changes will be applied on its permissions but if you are making another file remember to set permissions exactly as it was.
Finally, please do it on your own risk. It worked for me. (Samsung Discovery S730M)
i think there should be power sensor if you can add that in this code i belive it will work
public class Main extends Activity {
private SensorManager mSensorManager;
private PowerManager mPowerManager;
private WindowManager mWindowManager;
private WakeLock mWakeLock;
private Button button;
private TextView textView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
// Get an instance of the SensorManager
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Get an instance of the PowerManager
mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
// Get an instance of the WindowManager
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.getDefaultDisplay();
// Create a bright wake lock
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass()
.getName());
setContentView(R.layout.main);
textView = (TextView)findViewById(R.id.textView1);
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(mButtonStopListener);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("onCreate", e.getMessage());
}
} // END onCreate
View.OnClickListener mButtonStopListener = new OnClickListener() {
public void onClick(View v) {
try {
mWakeLock.release();
textView.setText("mWakeLock.release()");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("onPause",e.getMessage());
}
}
};
#Override
protected void onResume() {
super.onResume();
/*
* when the activity is resumed, we acquire a wake-lock so that the
* screen stays on, since the user will likely not be fiddling with the
* screen or buttons.
*/
try {
mWakeLock.acquire();
textView.setText("mWakeLock.acquire()");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("onResume", e.getMessage());
}
}
#Override
protected void onPause() {
super.onPause();
// and release our wake-lock
try {
mWakeLock.release();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("onPause",e.getMessage());
}
}
}
So I was trying to achieve this with a 3rd gen Moto G. It has a charge_only_mode file as per Rohit's answer, but simply moving/renaming it did not make the phone reboot on charge. Instead it just sat there with a Motorola logo. I got the same result when replacing charge_only_mode with either of the scripts referenced here.
I did get it to work, however. I copied /system/bin/reboot into /system/bin/charge_only_mode, and that did the trick.
Android v4.2.2. I'm trying to stop the screen from going to sleep. I've tried a few things like changing the relevant settings in the db:
adb shell "sqlite3 /data/data/com.android.providers.settings/databases/settings.db \"update system set value='-1' where name='screen_off_timeout'\";"
But that didn't work - screen just went to sleep almost immediately. If I go to the settings app there isn't an option to disable it. Instead, it ranges from 15s to 30m.
I have also tried to set the KEEP_SCREEN_ON FLAG in the application but that stops working when I switch to a new activity.
Is there anything else I can try. I was hoping a db setting would do the job. Here is my system db as it stands. Perhaps a setting I am missing and can insert?
1|volume_music|11
2|volume_ring|5
3|volume_system|7
4|volume_voice|4
5|volume_alarm|6
6|volume_notification|5
7|volume_bluetooth_sco|7
8|mode_ringer_streams_affected|174
9|mute_streams_affected|46
10|vibrate_when_ringing|0
11|dim_screen|0
13|dtmf_tone_type|0
14|hearing_aid|0
15|tty_mode|0
16|screen_brightness|102
17|screen_brightness_mode|0
18|window_animation_scale|1.0
19|transition_animation_scale|1.0
20|accelerometer_rotation|1
21|haptic_feedback_enabled|1
22|notification_light_pulse|1
23|dtmf_tone|1
24|sound_effects_enabled|1
26|lockscreen_sounds_enabled|1
27|pointer_speed|0
28|next_alarm_formatted|
29|alarm_alert|content://media/internal/audio/media/5
30|notification_sound|content://media/internal/audio/media/7
31|ringtone|content://media/internal/audio/media/9
32|volume_music_headset|10
33|volume_music_last_audible_headset|10
34|volume_music_headphone|10
35|volume_music_last_audible_headphone|10
36|time_12_24|24
37|date_format|dd-MM-yyyy
39|stay_on_while_plugged_in|1
45|screen_off_timeout|-1
Your setting db contains default time out set by the system which is probably low so the device went to sleep immediately due to low timeout value. You can issue adb shell command to increase screen timeout.
adb shell settings put system screen_off_timeout 60000
Note: 60000 = 1 minute
You can also update setting db with the desired timeout and then push db back to device but it requires root. Above command does not require device to be rooted.
This is related to Activity , There is no impact from DB. Just add android:keepScreenOn="true" to the layout in your xml
Did you try this
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
For more go through this link http://thiranjith.com/2012/02/22/android-prevent-screen-timeout/
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.