Ankhit Sharma Ankhit Sharma - 4 months ago 42
Java Question

SetTestProviderLocation Error...Location not being set despite all parameters?

I am trying to set my phone's location however, It throws an error saying I am missing some values? However, both of those are defined in my method so not to sure what I must do...Any ideas? With an explanation please?

Class:

//Initiates the method to set the phones location
private void setMockLocation() {
mLocationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
mLocationManager.addTestProvider
(
LocationManager.GPS_PROVIDER,
"requiresNetwork" == "",
"requiresSatellite" == "",
"requiresCell" == "",
"hasMonetaryCost" == "",
"supportsAltitude" == "",
"supportsSpeed" == "",
"supportsBearing" == "",

android.location.Criteria.POWER_LOW,
android.location.Criteria.ACCURACY_FINE
);

Location newLocation = new Location(LocationManager.GPS_PROVIDER);

newLocation.setLatitude (55.9500);
newLocation.setLongitude(3.1833);

newLocation.setAccuracy(500);

mLocationManager.setTestProviderEnabled
(
LocationManager.GPS_PROVIDER,
true
);

mLocationManager.setTestProviderStatus
(
LocationManager.GPS_PROVIDER,
LocationProvider.AVAILABLE,
null,
System.currentTimeMillis()
);

mLocationManager.setTestProviderLocation
(
LocationManager.GPS_PROVIDER,
newLocation
);
}


Error:

04-28 19:52:13.716 17289-17289/com.example.ankhit.saveme E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalArgumentException: Incomplete location object, missing timestamp or accuracy? Location[gps 55.9500,3.1833 acc=500 t=?!? et=?!?]
at android.location.LocationManager.setTestProviderLocation(LocationManager.java:1218)
at com.example.ankhit.saveme.UserLocation.setMockLocation(UserLocation.java:253)
at com.example.ankhit.saveme.UserLocation.access$000(UserLocation.java:41)
at com.example.ankhit.saveme.UserLocation$4.onClick(UserLocation.java:173)
at android.view.View.performClick(View.java:4439)
at android.view.View$PerformClick.run(View.java:18398)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5299)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)

Answer

Do you see the following in your stacktrace:

java.lang.IllegalArgumentException: Incomplete location object, missing timestamp or accuracy? Location[gps 55.9500,3.1833 acc=500 t=?!? et=?!?]

Starting with API 17, the LocationManager does a check on the Location object (isComplete() method). Your code is failing the checks for "t" - time and "et" - elapsed real time in nanos.

Setting the time is easy, just do something like this: mockLocation.setTime(System.currentTimeMillis());

Setting the elapsed time is only available in API 17+. If you support devices with a lower API (minimum target), you will need reflection to add this parameter.

What you need to do to make sure your mock LocationManager doesn't break, is simply check if the device is API 17 or greater and then choose one of three methods (either to set the time or disregard it):

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
   mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
   // Elapsed time can also be set using
   // mockLocation.setElapsedRealtimeNanos(System.nanoTime());
   // Elapsed time can be disregarded using
   // mockLocation.makeComplete();
}

One last thing. You should annotate your setMockLocation() method to disable Lint checks like this:

@TargetApi(17)
public void setMockLocation() {
// etc