I have an dashcam which automatically starts and stops recording based on charging (start on charging and stop when it stops charging)
So I have something like this at the BroadcastReceiver.onReceive
Intent.ACTION_POWER_CONNECTED -> {
startRecording()
}
Intent.ACTION_POWER_DISCONNECTED -> {
stopRecording()
}
Some users reported that recording stops when their device becomes fully charged though it is still plugged to a power source via USB.
So it seems BatteryManager sends the event that the power is not connected.
What can I do in this case to know for sure that it is still plugged to a source power?
Mb should I use the following solution?
Intent.ACTION_BATTERY_CHANGED -> {
val plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0
// conditionally it looks like this: if (plugged) startRec() else stopRec()
}
Related
How to check if a device running Android has a speaker on it or not? Meaning is it able to play audio?
Are there any Configuration qualifiers for it? and what about programmatically
EDIT: just bought an Android Wear watch and it does NOT have a speaker so not sure how I would check this
Since API level 21 (most Android Wear based on this level), Android provide a feature, PackageManager.FEATURE_AUDIO_OUTPUT, witch can be used to detect whether there is a way to output the audio.
I tested this feature on my MOTO 360 (no speaker), it don't has this feature, and Ticwatch (with speaker) do have this feature.
But when I connected a Bluetooth headset to the MOTO 360, it still don't have this feature, this confused me.
So I use AudioManager.isBluetoothA2dpOn() for further check.
The detection code can be like this:
public boolean hasAudioOutput() {
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
PackageManager packageManager = getPackageManager();
if (audioManager.isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
return true;
} else if (audioManager.isBluetoothScoOn()) {
// Adjust output for Bluetooth of sco.
return true;
} else if (audioManager.isWiredHeadsetOn()) {
// Adjust output for headsets
return true;
} else if (audioManager.isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
return true;
} else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Has internal speaker or other form of audio output.
return true;
} else {
// No device for audio output.
return false;
}
}
Android API doesn't have any such qualifiers neither there is any library method.
But just a raw idea, try playing some audio and simultaneously record through the mic.
Check if they are same.
This is not a fool proof way, but just a thought!
Probably most android phones have a speaker i guess :P /.. But if you are asking if you can check whether its connected to a speaker or headphones or something like that..then you can use
if (isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
// Adjust output for headsets
} else {
// If audio plays and noone can hear it, is it still playing?
}
SOURCE: http://developer.android.com/training/managing-audio/audio-output.html#CheckHardware
I am currently trying to make a reliable way to determine a specific charger type, in my case a music dock like this. The problem is that this dock unfortunately does not send a dock event when docked.
Since I am making an app relying on being able to determine when the device has been docked or undocked. I therefore need a way to filter out and separate these events:
Device is charging through the USB connector(no separate charger)
Device is not connected to a computer
Some sort of way to separate the slow charging dock from a standard charger
I have noticed that my device (LG optimus 4x HD) manages to react differently for every one of these actions. When it is connected to a standard charger it gives no notification message, when it is connected to a computer it tells me USB mode has been activated, and when it is connected to the dock it gives me a slow charger warning.
I need to make a system with the same ability to separate these actions and react to them. Until now I have only made a simple BroadcastReceiver that reacts if the device is connected or unconnected to a charger. I have also managed to monitor the charging state using the code found in the documentation.
Is there any way of determine this specific charger input?
Whenever the device is docked or undocked, the ACTION_DOCK_EVENT action is broadcast. To monitor changes in the device's dock-state, simply register a broadcast receiver in your application manifest as shown in the snippet below:
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
If a device is docked, it can be docked in any one of four different type of dock:
Car
Desk
Low-End (Analog) Desk
High-End (Digital) Desk
The dock-state details are included as an extra in a sticky broadcast of the ACTION_DOCK_EVENT action. Because it's sticky, you don't need to register a BroadcastReceiver. You can simply call registerReceiver() passing in null as the broadcast receiver as shown in the next snippet.
IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
Intent dockStatus = context.registerReceiver(null, ifilter);
You can extract the current docking status from the EXTRA_DOCK_STATE extra:
int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
You can find the dock state by
boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
dockState == EXTRA_DOCK_STATE_LE_DESK ||
dockState == EXTRA_DOCK_STATE_HE_DESK;
EDIT :
If your app still not receiving the broadcast try this code to sent manual broadcast and check the code :
adb shell am broadcast -a android.intent.action.POWER_CONNECTED -n com.jm.monitoringbatterydemo/.PowerConnectionReceiver
Change the name of the broadcast and your receiver.
What you can do to solve this problem is look at the % of battery left on your phone. You can then determine that the value is going up, which means it is docked. Only problem with this could be that if you sometimes charge it on a regular charger rather than a dock, you'd still have it respond as if it were one.
More info on reading battery level etc: http://developer.android.com/training/monitoring-device-state/battery-monitoring.html
Would it be helpful to identify the power source using
int BATTERY_PLUGGED_AC Power source is an AC charger.
int BATTERY_PLUGGED_USB Power source is a USB port.
int BATTERY_PLUGGED_WIRELESS Power source is wireless.
from BatteryManager?
Hope this code helps:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = mContext.registerReceiver(null, ifilter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == 2;
boolean acCharge = chargePlug == 1;
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
I know that some devices headphone ports (maybe all of them? any reference here would be good) have 3 channels, for stereo sound and microphone. So I was wondering if it's possible to detect something like this pedal on these devices.
If it's possible, using the audio recorder would be enough? I'm studying possibilities for an app here, and this sounds promising if possible.
Thanks
EDIT
I was searching more about it and I was wondering if the pedal would have the same effect as those headsets with buttons. It's deadly easy to override their effects, I created a simple app that does it and now I'm waiting for my pedal to try. Any thoughts about it ?
UPDATE
I just tried it in the pedal and it doesn't work. Although we managed to use the pedal to pause a music app. The device was running Cyanogen though. The voice recorder also didn't detect anything on the key press. Need suggestions on how to detect it :).
UPDATE
AS the bounty is about to expire, a minor update. The last link provided by #Nick.T got some helpful info but I'm still not able to create a sample to detect the pedal. So I made a small change on the title question, and any guidance on that direction would be very much appreciated!
It's not clear if this will work without having the actual hardware in my hands, but... Don't plug the jack all the way into the socket. The tip of the jack should then connect to pin 2, left audio out, of this diagram:
http://pinoutsguide.com/CellularPhones-P-W/samsung_galaxy_headset_pinout.shtml
and the ring should connect to pin 3, microphone in. If you push the jack all the way in, the ground pin on the jack shorts out the microphone input and you won't detect anything - pictures at https://en.wikipedia.org/wiki/File:Photo-audiojacks.jpg show how the connections will mate.
Play some audio out the Left channel, record it on the mic channel, and measure the amplitude. That may - if it's all wired up right - tell you the pedal position. If the far end of the potentiometer is connected to the ring of the jack, that's not going to work.
That all sounds rather Heath Robinson. You could buy an inline 3-pin female jack socket and a 4-pin male jack plug and wire the two together to get whatever pinout you need. No electronics; just connectors and bits of wire! Or use a cable like this one:
http://www.ebay.co.uk/itm/1mt-3-5mm-4-Pin-Jack-Male-Plug-4-Pole-Jack-female-Socket-Extension-Lead-Cable-/251172651017?pt=UK_Computing_Sound_Vision_Audio_Cables_Adapters&hash=item3a7b0e8009&_uhb=1
and a sharp knife and some stickytape.
The other problem would come if the phone refuses to send audio to the jack when the jack isn't plugged fully home - there's an extra contact in the socket that detects that mechanically. But it would work if you made 3-pin to 4-pin adapter.
Or, just cut the 3.5mm jack off your (shiny new) expression pedal. Replace it with the 4-pin connector off one of those broken phone headsets you have lying around.
According to your last update, it looks like the pedal reacts like the button on a hands free headset. So as to say, to play, pause and skip music or pickup/hangup a call.
If the basics on the API don't give you a way to get hold of it (which I doubt) then you could move down to the NDK and see if it can be catched by the native level.
I looked it up and thought this might help you find your way :
Audio Hardware
Never know...
There are two potential paths of possibility here.
One would be to use the headset (or perhaps more specifically microphone) presence detection circuitry, and read that status via the appropriate API. This would be fairly simple (just have to figure out what property of a real headset is being measured). However, there is a good chance that the response may be fairly slow, as the phone is likely to go through some audio configuration changes and will not want to do that until it is "sure" that the headset has been connected or disconnected. Also the simplest non-microphone headset detection may be via a mechanical mechanism in the jack which could be difficult to electrically actuate across models.
A more complicated idea would be to couple some sound into the microphone input, and detect that in software. However, it will have to be an oscillating signal, as the microphone bandwidth typically does not range down to DC. If you just apply a steady voltage, you would get a "click" transient when it changes, but not otherwise. Injecting an audio frequency signal would require a power source - with careful design you may be able to steal enough power from the microphone bias supply to run a small oscillator. But perhaps simpler would be to have software output an audio tone on the speaker, and have your pedal switch couple this back into the microphone through a small capacitor.
I finally managed to read the pedal input. #emrys57 is right, replacing the jack with the 4-pin connector, triggered the input the same way microphones with a hook button do. However occasionally it seems to trigger the volume up and the volume down keys as well. I suppose this is related to me replacing the 4-pin jack with a knife and tape.
It was fairly simple to override onKeyUp. Be aware that you also have to override onKeyDown to prevent the default behavior:
#Override
public boolean onKeyDown(int keyCode,KeyEvent event){
int action = event.getAction();
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
if (action == KeyEvent.ACTION_UP) {
Log.d(TAG, "action_up");
clickStart(null);
return true;
} else if (action == KeyEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
return true;
} else {
Log.d(TAG, "action:" + action);
return true;
}
}
return false;
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
int action = event.getAction();
Log.d(TAG, "onKeyDown!");
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
if (action == KeyEvent.ACTION_UP) {
Log.d(TAG, "action_up");
clickStart(null);
return true;
} else if (action == KeyEvent.ACTION_DOWN) {
Log.d(TAG, "action_down");
return false;
} else {
Log.d(TAG, "action:" + action);
return true;
}
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
Log.d(TAG, "returning false");
return false;
}
I am writing an application that relies on the Android device (for my current testing purposes an HTC Evo 4G and several original Motorola Droids) being discoverable via bluetooth for 300 seconds.
I am targeting Android version 2.0.1, so according to the API I should be able to prompt the user to enable discoverability for a maximum of 300 seconds. On both my Droids and my Evo the prompt window has 300 seconds listed, but they both end after 120 seconds.
The code I used to prompt the user is here:
private void makeDiscoverable() {
Intent discoverableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(
BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
I am certain that this code runs. However, I later have a handler for when my discoverability status changes (in this case ends, I assume) that reads like this:
if (isDiscoverableChange(action)) {
int discoverState = intent.getIntExtra(
BluetoothAdapter.EXTRA_SCAN_MODE, Short.MIN_VALUE);
if (isDiscoverableState(discoverState)) {
setItOrder();
setUpScanAndDisplay();
} else {
discoverScheduler.cancel();
itScheduler.cancel();
}
}
private boolean isDiscoverableChange(String action) {
return BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action);
}
private boolean isDiscoverableState(int state) {
return state == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
}
I tried commenting out the portion that runs when discoverability mode ends, just in case it was cancelling everything prematurely, but discoverability really does end after 120 seconds.
Is this a hardware issue, or am I doing something wrong here?
It appears to be a bug:
Issue 15486: Bluetooth Adapter.EXTRA DISCOVERABLE not obeyed
http://code.google.com/p/android/issues/detail?id=15486
Issue 13361: BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION intent Extra does not extend 120 sec discovery interval
http://code.google.com/p/android/issues/detail?id=13361
First reported Dec 22, 2010, still listed as 'new' status, so I wouldn't expect this to be fixed.
There is bluetooth DiscoverableTimeout value besides Android timeout.
Usually, DiscoverableTimeout is set in file /system/etc/bluetooth/main.conf to 120 .
You should write
DiscoverableTimeout = 0
in /system/etc/bluetooth/main.conf to disable bluetooth timeout. This will allow you to extend Android timeout over than 120 sec.
I'm doing some test with Intent.ACTION_HEADSET_PLUG.
Giving the fact that the following code should be the one who give the responses (From com.android.server.HeadsetObserver class 2.2.1 r1):
private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
if ((headsetState & headset) != (prevHeadsetState & headset)) {
// Pack up the values and broadcast them to everyone
Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
int state = 0;
int microphone = 0;
if ((headset & HEADSETS_WITH_MIC) != 0) {
microphone = 1;
}
if ((headsetState & headset) != 0) {
state = 1;
}
intent.putExtra("state", state);
intent.putExtra("name", headsetName);
intent.putExtra("microphone", microphone);
if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
// TODO: Should we require a permission?
ActivityManagerNative.broadcastStickyIntent(intent, null);
}
}
And in the documentation they say: state - 0 for unplugged, 1 for plugged.
I strangely get two different state by plugging two different headsets:
0 = unplugged
1 = Headset with microphone
2 = Headset without microphone
The question is: where the State 2 (two) come from? Can someone enlighten me?
Thanks
I am using that extra state myself in one of my applications. One of your headsets has a mic the other doesn't. Also make sure you a plugging it in all the way, but don't break anything :)
0 - unplugged as in no headset attached to the device
1 - headset with microphone as in wired headset that had a mic so you can talk and the device uses it as a input as you talk
2 - a headset with no microphone as in your regular old stereo headset that you would normally hook up to your stereo system to listen to music with
This is extremely good info to verify that what was just connected is a wired headset that you expect to be able to talk in to and be heard correctly.