Obtaining usb cable plugged IN/OUT event using EXT

2019-02-17 05:20发布

My intention is to have saved in Preferences current status of Android device usb/power cable: connected/disconnected. From Developer site I see that there are two Intent for obtaining that status: ACTION_POWER_CONNECTED / DISCONNECTED. So I used same code as published at Developers:

http://developer.android.com/training/monitoring-device-state/battery-monitoring.html

in section Monitor Changes in Charging State.

Manifest

<receiver android:name=".PowerConnectionReceiver">
  <intent-filter>
    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
  </intent-filter>
</receiver>

Java code

public class PowerConnectionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) { 

        int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
        boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

        Toast.makeText(context, "pvr = " + usbCharge + ", " + acCharge + "," + isCharging, Toast.LENGTH_SHORT).show();
    }
}

When I am plugging USB cable IN/OUT than broadcast is always correctly sent and caught in PowerConnectionReceiver but always with same result (=cable is plugged out).

I tested it with Galaxy Nexus 4.1.1 / 4.2.1 - I am always getting 2xFALSE in Toast (chargePlug = FALSE, usbCharge = FALSE).

Why intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) always return default value "-1" ?

Thank you.

ps. everything works fine if I register receiver in Java

Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

...in Service or in Activity. But according to Android Developers site it is not prerequisity to make code above to return correct value;

3条回答
做个烂人
2楼-- · 2019-02-17 06:07

I was dealing with the same problem, coming across your post. I think the issue is that the code, in the Android training page to which you provided a link, is wrong.

ACTION_POWER_CONNECTED and ACTION_POWER_DISCONNECTED aren't "carrying" the data that you're querying from the intent in your code. I couldn't get that same stuff to work on my devices either (1st gen Nexus 7 running Android 4.3 and Nexus One running Android 2.3.6) and, because it seems to not be working anywhere, I come to the "bad code" conclusion.

I fixed it with the following code. It's actually very close to what you've provided as a fix except that it's going into my BroadcastReceiver directly and not into an activity. In your code above, the snippet here would go just before the line beginning "int chargePlug". After that, change "intent" in that same line (your line), beginning "int chargePlug", to "mIntent".

final Intent mIntent = context.getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

Be aware that your BroadcastReceiver will now have two intents. One passed to it, which will be the intent containing the action ACTION_POWER_CONNECTED (or ACTION_POWER_DISCONNECTED), and the other created within the BroadcastReceiver expressly to extract battery information.

The code snippet that I've supplied would not work if you placed it into an activity (it wouldn't connect to your BroadcastReceiver) because of the null in the parameter list. You're not actually registering a BroadcastReceiver with that null. Changing the null to your BroadcastReceiver wouldn't be ideal either since the ACTION_BATTERY_CHANGED notification can trigger A LOT. I'm quite confident that ACTION_BATTERY_CHANGED wasn't intended to be used as a trigger for a BroadcastReceiver. Instead, I think it's meant to be used in real time to get the last "sticky" broadcast with information about a change in battery info (look up "sticky broadcast" in the Android documentation).

Note also that the snippet I've given includes "getApplicationContext()" in the call chain. Take it out and Gingerbread devices will crash (thanks CommonsWare).

查看更多
淡お忘
3楼-- · 2019-02-17 06:08

I'm not sure why you're having problems but what worked for me was registering the for the ACTION_POWER_CONNECTED and ACTION_POWER_DISCONNECTED actions:

<receiver android:name="PowerReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
    </intent-filter>
</receiver>

And implementing the broadcast receiver like this:

public class PowerReceiver extends BroadcastReceiver {

    @Override public void onReceive(Context context, Intent intent) {
        if(intent.getAction() == Intent.ACTION_POWER_CONNECTED) {
            //Handle power connected
        } else if(intent.getAction() == Intent.ACTION_POWER_DISCONNECTED){
            //Handle power disconnected
        }
    }
}
查看更多
成全新的幸福
4楼-- · 2019-02-17 06:16
public class PowerConnectionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final Intent mIntent = context.getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

        int status = mIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;


        int chargePlug = mIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
        boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;

    }
}
查看更多
登录 后发表回答