使用LocationManager.SetProviderLocation模拟位置,如何使位置完成

时间:2013-10-14 06:06:24

标签: c# android xamarin.android android-location

我正在尝试通过创建Location实例然后使用LocationManager.SetTestProviderLocation(string providerName,Locatin location)方法来模拟我的位置。

例如:

Location location = new Location(providerName)
{
    Latitude = 51.20958,
    Longitude = 2.92372,
    Accuracy = 100.0f,
    Time = DateTime.Now.Ticks,
    Altitude = 1.0,
    Speed = 0.0f,
    Bearing = 0.0f,
    Provider = providerName,
};


locationManager.SetTestProviderLocation(providerName, location);

这总是会导致异常:

  

“位置对象不完整,缺少时间戳或准确性?   位置[gps 51.209580,2.923720 acc = 1 et =?!? alt = 1.0 vel = 0.0   承担= 0.0]“

我找到了有关该主题here的一些信息 作者提到LocationManger检查isComplete(方法)
以确定位置是否完整。

我希望该类的单声道版本具有IsComplete属性
和MakeComplete方法,但它们不存在(或者至少我找不到它们)

仔细查看Android SDK source code

public void makeComplete() 
{
        if (mProvider == null) mProvider = "?";
        if (!mHasAccuracy) {
            mHasAccuracy = true;
            mAccuracy = 100.0f;
        }
        if (mTime == 0) mTime = System.currentTimeMillis();
        if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
}

我猜是“et =?!?”异常中的值是指 mElapsedRealtimeNanos 字段,因为我无法知道访问该字段,所以我无法嘲笑工作。

我错过了什么,这是Android或者Mono的缺失功能 是否有另一种方法可以使它发挥作用。

注意:我知道有很多方法可以使用DDMS设置虚假位置,       但我正在寻找一种自动化位置模拟的方法

更新

发布此问题一段时间后,我意识到我没有针对API级别16 因此,Mono for Android没有公开 ElapsedRealtimeNanos 属性。

切换到API级别16后,该属性变为可用。但是,它没有 提供 MakeComplete 方法。 (也许这是一个错误/缺失的功能)。

所以我做了一个快速的解决方案来验证行为:

Location location = new Location(providerName)
{
    Longitude = locations[position, 0],
    Latitude = locations[position, 1],                    
    Accuracy = 100.0f,
    Time = DateTime.Now.Ticks,
    Altitude = 1.0,
    Speed = 0.0f,
    Bearing = 0.0f,
    Provider = providerName,
    ElapsedRealtimeNanos = (long)(TimeSpan.FromTicks(DateTime.Now.Ticks)
                                          .TotalMilliseconds * 1000000)
};

虽然这解决了Jelly Bean设备(4.1或更高版本)代码的问题 将破坏旧设备。这就是@Cheesebaron提出的解决方案发挥作用的地方。

1 个答案:

答案 0 :(得分:3)

您可能需要通过JNI访问makeComplete,代码如下:

public class MyLocation : Location
{
    protected MyLocation(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
    }

    public MyLocation(Location l) : base(l)
    {
    }

    public MyLocation(string provider) : base(provider)
    {
    }

    public void MakeComplete()
    {
        if ((int)Build.VERSION.SdkInt >= 16)
        {
            var locationClass = JNIEnv.FindClass("android/location/Location");
            var makeComplete = JNIEnv.GetMethodID(locationClass, "makeComplete", "()V");
            JNIEnv.CallVoidMethod(Handle, makeComplete);
        }
    }
}

然后只需使用MyLocation的实例,即调用MakeComplete。但是它只能在API 16上运行。