●位置情報を取得する

■GPSで位置情報を取得する

Android6.0以降は、Dangerous Permissionのためこのままでは動きません。
対応するには下の方を見てください。

まず、権限をアプリに追加しないと始まりません。
そこで、GPSのアクセス権限を与える為に、
MyApplication?\app\src\main\AndroidManifest.xml
この場所にある、AndroidManifest.xmlファイルを開きます。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="gps.myapplication">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
赤文字の部分を追加します。


■javaからGPSの位置情報を取得する

位置情報を取得するには、requestLocationUpdates(プロバイダー,通知の最小時間間隔(ms),通知の最小距離間隔(m),リスナー);を実行して、
位置情報の取得を開始する必要があります。
removeUpdates(リスナー);を読んで位置情報取得を停止しないと、画面を暗くしても、アプリケーションをバックグラウンドに移動しても位置情報を取得し続けます。


public class MainActivity extends AppCompatActivity {
    // GPS用
    static private android.location.LocationManager locationManager=null;
    static private _LocationListener locationListener=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(null==locationListener) {
            locationManager = (android.location.LocationManager) getSystemService(android.content.Context.LOCATION_SERVICE);
            locationListener = new _LocationListener();
        }

        //位置情報取得開始ボタン
        ((android.widget.Button) findViewById(R.id.button))
                .setOnClickListener(new android.view.View.OnClickListener() {
                    public void onClick(android.view.View view) {
                        if(locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)){
                            //requestLocationUpdates(プロバイダー,通知の最小時間間隔(ms),通知の最小距離間隔(m),リスナー);
                            locationManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER,0,10,locationListener);
                        }
                    }
                });

        //位置情報取得停止ボタン
        ((android.widget.Button) findViewById(R.id.button1))
                .setOnClickListener(new android.view.View.OnClickListener() {
                    public void onClick(android.view.View view) {
                        locationManager.removeUpdates(locationListener);
                    }
                });
    }


    class _LocationListener implements android.location.LocationListener {
        @Override
        public void onLocationChanged(android.location.Location location) {
            //位置情報を文字列に変換
            String str=location.getLatitude() + " " + location.getLongitude();
            android.widget.TextView t=(android.widget.TextView)findViewById(R.id.textView);
            t.setText(str);
        }

        @Override
        public void onProviderDisabled(String provider) {}
        @Override
        public void onProviderEnabled(String provider) {}
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    }
}
このプログラムを実行して、位置情報取得を開始すると、停止するまで位置情報を取得し続けます。
プログラム中で設定した通知の最小時間間隔と通知の最小距離間隔を超えるとリスナー内のonLocationChangedが呼ばれて位置情報を取得できます。


■位置情報取得のタイムアウトと、1回だけの取得

位置情報の取得ができないといつまでも取得待ちの状態になります。
そもそも、位置情報取得にタイムアウトという考えがありませんので、別にタイマーを作成して 時間が過ぎると停止させるようにします。

また、意図的に停止させないとずっと取得状態が続いて止まりません。
そこで、一回取得した段階で停止させるようにします。

public class MainActivity extends AppCompatActivity {
    // GPS用
    static private android.location.LocationManager locationManager=null;
    static private _LocationListener locationListener=null;
    java.util.Timer timer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(null==locationListener) {
            locationManager = (android.location.LocationManager) getSystemService(android.content.Context.LOCATION_SERVICE);
            locationListener = new _LocationListener();
        }

        //位置情報取得開始ボタン
        ((android.widget.Button) findViewById(R.id.button))
                .setOnClickListener(new android.view.View.OnClickListener() {
                    public void onClick(android.view.View view) {
                        if(locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)){
                            //requestLocationUpdates(プロバイダー,通知の最小時間間隔(ms),通知の最小距離間隔(m),リスナー);
                            locationManager.requestLocationUpdates(android.location.LocationManager.GPS_PROVIDER,0,10,locationListener);
                            //タイムアウトを作るため、タイマーに位置情報取得キャンセルをスケジュールする
                            java.util.TimerTask tt =new java.util.TimerTask(){
                                android.os.Handler handler=new android.os.Handler();
                                @Override
                                public void run() {
                                    locationManager.removeUpdates(locationListener);
                                }
                            };
                            timer=new java.util.Timer(true);
                            timer.schedule(tt,(long)5*60*1000);//5分でスケジュール
                        }
                    }
                });
    }

    class _LocationListener implements android.location.LocationListener {
        @Override
        public void onLocationChanged(android.location.Location location) {
            //位置情報を文字列に変換
            String str=location.getLatitude() + " " + location.getLongitude();
            android.widget.TextView t=(android.widget.TextView)findViewById(R.id.textView);
            t.setText(str);
            //位置情報が取得できたため、取得を停止する
            locationManager.removeUpdates(this);
            timer.cancel();
        }

        @Override
        public void onProviderDisabled(String provider) {}
        @Override
        public void onProviderEnabled(String provider) {}
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    }
}
プログラムの最初の赤文字部分でタイマーに停止をスケジュールしてタイムアウトを作成しています。
下側の赤文字部分で位置情報が取得できた段階で停止するようにしています。


■ネットワークから位置情報を取得する

本当におおよその位置しか取得できません。

まず、権限をアプリに追加します。
AndroidManifest.xmlを開いて、GPSの権限を追加した位置に、
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
この行を追加します。

次に、javaプログラムを開いて、GPSの位置情報を取得する上のプログラムの、位置情報取得開始部分の

if(locationManager.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER)){
    //requestLocationUpdates(プロバイダー,通知の最小時間間隔(ms),通知の最小距離間隔(m),リスナー);
    locationManager.requestLocationUpdates(android.location.LocationManager.NETWORK_PROVIDER,0,10,locationListener);
}
プログラム中のGPS_PROVIDERの部分を、NETWORK_PROVIDERに書き換えます。
これで、ネットワークから位置情報を取得できるはずです。
本当に大まかな位置なので、通知の最小距離間隔として設定してある10メートルの誤差なんて検出できません。


■Dangerous Permissionに対応する

android6.0以前はインストールする段階で権限を取得できましたが、android6.0では実行時に権限を取得するように改良されました。
そのため、Android6.0以降は権限を取得するコードを書かないと例外が発生してしまい、このままでは動きません。
実行時に権限を取得するには次のようにする必要があります。

final int REQUEST_ID = 99;
void permission(String permission){
    //android version 6.0以上の場合は実行する必要がある
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
        //権限が許可されてない場合には
        if (android.support.v4.app.ActivityCompat.checkSelfPermission(this, permission)!= android.content.pm.PackageManager.PERMISSION_GRANTED){
            //権限をリクエストする
            android.support.v4.app.ActivityCompat.requestPermissions(this, new String[]{permission}, REQUEST_ID);
        }
    }
}
//権限のリクエスト結果が返ってくる
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_ID) {
        if (grantResults[0] != android.content.pm.PackageManager.PERMISSION_GRANTED) {
            //権限が許可されなかった
            android.widget.Toast.makeText(getApplicationContext(), "権限が許可されませんでした\nアプリを終了します。", android.widget.Toast.LENGTH_LONG).show();
            //アプリを終了する
            finish();
            moveTaskToBack(true);
        }
    }
}
上の関数を追加した上で、権限を取得するタイミングで、次の関数をコールします

        //GPSの権限をユーザーから取得する
        permission(android.Manifest.permission.ACCESS_FINE_LOCATION);
android6.0以上で関数をコールするとこのようなメッセージボックスが表示されます。



GPSで位置情報を取得する前に権限を取得することによりandroid6.0以降でも例外が発生しなくなります。


▲トップページ > android