2013年3月14日木曜日

Xamarin で android の GPS 位置情報を利用

android で GPSの位置データの取得するテストを Xamarin で やってみました。
文字を表示するために、TextView をふたつ貼りつけたアクティビティを作っておきます。

以下コード。

まずは GPS 使用の許可を求めるために [Properties] - [Assemblyinfo.cs] を編集。
JAVA で書く時には AndroidManifest.xml でやることですね。

using System.Reflection;
using System.Runtime.CompilerServices;
using Android.App;
using Android; // Manifest のため追加

// Information about this assembly is defined by the following attributes. 
// Change them to the values specific to your project.

[assembly: AssemblyTitle("test0314")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("uts")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.

[assembly: AssemblyVersion("1.0.0")]

// The following attributes are used to specify the signing key for the assembly, 
// if desired. See the Mono documentation for more information about signing.

//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

[assembly: UsesPermission(Manifest.Permission.AccessFineLocation)] // GPS アクセス許可



using Android; // Manifest のため追加
[assembly: UsesPermission(Manifest.Permission.AccessFineLocation)] // GPS アクセス許可

の 2行を追加しただけです。

次にメインのコード [MainActivity.cs] です。


using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Locations;    // GPSを使用するので追加
using System.Linq;          // クエリの処理に必要

namespace test0314
{
    [Activity (Label = "test0314", MainLauncher = true)]
    public class Activity1 : Activity, ILocationListener
    {                                           //  Activity と ILocationListener から継承
        private Location _currentLocation;
        private LocationManager _locationManager;
        private TextView text1;
        private TextView text2;
        private string _locationProvider;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            text1 = FindViewById<TextView> (Resource.Id.textView1);
            text2 = FindViewById<TextView> (Resource.Id.textView2);
            InitializeLocationManager();            // GPS を使う準備(すぐ下)
        }

        // GPSを使う準備
        private void InitializeLocationManager()
        {
            _locationManager = (LocationManager) GetSystemService(LocationService);
            var criteriaForLocationService = new Criteria
            {
                Accuracy = Accuracy.Fine
                // Fine なら GPS 、Coarse なら ネットワークを使用して測位
            };

            // criteriaForLocationService(すぐ上)を使いたいな とおねがい
            var acceptableLocationProviders
                 = _locationManager.GetProviders(criteriaForLocationService, true);

            // ロケーションプロバイダが使えるかな?
            if (acceptableLocationProviders.Any())
            {
                // acceptableLocationProvidersに何かクエリが入っていたら
                // 最初のクエリを取り出す
                _locationProvider = acceptableLocationProviders.First();
            }
            else
            {
                // ロケーションプロバイダが使えないみたい
                _locationProvider = String.Empty;
                text1.Text="測位サービスが使えないみたい";
            }
        }

        protected override void OnResume()
        {
            base.OnResume();

            // アクティビティがレジュームされたら
            // 位置情報を更新してくれるように依頼する
            _locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);

            text1.Text = _locationProvider.ToUpper () + " 位置情報更新待ち";
        }
        
        protected override void OnPause()
        {
            base.OnPause();

            // アクティビティが停止されたら
            // 位置情報更新しないように依頼
            _locationManager.RemoveUpdates(this);
        }


        // ここから Location クラスを使う時に実装しなきゃならない所

        // 位置情報が更新された時の処理
        public void OnLocationChanged(Location location)
        {
            _currentLocation = location;
            if (_currentLocation == null)
            {
                // 位置情報が空だった
                text1.Text = "位置を特定することができません";
            }
            else
            {
                // 位置情報が入っていた
                text1.Text=_locationProvider.ToUpper () + " 測位中";
                text2.Text =
                    String.Format("緯度 {0}\r\n経度 {1}\r\nProvider {2}"
                                  , _currentLocation.Latitude
                                  , _currentLocation.Longitude
                                  ,_currentLocation.Provider)
                    +String.Format("\r\nSPEED {0}\r\nTIME {1}"
                                   ,_currentLocation.Speed
                                   ,_currentLocation.Time)
                        +"\r\n(UTC 1970年1月1日からの経過時間[ミリ秒])";
            }
        }

        // ロケーションプロバイダが有効になった時の処理
        public void OnProviderEnabled(string provider) 
        {
            // 何もしない
        }
        
        // ロケーションプロバイダが無効になった時の処理
        public void OnProviderDisabled(string provider) 
        {
            // 何もしない
        }

        // ロケーションプロバイダのステータスが変わった時の処理
        public void OnStatusChanged(string provider, Availability status, Bundle extras)
        {
            // 表示してみる
            text1.Text=string.Format("{0}, {1}", provider, status);
        }
    }
}


実機で実行した様子