package com.
(プロジェクト名).Packaging;
import android.app.NativeActivity;
import android.os.Bundle;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.widget.Toast;
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
public class
(プロジェクト名) extends NativeActivity
{
// 緯度
double mLatitude ;
// 経度
double mLongitude ;
// 位置情報の状態( 0:使用可能かチェック中 1:使用可能 2:使用不可能 )
int mGPSState ;
// 使用するGPSプロバイダ
String mUseGPSProvider ;
// 位置マネージャ
LocationManager mLocationManager ;
// 位置情報取得の権限をリクエストする際に使用する識別番号
static final int PERMISSIONS_REQUEST_LOCATION = 1 ;
// 位置マネージャの初期化を行う
private void InitializeLocationManager()
{
// 位置マネージャの取得
mLocationManager = ( LocationManager )getSystemService( this.LOCATION_SERVICE ) ;
// 使用するGPSプロバイダの取得
// 端末のGPSの位置情報が取得できる場合は端末のGPSを使用
Location location = mLocationManager.getLastKnownLocation( LocationManager.GPS_PROVIDER );
if( location != null )
{
mUseGPSProvider = LocationManager.GPS_PROVIDER;
}
else
{
// ネットワークからの位置情報が取得できる場合はネットワークの位置情報を使用
location = mLocationManager.getLastKnownLocation( LocationManager.NETWORK_PROVIDER );
if( location != null )
{
mUseGPSProvider = LocationManager.NETWORK_PROVIDER;
}
else
{
// どちらからも位置情報が取得できない場合はOSに選択してもらう
Criteria criteria = new Criteria() ;
criteria.setAccuracy( Criteria.ACCURACY_FINE ) ;
// 位置精度優先
mUseGPSProvider = mLocationManager.getBestProvider( criteria, true ) ;
}
}
// 位置情報取得の開始
mLocationManager.requestLocationUpdates(
mUseGPSProvider,
3000,
// 位置情報更新を行う最低更新時間間隔( 単位:ミリ秒 )
0,
// 位置情報更新を行う最小距離間隔( 単位:メートル )
new LocationListener()
{
// 位置情報が更新されたときに呼ばれる関数
@Override
public void onLocationChanged( Location location )
{
// 位置情報取得権限のチェック
if( ActivityCompat.checkSelfPermission(
(プロジェクト名).this,
Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(
(プロジェクト名).this,
Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED )
{
// 位置情報取得の権限が無い場合は何もせずに終了
return ;
}
// ここに来たらGPSが使用可能ということにする
mGPSState = 1 ;
// 経度と緯度を取得
mLatitude = location.getLatitude() ;
mLongitude = location.getLongitude() ;
// 位置情報が更新された旨を表示
Toast.makeText(
(プロジェクト名).this, "位置情報が更新されました", Toast.LENGTH_SHORT ).show() ;
}
// 使用しているGPSプロバイダが無効になった場合
@Override
public void onProviderDisabled( String provider )
{
Toast.makeText(
(プロジェクト名).this, "GPSプロバイダが無効になりました", Toast.LENGTH_SHORT ).show() ;
}
// 使用しているGPSプロバイダが有効になった場合
@Override
public void onProviderEnabled( String provider )
{
Toast.makeText(
(プロジェクト名).this, "GPSプロバイダが有効になりました", Toast.LENGTH_SHORT ).show() ;
}
// 使用しているGPSプロバイダの状態が変化した場合
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Toast.makeText(
(プロジェクト名).this, "GPSプロバイダの状態が変化しました", Toast.LENGTH_SHORT ).show() ;
}
}
);
}
// 権限の許可を求めるダイアログで許可か不許可が選択されたら呼ばれる関数
public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults )
{
// 位置情報取得の権限を求めるリクエストに対する結果の場合のみ処理を行う
if( requestCode == PERMISSIONS_REQUEST_LOCATION )
{
// 許可されたのかどうかを判定
if( grantResults[ 0 ] == PackageManager.PERMISSION_GRANTED )
{
// 許可されたら位置マネージャを初期化
Toast.makeText(
(プロジェクト名).this, "位置情報取得が許可されました", Toast.LENGTH_SHORT ).show() ;
InitializeLocationManager() ;
}
else
{
// 許可されなかったらその旨を表示する
Toast.makeText(
(プロジェクト名).this, "位置情報取得が拒否されました", Toast.LENGTH_SHORT ).show() ;
// GPS使用不可の状態にする
mGPSState = 2 ;
}
}
}
// GPSの処理を開始する
public void StartGPS()
{
// UIスレッドで実行する処理を登録する
runOnUiThread(
new Runnable()
{
// UIスレッドで呼ばれる関数
@Override public void run()
{
// Android のバージョンチェック
if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M )
{
// Android 6.0以上の場合はアプリ実行中に位置情報取得の権限があるかをチェックする
// 位置情報取得の権限があるか判定
if( checkSelfPermission( Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED )
{
// 位置情報取得の権限があれば位置マネージャを初期化
Toast.makeText(
(プロジェクト名).this, "このアプリは位置情報取得の権限が既にあります", Toast.LENGTH_SHORT ).show() ;
InitializeLocationManager() ;
}
else
{
// 位置情報取得の権限が無ければ権限を求めるダイアログを表示
requestPermissions(
new String[]{ Manifest.permission.ACCESS_FINE_LOCATION },
PERMISSIONS_REQUEST_LOCATION
) ;
}
}
else
{
// Android 6.0未満の場合はアプリ実行時には位置情報取得の権限が許可されているので
// 無条件で位置マネージャの初期化を行う
InitializeLocationManager() ;
}
}
}
) ;
}
}
-->
( (プロジェクト名)となっている箇所は、お手元のプロジェクトの名前を入力してください )
5.Java の情報を取得する C++ のコードを入力する
次に Java の GPS の処理を開始する関数を呼び出したり、GPS の状態や GPS の緯度・経度を画面に表示したりする C++ 側のプログラムです。
『DXライブラリ Android版』でのみ使用できる GetNativeActivity という関数を使用しています。
#include "DxLib.h"
#include <string.h>
int android_main( void )
{
JNIEnv *env ;
const ANativeActivity *NativeActivity ;
int Counter = 0 ;
double Latitude = 0.0 ;
double Longitude = 0.0 ;
int GPSState = 0 ;
// 背景を灰色にする
SetBackgroundColor( 128,128,128 ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 描画先を裏画面に変更
SetDrawScreen( DX_SCREEN_BACK ) ;
// アプリの NativeActivity を取得しておく
NativeActivity = GetNativeActivity() ;
// Java の関数 StartGPS の呼び出し
{
// JavaVM とソフト実行用スレッドを関連付け( C++ から Java の機能を使用するために必要 )
if( NativeActivity->vm->AttachCurrentThreadAsDaemon( &env, NULL ) != JNI_OK )
{
return -1 ;
}
// Java のクラス (プロジェクト名) を取得
jclass jclass_
(プロジェクト名) = env->GetObjectClass( NativeActivity->clazz ) ;
// Java のクラス (プロジェクト名) のメンバー関数 StartGPS の ID を取得
jmethodID jmethodID_StartGPS = env->GetMethodID( jclass_
(プロジェクト名), "StartGPS", "()V" ) ;
// Java のクラス (プロジェクト名) のメンバー関数 StartGPS の呼び出し
env->CallVoidMethod( NativeActivity->clazz, jmethodID_StartGPS ) ;
// Java のクラス (プロジェクト名) の参照を削除
env->DeleteLocalRef( jclass_
(プロジェクト名) ) ;
// JavaVM とソフト実行用スレッドの関連付け終了
NativeActivity->vm->DetachCurrentThread() ;
}
// メインループ
while( ProcessMessage() == 0 )
{
// 裏画面の内容をクリア
ClearDrawScreen() ;
// GPSの位置情報は頻繁には更新されないので、10フレームに1回の間隔で情報を更新する
Counter ++ ;
if( Counter >= 10 )
{
// カウンタをリセット
Counter = 0 ;
// JavaVM とソフト実行用スレッドを関連付け( C++ から Java の機能を使用するために必要 )
if( NativeActivity->vm->AttachCurrentThreadAsDaemon( &env, NULL ) != JNI_OK )
{
return -1 ;
}
// Java のクラス (プロジェクト名) を取得
jclass jclass_
(プロジェクト名) = env->GetObjectClass( NativeActivity->clazz ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mLatitude の ID を取得
jfieldID jfieldID_mLatitude = env->GetFieldID( jclass_
(プロジェクト名), "mLatitude", "D" ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mLatitude の値をローカル変数 Latitude に代入
Latitude = env->GetDoubleField( NativeActivity->clazz, jfieldID_mLatitude ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mLongitude の ID を取得
jfieldID jfieldID_mLongitude = env->GetFieldID( jclass_
(プロジェクト名), "mLongitude", "D" ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mLongitude の値をローカル変数 Longitude に代入
Longitude = env->GetDoubleField( NativeActivity->clazz, jfieldID_mLongitude ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mGPSState の ID を取得
jfieldID jfieldID_mGPSState = env->GetFieldID( jclass_
(プロジェクト名), "mGPSState", "I" ) ;
// Java のクラス (プロジェクト名) のメンバー変数 mGPSState の値をローカル変数 GPSState に代入
GPSState = env->GetIntField( NativeActivity->clazz, jfieldID_mGPSState ) ;
// Java のクラス (プロジェクト名) の参照を削除
env->DeleteLocalRef( jclass_
(プロジェクト名) ) ;
// JavaVM とソフト実行用スレッドの関連付け終了
NativeActivity->vm->DetachCurrentThread() ;
}
// GPSの状態によって画面に表示する内容を変更
switch( GPSState )
{
case 0 :
// GPSが使用可能かチェック中
DrawString( 0, 80, "GPSが使用可能かチェック中", GetColor( 255,255,255 ) ) ;
break ;
case 1 :
// GPSが使用可能
DrawString( 0, 80, "GPSは使用可能", GetColor( 255,255,255 ) ) ;
// 経度と緯度を画面に描画
DrawFormatString( 0, 120, GetColor( 255,255,255 ), "経度 %f", Latitude ) ;
DrawFormatString( 0, 140, GetColor( 255,255,255 ), "緯度 %f", Longitude ) ;
break ;
case 2 :
// GPSは使用不可能
DrawString( 0, 80, "GPSは使用不可能", GetColor( 255,255,255 ) ) ;
break ;
}
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
( (プロジェクト名)となっている箇所は、お手元のプロジェクトの名前を入力してください )
以上です。
これでプロジェクトを実行すると、画面に GPS が使用可能かや、使用可能な場合は緯度・経度が表示されます。
詳細は割愛しますが、C++ から Java にアクセスする基本的な流れは。
① AttachCurrentThreadAsDaemon でソフト実行用スレッドと JavaVM を関連付け、JNIEnv も取得。
② GetObjectClass でアプリの Java クラスを取得。
③ GetMethodID や GetFieldID で Java の関数や変数の ID を取得。
④ Call???Method や Get???Field で Java の関数の呼び出しや変数の値を取得。
⑤ DeleteLocalRef で Get???Field で取得したオブジェクト系の変数の参照を削除。
⑥ DeleteLocalRef で GetObjectClass で取得したアプリの Java クラスの参照を削除。
⑦ DetachCurrentThread でソフト実行用スレッドと JavaVM の関連付けを終了。
となります。
C++ と Java でのやり取りを行う機能( JNI( Java Native Interface ) ) の詳しい扱い方については、検索サイトで
『Android Java JNI』などのキーワードで検索して調べてみてください。
戻る