I have an app for the SW2 that has a user option for whether the app should use low-power mode (LPM). Which works fine. The problem is that the SW API only calls my app's supportsLowPowerMode() registration method once, when it first starts up. Meaning that if the user later changes the setting in my app, it won't take effect until the whole shebang restarts.
I've tried a few tricks (like killing my app's process) to force a reload, but nothing's worked so far. My last resort is telling the user that s/he needs to reboot the phone before this takes effect, but that's pretty hokey. Is there a better way?
The solution is not to try to change your response to supportsLowPowerMode() at runtime, but to start and stop your extension instead.
Basically, if your extension can ever support LPM, then it should be returning a value of true in supportsLowPowerMode(). If the extension's LPM usage can change, you handle that by simply doing different things in the onActiveLowPowerModeChange() handler. Specifically, if the user has chosen NOT to use LPM, you want a handler that looks like this:
#Override
public void onActiveLowPowerModeChange(boolean lowPowerModeOn) {
super.onActiveLowPowerModeChange(lowPowerModeOn);
if (lowPowerModeOn) {
// User doesn't want to use LPM, so stop the app on the SW
stopRequest();
}
}
This has the effect of shutting down your extension when the device's backlight turns off, and it'll drop back to its default LPM watchface.
EDIT: I'm reopening this as I've found an unacceptable side effect to the above technique. If your app returns false to supportsLowPowerMode(), the SW2 will keep it running (but paused) in the background when the watch goes to sleep. This means that, when the user "wakes up" the SW2, your app will immediately reappear on screen. Calling stopRequest() (as in my code sample above) disrupts this behavior, requiring the user to reopen your app after awakening the SW2. I've not found any way around this; what's needed is a pauseRequest() instead, but the API doesn't have one.
As far as I know there is no way to change this at runtime. Let me double check with my team though just in case there is a way I don't know about.
Related
We are using intents to switch from one of our apps to another on request, typically a button that is pressed. That way our apps present themselves as a functional unit to the user. We switch back by means of results we hand back.
Recently we implemented a switch that is not triggered by an immediate user interaction, but by an implicit event. When navigating inside one app we use an activity from another app as a drop-in-replacement for some feature in the first app. So the first app sends the user to the second app if it detects that second app is installed.
I realize we have an issue here: if that second app is buggy, crashes, then the first app is broken. Since it switches to the second back again and again without the user being able to alter that behavior. So apparently it makes sense to enable the first app to realize that the second app just crashed. So that it would not switch over next time, although that second app is indeed installed.
This does not work out of the box, since the first app never is informed about the crash of the second app. Instead that app crashes, the OS hint comes app ("Unfortunately XY just crshed") and that's it. The flow never returns to the first app, so there is no return value to evaluate or similar.
So my question is: how can I enable the first app to learn about the fact that the second app just crashed?
I thought about registering a global handler for uncaught exceptions in the second app. That handler would have to somehow signal to the first app that it is currently crashing. Either by sending a specific intent itself (sounds ugly) or by handing back a result (is that possible at all?).
Is there a common practice for this? What is it? What other options exist? Or is that question itself obsolete, since I only failed to see how this is meant to be done?
UPDATE:
Interesting enough I learend that this actually works if the crash in that second app is raised not upon startup but much later ... In that case indeed the first app is in foreground again and is indeed able to detect the crash: the result is "CANCELED" in that case, which is perfectly fine for me.
The the question is reduced to "early crashes" and how this can be handled. Or, the other way round: what is the difference between early and later crashes in that second app?
You technically can't detect that the app crashed, but you can keep something like a "failure counter" in your 1st app. Basically, every time you're about to launch app #2, save a variable in SharedPreferences, something like launchAttempts. You'll want to increment it every time right before you launch app #2, and then decrement it in your onActivityResult() when a result is returned. Then you can set a threshold for how many failed attempts would qualify for "too many", and stop launching app #2
With the new Android 12 operating system, the user now has the ability to completely disable microphone and camera usage from ALL apps. This is actually a good thing, letting users easily control privacy.
If an app starts and has permission to use the microphone and the camera AND the user has disabled all access to either of these hardware, Android 12 automatically pops up an alert asking the user to re-enable the microphone or camera, or to continue with the hardware disabled for the app.
Also, on creation, the app can simply check when starting to see if the needed hardware is enabled, and can also prompt the user further or handle the condition as the app sees fit.
But what if the user disables the microphone or camera while the app is running? I can't seem to find any interfaces for something like onMicrophoneEnabled() or even a Broadcast of such an event.
It's possible to check every time onResume() is called, but I was hoping there'd be a more elegant solution.
If anyone knows of something that my app can use to capture this when the user has made changes either way, please let me know.
After carefully reading the google docs (https://developer.android.com/training/permissions/explaining-access#toggles) on their implementation of the user enable/disable of the camera and microphone I discovered something very interesting:
Apps are explicitly forbidden from knowing if the user has done any of these actions. So of course there is no way to get notified of these changes: it is by design.
If the user turns off the camera this way, the app will still get a camera feed, but it will be black. Similarly the microphone will still work, but we'll get only silence. This is a feature--a way to ensure privacy.
The operating system will remind users that they have disabled the microphone or camera and provide a chance to re-enable the hardware, which is nice. But the app is completely in the dark (hehe).
Another way to think of it: Just like putting a piece of tape over your camera or your thumb over the microphone. Only this time it's done by the operating system. This way a spy program or some other nefarious software will still think it's working and not try to bypass or give up.
This also explains why testing during onResume() or onWindowFocusChanged() didn't work either. I was getting results that didn't align with the settings (they aligned with current permissions).
So to answer my question: There is no way to be notified. That is the point.
About Android (6.0 to the last version)
I'm developing an app and we want that the user, once he accepts all the terms, don't be able to kill the process or force stop the app. Honestly, I'm completely lost right now, because on the last versions of android, and specially some brands like Xiaomi, we are having a lot of trouble with it, and we don't know how to act right now.
In the case that it could not be possible, could at least get an alert whenever the user is killing the app?
Thanks!!
It is not possible to prevent the user from killing an app. Android is a unique system where the app has no direct control over its lifecycle but the system has. The system can (and will, when required) kill the app or any of its processes at its own will. To make your app aware of these changes, the android framework provides for various callbacks such as onPause, onStop and onDestroy which are called in succession when the user kills the app.
Side Note : There is no guarantee that onDestroy() will be completely executed when the app is killed. Do not place essential code there.
Of course, you can block or try to prevent the user from closing your app by overriding the back, home and recent buttons but it is highly recommended not to do so. Even if you do so successfully, the user has other means to close your app such as rebooting their phone.
So what to do?
You are looking for a kiosk mode app. Kiosk mode is used for single purpose phones such as at a restaurant or for a cab driver. Kiosk mode apps lock down the user to only a specific app (or a specific set of apps).
For normal apps, it is not possible to prevent the user from force closing your app. You can only get alerts by checking for lifecycle changes as described above. Moreover, it is not at all recommended to change the natural behavior of the hardware buttons on android. The user can still find a way to close your app. If your app is doing something really essential which should proceed in the background, consider using a service for that instead. Also, the user can uninstall your app at anytime if they find your app being too intrusive and you won't be able to do anything in that scenario.
Tl;dr: Use kiosk mode to prevent the user from exiting the app. This will only allow the user to access your app(s) in their device.
Usually you cannot! Even if you try to disable some buttons, user can always stop app or restart device. In addition at times, the OS will stop the App. Your responsibility as a programmer is to program around this, and give the user the feel that it never stopped. If you are doing background monitoring, you will need to use service. Users will still be able to stop service. Having said that, you can set your app as a Device Administration app, see here, which may disallow stopping, but unless you are distributing internally to a company, noone will install.
I'm trying to start an app upon the first boot of the device before the keyguard appears. I need to ensure the first thing the user sees after the boot animation (which I've also changed) is this app. My app is just three screens of text in fullscreen mode with a next button in between them.
I realize that for most cases, this would be a terrible user experience. However, the phones we're shipping have a very specific purpose and because of this I need to meet the following criteria:
my app needs to be the first thing the user sees (after the boot animation of course) when they take the phone out of the box and power it on for the first time.
after the first boot, the phone should function as normal (i.e the keyguard should appear upon bootup instead of my app).
this only needs to work for lollipop since that's the android version we're shipping.
I can modify the Android framework if needed, but a solution where I don't have to is preferred.
My (Failed) Approach
Create an app that starts upon boot. Have the app dismiss the keyguard as the first thing it does.
The problem I found with this approach is the keyguard code is called before the app initialization code so the user sees the keyguard briefly and then sees my app.
A Possible Solution
I think the best way to do this is to add code in the framework to call my app before calling the keyguard. I'm imagining having a boolean that's used to keep track of whether it's the first time the device is powered on. If that boolean is true, open the app. If not, open the keyguard.
The problem is there's a lot of code in the android userspace boot process and I have a quickly-approaching deadline (don't we all?). How can I modify the framework code to show my app before the keyguard?
If there's a better way, please let me know that too!
I want to create a password-protected android application. The password should be asked when the task is started or when it comes to foreground.
The complex part is that my app can invoke device inbuilt camera application to capture photo/video, so I cannot control that activity.
So the behavior should be that whenever user starts/returns to my app then password should be asked except for the scenario when he is returning from camera that I sent him to in the first place.
I have thought following ideas, but none of them solve my problem completely, the best one I could think of is
1) Set a flag(flagA) while sending the user to camera, then in a service keep checking that the foreground app is our app. When the foreground app is not our app then set another flag(flagB) to indicate that our app has gone to background. When the app in foreground is our app again, then check if flagA is false (we didnt send him to camera) and flagB is true (app is coming from background). Then show the password screen
Problems
1) The polling interval must be small like 3-4 seconds, so that foreground is detected quickly. This drains the battery.
Thanks
A few ideas come to mind.
This is just a quick idea of mine so it might not be useful but considering you haven't told us what you've already tried / have in mind we don't have a lot to go with.
You'll need at least 2 Activities to handle the whole password idea.
Firstly, when you start the app, run Activity A. This will ask for the password (assuming the password is always the same). If the password is correct -> start an intent with Activity B.
If the password is incorrect, close the app.
In B, give the user the option to invoke the camera. After using the camera, return to Activity B.
It doesn't get much better with the amount of info you've given us, but it should give you an idea on how to start.
I have solved the problem partially
1) Have a static long variable to track the time between onPause() and onResume(). During normal app operation this time is under 1 second, but if app goes to background and comes to foreground then this duration is more than 1 second. So in onResume() if the duration is more than 1 second then show the Password screen.
2) To handle the camera problem I am having a flag to detect whether I opened the camera, if that flag is set then dont ask for password in onResume().
This solution is not fool proof but works in most scenarios.