ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Protect your Android app content and embrace its security

If you develop an app that has access to secure data (e.g. finance data), it would be great to add an additional security layer. For example, protect its content visually until the user confirms their fingerprint and hide the app’s content in the Recent App menu.

Русская версия статьи.

Photo by yang miao on Unsplash

The user of new iOS versions can open any more or less decent financial app and (likely) they will see that the problem is solved by blurring the content when it’s needed.

But we might have a better solution for Android. Let’s dive in!

Content protection until the user confirms fingerprint

Usecase — user launches the app or resuming it from the background. The app needs to ask a fingerprint but show the content only when biometrics is confirmed.

So, how to hide the content?

The first thing that comes into the head is to blur it.

Starting from Android 12 a new API RenderEffect was added. Android Compose also got a convenient blur modifier. All this is good but what to do with lower APIs?

How blur looks on the Android 12

For Android 8.0+ there is a 3rd-party solution blurkit. Still not ideal, at first, because this is a dependency, at second, my app works with the lower Android versions.

There is one more not obvious moment with the blur itself. If behind the blur there are some movements on UI or any animation is playing — it will still be visible and this distracts.

Eventually, we decided to go with a simpler and straightforward solution — show a static view instead of blurring the content. Less code — fewer bugs.

Example on Xiaomi Mi 10T Pro (Android 10)

The code will be at the end and now let’s talk about the second problem — protect apps content in the Recent Apps.

Protect apps content in the Recent Apps

Naturally, I’ve started from Stackoverflow.

So what we can do:

  1. System solution android:excludeFromRecents — removes the app from the Recents. Possible but really bad UX. I don’t want to explain to the users where the app disappeared.
  2. 3rd-party solutions e.g. myopic-app-switcher that uses blurkit-android under the hood. This option works starting from Android 8.0 and again this is a dependency. We should rely on it and trust that it will blur all the content and not crash with some bug.
  3. System solution FLAG_SECURE — quite an interesting feature. User sees a white screen in the Recents + cannot make app’s screenshot (using default tools). It’s possible to allow making screenshots setting the flag in onPause and clearing it in onResume. So only Recent App feature will be left. It doesn’t work on Android 6.0 and 7.0. Only on Android 8.0.
Android 8.0 (API 26)

4. Show custom view in onPause and hide it in onResume. Perfectly works on Android 8.0+. On lower Androids systems works differently, and the approach doesn’t work. Still a straightforward solution without dependencies and UX issues.

Android 6.0 (API 23)
Android 7.0 (API 24)
Android 8.0 (API 26)
Android 8.0 (API 26)

So basically there is no solution below Android 8 (except hiding the app from Recents at all). We decided to go with №4.

Code

MainActivity.kt

class MainActivity : FragmentActivity() {private var recentAppsView: View? = nulloverride fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
createRecentApppsView()
addRecentAppsView()
}
override fun onResume() {
super.onResume()
viewModel.checkSecurityAuth(
activity = this,
onSuccess = ::removeRecentAppsView,
onFailure = ::finish
)
}
override fun onPause() {
addRecentAppsView()
super.onPause()
}
private fun createRecentApppsView() {
recentAppsView = ComposeView(this).apply { setContent { RecentApps() } }
}
private fun addRecentAppsView() {
removeRecentAppsView()
recentAppsView?.let { (window.decorView as ViewGroup).addView(it) }
}
private fun removeRecentAppsView() =
recentAppsView?.let { (window.decorView as ViewGroup).removeView(it) }
}

RecentApps.kt

@Composable
fun RecentApps() =
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
StrictIcon(painter = painterResource(id = R.drawable.logo_light))
}

Edge case: Xiaomi MIUI

Xiaomi Mi 10T Pro (Android 10) — installed apps are not blurred by default

To enable blurring user has to go to Settings and do it manually. By default, the blur is disabled for 99% of the apps that I installed.

Xiaomi Mi 10T Pro (Android 10) — after blur was enabled

Perhaps this is not the only edge case since there are lots of firmware.

Summary

Hiding app content seems to be simple at the first glance but the fragmentation of Android OS makes it not an easy walk.

So ideal solution is to make minSdk = 26 (Android 8) and use any of the solutions above.

Hope that this article was useful for you.

Happy coding! Follow me on Twitter.

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Alex Zaitsev

Migrating to https://alexzaitsev.substack.com, follow me there! #android #mobile #kmp #kmm #kotlin #multiplatform #flutter #crossplatform

Responses (2)

Write a response

Hello, Alexander!
This point "Protect apps content in the Recent Apps" in number 4 has wrong. It's doesn't work on Android 8 and high. This branch describe about reason…

1

The way you have written the blog is very engaging and the content is top notch. I got to know a lot of things from your blog. The paper is very informative. Also I wish you to present your valuable views on our blogs too if you have time. Also it…