I'm developing a tracking application and I need to prevent users from turning off the basic sensors used to determine the location. I can not modify the devices ROM or have root access (or at least it would be very desirable to had not), but I thought of using the Device Administration API to perform these functions through the Profile Owner or Device Owner modes. I'm basically looking for a method to block these functions in Android settings.
I'm unsure about whether this is possible and how to do it, I have not found examples in GitHub for applications that have implemented this. Could anyone give me a light, some example or specific documentation?
I tried to follow these three documentations, without success in finding a solution to this specific feature:
https://source.android.com/devices/tech/admin
https://developer.android.com/guide/topics/admin/device-admin
https://developers.google.com/android/management/introduction
This is an excerpt from what I've been trying:
setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true);
setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, active);
setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, active);
private void setUserRestriction(String restriction, boolean disallow){
if (disallow) {
mDevicePolicyManager.addUserRestriction(mAdminComponentName, restriction);
} else {
mDevicePolicyManager.clearUserRestriction(mAdminComponentName,
restriction);
}
}
DISALLOW_CONFIG_BLUETOOTH
Added in API level 18
public static final String DISALLOW_CONFIG_BLUETOOTH
Specifies if a user is disallowed from configuring bluetooth. This does not restrict the user from turning bluetooth on or off. The default value is false.
This restriction doesn't prevent the user from using bluetooth. For disallowing usage of bluetooth completely on the device, use DISALLOW_BLUETOOTH.
This restriction has no effect in a managed profile.
Key for user restrictions.
Type: Boolean
You cannot prevent them from turning GPS, WIFI and Bluetooth off. What you can do is have an implementation as below or use this library.
https://github.com/KI-labs/gps-permission-checks-livedata
You can't, obviously for security reasons. If you want to achive something like that you'll probably need to modify the devices ROM. You should create a BroadcastReceiver and keep tracking Internet and Bluetooth connection changes, than you can properly handle it when user disconnect them pausing the service, showing a dialog, finishing the application or whatever you need to do.
It would be pretty weird if an app could have some control of user settings, imagine if you install an app, then suddently you can't disable wi-fi anymore until you unistall it. You can't do that for a good reason
Preventing bluetooth/wifi disconnection will also prevent usage of aircraft mode, that is a security issue bounded in the ROM and not overridable.
As suggested above your option is to monitor for wifi/bluetooth/gps deactivations and prompt the user with an alert.
By the way, GPS is not affected by aircraft mode, as it's a pure receiver and doesn't make active transmissions. In that case GPS will be always active and collecting informations (if active and the phone is not in power save mode, aka relying on wifi location). I suggest you to check if the user activated aircraft mode, in order to be less annoying with your alerts (air mode is mandatory in same situations, and should be considered "legal" by your application, and maybe less critical than an user voluntary disconnection
In simple words, You cannot, but you can listen to when wifi is enabled/connected, and you can prompt a dialog stating the reason.
This way it gives the user a more concise grip on what needs to be done.
Just a suggestion
Related
I have an Android VPN application. When I fire the intent to start the VPN (via VPNService.prepare), it fails immediately if there's an always-on VPN already configured on the device. That seems reasonable, but I'd like to be able to easily detect that case, so I can show a helpful message to the user.
By 'always on' I mean the specific VPN always-on Android VPN flag: https://developer.android.com/guide/topics/connectivity/vpn#always-on
I can't seem to find a way to access that info, even though it is used internally in Android (e.g. here but that getAlwaysOnVpnPackage doesn't seem to be available publicly AFAICT).
The best option I've seen is Check if a VPN connection is active in Android?, which will tell you if any VPN connection is currently active, but that's not enough, because:
I don't want to know about temporary VPN connections: I'm only interested if it's an always-on VPN connection.
Sometimes 'always-on' connections aren't actually always on. If you have a disconnected connection and set it as 'always-on', it's configured as such, and blocks all other VPN installs, but there's no network connection created (Android shows a persistent warning instead, which takes you to the other app to activate the connection). Because there's no connection, the above technique doesn't work. I still need to detect this case, since it still blocks my VPN setup.
Is there any way to check whether the device currently has a VPN configured as 'always-on'?
You can use this method
private fun isVpnAlwaysOn(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
val alwaysOn = Settings.Secure.getString(contentResolver, "always_on_vpn_app")
return !alwaysOn.isNullOrEmpty()
} else false
}
'alwaysOn' contains the package name of the app for which always-on is configured.
In the end, it seems this isn't possible on a normal device any way that I can find. I think is possible if you're a device admin, but that requires managed enterprise devices etc.
For now, I've handled this by watching for near-instant (less than 200ms) VPN setup failures (between running startActivityForResult(vpnIntent) and receiving onActivityResult with RESULT_CANCELED) and then showing a helpful message in that case.
Full implementation is in https://github.com/httptoolkit/httptoolkit-android/commit/928fbf92a4f868042789471be0d42800a226194b in case you're trying to do the same.
I'm using Connectivity library to see the internet(Wifi or network data) is active and saving the data in Storage if there is no connectivity(Offline) and synchronize with server when connected to internet. I'm having issues in public places where the internet is consistently unstable(esp. in basements, offices, stores, Coffee shops etc., where there is internet connects in and out). When I check the Connectivity is active but by the time I started synchronizing internet goes offline (Something like this). this leads inconsistent /partial updates to the server. Also, in coffee shops and Airports where wifi gets connected but there will be "Agree Terms and Conditions" page to connect. Not all the browsers will take you to that page directly after joining the Wifi. In that case I see the wifi is active in Mobile but actually it is not activated until I accept the terms and Conditions in IE or some specific browser. Any one else having difficulty in handling these kind of issue from Mobile App?
My App - Hangs on Login screen if I'm trying to login when there is in-stable/in consistent internet.It thinks wifi is there but not.
IF I'm on a screen where I will display list, screen will show blank for infinite time. Adding timeout for server request/response or something will help such scenario.
I know I'm not handling this case in code to show some kind of error message but I need some guidance to detect these conditions suing CN1 API to handle through my app.Please advise.
Code:
public boolean isOffline() {
if (Connectivity.isConnected() && forceOffline) {
relogin();
}
return forceOffline || !Connectivity.isConnected();
}
The problem is that it's impossible to detect online/offline properly as you might be connected to a local wifi/network but it might be a bad connection that won't let you reach the server. As far as the library is concerned you are connected... But in reality you don't have a connection.
First set the timeout values in NetworkManager to lower values to improve the experience although this won't solve a situation where data starts downloading and stops in the middle.
Next you need to handle these cases one by one and provide the user with a way to toggle the offline mode. Unfortunately there is no silver bullet for network reliability. You just need to go through every path and try to detect these things.
We are developing a locked down "kiosk-style" Android app on a stock Samsung tablet, which is mounted in customer vehicles. We would like to be able to allow customers to edit their wifi settings, without giving them access to the rest of the Settings app (e.g. Launcher, accounts, etc)
We have been able to launch the Wifi Settings activity, but it allows the user to go into other areas.
I'm not sure whether it's possible to create a custom interface for connecting to wifi, but even if it were possible, this seems fragile and a lot of work for something quite simple.
Is there any way to solve this well?
I would create a device policy controller app that is provisioned on the device as a device owner using Android Enterprise (Android for Work) APIs.
https://developers.google.com/android/work/dpc/build-dpc
As a device owner, you can set your app in lock task mode which is generally used for kiosks.
https://developer.android.com/work/cosu.html
Then, you can set user restrictions:
addUserRestriction api
user restrictions list
The user restrictions don't cover everything in the settings app, but the coverage is pretty good.
Then I would provision it using NFC or QR code reader from the Google Setup Wizard welcome screen.
https://github.com/googlesamples/android-NfcProvisioning
You might want to also look at existing open source EMM/MDM implementations that already exist such as WSO2.
Other references:
How to enable task locking in Android 5.0 production devices
How to make sure there is only one app
I was also working on Kiosk Type applications and we have to give options for Change wifi and Display Settings So we have used these commands on Button click for Wifi And Display
Settings
btnWifiSetting.setOnClickListener {
startActivityForResult( Intent(android.provider.Settings.ACTION_WIFI_SETTINGS), 0);
}
And For Display Setting
btnDisplay.setOnClickListener {
startActivityForResult(Intent(android.provider.Settings.ACTION_DISPLAY_SETTINGS),0)
}
And you can also check the full list of Available Commands here
https://ourcodeworld.com/articles/read/318/how-to-open-android-settings-programmatically-with-java
try LineAgeOS
https://lineageos.org/
Your requirement needs to access OS System level, this way you have access and customize the WIFI settings before releasing the phone itself
can you try this way.
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(false);
Tools_WiFi.setImageResource(R.drawable.tool_wifi_off);
} else {
wifiManager.setWifiEnabled(true);
Tools_WiFi.setImageResource(R.drawable.tool_wifi_on);
}
You can try this:
startActivityForResult(new Intent(Settings.ACTION_WIFI_SETTINGS), 0);
Hope it helps you.
My app is working fine, until Android 5.0.2 doesn't allow third party app to connect to HID device over Bluetooth low energy.
myGatt.setCharacteristicNotification(gattChar, true);
06-01 17:39:35.356: W/BluetoothGatt(21599):
java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission:Neither
user 10157 nor current process has android.permission.BLUETOOTH_PRIVILEGED.
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
BLUETOOTH_PRIVILEGED permission doesn't work on a third party app. It's only for system or manufacturer apps.
The latest changes from Android note:
Enforce BLUETOOTH_PRIVILEGED permission for HID-over-GATT
https://android.googlesource.com/platform/packages/apps/Bluetooth/+/02bebee
Code snippet:
private static final UUID[] HID_UUIDS = {
UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB") };
if (isHidUuid(charUuid)) enforcePrivilegedPermission();
My question: is there a way to overwrite HID_UUIDS or enforcePrivilegedPermission? Can I use reflection to by pass it?
Every times Android released a new version, it breaks the previous code.
Thanks!
The question is old, but still worth answering.
The HID (and FIDO https://fidoalliance.org/) service is protected and indeed requires system permission source. Only apps signed with the system key may use this service, that is only Bluetooth settings. This is to ensure that 3rd party apps are not able to listen to keys typed on a wireless keyboards, as all notifications and indications are transferred to all BluetoothGatt objects. Without this protection you would be able to connect to a HID device (you still can), enable notifications using gatt.setCharacteristicNotification(.., true) and receive updates whenever a key is typed. With a bit of knowledge about Report characteristics you can then get all the keys and mouse positions, including passwords, etc. So it's not a break, but a bug fix. On KitKat you still may do this.
The only solution is to compile your own AOSP Android version and sign your app with the same key. Otherwise it would be useless protection.
Btw, starting form Android 8 or perhaps earlier you don't get SecurityException. The call just returns true as if any other and you never get any callback.
This might have been changed here: https://android.googlesource.com/platform/packages/apps/Bluetooth/+/32dc7a6b919375aede777f3c821fa316d85449ae%5E%21/#F2
I'm writing small app for our workers, to work in terrain, and I have some idea. We want to track their location for better logistics and better work control.
App is not a problem for me, but button to turning on/off GPS/Locations Manager. Is there any possibility to set GPS always ON, and unable to turn OFF, or maybe something that will detect turning OFF, and turn GPS back ON every few seconds (?bash script?).
I've rooted my device (GALAXY GIO) and I have full access to CLI. I know how to disable/enable almost every device, but GPS is still puzzle for me...
Is it possible to do something like that without changing ROM? Current ROM is 2.3.6 Gingerbread.
Thanks in advance!, Mike
Use services and place this code in your services.
String provider = Settings.Secure.getString(getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if (!provider.contains("gps")) {
// if gps is disabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings","com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
/*
* Toast.makeText(getApplicationContext(), "GPS On Success",
* Toast.LENGTH_SHORT).show();
*/
}
There's no reliable way of doing what you need, other than exploits (which looks like only work for 2.2 and some 2.3 builds) and custom ROMs (If you can find one that does this).
In Android, the user has control over most functions. Android is aimed for personal use, and it's not very well suited for this kind things. You migh be better off switching to another platform (e.g.: BlackBerry) that allowed you to do this, or even reading data via bluetooth from a GPS tracking device that is turned on always. They can still disable bluetooth, so you migh need to search for a fully autonomous GPS tracking device (there are many available in the market, some of them also have a SIM card so they can send data in real time).
As a final note, I'd say most workers will gladly enable the GPS if they are required to do so, and in case they disable it, you can still detect it and report to a WS or log, in order to ask them for an explanation later.