Мои другие приложения не обнаруживают ложное местоположение

#android #mock-location

#Android #ложное местоположение

Вопрос:

Я создаю приложение ложного местоположения, но когда я его включаю, другие приложения (например, Google Maps) его не обнаруживают. В приложении я могу определить реальное местоположение, если включен gps, и ложное местоположение, если gps выключен, а приложение включено в приложениях для определения местоположения

Мой код:

MainActivity

 package com.example.a;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.TextView;

public class MainActivity extends Activity implements LocationListener
{
    private FakeLocation task = null;
    private TextView latituteField;
    private TextView longitudeField;
    private TextView prov;
    private TextView other;
    private TextView provList;
    private LocationManager locationManager;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        latituteField =  findViewById(R.id.TextView02);
        longitudeField =  findViewById(R.id.TextView04);
        prov = findViewById(R.id.TextView06);
        other = findViewById(R.id.TextView08);
        provList = findViewById(R.id.TextView10);

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1222);
        }

        int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION);

        if (PackageManager.PERMISSION_GRANTED == permissionCheck)
        {

            if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
            {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
                Location auxLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                prov.setText("GPS");
                if(auxLocation != null)
                {
                    onLocationChanged(auxLocation);
                }
                else
                {
                    latituteField.setText("null");
                    longitudeField.setText("null");
                }

            }
            else if(locationManager.isProviderEnabled(FakeLocation.FAKE_LOCATION))
            {
                // otherwise enable the mock GPS provider
                if(!locationManager.getAllProviders().contains("FakeLocation"))
                {
                    locationManager.addTestProvider(FakeLocation.FAKE_LOCATION, false, false, false, false, true, false, false, 0, 5);
                    locationManager.setTestProviderEnabled(FakeLocation.FAKE_LOCATION, true);
                }

                if(locationManager.isProviderEnabled(FakeLocation.FAKE_LOCATION))
                {
                    prov.setText("FAKE");
                    locationManager.requestLocationUpdates(FakeLocation.FAKE_LOCATION, 0, 0, this);
                    try
                    {
                        other.setText("Inicia task");
                        task = new FakeLocation();
                        task.execute();
                    }
                    catch(Exception e)
                    {
                        other.setText("Excepcion en onCreate");
                    }
                }
            }
        }
        else
        {
            other.setText("Permisos NOK");
        }
        provList.setText(locationManager.getAllProviders().toString());
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    public void onLocationChanged(Location location)
    {
        int lat = (int) (location.getLatitude());
        int lng = (int) (location.getLongitude());
        latituteField.setText(String.valueOf(lat));
        longitudeField.setText(String.valueOf(lng));
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}

    @Override
    public void onProviderEnabled(String provider) {}

    @Override
    public void onProviderDisabled(String provider) {}


    private class FakeLocation extends AsyncTask<String, Integer, Void>
    {
        public static final String FAKE_LOCATION = "FakeLocation";

        @Override
        protected Void doInBackground(String... data)
        {
            double latitude = 40d;
            double longitude = 20d;
            double altitude = 0d;

            Location location = new Location(FAKE_LOCATION);
            location.setLatitude(latitude);
            location.setLongitude(longitude);
            location.setBearing(5);
            location.setSpeed(5);
            location.setAltitude(altitude);
            location.setTime(System.currentTimeMillis());
            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
            location.setProvider(LocationManager.GPS_PROVIDER);
            location.setAccuracy(100);

            LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            locationManager.setTestProviderLocation(FAKE_LOCATION, location);
            onLocationChanged(location);

            try
            {
                Thread.sleep(200);

                if(Thread.currentThread().isInterrupted())
                    throw new InterruptedException("");
            }
            catch (InterruptedException e)
            {
                other.setText("doInBackground");
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values)
        {
            other.setText("Actualizando...");
        }
    }
}
  

Манифест

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.a">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_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"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
  

build.gradle (приложение)

 apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.a"
        minSdkVersion 27
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies
        {
            implementation 'com.google.android.gms:play-services-location:16.0.0'
            //noinspection UseOfBundledGooglePlayServices
            implementation 'com.google.android.gms:play-services:12.0.1'
            implementation 'com.google.android.gms:play-services-base:16.1.0'
            implementation 'com.google.android.gms:play-services-places:16.0.0'
            implementation 'com.android.support:multidex:1.0.3'
        }
  

Build.gradle (projecto)

 buildscript {
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        subprojects {
            project.configurations.all {
                resolutionStrategy.eachDependency { details ->
                    if (details.requested.group == 'com.google.android.gms'
                            amp;amp; !details.requested.name.contains('multidex') ) {
                        details.useVersion "12.0.1"
                    }
                }
            }
        }
    }
}

allprojects {
    repositories {
        google()
        jcenter()

    }
}
  

activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@ id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dip"
        android:orientation="horizontal" >

        <TextView
            android:id="@ id/TextView01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Latitude: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@ id/TextView02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>

    <LinearLayout
        android:id="@ id/linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@ id/TextView03"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Longitute: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@ id/TextView04"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>

    <LinearLayout
        android:id="@ id/linearLayout3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@ id/TextView05"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Provider: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@ id/TextView06"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>


    <LinearLayout
        android:id="@ id/linearLayout4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@ id/TextView07"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Other info: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@ id/TextView08"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>

    <LinearLayout
        android:id="@ id/linearLayout5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@ id/TextView09"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Provider List: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@ id/TextView10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>
</LinearLayout>
  

Ответ №1:

Приложения должны явно запрашивать положение ложного местоположения. Если они не запрашивают макет, они получат реальное местоположение независимо от того, существует ли макет. Большинство разработчиков не оставляют запрос ложного разрешения в коде выпуска, чтобы приложение не было обмануто.

В общем, ложное местоположение — это инструмент для отладки ваших приложений, использующих местоположение, а не инструмент для обмана приложений, которые не хотят отлаживаться.