Android Management API - Seamless update of a kiosk app - android

I've read the Management API documentation and I think there's no reference to this topic, I didn't find any information about it here on SO either.
We're analyzing EMM solution providers for provisioning devices with a set of applications, trying to understand if they cover all our needs, or as a last resort we might come up with a custom implementation.
Can we control policies to be enforced on the devices only within a given time window? Specially at what times applications updates are allowed? I know system updates can be controlled, so I was wondering if I missed something in the docs.
We need to have control over that because we don't want to disrupt the UX on the devices when a new app update is available, especially in our launcher app. We have one main application running in KIOSK mode, with a few other apps accessible from within that kiosk app. The UX is really important, so app updates must be seamless - right now, updates are managed through a DO application that handles a few scenarios, one of which is checking for available app updates, downloading and applying them (the applications are not publicly available in Google Play Store at the moment). When the launcher updates, the DO application takes its place on screen during the update, providing the end user custom visual feedback about what's happening, and when the update is done the kiosk app takes control of the screen again.
So imagine one user has the kiosk app opened on his device, and we distribute a new version for it. When the policy is enforced, is it likely that the app would be abruptly closed for updating? Would it update only if not in use? Will we need to keep custom logic for ensuring a smooth update, and if so, how can we know an update will take place inside our app, since policies are enforced by a 3rd party application?

