14

I am trying to find a way of reading the new settings for mock locations in Android M.

Before Android M, the mock location setting was a toggle option called "use mock locations", and it was readable with this setting: Settings.Secure.ALLOW_MOCK_LOCATION

With Android M, the mock location setting is an app to select for mock locations, so it is a multi-elements list, which selected element can be "none".

That thread has a solution for determining the source of the location update when listening for locations, but unfortunately I would like to read the setting itself: How to check for Mock Location in Android Marshmallow?

I would like to read whether there is a selected app for mock locations or not, and ideally the selected app as well. Any idea about how to do that are welcome!

Community
  • 1
  • 1
androidseb
  • 1,257
  • 2
  • 14
  • 17

4 Answers4

21

Ok digging through the android developer site this is what I have come up with. You have to use the AppOpsManager. checkOp("android:mock_location", "yourUID", "com.your.package.name")

I think you can check if a different app is enabled by changing the package name.

public boolean isMockLocationEnabled(){
    boolean isMockLocation = false;
    try {
        //if marshmallow
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            AppOpsManager opsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
            isMockLocation = (opsManager.checkOp(AppOpsManager.OPSTR_MOCK_LOCATION, android.os.Process.myUid(), BuildConfig.APPLICATION_ID)== AppOpsManager.MODE_ALLOWED);
        } else {
            // in marshmallow this will always return true
            isMockLocation = !android.provider.Settings.Secure.getString(mContext.getContentResolver(), "mock_location").equals("0");
        }
    } catch (Exception e) {
        return isMockLocation;
    }
    return isMockLocation;
}
Marlon
  • 1,839
  • 2
  • 19
  • 42
  • 4
    Thank you for you answer. Unfortunately this answer only allows to check whether my own app has access to mock locations, it does not allow to check for the system setting itself: for example if another app is selected for mock location. – androidseb Oct 14 '15 at 17:49
  • @androidseb I have exactly same requirement as yours. Did you find any solution to your requirement. Please guide me as well. Thanks! Moreover I tried Marlon's solution on Marshmallow and faced an issue. In first attempt there was no app selected for mocking, hence I received expected result from this code. Then I selected FakeGPS mocking app in settings, I still got expected result(Security Exception). Then I selected Nothing in mocking app, but this code still gives Security Exception. I went ahead and stopped the FakeGPS service, still it didn't help. Any idea what might be causing this? – LoveForDroid Jun 02 '16 at 15:13
  • @LoveForDroid I have not found a solution for scanning which app is selected for mock location, I think your app needs system access permissions (aka needs to be a system app) for Marlon's solution to work, and since your app does not have permission, that is probably why you get a Security Exception. I ended up taking a different approach and checking the Location updates like suggested here: http://stackoverflow.com/questions/32668494/how-to-check-for-mock-location-in-android-marshmallow – androidseb Jun 02 '16 at 15:30
  • 1
    @androidseb I don't need to know which app is selected for mock location. My exact requirement is to know if there is any app selected for mock location. Can you suggest something for this?? Since I was not getting hold of anything for it, I ended up doing location.isFromMockProvider(). But unfortunately it always returns true immaterial i select or do not select mock app. Looks like Fake GPS overwrites location coordinates and Location Manager is not refreshing its coordinates after me even stopping Fake GPS. – LoveForDroid Jun 02 '16 at 20:16
  • @LoveForDroid no I don't have any suggestion for this, since I could not find any info about the configured app for mock location, or even if there is an app selected for mock locations, I gave up and used the method in the location object with FusedLocationProvider: Location.getExtras().getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false); – androidseb Jun 04 '16 at 13:44
  • Context.APP_OPS_SERVICE is only avaible on SDK 19, is there another option? – Sibelius Seraphini Jun 24 '16 at 14:53
  • Your Answer is really helpful, – Sruit A.Suk Jun 28 '16 at 20:33
  • better to use checkOpNoThrow as checkOp which throwing SecurityException if mode == MODE_ERRORED – ceph3us Feb 23 '18 at 17:30
9

For those attempting to do this using ADB, here are the commands for getting and setting the mock app:

Allowing app for mock locaiton

adb shell appops set <PACKAGE> android:mock_location allow

Removing app for mock location

adb shell appops set <PACKAGE> android:mock_location deny

Checking if app is set for mock location

adb shell appops get <PACKAGE> android:mock_location
Pablo Baxter
  • 2,144
  • 1
  • 17
  • 36
0

If you want to detect if mock locations are used currently or recently.

    val manager = getSystemService(Context.LOCATION_SERVICE) as? LocationManager
    if (manager?.getLastKnownLocation(LocationManager.GPS_PROVIDER)?.isFromMockProvider == true) {
    // Mock locations are/were used
    }
mobo
  • 405
  • 3
  • 7
-1
  PackageManager pm = context.getPackageManager();
    List<ApplicationInfo> packages =
            pm.getInstalledApplications(PackageManager.GET_META_DATA);

    for (ApplicationInfo applicationInfo : packages) {
        try {
            PackageInfo packageInfo = pm.getPackageInfo(applicationInfo.packageName,
                    PackageManager.GET_PERMISSIONS);

            // Get Permissions
            String[] requestedPermissions = packageInfo.requestedPermissions;

            if (requestedPermissions != null) {
                for (int i = 0; i < requestedPermissions.length; i++) {
                    if (requestedPermissions[i].equals("android.permission.ACCESS_MOCK_LOCATION")
                            && !applicationInfo.packageName.equals(context.getPackageName())) {
                        //we get Package name here
                    }
                }
            }
        } catch (PackageManager.NameNotFoundException e) {

        }
    }
Sanket Parchande
  • 894
  • 9
  • 14