I have an issue with Android Vibrator. Basically, I have only one Singletone - scoped class incapsulating the android.os.Vibrator in a way, that it has two methods
startVibrating() {
if (VERSION.SDK_INT < VERSION_CODES.O) {
vibrator.vibrate(PATTERN, 0);
} else {
vibrator.vibrate(VibrationEffect.createWaveform(PATTERN, 0));
}
}
stopVibrating() {
vibrator.cancel();
}
The issue is that on some Samsung devices the Vibrator stops when the phone screen is turned off even I have a WakeLock for CPU.
Recently, we've got into the same situation.
According to Android docs:
If your process exits, any vibration you started will stop.
And you would expect that if you have any CPU-related WakeLock, it should work fine. However, we found that Samsung devices on Android 6 and Android 7 stop the Vibrator in some other cases too. For example, each time when the screen is turned off using PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, even if you take some other wake lock explicitly.
The good news that Samsung stops the Vibrator but it does not prohibit it from the future starts.
We've ended up with the next workaround:
When the screen goes off, the current activity gets onStop() call. So, we check if we should vibrate on that moment, and if we do, we simple start the Vibrator again. Maybe, not the best solution, but it works.
Related
I have an alarm clock app and some users complain phone vibrates during alarm, while vibrations should be disabled.
After some digging I have found out, that on some devices there's a system option for device to vibrate along alarm music. For example in my test Pixel 4 it is located at Settings->Sound&Vibration->Vibration&Heptics->Alarm vibration.
What this setting, enabled by default, causes, is that vibrations try to "emulate" the music played through MediaPlayer and I cannot find a way to prevent that from happening from within the app or even detect if such setting is present/enabled.
Anyone knows how to get rid of that?
Here's a sample method I used for testing:
private fun startThePlayer(context: Context, playInLoop: Boolean = true) {
try {
mediaPlayer.reset()
mediaPlayer.isLooping = playInLoop
val uri = Settings.System.DEFAULT_RINGTONE_URI
mediaPlayer.setDataSource(context, uri)
mediaPlayer.setOnPreparedListener {
mediaPlayer.start()
}
mediaPlayer.prepareAsync()
} catch (e: Exception) {
log(e.toString())
}
}
VIBRATE permission is necessary for this to work.
Effect on Pixel 4 with Android 13:
Device is vibrating, as if trying to "emulate" the music played. Vibrations strength depends on value set in device's settings, completely ignoring volume set for alarm's music, and also messing up any vibrations set directly in my app.
What's interesting, is that for some reason Android's default clock app ignores this settings and device doesn't vibrate during it's alarms.
First, I suggest that you use android's VibratorManager to control your app vibrations settings (this is how the android development team called this service.. how bizarre). Use the getDefaultVibrator and cancel methods to stop any vibrations produced by your app (official docs to the rescue)
Second, because your app is an alarm clock please consider using the setWakeMode which will allow you to keep your app running in the background regardless to the display (in order to prevent the alarm from stopping if the screen is off). Here's the method documentation and also the PowerManager flags documentation
Hope you will find the right combination to satisfy your needs
I have created an application that generates a tracklog of the Android devices location. A GPS coordinate is recorded at regular intervals and stored on the device for later download. Currently, when the phone goes on standby, the program stops recording points. Is there a method that would allow the application to continue documenting location while the unit is on standby? Thanks in advance.
According to android documentation, if your app targets API level 26 or higher, the system imposes restrictions on running background services when the app itself isn't in the foreground. Also for accessing location in the background you may need additional permissions
You can run a foreground service with showing an ongoing notification if you want to run a service which is always alive in the background. Or you can schedule tasks using WorkManager.
I found two solutions.
1.) Use Wakelock
public void wakeLock() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MyApp::MyWakelockTag");
wakeLock.acquire();
}
with the following added to the manifest XML file,
<uses-permission android:name="android.permission.WAKE_LOCK"/>
or, 2.) use WindowManager to keep the device awake,
public void noSleep() {
if (bNoSleep == true){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else if (bNoSleep != true){
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
I've chosen the latter as a user selectable feature accessible via checkbox in the main workspace. I've also set this to engage automatically when a tracklog is initiated with the user having the option to disable this and allow standby/sleep to occur. I did implement a wakelock, but had some issues with it that may be related to a custom ROM on some of my Android devices. This is why I went ultimately went w/the windowmanager solution.
I am currently updating my Android app with Samsung Galaxy S3 and was shocked that I couldn't stop the phone pausing my app when turning idle. With the Galaxy S2 of our department there doesn't occur this particular problem, if the screen goes black the app still streams data to the sd-card and over the wifi-network. The S3 stops any data-stream.
I tried now fiddling with the energy- and display-settings but I have no solution to the problem so far. My Internet-search was not succesfull either.
Possible solutions are rooting the new phone and thus making advanced settings visible
or increasing the time-out (which i dont like so much as a solution).
Do you have any ideas how to solve the issue or general input that might enlighten me?
Thnx!
BTW: here is the app in question (no ad):
Google Play Link
I have an app which needs to do something similar (it's a running trainer, so it needs to keep talking while the user keeps their phone in their pocket for half an hour or so.)
First off, a caveat for other people reading: don't do this if you don't have to. If you only need to do something periodically, rather than continuously, consider using AlarmManager, which can wake the phone up from sleep every now and again to do something, so won't hit the user's battery so hard.
But, if you're sure you need to keep the phone awake, you need to use a WakeLock. Here's roughly what I do in my service's onStartCommand:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK;, "RunClockService");
mWakeLock.acquire();
...where mWakeLock is an instance variable of type PowerManager.WakeLock. PARTIAL_WAKE_LOCK keeps the CPU running, but doesn't keep the screen on. The "RunClockService" tag is just used for debugging, according to the documentation. Change it to your class name.
Then, when I finish needing to keep the phone awake:
mWakeLock.release();
You'll also need to add WAKE_LOCK permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK"/>
There are a few questions already on StackOverflow related to turning the screen on / off, however not a single solution has worked for me.
I do not want to use a wakelock as it's no longer recommended. My app wakes up the screen using WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON, which is far simpler and doesn't lead to a situation where one can drain the entire battery if you forget to release it.
Setting brightness to 0 like the following code also does not work. On my two test phones (Samsung Galaxy S2 and S3), this code only dims the screen, but does not turn it off.
layoutParam.screenBrightness = 0;
layoutParam.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
getWindow().setAttributes(layoutParam);
My scenario - it's a VoIP app which turns on the screen for an incoming call, but then needs to switch off the screen (but keep the CPU running) if the user holds the phone up to their face. The proximity sensor code is running fine.
Have you tried changing the Screen off timeout value?
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 1000);
The value of 1000 means 1000 milliseconds, or 1 second, you can change it if you want.
Afterwards change it back to the standard like this
Settings.System.putInt(getContentResolver(),Settings.System.SCREEN_OFF_TIMEOUT,-1);
This requiers a permission in the manifest file:
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
I’m working on an app that posts to the internet every 30 sec. Everything is working fine until the screen goes off. The timer appears to have slowed down. It takes like 5 min to post. I’ve tried acquiring wake-lock and setforegroundactivity but nothing works. Any ideas here?
Its running as a service, I use this for wake-lock:
PowerManager mgr = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
And the example here to set foreground: http://developer.android.com/reference/android/app/Service.html
I’ve also tried to check what it can be using the debugger, but everything works fine when the USB is connected.
More detail:
To check with regular intervals I use this:
Private void startCheck() {
mCheckHandler.sleep(30000);
}
private CheckHandler mCheckHandler = new CheckHandler();
private class CheckHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Pservice.this.startCheck();
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
};
I set it to acquire wake lock every time it checks the internet. Now it works fine :) Thanks for all your help :)
When the screen goes off, the device will eventually go into a low power state. This low power state basically means your code will not be executed. The reason it takes 5 minutes is because some other app is waking the device up and then your app gets the chance to run again.
By having the device connected via USB, you are preventing the low power state from ocurring.
It sounds like your wake lock is not actually being acquired or it's being released too soon.
Have you tested on any other devices, roms, emulators? Sometimes a simple problem with the way a device manufacture's code can cause issues like that.
What device and rom are you using?
I for one aggressively underclock my android devices when the screen is off.
Also, you mentioned:
I’ve also tried to check what it can be using the debugger, but everything works fine when the USB is connected.
Try using ADB Wireless to debug without being on USB power or just use logging instead.