The sole user interaction for my app is through the accelerometer, so there is never a reason for the user to touch the screen. What I need is the ability to elevate a non-touch event so that the system recognizes it as user interaction, delaying the screen timeout. Either that or I need to be able to manually extend the timer.
I have already read (and commented on) the thread about disabling the timeout. That is not what I need. The interaction my users are performing is very explicit (turning it over 180 degrees) so it won't happen if it is set down or stuck in their pocket (unless they are riding a rollercoaster.
Currently, the device is constantly shutting down when the user is in the middle of actively using my app.
Have you tried flipping UserIdleDetectionMode from enabled to disabled again to see if it resets the timer? If that works you could do it in response to your application events.
Otherwise there is no means of simulating user events, so I would say you are out of luck on this one for the moment.
Related
I'm implementing some basic usage statistics for the first time in an Android/iOS app using Firebase Analytics, but the docs seem a little ambiguous to me on how exactly session durations are calculated and how sessions are timed out, and the 24-hour cycle for seeing results does not help in understanding by trial-and-error.
I'm only interested in a very simple statistic for now - the time users spend in the app. What exactly happens when the app is "minimised"/"in the background" - does that count as active usage or the same as the app being closed - is not so important right now, but if you have something to add in this regard in the context of the question, please do.
From what I understand such an easy statistic should probably be available out-of-the-box with Firebase Analytics, so I'm currently not using any custom events or anything fancier than simply linking Firebase Analytics into the projects, adding the configuration files, and calling FirebaseAnalytics.getInstance(this); on Android and [FIRApp configure]; on iOS.
I'm seeing first_open, session_start and app_remove events show up in the console as expected, some aggregate session data in the dashboard, etc, and I also know there is a configurable session timeout available.
But what is unclear to me is, when exactly does a user session expire - does Firebase automatically keep it open as long as the app is open, or do I need to make sure to post some artificial "keep-alive" events to prevent user sessions from expiring while a user is still actually using the app.
Assuming the following:
I send no explicit custom events using Firebase, as this is not
explicitly required by the app.
I only touch Firebase once during a single run of the app - initialising it on startup.
The user stays in the app for a long time (let's say 2 hours - much longer than the default 30 minute session timeout), without interacting with it - e.g. reading something, watching a video, etc, none of this generates any events that Firebase can see, but the app prevents the screen from locking, the app remains in foreground.
Will that count as a single 2 hour session for the user? Will it only count as a 30 minute session since the session expires after 30 minutes and no events are generated to keep it alive? Will something else happen?
Bonus question: what happens if the user exits the app for a time shorter/longer than the session timeout?
Bonus bonus question: does something change if instead of exiting from the app, it is simply put into background?
Thanks!
Quick answer: The scenario you describe will result in a single 2-hour session.
Sessions are based on the time that an app's activity is the current activity. There is no need to send events; the period from the time an activity resumes to the time it is suspended is counted as engagement time. At the end of an hour of continuous engagement an engagement event will be logged but this does not end the session. A session expires when there is a continuous period (30 minutes by default) that none of the app's activities is the current activity.
If the user exits the app for a shorter period than the session timeout and then restarts it, the session continues. If the user exits the app for longer than the session timeout, then the session ends. No change between exiting the app and putting it in the background. If it's not the thing the user is looking at, it doesn't count as engagement for the app to be running.
I need to know if there is a way to keep an android wear app always in interactive mode. (i knonw this will drain battery life)
Is the 'rotate away' gesture adressable or will the watch just go in ambient whenever the watch goes on it outer side?
The answer depends on whether your "app" is an activity or a service.
An activity should simply specify android:keepScreenOn="true" without the need to do anything further.
If it's a service (e.g. you are making an alarm/timer watch face), I recommend starting a transparent "always-on" activity. AFAIK, currently, the system will not allow your service to keep the screen on with a full wake lock beyond the normal screen-on cycle duration. This is likely due to wake lock misuse. With an Activity, this is possible currently, and has the benefit of handling dismiss actions for you (e.g. side button press, palm, etc). I used a similar pattern in a set of "timer" watch faces.
Here's how you might achieve always-on from a service:
In a Service/Activity responsible for waking the watch:
private PowerManager.WakeLock mFullWakeLock;
// Initialization...
PowerManager pm =(PowerManager) getSystemService(Context.POWER_SERVICE);
mFullWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "WatchFaceAlarmWokenUp");
// Elsewhere, when the watch needs to be woken by the service...
// Wake the watch to give ourselves some time to start the activity
mFullWakeLock.acquire(2000l);
Intent intent = new Intent(this, AlarmExpiredActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Your AlarmExpiredActivity layout must specify the following property:
android:keepScreenOn="true"
I would recommend you also specify android:onClick="hide" to make it easier for users to kill something that's draining their watch.
I am building an Android App to control power outlets with a smartphone. The app features an Android Wear app so people can control their lights right from their wrist.
When the user wants to control a light I send a String action via the MessageApi from the smartwatch to the smartphone, which receives this action in a WearableListenerService and sends the appropriate network signal to the power outlet/gateway in an AsyncTask.
This works fine as long as the phone has not been in idle for too long. However if the phone is still on the table for too long and doze kicks in Wear actions do execute very slow or sometimes not at all. I guess this is in part intended behavior however it is not practical in my case as the user cant wait that long for his lights to turn on if he wants to enter a dark room.
I am aware that doze completely cuts the networking for everything except FCM/GCM if you are not on the doze whitelist. But even when my app is on this whitelist and the networking part works actions can take a long time to execute on the phone.
So my specific question is:
Whats the recommended way to handle this scenario, where an action from a wearable device needs to be done via network on the connected smartphone which is in doze mode?
Is there a way to exit doze for a quick amount of time to execute calculations triggered by the wearable companion app faster?
I know the AlarmManager has a new method that works even in doze mode, but will this fix the processing delay too? Firing an alarm after receiving a MessageEvent from MessagApi seems like a workaround to me.
Or maybe is an AsyncTask just the wrong way to handle background networking and thats where the delay comes from?
Actually, there are a few options that you can do to handle Doze's effects as given in Adapting your app to Doze. You may want to consider the following options:
If your app requires a persistent connection to the network to receive messages, you should use Google Cloud Messaging (GCM) if possible.
GCM is optimized to work with Doze and App Standby idle modes by means of high-priority GCM messages. GCM high-priority messages let you reliably wake your app to access the network, even if the user’s device is in Doze or the app is in App Standby mode.
To help with scheduling alarms, Android 6.0 (API level 23) introduces two new AlarmManager methods: setAndAllowWhileIdle() and setExactAndAllowWhileIdle(). With these methods, you can set alarms that will fire even if the device is in Doze.
However, please note that with these methods, neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can fire alarms more than once per 9 minutes, per app.
Please try going through Optimizing for Doze and App Standby for a more detailed information or discussion.
In addition to these given documentations, the same options in handling Doze were also given and discussed in Diving into Doze Mode for Developers which might also help.
I wonder if the background time that an app receives when entering an ibeacon region can be used for opening a session with an external accessory object. Can the app then also keep on running in the background while the session remains open?
This of course assuming that the external-accessory background mode is enabled.
While I have not tried this myself, I do not see any reason why it wouldn't work. You would need to have a legitimate reason in Apple's eyes to use the external-accessory background mode in order to get your app approved.
Assuming you have this, as soon as the app sees an iBeacon in the background, the app gets about 5 seconds of run time, which should generally be sufficient to establish a connection to an external accessory. If the connection is made, and the app is exchanging data with it regularly, the external-accessory background mode should keep it going in the background indefinitely, so long as the connection to the external accessory stays open. So long as this is true, the app will probably be able to get ranging updates in the background indefinitely, too.
It doesn't take a huge leap of logic to see that you could build a device that behaves as an external accessory and an iBeacon simultaneously, and use this to get around the usual iBeacon background rules. That said, you'd need to be careful that Apple doesn't think this is illegitimate, or the app could get rejected quickly. To avoid this rejection, you probably would need to be providing some benefit to the end-user via that external accessory channel.
I'm trying to figure out how to detect when the user presses the power key on the keyboard.
I'm developing a kiosk application and I want to run a routine when the user want to force shut down the computer by pressing and holding the power key.
Thank you in advance.
There are no methods that will be called when a user presses and holds the power key. That's directly handled in hardware and doesn't even get routed to the OS, much less to your application - it's the equivalent of pulling the power cord.
Your best bet is to create a "clean shut down" user preference key or temporary file that your app will remove as part of its normal shutdown procedure. When your app starts up, it can then check for it to see if the previous run was shut down normally, or had the rug yanked out from under it.
Oh, and since this is a kiosk - don't give users physical access to the power switch to begin with. Sometimes the simplest solutions are best!
You don't.
From Apple's Cocoa Event Handling Guide:
Note: Lower levels of the system trap
and handle some events early in the
event stream. These events are never
routed to a Cocoa application. These
events are generated by reserved keys
or key combinations, such as the power
and media-eject keys.
You can make your application perform some action and/or prevent a shutdown with applicationShouldTerminate, somewhat covered at the Graceful Application Termination doc page. This won't be exactly the same as just responding to the key event, though.
You can also use the NSApplicationPresentationDisableSessionTermination flag to just disable logout and shutdown.