Clever way to wakeup Android background service on shake - android

I want my Android background to go into sleep mode - but then wake up when the user starts moving.
However, if I use the accelerometer in NORMAL mode (the lowest sample rate ~ 5Hz) I fear it would still consume too much power.
The best way to do it so far is on USER_PRESENT - screen on and unlocked.
Not even screen on(possibly with keyguard present) works, because, as many of you may know, there are plenty of bad apps out there that will hold a wakelock and start the screen from time to time.
I am contemplating having the user push the volume up/down buttons..
Is there any better solution to this?

don't know if you're still looking for a way to do this, but i discovered (by accident) that you can start a shakeListener, and your app will get the events, even when in the background.
(and by "by accident", i mean that i did not want my app playing the sound that it is supposed to play when the app is in the background, but even when had another app in the background, and then even put the phone to sleep, when i would walk with the phone in my pocket, it was enough shaking to cause the app to perform the operation in the background.)
/**
* load and set up the listener for shake detection
*/
private void loadShaker() {
mShaker = new ShakeListener(this);
mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () {
public void onShake() {
if (!mActivityPaused)
performMyOperationCausedByShake();
}
});
}
you could probably thus set this up so that performMyOperationCausedByShake() performs an intent that causes your desired Activity to happen.
(it might be the case that this is not quite sensitive enough for what you're looking for …)

Related

Touch event UP being fired when not supposed to, after using "PROXIMITY_SCREEN_OFF_WAKE_LOCK" wakelock

I'm having a really weird issue here.
(Running on device,Motorola XT910 Android 4.1.2, Xamarin.Android 4.16.0)
I have an activity with a button that the user presses an holds to record some audio. I handle the onTouch event and listen to the DOWN and UP events (on DOWN I start recording, on UP I stop it). So far so good.
Now, I also handle the onSensorChanged event in order to turn the screen off when the user holds up the device to his ear. I achieve this by using a wakelock like this:
private void AcquireScreenWakeLock()
{
if (screenWakeLock == null) {
PowerManager pm = (PowerManager)GetSystemService (Context.PowerService);
field = pm.Class.GetField ("PROXIMITY_SCREEN_OFF_WAKE_LOCK").GetInt (null);
screenWakeLock = pm.NewWakeLock ((WakeLockFlags)field, "ScreenWakeLock");
}
screenWakeLock.Acquire();
}
private void ReleaseScreenWakeLock()
{
if (screenWakeLock == null)
return;
if (screenWakeLock.IsHeld)
screenWakeLock.Release();
}
The problem comes when pressing and holding the button to record, right after the DOWN event, I receive an UP event WITHOUT lifting my finger...
Of course there are other things that I do in between but I managed to narrow the problem down to this code (if I comment it out everything works as expected).
I know I'm using a hidden field to make the wakeLock (actually it seems it's released in API 21, docs here) but I haven't found a better way to do this, and the whole screen off/on process works flawlessly.
I'm having this issue while testing on a Motorola XT910 running Android 4.1.2, I've tested it on a Moto G running Android 4.4.4 and everything works fine there (no UP events being fired up when holding down the button).
I'm really at a loss here figuring this out...how can a wakelock cause this behaviour? Do you have any other way to effectively turn the screen off/on? I've searched other posts but none seemed to help me. Using a partial wakeLock doesn't work either (I've checked with this code).
Thanks in advance!
P.S: I've checked and the touch event is only being registered once.
PROXIMITY_SCREEN_OFF_WAKE_LOCK turns screen off/on according to proximity state by itself. No need to handle also onSensorChanged event. This might cause an issue.

Switch on screen and let default display timeout take over?

I'd like to switch on the screen from a service and immediately let the default system timeout take over (i.e. not hold a wakelock for a specific time, but just hand over control to the system). I've tried WakeLock.acquire() followed immediately by WakeLock.release() (with a SCREEN_BRIGHT_WAKE_LOCK), but that doesn't even switch on the screen at all. Is there any way to achieve this from a Service (short of launching a new WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON-dummy-activity)?
I think this is what you are looking for. You need to use
PowerManager.ACQUIRE_CAUSES_WAKEUP

Android: Make app transparent and act on the background application

