2014-10-21 3 views
1

У меня есть приложение Xamarin Forms. Довольно простая настройка с помощью PCL, содержащего некоторые страницы XAML.Использование служб местоположения Android в приложении XamarinForms

Я пытаюсь получить очень простой пример «показывать мои координаты gps» на основе нажатия кнопки на моей странице Xaml.

Я создал интерфейс ILocationService в своем PCL и специальную реализацию 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 
     } 
    } 
} 

_locationProvider получает значение величины gps методом GetBestProvider, и он проходит проверку isEnabled, но как только он пытается запросить обновления ... Я получаю следующее (бесполезные) Exception. Я дважды проверил манифест приложения, чтобы убедиться, что разрешения включены для курса &. Есть идеи ?

{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) 
} 

ответ

3

В «обычных» образцах Android RequestLocationUpdates вызывается в OnResume. Мне кажется, что, вызывая этот метод в конструкторе (методом init), вы пытаетесь получить эту информацию слишком рано. Вы можете попытаться переместить вызов RequestLocationUpdates на метод Start(), который затем вы можете вызвать в методе OnAppearing на своей странице. Я пытаюсь получить образец работать, но мой макинтош требует доработок после Йосемити-обновлений ;-)

UPDATE:

Хорошо, я думаю, что я понял это. Хотя мой предыдущий комментарий все еще может быть правдой, я обнаружил, что вместо реализации Handle и Dispose в вашей реализации ILocationListener вы вместо этого извлекаете его из 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() и обрабатывать код и изменить определение класса для:

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

Я сделал эти изменения в моем маленьком тестовом приложении, и она работает, как ожидалось. Обратите внимание, что я начал процесс в OnAppearing() (в PCL) и что я использую обмен сообщениями (MessagingCenter) для обновления метки. В полном приложении я бы использовал MVVM и привязал метку к ViewModel, но даже тогда ILocationService, вероятно, все равно отправит свои обновления через MessagingCenter (вы также можете использовать события, но, по моему опыту, обмен сообщениями более надежный).

+0

Спасибо ... будет принимать это во внимание. Служба DI копирует это в CTOR страницы XAML обратно в PCL. Я попробую переместить его в OnResume или в другую часть приложения, или, возможно, получить его во время нажатия кнопки и посмотреть, что произойдет. –

+0

Спасибо за обновление ... Я сделал быстрый тест, расширив java.lang.object и инициализируя locMgr в OnAppearing моего приложения, и это заставило исключения уйти, но метод OnLocationChanged никогда не срабатывает ... будет выглядеть в материал центра сообщений. –

+0

Если вы хотите, я могу немного почистить свой тестовый проект и поставить его на Github. Кроме того, вы можете попробовать использовать Xamarin Mobile, который также имеет класс GeoLocator. Или копайте в код MVVMCross, который также имеет плагин Location. Это не Xamarin Forms специфические (хотя я думаю, что они работают над этим), но похоже, что ваша проблема - Android. – user2414891

1

Если вы используете Xamarin Forms Labs это становится гораздо проще

 var geolocator = DependencyService.Get<IGeolocator>(); 
+0

Спасибо, Ян, это похоже на хорошее место для начала. –

Смежные вопросы