2016-11-13 47 views
1

我看到,在市场上有很多模拟位置应用程序适用于整个系统。 (这意味着当我们使用谷歌地图,超级...)它会显示新的位置。如何写模拟GPS提供商影响整个系统应用程序

我跟着一些教程。这里是我的示例代码:

public class MainActivity extends AppCompatActivity { 

    LocationManager mLocationManager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 

     setupMockLocations(LocationManager.GPS_PROVIDER); 
     setupMockLocations(LocationManager.NETWORK_PROVIDER); 
     setupMockLocations(LocationManager.PASSIVE_PROVIDER); 

    } 

     private void setupMockLocations(final String providerName) { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      for (; ;) { 
       mLocationManager.addTestProvider(providerName, false, //requiresNetwork, 
         false, // requiresSatellite, 
         false, // requiresCell, 
         false, // hasMonetaryCost, 
         false, // supportsAltitude, 
         false, // supportsSpeed, s 
         false, // upportsBearing, 
         Criteria.POWER_LOW, // powerRequirement 
         Criteria.ACCURACY_FINE); // accuracy 

       mLocationManager.setTestProviderEnabled(providerName, true); 
       location.setTime(System.currentTimeMillis()); 
       location.setAccuracy(1); 
       location.setTime(System.currentTimeMillis()); 

       Method locationJellyBeanFixMethod = null; 
       try { 
        locationJellyBeanFixMethod = Location.class.getMethod("makeComplete"); 
       } catch (NoSuchMethodException e) { 
        e.printStackTrace(); 
       } 

       if (locationJellyBeanFixMethod != null) { 
        try { 
         locationJellyBeanFixMethod.invoke(location); 
        } catch (IllegalAccessException e) { 
         e.printStackTrace(); 
        } catch (InvocationTargetException e) { 
         e.printStackTrace(); 
        } 
       } 

       mLocationManager.setTestProviderLocation(providerName, location); 


       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 

       Log.e("print", "mocking " + providerName); 
      } 

     } 
    }).run(); 
} 


} 

但看起来像这样的代码不起作用。 (它应该在Google地图上显示我的sampleLocation而不是当前位置)。我也伪造GPS_PROVIDERNETWORK_PROVIDERPASSIVE_PROVIDER。请告诉我如何做到这一点。

回答

1

如何编写模拟GPS提供商影响整个系统应用

它已经影响到整个系统和它的工作。但条件可能会改变结果。例如,在您的情况下,

当您拨打setupMockLocations(LocationManager.GPS_PROVIDER); GPS提供商缓存您的假位置。但在此时(或之后),如果有任何其他应用程序对GPS进行位置请求并接收到新的GPS位置,则您的假位置将被覆盖。

您的代码是正确的,但只需定期拨打setupMockLocations(...);以防止出现上述情况。

此示例对我的作品时,请考虑采取措施

public class SampleMocker { 

    private int mPeriod = 2 * 1000; 
    private Location mMockLocation; 
    private LocationManager mLocationManager; 
    private Handler mHandler = new Handler(); 

    public SampleMocker(Context context){ 
     mLocationManager = (LocationManager) 
      context.getSystemService(Context.LOCATION_SERVICE); 

     mMockLocation = new Location(LocationManager.GPS_PROVIDER); 
     mLocationManager.addTestProvider(GPS_PROVIDER, false, false, false, 
     false, false, true, true, 0, 5); 
     mLocationManager.setTestProviderEnabled(GPS_PROVIDER, true); 
    } 

    private void start(){ 
     mHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       mMockLocation.setTime(System.currentTimeMillis()); 

       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
        mMockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); 
       } 

       mLocationManager.setTestProviderLocation(GPS_PROVIDER, mMockLocation); 

       mHandler.postDelayed(this, mPeriod); 
      } 
     }); 
    } 
} 

这个代码在每2秒定期设置模拟位置。 private int mPeriod = 2 * 1000;

您应该调整使用时间段。因为如果其他应用可能会以较低的周期发出位置请求。那么你的模拟位置不会经常出现。

对于测试:在运行此代码时,打开Goog​​le地图并且请勿使用高精度,请设置仅设备模式。

+0

我改变了我的代码。我定期调用'setupMockLocation',但它仍然不起作用。也许还有其他错误? –

+0

当你离开你的应用程序时发生了什么?您应该在服务中运行相关代码,因为在切换到Google地图(或其他任何地方)后,您的活动(和模拟位置)将停止,然后Google地图会收到新的位置信息。 – Blackkara

+0

当我离开我的应用程序时,线程仍定期运行模拟位置(我已通过打印日志进行检查)。 –

相关问题