How to check if "verify app" is enabled or disabled programmatically - android

I've a security requirement to alert users if google's "verify app" is disabled on app launch. The problem is that I dont know any way to check whether "verify app" is disabled or not.
I tried to use the code below, but it's always returning 1.
int verifierInt = -1;
if (Build.VERSION.SDK_INT >= 17) {
verifierInt = Settings.Global.getInt(context.getContentResolver(), "package_verifier_enable", -1);
} else if (Build.VERSION.SDK_INT >= 14) {
verifierInt = Settings.Secure.getInt(context.getContentResolver(), "verifier_enable", -1);
} else {
// No package verification option before API Level 14
}
boolean isVerifyAppEnabled = verifierInt == 1;
Also, as a requirement, want user to be navigated to the "verifiy app" settings if this feature is disabled.

You should check like this:
Settings.Global.getInt(context.getContentResolver(), "verifier_verify_adb_installs", -1);

Reading preferences, won't help anymore as android don't update preferences now. So basically reading preferences value for google Verify won't work.
Please use below SaftyNet callbacks to verify google protect.
SafetyNet.getClient(context)
.isVerifyAppsEnabled()
.addOnCompleteListener(new OnCompleteListener<SafetyNetApi.VerifyAppsUserResponse>() {
#Override
public void onComplete(#NonNull Task<SafetyNetApi.VerifyAppsUserResponse> task) {
---
}
});

Related

Biometrics prompt (face authentication) when camera access is blocked (Android 12 - Pixel)

