微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Google地图上的模拟虚假或欺骗位置有时会返回真实位置

如何解决Google地图上的模拟虚假或欺骗位置有时会返回真实位置

我开始使用在后台运行的服务来更改用户位置(使用伪造位置)的应用程序。我从UI中的开关启动或停止服务以启用或禁用欺骗位置。总体而言,一切工作都很好,服务每秒都会更改用户的位置。 不幸的是,经常发生用户在Google Maps应用上的位置恢复(返回)到真实用户的位置的情况。

有人遇到过这个问题,并且/或者有解决此问题的想法吗?预先谢谢你

PS:在Android系统参数的开发人员选项中选择了我的自定义应用,以模拟位置

您可以在此处显示3个主要文件的演示代码

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] 举报,一经查实,本站将立刻删除。