检测或防止用户使用虚假位置 [英] Detect or prevent if user uses fake location
问题描述
如果用户伪造该位置,我将阻止其使用我的应用程序.
因此,我使用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屋!