Android 12 came up with a new Privacy Settings to disable access to the Camera and Mic sensors, which is referred as Toggles in the docs.
As it is mentioned in the docs:
the system reminds the user that the device-wide toggle is turned off
However, it seems that it only reminds the user when requesting the Camera permission and not when trying to authenticate the user using biometrics (face authentication on Pixel phones, which guess what!? It uses the camera). [I'm using AndroidX biometrics library]
Is there any way to find out if the Camera access has been blocked by the user without requesting any permission?
I guess the note in the docs didn't take into account that the app might use face authentication:
Note: The toggles mentioned in this section shouldn't require changes to your app's logic, as long as you follow privacy best practices.
Notes:
You can't register a new face in Settings when camera access is blocked. The Settings app does not show any error, just a blank camera feed
I am using Pixel 4 (Android 12)
The feature 'Join Wi-Fi by scanning a QR code' does not work and neither shows a feedback to the user if Camera access is blocked (Pixel 5)
So, I also looking for a solution - a have a biometric library and few reports appear in DM with the same problem - FaceUnlock doesn't work on Pixel 4 when the camera 'muted'
For now, still now fix, but maybe my research can help someone.
1. I checked the new API for PrivacyToggle's.
Android 12 introduces a new SensorPrivacyManager with supportsSensorToggle() method - it returns TRUE in case of device able to 'mute' camera or mic.
val sensorPrivacyManager = applicationContext
.getSystemService(SensorPrivacyManager::class.java)
as SensorPrivacyManager
val supportsMicrophoneToggle = sensorPrivacyManager
.supportsSensorToggle(Sensors.MICROPHONE)
val supportsCameraToggle = sensorPrivacyManager
.supportsSensorToggle(Sensors.CAMERA)
If you look into SensorPrivacyManager, you can find that it provides some more useful methods, so I develop the next code:
fun isCameraAccessible(): Boolean {
return !checkIsPrivacyToggled(SensorPrivacyManager.Sensors.CAMERA)
}
#SuppressLint("PrivateApi")
private fun checkIsPrivacyToggled(sensor: Int): Boolean {
val sensorPrivacyManager: SensorPrivacyManager =
appContext.getSystemService(SensorPrivacyManager::class.java)
if (sensorPrivacyManager.supportsSensorToggle(sensor)) {
val userHandleField = UserHandle::class.java.getDeclaredField("USER_CURRENT")
userHandleField.isAccessible = true
val userHandle = userHandleField.get(null) as Int
val m = SensorPrivacyManager::class.java.getDeclaredMethod(
"isSensorPrivacyEnabled",
Int::class.javaPrimitiveType,
Int::class.javaPrimitiveType
)
m.isAccessible = true
return m.invoke(
sensorPrivacyManager,
sensor,
userHandle
) as Boolean
}
return false
}
Unfortunately, the service rejects this call due to SecurityException - missing android.permission.OBSERVE_SENSOR_PRIVACY, even if we declare it in Manifest.
At least on emulator.
2. We can try to identify a new "sensor-in-use" indicator
fun checkForIndicator(){
findViewById<View>(Window.ID_ANDROID_CONTENT)?.let {
it.setOnApplyWindowInsetsListener { view, windowInsets ->
val indicatorBounds = windowInsets.privacyIndicatorBounds
if(indicatorBounds !=null){
Toast.makeText(view.context, "Camera-in-use detected", Toast.LENGTH_LONG).show()
}
// change your UI to avoid overlapping
windowInsets
}
}
}
I didn't test this code (no real device), but as for me - it's not very useful, because we can check the camera indicator only AFTER we start Biometric Auth flow, when I need to understand is camera accessible BEFORE Biometric Auth started.
3. Because of PrivicyToogle related to QuickSettings, I decide that perhaps exists a way how Tiles determinate current Privacy Toggle state.
But this API use a very interesting solution - it does not use Settings.Global or Settings.Security section, instead, all preferences saved in "system/sensor_privacy.xml" and not accessible for 3rd party apps.
See SensorPrivacyService.java
I believe that exists a way how to find that Camera is blocked, but seems like some deeper research required
UPDATED 28/10/2021
So after some digging in AOSP sources, I found that APP_OP_CAMERA permission reflects the "blocking" state.
Just call if(SensorPrivacyCheck.isCameraBlocked()){ return } - this call also notify the system to show the "Unblock" dialog
Example
Solution:
#TargetApi(Build.VERSION_CODES.S)
#RestrictTo(RestrictTo.Scope.LIBRARY)
object SensorPrivacyCheck {
fun isMicrophoneBlocked(): Boolean {
return Utils.isAtLeastS && checkIsPrivacyToggled(SensorPrivacyManager.Sensors.MICROPHONE)
}
fun isCameraBlocked(): Boolean {
return Utils.isAtLeastS && checkIsPrivacyToggled(SensorPrivacyManager.Sensors.CAMERA)
}
#SuppressLint("PrivateApi", "BlockedPrivateApi")
private fun checkIsPrivacyToggled(sensor: Int): Boolean {
val sensorPrivacyManager: SensorPrivacyManager =
AndroidContext.appContext.getSystemService(SensorPrivacyManager::class.java)
if (sensorPrivacyManager.supportsSensorToggle(sensor)) {
try {
val permissionToOp: String =
AppOpCompatConstants.getAppOpFromPermission(
if (sensor == SensorPrivacyManager.Sensors.CAMERA)
Manifest.permission.CAMERA else Manifest.permission.RECORD_AUDIO
) ?: return false
val noteOp: Int = try {
AppOpsManagerCompat.noteOpNoThrow(
AndroidContext.appContext,
permissionToOp,
Process.myUid(),
AndroidContext.appContext.packageName
)
} catch (ignored: Throwable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
PermissionUtils.appOpPermissionsCheckMiui(
permissionToOp,
Process.myUid(),
AndroidContext.appContext.packageName
) else AppOpsManagerCompat.MODE_IGNORED
}
return noteOp != AppOpsManagerCompat.MODE_ALLOWED
} catch (e: Throwable) {
e.printStackTrace()
}
}
return false
}
}

Unity toggle to save password works flawlessly in Unity but doesn't work as expected

I have a problem with saving users login and password in PlayerPrefs. While it works very well in Unity (if the password is saved, the toggle is on on start) it doesn't work on Android (if the password is not saved, the toggle is still on on start). Before building for Android, I'm making sure that the toggle is off and password is not saved.
Here is my code:
void LoadUserPassOnStart(){
if(PlayerPrefs.HasKey("userSaved")){
if(PlayerPrefs.GetInt("userSaved") == 1){
loginEmail.text = PlayerPrefs.GetString("savedUsername");
loginPassword.text = PlayerPrefs.GetString("savedPass");
saveUserPassToggle.isOn = true;
int saved = PlayerPrefs.GetInt("userSaved");
Debug.Log(saved);
}
else if(PlayerPrefs.GetInt("userSaved") == 0)
{
saveUserPassToggle.isOn = false;
Debug.Log("Called false");
}
}
}
void SaveUserPass(Toggle saveUserPassToggle){
if(saveUserPassToggle.isOn){
PlayerPrefs.SetString("savedUsername", loginEmail.text);
PlayerPrefs.SetString("savedPass", loginPassword.text);
PlayerPrefs.SetInt("userSaved", 1);
Debug.Log("Saved");
}
else if(!saveUserPassToggle.isOn){
PlayerPrefs.SetString("savedUsername", "");
PlayerPrefs.SetString("savedPass", "");
PlayerPrefs.SetInt("userSaved", 0);
Debug.Log("Nulled");
}
}
I'm calling LoadUserPassOnStart in Start(){} and I'm adding SaveUserPass to the toggle:
saveUserPassToggle.onValueChanged.AddListener(delegate{ SaveUserPass(saveUserPassToggle);});
This issue drives me nuts, will be very grateful for suggestions.
try using PlayerPrefs.Save(); after Set the keys.
The issue was caused by the fact, that Android stores the info from PlayerPrefs even after the game is uninstalled.

How to check if my app has been configured battery optimized on Android?

I'm wondering if there's any way in React Native that allows us to know if user has been selected "Battery Optimized" for our app?
in native android,You can use PowerManager.isIgnoringBatteryOptimizations() boolean to determine if an application is already ignoring optimizations ie whether the app is on the whitelist .
#ReactMethod public void isAppIgnoringBatteryOptimization(Callback callback){
String packageName = getReactApplicationContext().getPackageName();
PowerManager pm = (PowerManager) getReactApplicationContext().getSystemService(Context.POWER_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
callback.invoke(pm.isIgnoringBatteryOptimizations(packageName));
}else{
callback.invoke(true);
}
and then in js
isAppIgnoringBatteryOptimization: function(callback) {
jobModule.isAppIgnoringBatteryOptimization(ignoringOptimization => {
if (ignoringOptimization != null) {
callback("", ignoringOptimization);
} else {
callback("error", null);
}
});
}
https://github.com/vikeri/react-native-background-job/ is a good library that sees all the edge cases of background execution
If you want to ask user to turn it off - ask for
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission
from
https://developer.android.com/reference/android/provider/Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS

Android - How to check if Developer option is enabled

How can I check if the user has developer option enabled on its device?
(not with adb comunication active, or debug USB active, I need to know only if Developer Option are enabled).
I've tried this solution:
How to check programmatically whether app is running in debug mode or not?
but it doesn't work for me.
Thanks in advance
try this:
int adb = Settings.Secure.getInt(this.getContentResolver(),
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0);
You should use
getInt or another in Settings.Global
with
DEVELOPMENT_SETTINGS_ENABLED
Edit :
Below API 17, it is the same but with Settings.Secure
Here's a method that returns true if developer mode is enabled for all devices at Android 4.1 or above (API 16), returns false if developer mode is not enabled on such devices, and returns false on all earlier Android devices down to 1.0.
#android.annotation.TargetApi(17) public boolean isDevMode() {
if(Integer.valueOf(android.os.Build.VERSION.SDK) == 16) {
return android.provider.Settings.Secure.getInt(getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED , 0) != 0;
} else if (Integer.valueOf(android.os.Build.VERSION.SDK) >= 17) {
return android.provider.Settings.Secure.getInt(getApplicationContext().getContentResolver(),
android.provider.Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0) != 0;
} else return false;
}
Kotlin solution:
#RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
fun isDevMode(context: Context): Boolean {
return when {
Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN -> {
Settings.Secure.getInt(context.contentResolver,
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0
}
Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN -> {
#Suppress("DEPRECATION")
Settings.Secure.getInt(context.contentResolver,
Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0
}
else -> false
}
}
It's Simple to Find -- Developer Mode is On or Not!!!
Java solution:
if (PreferenceHelper.isDevMode(context)) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Please Turn Off Developer Option \n" +
" \n" +
" Go to Settings > Search developer options and toggle them off.");
builder.setCancelable(false);
builder.setNegativeButton(" Ok ", (dialog, which) -> {
dialog.dismiss();
finish();
});
builder.setPositiveButton(" Turn Off ", (dialog, which) -> {
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
alertDialog.getButton(android.app.AlertDialog.BUTTON_POSITIVE).setTextColor(Color.parseColor("#37367C"));
return;
}
Cordova or Ionic solution :
https://github.com/Secullum/cordova-plugin-devoptionschecker
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
cordova.plugins.devoptionschecker.check(successCallback, errorCallback);
}
function successCallback(result) {
// json object which returns devOptionsEnabled: true - enabled, false - disabled
console.log(result);
}
function errorCallback(error) {
console.log(error);
}
I had search for so many methods finally i got the method and its is working fine in android studio also in app
it is mentioned below
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));