SystemUpdate can also be used for updating your app within the desired window hours, you can setup this by setting your SystemUpdateType to WINDOWED, and change the setting of startMinutes to your desired time (the start of the maintenance window, measured as the number of minutes after midnight in the device's local time. This value must be between 0 and 1439, inclusive.)
"systemUpdate":
{
"type": "WINDOWED",
"startMinutes": 0,
"endMinutes": 1439
}

Related

Exclude Android app from being put into standby bucket

With Android 9 battery optimization has been pushed further and apps are classified into standby buckets depending on how much the user has recently interacted with the app (see Android documentation). The system limits the device resources available to each app based on which bucket the app is in.
How can I keep my app in the "working set" bucket, even if the user does not interact with it? (I do not find any permission or similar that allows to override this power management feature.)
More specifically, I have a PeriodicWorkRequest that must run once every 30 minutes with a flexibility of 10 minutes. However, if I understand the table of imposed power restrictions such a work request could be deferred up to 24 hours, if my app is put into the "rare" bucket. (Under the hood, the Work library uses the job scheduler.)
Further Details on the Scenario
The app is safety critical and not intended for public use but only meaningful to a restricted set of users. However, if anyone else uses this app nothing bad happens, but the app does not serve any purpose for him/her.
More precisely, the app is connected to the central fire alarm station of a specific building. All employees are asked to install the app on their smartphone. If the central fire alarm station of that building detects an event, it sends a push notification (via FCM) to all registered smartphones and the app plays an alarm sound. This implies nothing happens for (hopefully) a long time and the user has no intention to interact with the app in any way. The app itself does not provide any interaction, it only illustrates the current state (which is either a green "OK" sign or a red "ALERT" sign) and waits in the background for the rest of the time.
As the app is safety critical, the fault condition that the app looses the connection to the server must be detected. To this end, the server actually sends messages in the background periodically, i.e. a sequence idle, idle, idle, idle, alarm, alarm, alarm, alarm, idle, idle, idle, ... Normally, messages are broadcasted with low FCM-priority every 5 minutes. If the state changes, an additional message is immediately sent with high FCM-priority (cp. bold letters).
The app implements a watchdog using PeriodicWorkRequest as mentioned in the question above. This watchdog does twofold: Wake up the device and make the device receive all (low priority) FCM-messages that have been postponed and then check if the most recent message is not older than 1.5*5min. If this fails, the app tries to re-register itself with the server and waits if state messages start to come in again. If this fails too, the app presents a warning to the user.
Everything works fine so far. The only problem is the new kind of battery optimization which slows down the watchdog at some point of time. Of course, I could hand out a standing regulation that forces all employees to open the app once in a while and simply look at it, but that is a little bit silly.
I could re-phrase the question above: I totally understand why Android is pushing battery optimization to an edge. There are a lot of (insane) apps that have misused periodic tasks for purposes that should have been solved differently. And the web is still full of "idiotic" programming advises, like checking a specific webpage for modifications every 5secs. However, how am I expected to write safety critical apps that require a watchdog for legitimated purposes if battery optimization becomes more and more an obstacle. Google's thumb of rule "if the user does not use your app, it is obviously unimportant to him/her" does not apply here.
How can I keep my app in the "working set" bucket, even if the user does not interact with it?
You can't and you shouldn't. That same documentation says:
Do not try to manipulate the system into putting your app into one bucket or another. The system's bucketing methods can change, and every device manufacturer could choose to write their own bucketing app with its own algorithm. Instead, make sure your app behaves appropriately no matter which bucket it's in.
Even whitelisting won't work in your case because:
the whitelisted app’s jobs and syncs are deferred
There's this too:
Note: Google Play policies prohibit apps from requesting direct exemption from Power Management features in Android 6.0+ (Doze and App Standby) unless the core function of the app is adversely affected.
If your app is site-specific and not distributed from the play store, you can ask your users to disable battery optimization for your app. That will exempt your app from the standby app bucketing system. Obviously it's not a great user experience to have to go through a bunch of menus to disable some obscure feature, but given that you are considering forcing users to open the app manually, disabling battery optimization would be preferable.

Android- programmatically restrict which apps can be run

I'm building an app that needs to restrict which apps can be run along with it.
In example, when my app is running (foreground or background) I can allow user to run only GoogleMaps, and MusicPlayer.
I've read a bit about Device Policy Controller and creating profiles, and up to some point it seems to have the feature I need, but it is designed for enterprise deployment, and user needs to encrypt their phone beforehand. Is creating personalized profiles a way to go?
My other idea was to run a service that each few milliseconds check if there is any forbidden app running and finish it, but it seems to be not robust.
Is there any way of handling this problem programmatically?
I don't think that Device Policy Controller is a right thing for you.
And you can't just kill other apps without root.
So some kind of user-friendly way to achieve the goal is to check running apps list with ActivityManager.getRunningAppProcesses and to notify user that he has to finish particular apps to use your app.

Is it common practice to ask users whether they wish to receive push notifications?

I'm new to the Android platform. Apple requires every iOS app to ask for and confirm push notifications, but I have not noticed any apps that I've downloaded on my new Android phone prompting me if I want to receive push notifications. It just automatically registers me for them. Is this normal Android convention, to automatically register users for push notifications, assuming they can disable them later?
In my own Android application, should I be prompting users and asking if they want them before I register them? Obviously it would be the polite thing to do to ask permission before signing them up for push notifications, but if that's not common practice I see no reason to potentially lose some receivers of them.
Making decisions for the user is actually a strong Android guideline. Here is a list of the "Android Design Principles", written by Google. As you can see "Decide for me, but let me have the final say" fits the behavior that you've mentioned.
Some things to keep in mind when discussing Android notifications:
Users can disable your app's notifications in their OS settings. If they really don't want to hear from your app, they'll disable notification's there.
User context. You don't know what context the user is installing your app in. Users who are on a crowded train, relaxing on their day off, hanging out at a friend's place, or maybe waiting for a flight, all want different things out of your app at the time of installation. The guy on a crowded train is going to want your app to work immediately, with very minimal setup, while the guy relaxing at home may not mind a long setup process.
Your setup process can have a significant impact on your user retention. This Forbes article briefly discusses intrusive setup forums and their impact on app uninstalls.
At the end of the day however, it all depends on the needs of your audience. If you're targeting professionals, then they might be willing to put in some extra time up-front if they believe your app could help make their job easier. If you're targeting a casual gamer, you'll want them to get in and rolling as fast as possible. It's up to you to decide how best to serve your audience.
Here's a video from Google I/O 2013 that discusses the Android Design Principals in greater detail.
Hope I was able to provide some insight.
Sadly, it does not appear to be a very common practice. I've installed several Android applications that will randomly give me a notification in the middle of the night. I've recently made a new habit of disabling notifications for every new app that I install unless I really want notifications from it. I think your application would result in a much better user experience if you prompted them for notifications. You could also offer configurations for which notifications they wish to receive. If other apps were like this I might choose to receive some notifications instead of globally turning them off.

Is there a way to make user only able to use a specified app on an Android device without rooting?

For example, it's for promotions or events. Therefore I want users not able to leave our app. For iOS, i guess I can make a frame to physically block the main button. But for Android, i don't know how.
This is currently not possible. It is scheduled to be included in the upcoming L release. See Task locking.
"The L Developer Preview introduces a new task locking API that lets you temporarily restrict users from leaving your app or being interrupted by notifications. This could be used, for example, if you are developing an education app to support high stakes assessment requirements on Android. Once your app activates this mode, users will not be able to see notifications, access other apps, or return to the Home screen, until your app exits the mode."

programmatically temporarily disable auto-update

I have a Bike computer app that logs data while the user is riding. I have had a user report an issue I had not considered. He was out for a long ride (100+ miles) but while out and logging data the app got updated via Google plays auto-update. This unfortunately killed off the app mid recording and the user lost data till they spotted what had happened and restarted the app.
Ideally I would like to be able to programmatic stop the auto-update happening while the app is data logging. All my research indicates that this is not possible possible but I may of missed something so dose anyone know of a way of doing this?
Given no solution the best I can do is advice the users to enable the update only over wifi option in the Play app which in this instance would of helped. Unfortunately one of the key points about my app is that it will log indoor sessions using ANT+ sensors so I have a good number of people using it with wifi active.
Edit
I managed to do the experiment to see what happens myself last night. I had an app going in the background data logging then pushed a new version to Google Play. Unfortunatly it was not picked up totaly automaticaly when I had to leave 10 hours latter but I opened up the play store app and it found the update it did not start updating automaticaly but I forced it. The act of downloading and installing the new version killed off what was in progress. It was already dead before I used the notification to go to the new version.
As you say yourself, you can't do that what you are asking for. You could hack your way around it by changing the permissions each time you update. The users will then be prompted about it in the regular way.
I'm not sure about the "life-cycle" for automatic updated apps that are running. But I read somewhere that is wasn't the re-install but the reopen of the app that crashed it. If that is the case you could set a flag indicating that the user is currently logging and then on restart just resume the logging. But again we need to know more about the inner workings of activities/apps which are running and get an automatic update (actually didn't think it could happen).
Edit
Based on your findings I'd say you have to handle the app is shut down in onDestroy etc. or/and make sure you save everything persistently. Then you might need to have 2 apps where 1 listens to the other being re installed and when that happens it starts it up again (there is an interesting discussion here). If you are targeting api >= 12 then the broadcast action ACTION_MY_PACKAGE_REPLACED might also have interest.

Categories

Resources