package net.nkzn.android.sample.effective_android;
import android.app.Dialog;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
public class MainActivity extends FragmentActivity implements GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = MainActivity.class.getSimpleName();
/** Google Play Servicesの問題を解決する画面を開くためのrequestCode */
protected final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
/** 位置情報リクエストを制御する */
private LocationClient mLocationClient;
/** 位置情報リクエストの内容を定義する */
private LocationRequest mLocationRequest;
/** 位置情報をリクエスト済みかどうか(onPause->onResume対策) */
boolean mLocationUpdatesRequested = false;
final Spot SPOT_SKYTREE = new Spot("スカイツリー", 35.710213, 139.812741);
final Spot SPOT_GORYOKAKU = new Spot("五稜郭", 41.796912, 140.757087);
final Spot SPOT_SAKURAJIMA = new Spot("桜島", 31.583581, 130.650602);
Spot selectedSpot = SPOT_SKYTREE; // 初期値:スカイツリー
Spinner spSpot;
TextView tvDistance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// スポット用のアダプタを作成
ArrayAdapter<Spot> adapter = new ArrayAdapter<Spot>(this, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.add(SPOT_SKYTREE);
adapter.add(SPOT_GORYOKAKU);
adapter.add(SPOT_SAKURAJIMA);
// スピナーを初期化
Spinner spSpot = (Spinner) findViewById(R.id.sp_spot);
spSpot.setAdapter(adapter);
spSpot.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d("tag", "onItemSelected");
selectedSpot = (Spot) parent.getItemAtPosition(position);
if (mLocationClient != null && mLocationClient.isConnected()) {
Location lastLocation = mLocationClient.getLastLocation();
if (lastLocation != null) {
updateDistanceText(lastLocation);
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// 距離表示用TextViewを初期化
tvDistance = (TextView) findViewById(R.id.tv_distance);
updateDistanceText(999);
// LocationRequestを初期化
{
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setFastestInterval(1000);
}
// LocationClientを初期化
mLocationClient = new LocationClient(this, this, this);
startLocationUpdates();
}
/**
* 現在地と目的地の間の距離を計算
*
* @param spot
* 目的地
* @param location
* 現在地
* @return 2点間の距離をメートルで返します
*/
private float calcDistance(Spot spot, Location location) {
float[] results = new float[3];
Location.distanceBetween(spot.getLatitude(), spot.getLongitude(), location.getLatitude(), location.getLongitude(), results);
return results[0];
}
/**
* 現在地を指定して、選択中の目的地との距離を画面に表示する
*
* @param location
* 現在地
*/
private void updateDistanceText(Location location) {
float calcDistance = calcDistance(selectedSpot, location);
updateDistanceText((int) (calcDistance / 1000)); // kmに変換して画面を更新
}
private void updateDistanceText(int kilometers) {
tvDistance.setText(String.valueOf(kilometers));
}
/**
* 場所
*/
class Spot {
String name;
double latitude;
double longitude;
public Spot(String name, double latitude, double longitude) {
this.name = name;
this.latitude = latitude;
this.longitude = longitude;
}
public String getName() {
return name;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
@Override
public String toString() {
// Spinnerの表示のために必要
return name == null ? "" : name;
}
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart");
mLocationClient.connect();
Log.d(TAG, "\tLocation Client requests connection.");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
if (mLocationUpdatesRequested && mLocationClient.isConnected()) {
startLocationUpdates();
}
}
@Override
protected void onPause() {
Log.d(TAG, "onPause");
if (mLocationClient.isConnected()) {
stopLocationUpdates();
}
super.onPause();
}
@Override
public void onStop() {
Log.d(TAG, "onStop");
mLocationClient.disconnect();
Log.d(TAG, "\tLocation Client requests disconnection.");
super.onStop();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST:
switch (resultCode) {
case RESULT_OK:
if (servicesConnected()) {
startLocationUpdates();
mLocationUpdatesRequested = true;
}
break;
default:
// TODO Google Play Servicesに関する問題を解決できなかった場合の処理を書く
break;
}
break;
default:
Log.w(TAG, "不明なrequestCode");
break;
}
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged(" + location.getLatitude() + "," + location.getLongitude() + ")");
updateDistanceText(location);
}
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
startLocationUpdates(); // 位置情報取得を開始
mLocationUpdatesRequested = true;
if (mLocationClient != null) {
Location lastLocation = mLocationClient.getLastLocation();
if (lastLocation != null) {
updateDistanceText(lastLocation);
}
}
}
@Override
public void onDisconnected() {
Log.d(TAG, "onDisconnected");
stopLocationUpdates();
mLocationUpdatesRequested = false;
}
void startLocationUpdates() {
if (mLocationClient.isConnected()) {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
Log.d(TAG, "Location Client requests update.");
}
void stopLocationUpdates() {
mLocationClient.removeLocationUpdates(this);
Log.d(TAG, "Location Client removes update.");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed");
/*
* Google Play servicesに接続できなかった場合でも、解決策が提示される場合があります。 インテントを投げるとよしなに解決してくれます。
*/
if (connectionResult.hasResolution()) {
try {
// エラーを解決してくれるインテントを投げます
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* 失敗することもあります
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
// 解決策がない場合はエラーダイアログを出します
showErrorDialog(connectionResult.getErrorCode(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
}
}
protected boolean servicesConnected() {
// Google Play Servicesが利用可能かどうかチェック
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
// Google Play Servicesが利用可能な場合
return true;
} else {
// Google Play Servicesが何らかの理由で利用できない場合
// 解決策が書いてあるダイアログが貰えるので、DialogFragmentで表示する
showErrorDialog(resultCode, 0);
return false;
}
}
/**
* エラーダイアログを表示します。
*
* @param errorCode
* {@link GooglePlayServicesUtil#isGooglePlayServicesAvailable(android.content.Context)}でもらえたコード
* @param requestCode
* 特に使わない場合は0にします
*/
protected void showErrorDialog(int errorCode, int requestCode) {
// Google Play servicesからエラーダイアログを受け取る
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode, this, requestCode);
if (errorDialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(errorDialog);
errorFragment.show(getSupportFragmentManager(), ErrorDialogFragment.TAG);
}
}
/**
* Dialogを外からセットできるエラー表示用DialogFragment
*/
public static class ErrorDialogFragment extends DialogFragment {
public static final String TAG = ErrorDialogFragment.class.getSimpleName();
private Dialog mDialog;
/*
* コンストラクタ。Dialogインスタンスの初期化だけを行う。
*/
public ErrorDialogFragment() {
super();
mDialog = null;
}
/**
* Dialogをセット
*
* @param dialog
* {@link GooglePlayServicesUtil#getErrorDialog(int, android.app.Activity, int)}でもらったDialog
*/
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
/*
* セット済みのDialogをそのまま使ってダイアログを初期化
*/
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
}