Android UserManager: Check if user is owner (admin)

Im developing an app with the latest android version (4.2.1 API-Level 17) for tablets with multiuser capabilities.
I want to restrict certain features (like the access to the app preferences) to the owner of the tablet (that is the user who can add and remove other user accounts)
is there any way i can find out if the current user is the owner?
i read through the UserManager and UserHandle API docs but couldn't find a function that allows me to check for it.
have i missed something or is there another way to do that?
Similar but without reflection:
static boolean isAdminUser(Context context)
{
UserHandle uh = Process.myUserHandle();
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if(null != um)
{
long userSerialNumber = um.getSerialNumberForUser(uh);
Log.d(TAG, "userSerialNumber = " + userSerialNumber);
return 0 == userSerialNumber;
}
else
return false;
}
You can create an extension property in Kotlin to make it simpler:
val UserManager.isCurrentUserDeviceOwner: Boolean
get() = if (SDK_INT >= 23) isSystemUser
else if (SDK_INT >= 17) getSerialNumberForUser(Process.myUserHandle()) == 0L
else true
Then, using it is as simple as the following:
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
if (userManager.isCurrentUserDeviceOwner) TODO() else TODO()
You can further reduce boilerplate by using global system services definitions that makes userManager and other Android System Services available anywhere in your Kotlin code, with code included in this library I made: https://github.com/LouisCAD/Splitties/tree/master/systemservices
After researching further i found out that the multiuser api is not functional yet, it cant really be used for anything. there is a hack though for checking if the user is the owner using reflections:
public boolean isCurrentUserOwner(Context context)
{
try
{
Method getUserHandle = UserManager.class.getMethod("getUserHandle");
int userHandle = (Integer) getUserHandle.invoke(context.getSystemService(Context.USER_SERVICE));
return userHandle == 0;
}
catch (Exception ex)
{
return false;
}
}
This works for me on the Nexus 7 and Nexus 10 with Android 4.2.1
Its very dirty. so i wouldnt recommend using it unless you are making an app thats device and version specific

Categories

Resources