1

我有一个 Xamarin 表单应用程序。包含一些 XAML 页面的 PCL 的相当基本的设置。

我正在尝试根据我的 Xaml 页面中的按钮单击运行一个非常简单的“显示我的 gps 坐标”示例。

我在我的 PCL 中创建了一个 ILocationService 接口,并在我的 Android 应用程序中创建了一个特定于 android 的实现,并标记了[assembly:Dependency]属性,以便我可以使用 XamForms DI 服务获取它。

这是Android实现的代码。

[assembly: Dependency(typeof(AndroidLocationService))]

namespace LoginDemo.Droid
{
    public class AndroidLocationService : ILocationService, ILocationListener
    {
        Location _currentLocation;
        LocationManager _locationManager;
        String _locationProvider;

        public AndroidLocationService()
        {
            this.InitializeLocationManager();
        }

        //When the DI Container fetches a new instance of the AndroidLocationService
        //Wire up the _locationManager/Provider stuff and tell it to start fetching updates every 2 ses
        void InitializeLocationManager()
        {
            _locationManager = (LocationManager)Forms.Context.GetSystemService(Context.LocationService);
            Criteria criteriaForLocationService = new Criteria { Accuracy = Accuracy.Fine };
            try
            {
                _locationProvider = _locationManager.GetBestProvider(criteriaForLocationService, true);
                if (_locationManager.IsProviderEnabled(_locationProvider))
                {
                    _locationManager.RequestLocationUpdates(_locationProvider, 2000, 1, this);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
        }

        //MyInterface Method
        public LocationResult GetLocation()
        {

            if (_currentLocation == null)
            {
                return new LocationResult() { Data = "Can't determine the current address." };
            }

            return new LocationResult { Data = string.Format("{0} - {1}", _currentLocation.Latitude, _currentLocation.Longitude)};

        }

        public void Dispose()
        {
        }

        public IntPtr Handle { get; private set; }

        public void OnLocationChanged(Location location)
        {
            _currentLocation = location;
        }

        public void OnProviderDisabled(string provider)
        {
            //Not Implemented
        }

        public void OnProviderEnabled(string provider)
        {
            //Not Implemented
        }

        public void OnStatusChanged(string provider, Availability status, Bundle extras)
        {
            //Not Implemented
        }
    }
}

_locationProvidergps通过该方法设置为该值GetBestProvider,并且它通过了isEnabled检查,但是一旦它尝试请求更新...我得到以下(相当无用的)异常。我已经仔细检查了应用程序清单,以确保为课程和精细位置请求打开了权限。有任何想法吗 ?

{Java.Lang.IllegalArgumentException: Exception of type 'Java.Lang.IllegalArgumentException' was thrown.
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0 
  at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00063] in /Users/builder/data/lanes/1131/2a7b6821/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:508 
  at Android.Locations.LocationManager.RequestLocationUpdates (System.String provider, Int64 minTime, Single minDistance, ILocationListener listener) [0x0004a] in /Users/builder/data/lanes/1131/2a7b6821/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.Locations.LocationManager.cs:814 
  at LoginDemo.Droid.AndroidLocationService.InitializeLocationManager () [0x00058] in c:\Work\Code\Sandbox\LoginDemo\LoginDemo\LoginDemo.Android\LocationService.cs:46 
  --- End of managed exception stack trace ---
java.lang.IllegalArgumentException: invalid listener: null
    at android.location.LocationManager.checkListener(LocationManager.java:1606)
    at android.location.LocationManager.requestLocationUpdates(LocationManager.java:426)
    at xamarin.forms.platform.android.ButtonRenderer_ButtonClickListener.n_onClick(Native Method)
    at xamarin.forms.platform.android.ButtonRenderer_ButtonClickListener.onClick(ButtonRenderer_ButtonClickListener.java:29)
    at android.view.View.performClick(View.java:4247)
    at android.view.View$PerformClick.run(View.java:17728)
    at android.os.Handler.handleCallback(Handler.java:730)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5289)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
    at dalvik.system.NativeStart.main(Native Method)
}
4

2 回答 2

3

在“普通”Android 示例中,RequestLocationUpdates 在 OnResume 中调用。在我看来,通过在构造函数中调用此方法(通过 init 方法),您正试图过早获取此信息。您可以尝试将对 RequestLocationUpdates 的调用移至 Start() 方法,然后您可以在页面的 OnAppearing 方法中调用该方法。我正在尝试使示例正常工作,但是我的 mac 需要一些优胜美地更新后的工作;-)

更新:

好吧,我想我明白了。虽然我之前的评论可能仍然成立,但我发现不是在 ILocationListener 实现中实现 Handle 和 Dispose,而是从 Java.Lang.Object 派生它。我从http://forums.xamarin.com/discussion/19559/xamarin-gps-location-code-fails-exception-in-mono-works-in-native-android-bug-or-mistake找到了答案。

因此,在您的代码中,删除 Dispose() 和 Handle 代码并将您的类定义更改为:

public class AndroidLocationService : Java.Lang.Object, ILocationService, ILocationListener

我在我的小测试应用程序中进行了这些更改,它按预期工作。请注意,我确实在 OnAppearing() (在 PCL 中)中启动了该过程,并且我使用消息传递 (MessagingCenter) 来更新标签。在一个完整的应用程序中,我会使用 MVVM 并将标签绑定到 ViewModel,但即便如此,ILocationService 可能仍会通过 MessagingCenter 发送其更新(您也可以使用事件,但根据我的经验,消息传递更可靠)。

于 2014-10-21T17:50:44.143 回答
1

如果您使用Xamarin Forms Labs,这将变得容易得多

        var geolocator = DependencyService.Get<IGeolocator> ();
于 2014-10-22T00:57:06.680 回答