Is it feasible to make our Android application completely transparent (as if its not active at all) and work on the other apps?
My Requirement:
First last an app and after some few settings, make it transparent. Once its transparent, the user will not know that this app is active, however, our app should respond to only specific controls.
This is because of the Broadcast receiver limitation, I will have to use the Volume button for some actions in my application. But, this button doesn't broadcast. So, currently I am using Power button which is not the requirement.
Please throw some light on this. I did some research but, couldnt find any. :(
This is because of the Broadcast receiver limitation, I will have to use the Volume button for some actions in my application. But, this button doesn't broadcast.
I am not sure it this is right. If you read Android BroadCastReceiver for volume key up and down question, it seems that you can detect it in BroadCastRceiver. I've never tried but it might be worth a try. Do something like following:
In your BroadcastReceiver onReceive function, do something like following:
public void onReceive(Context arg0, Intent intent) {
if (intent!=null){
int volume = (Integer)intent.getExtras().get("android.media.EXTRA_VOLUME_STREAM_VALUE");
// Get the old volume from the SharedPOreferences
// volume variable contains the current volume
// Compare it to the old value saved. If it is greater than old value then user pressed the UP Volume button else DOWN volume.
}
}
Also I am not sure that you can make it transparent and still keep it running. You can have a background of an activity as transparent though. How do I create a transparent Activity on Android?. Hope it helps.

How to turn keyguard on in reliable way?

DUPLICATE WARNING: this problem deals with details of Android API, suitable for calling both from some frontend and services, there are many similar threads on SO, but focused only on frontends.
Problem
I would like to turn on keyguard programmatically, so for example user clicks a button in my app and the phone gets locked (to use phone user has to unlock it first).
The catch is -- I would like to find rock-solid way, that works in every valid case.
Attempts
I tried:
lockNow with DevicePolicyManager -- when the screen is off (but phone is not locked) this call is ignored (i.e. the keyguard is not activated)
reenableKeyguard with KeyguardManager.KeyguardLock -- the call to the method is ignored in every possible case
goToSleep with PowerManager -- I cannot call it, because of the problem with permission, it requires DEVICE_POWER despite I already have this permission set
So far I pursue the first way (lockNow) with extra hacks that somehow deal with the case when the screen is off, but it extremely ugly, thus I am hoping there is some straightforward way.
One solution could be using thread on postdelayed handler.
the catch here is, thread will stay alive even after the screen is off, where your application would be under paused state (unless process is killed)
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
keyLock.reenableKeyguard();
Log.i("LOCK","key guard back on");
finish();
}
}, 300);
Another way of doing this would be to use timer task, but timer task might get killed sometimes (don't know for sure, but my past experiences says not sure)
TimerTask Active = new TimerTask() {
#Override
public void run() {
keyLock.reenableKeyguard();
Log.i("LOCK","key guard back on");
finish();
}
};
Timer starter = new Timer();
starter.schedule(Active, 300);
I can't be 100% sure this is the "rock solid way" you were looking for, but I've been working with the device policy manager along with the keyguard manager for some while and I came across similar problem that locknow() method would turn off screen and then turns back on devices with android 4.0 above.
I came across this solution while looking through the DDMS debug logs, and hopefully, testing on some devices. So far, it hasn't failed me so here a tip anyway.
Disable keyguard
call locknow()
reenable keyguard in a 300ms or so, with the above methods... ( I prefer the handler and it worked like a charm for me)

GPS Tracking App (strategy)

I am currently working on a GPS tracking App (only the distance, not storing each value or displaying in a MapView) for a car-drivers logbook.
Cause of a docked phone, I do not care about power consumption.
My implementation so far is an activity that calls a GPS-Helper class which is getting the long/lat.
The activity itself calculates the driven distance, displays it for the user and starts a notification bar that also displays the distance. To keep the activity active and not killed by the OS, I am using a PARTIAL WakeLock for the activity.
My problem is that this is not working correctly, cause my App seems to be killed by the OS inspite of the WakeLock. I think that it is killed, cause when I click on the notification bar item (after 15-30 min. for example) to see the driven distance in my running activity, the activity is shown as it is to start a new GPS-track instead of displaying the driven distance from the former started track.
The WAKELOCK Permission is correctly set in the Manifest.
My question now is to get know if this costruct could be working or is there a better way to do this?
Your problem may be with the Intent you are launching when you click on the notification. This intent is most likely thinking that you want to launch a brand new Activity rather than returning the old activity to the foreground.
This link may help you to do what you want:
How to bring Android existing activity to front via notification
You should use a service which calls startForground, which requires a notification. This notification will be your entry point back into the app. The service can run in the background and log coordinates without depending on the life cycle of your Activity.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getAction().equals(DRIVELOG_ACTION_STOPLOGGING)){ handleStopLoggingCommand(intent.getBooleanExtra(SAVE_LOG,false));
}
else if(intent.getAction().equals(DRIVELOG_ACTION_STARTLOGGING)){
handleStartLoggingCommand();
}
return START_STICKY;
}
private void handleStartLoggingCommand() {
startForeground(DriveLoggerNotification.notificationId,DriveLoggerNotification.createInDriveLogNotification(this,driveLogLiveData));
if(googleApiClient.isConnected()){
startMonitoringLocation();
}else {
googleApiClient.connect();
}
}
This code is from my GpsLoggingService

Categories

Resources