检测或防止用户使用虚假位置 [英] Detect or prevent if user uses fake location

查看:104
本文介绍了检测或防止用户使用虚假位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果用户伪造该位置,我将阻止其使用我的应用程序. 因此,我使用isFromMockProvider来检查该位置是否为伪造(按照此处).但是isFromMockProvider()在某些情况下对于伪造的位置可能返回false.

I will block a user from using my app if they fake the location. So I use isFromMockProvider to check if the location is fake (follow here). But isFromMockProvider() may return false for faked locations in some cases.

public void onLocationChanged(Location location) {
    textView.append("long:"+location.getLatitude()+" - lat:"+location.getLongitude()+" - isMock :"+location.isFromMockProvider() + "\n");
}

我的情况是:我使用应用程序伪造GPS位置,将其伪造到某个位置,然后我禁用伪造位置并转到我的应用.然后onLocationChanged用isFromMockProvider() = false

My case is: I use app Fake GPS location for fake to a location then I disable fake location and go to my app. Then the onLocationChanged returns the fake location with isFromMockProvider() = false

录像机: https://www.youtube.com/watch?v = rWVvjOCaZiI (在此视频中,我当前的位置是16.06,108.21,假位置是36.26,138.28.您可以在上一个视频中看到该位置是36.26,138.28但isFromMockProvider = false)

Video recorder: https://www.youtube.com/watch?v=rWVvjOCaZiI (in this video, my current location is 16.06, 108.21, the fake location is 36.26,138.28. You can see in last video the location is 36.26,138.28 but isFromMockProvider=false)

在这种情况下,是否有任何方法可以检测用户是否使用了虚假位置?任何帮助或建议将不胜感激.
DEMO项目

Is there any way to detect if a user uses a fake location in this case? Any help or suggestion would be great appreciated.
DEMO project

推荐答案

我使用两种方法来识别虚假位置. 首先,我要检查模拟位置,就像这里的其他代码一样.

I use two ways to identify fake locations. First, i check mock location, like in other code here.

public static boolean isMockLocationOn(Location location, Context context) {
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        return location.isFromMockProvider();
    } else {
        String mockLocation = "0";
        try {
            mockLocation = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return !mockLocation.equals("0");
    }
}

第二,我检查正在运行的应用程序和服务,这些应用程序和服务需要访问模拟位置的权限.

Second, i check running apps and services, that need permission to access mock location.

public static List<String> getListOfFakeLocationApps(Context context) {
    List<String> runningApps = getRunningApps(context);
    List<String> fakeApps = new ArrayList<>();
    for (String app : runningApps) {
        if(!isSystemPackage(context, app) && hasAppPermission(context, app, "android.permission.ACCESS_MOCK_LOCATION")){
            fakeApps.add(getApplicationName(context, app));
        }
    }
    return fakeApps;
}

public static List<String> getRunningApps(Context context, boolean includeSystem) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    HashSet<String> runningApps = new HashSet<>();
    try {
        List<ActivityManager.RunningAppProcessInfo> runAppsList = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo processInfo : runAppsList) {
            runningApps.addAll(Arrays.asList(processInfo.pkgList));
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    try {
        //can throw securityException at api<18 (maybe need "android.permission.GET_TASKS")
        List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(1000);
        for (ActivityManager.RunningTaskInfo taskInfo : runningTasks) {
            runningApps.add(taskInfo.topActivity.getPackageName());
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    try {
        List<ActivityManager.RunningServiceInfo> runningServices = activityManager.getRunningServices(1000);
        for (ActivityManager.RunningServiceInfo serviceInfo : runningServices) {
            runningApps.add(serviceInfo.service.getPackageName());
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return new ArrayList<>(runningApps);
}

public static boolean isSystemPackage(Context context, String app){
    PackageManager packageManager = context.getPackageManager();
    try {
        PackageInfo pkgInfo = packageManager.getPackageInfo(app, 0);
        return (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return false;
}

public static boolean hasAppPermission(Context context, String app, String permission){
    PackageManager packageManager = context.getPackageManager();
    PackageInfo packageInfo;
    try {
        packageInfo = packageManager.getPackageInfo(app, PackageManager.GET_PERMISSIONS);
        if(packageInfo.requestedPermissions!= null){
            for (String requestedPermission : packageInfo.requestedPermissions) {
                if (requestedPermission.equals(permission)) {
                    return true;
                }
            }
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return false;
}

public static String getApplicationName(Context context, String packageName) {
    String appName = packageName;
    PackageManager packageManager = context.getPackageManager();
    try {
        appName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)).toString();
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return appName;
}

(更新)

不幸的是,谷歌禁止应用程序接收当前正在运行的应用程序列表. (从5.1.1开始,但是我仍然可以在运行android 7.1的测试设备中获取应用列表)

Unfortunately, google forbid applications from receiving the list of currently running apps. (It was since 5.1.1, but i still can get app list in test devices runned android 7.1)

现在,您可以使用UsageStatsManager仅获得最近使用过的应用程序列表(具有请求的运行时权限),例如此处 Android 5.1 .1及更高版本-getRunningAppProcesses()仅返回我的应用程序包

Now you can get only list of recently used apps (with request runtime permission for it) by using UsageStatsManager, for example like here Android 5.1.1 and above - getRunningAppProcesses() returns my application package only

因此,如果用户关闭或退出虚假的位置应用程序,我将无法确定.

So if user close or exit from fake location app, i can't determinate it.

现在,要获取虚假位置应用程序的列表,我会尝试获取位置,如果location.isFromMockProvider()返回true,则我将在设备上扫描所有已安装的应用程序,这些应用程序需要访问模拟位置,例如:

And now, to get list of fake location apps, i try to get locations, and if location.isFromMockProvider() return true, i scan device for all installed apps, that need permission to access mock location like this:

public static List<String> getListOfFakeLocationAppsFromAll(Context context) {
    List<String> fakeApps = new ArrayList<>();
    List<ApplicationInfo> packages = context.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA);
    for (ApplicationInfo aPackage : packages) {
        boolean isSystemPackage = ((aPackage.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
        if(!isSystemPackage && hasAppPermission(context, aPackage.packageName, "android.permission.ACCESS_MOCK_LOCATION")){
            fakeApps.add(getApplicationName(context, aPackage.packageName));
        }
    }
    return fakeApps;
}

这篇关于检测或防止用户使用虚假位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