如何解决Google地图上的模拟虚假或欺骗位置有时会返回真实位置
我开始使用在后台运行的服务来更改用户位置(使用伪造位置)的应用程序。我从UI中的开关启动或停止服务以启用或禁用欺骗位置。总体而言,一切工作都很好,服务每秒都会更改用户的位置。 不幸的是,经常发生用户在Google Maps应用上的位置恢复(返回)到真实用户的位置的情况。
有人遇到过这个问题,并且/或者有解决此问题的想法吗?预先谢谢你
PS:在Android系统参数的开发人员选项中选择了我的自定义应用,以模拟位置
MainActivity.java
package com.test.Mocklocation;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final static int PERMISSION_LOCATION_CODE = 100;
private Switch switchService = null;
private Intent mServiceIntent = null;
private MocklocationService serviceMocklocation = new MocklocationService();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mServiceIntent = new Intent(this,serviceMocklocation.getClass());
initiateUI();
}
/**
* Initiate UI components,declare actions when switch status is changed (try to launch mock location service or stop it if permission location is granted yet)
*/
private void initiateUI(){
switchService = findViewById(R.id.switchService);
switchService.setonCheckedchangelistener(new CompoundButton.OnCheckedchangelistener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton,boolean b) {
//If switch service is checked,try to launch Mocklocation service
if(switchService.isChecked()){
//If permission granted,start Mocklocation service
if(permissionAccessLocationGranted()){
startServiceMocklocation();
}
//else change switch value and request permission location to user
else{
switchService.setChecked(false);
requestLocationPermission();
}
}
//Else stop Mocklocation service
else{
stopServiceMocklocation();
}
}
});
}
/**
* Check if Mocklocation service is running
* @return true if Mocklocation service is running,false if it's stopped
*/
private boolean isServiceMocklocationRunning(){
if(serviceMocklocation!=null){
return isMyServiceRunning(serviceMocklocation.getClass());
}
return false;
}
/**
* Try to start Mocklocation service
*/
private void startServiceMocklocation(){
if (mServiceIntent!=null && !isServiceMocklocationRunning()) {
startService(mServiceIntent);
}
}
/**
* Try to stop Mocklocation service
*/
private void stopServiceMocklocation(){
if (mServiceIntent!=null && isServiceMocklocationRunning()) {
stopService(mServiceIntent);
}
}
/**
* Check if a service is started or stopped
* @param serviceClass class of service
* @return true if service is started,else return false
*/
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("Service status","Running");
return true;
}
}
Log.i ("Service status","Not running");
return false;
}
/**
* Check if permission location is granted
* @return true if permission location is granted,else return false
*/
private boolean permissionAccessLocationGranted(){
if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
return false;
}
return true;
}
/**
* Request location permission to user if it's not granted yet
*/
private void requestLocationPermission(){
if(!permissionAccessLocationGranted()){
ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.ACCESS_FINE_LOCATION },PERMISSION_LOCATION_CODE);
}
}
@Override
/**
* display a message whether or not user allows permission
*/
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults){
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
if (requestCode == PERMISSION_LOCATION_CODE) {
// Checking whether user granted the permission or not.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,"Location Permission Granted",Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this,"Location Permission Denied",Toast.LENGTH_SHORT).show();
}
}
}
}
MocklocationService.java
package com.test.Mocklocation;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.notificationmanager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import java.util.Timer;
import java.util.TimerTask;
public class MocklocationService extends Service implements LocationListener{
private static String TAG = "Mocklocation";
public static int refreshPositionUser = 1000; //value used on timer for mock location frequency
private LocationManager locationManager = null;
private Timer timer;
private TimerTask timerTask;
public int counter=0;
@Override
public void onCreate() {
super.onCreate();
initiateLocationManager();
launchNotificationService();
}
@Override
public void onDestroy() {
super.onDestroy();
stoptimertask();
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
super.onStartCommand(intent,flags,startId);
startTimer();
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Start time to change user's position location every second
*/
public void startTimer() {
timer = new Timer();
timerTask = new TimerTask() {
public void run() {
setMocklocation(48.8534,2.3488,35,LocationManager.NETWORK_PROVIDER);
setMocklocation(48.8534,LocationManager.GPS_PROVIDER);
Log.i("Count","========= "+ (counter++));
}
};
timer.schedule(timerTask,2000,refreshPositionUser);
}
/**
* Stop timer that change user's position location
*/
public void stoptimertask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
/**
* Launch notification to show if service is running or not
*/
private void launchNotificationService(){
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O){
String NOTIFICATION_CHANNEL_ID = "example.permanence";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID,channelName,notificationmanager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationmanager manager = (notificationmanager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setongoing(true)
.setContentTitle("App is running in background")
.setPriority(notificationmanager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2,notification);
} else{
startForeground(1,new Notification());
}
}
/**
* Try to add test provider and start listener to show user movement
*/
private void initiateLocationManager(){
if(locationManager==null){
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
try {
addTestProvider(locationManager,LocationManager.GPS_PROVIDER,true);
addTestProvider(locationManager,LocationManager.NETWORK_PROVIDER,true);
requestLocationUpdates(LocationManager.GPS_PROVIDER);
requestLocationUpdates(LocationManager.NETWORK_PROVIDER);
} catch (IllegalArgumentException error) {
error.printstacktrace();
}
}
}
/**
* Remove test provider if it already exists,then add new test provider
* @param locationManager
* @param provider provider test name
* @param enabled choose to enable or disable provider test
*/
private void addTestProvider(LocationManager locationManager,String provider,boolean enabled){
if(locationManager.getProvider(provider)!=null){
try{
locationManager.removeTestProvider(provider);
Log.d(TAG,"Removing Test provider : "+provider);
} catch (Exception e){
}
}
locationManager.addTestProvider (provider,false,Criteria.POWER_LOW,Criteria.ACCURACY_FINE);
locationManager.setTestProviderEnabled(provider,enabled);
Log.d(TAG,"Add Test provider : "+provider);
}
/**
* Set false user's location position (Fake user's position)
* @param latitude latitude to fake location
* @param longitude longitude to fake location
* @param altitude altitude to fake location
* @param accuracy accuracy to fake location
* @param provider provider to fake location
*/
private void setMocklocation(double latitude,double longitude,double altitude,float accuracy,final String provider) {
try {
Location newLocation = new Location(provider);
newLocation.setLatitude(latitude);
newLocation.setLongitude(longitude);
newLocation.setAccuracy(accuracy);
newLocation.setAltitude(altitude);
newLocation.setbearing(0F);
newLocation.setSpeed(0);
newLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
newLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
locationManager.setTestProviderLocation(provider,newLocation);
Log.d(TAG,"mock location : "+provider+" -> latitude : "+latitude+" longitude : "+longitude);
} catch (SecurityException e) {
e.printstacktrace();
}
}
/**
* Request listener to kNow when provider location position change
* @param provider provider name to listen
*/
private void requestLocationUpdates(final String provider){
if (locationManager.isProviderEnabled(provider)) {
locationManager.removeUpdates(MocklocationService.this);
new Handler(Looper.getMainLooper()).post(new Runnable() {
@SuppressLint("MissingPermission")
@Override
public void run() {
locationManager.requestLocationUpdates(provider,0*1000,MocklocationService.this);
}
});
}
}
@Override
public void onLocationChanged(Location location) {
Log.i(TAG,"Location changed : Latitude: "+location.getLatitude() + " | Longitude: "+location.getLongitude());
}
@Override
public void onStatusChanged(String s,int i,Bundle bundle) {
Log.i(TAG,"onStatusChanged : "+s);
}
@Override
public void onProviderEnabled(String s) {
Log.i(TAG,"onProviderEnabled : "+s);
}
@Override
public void onProviderdisabled(String s) {
Log.i(TAG,"onProviderdisabled : "+s);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.Mocklocation" xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" tools:ignore="Mocklocation,ProtectedPermissions" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MocklocationService"
android:enabled="true"
android:exported="false"
android:launchMode="singleTask"/>
</application>
</manifest>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。