|
@@ -0,0 +1,813 @@
|
|
|
|
+package jp.co.ecosysnetwork.ccloca_app.activity;
|
|
|
|
+
|
|
|
|
+import androidx.fragment.app.DialogFragment;
|
|
|
|
+
|
|
|
|
+import android.annotation.SuppressLint;
|
|
|
|
+import android.app.NotificationChannel;
|
|
|
|
+import android.app.NotificationManager;
|
|
|
|
+import android.content.Intent;
|
|
|
|
+import android.location.Location;
|
|
|
|
+import android.os.Bundle;
|
|
|
|
+import android.os.Handler;
|
|
|
|
+import android.os.Looper;
|
|
|
|
+import android.os.PowerManager;
|
|
|
|
+import android.util.Xml;
|
|
|
|
+import android.view.View;
|
|
|
|
+import android.widget.Button;
|
|
|
|
+import android.widget.ImageView;
|
|
|
|
+import android.widget.LinearLayout;
|
|
|
|
+import android.widget.ProgressBar;
|
|
|
|
+import android.widget.TextView;
|
|
|
|
+
|
|
|
|
+import com.google.android.gms.location.FusedLocationProviderClient;
|
|
|
|
+import com.google.android.gms.location.LocationCallback;
|
|
|
|
+import com.google.android.gms.location.LocationRequest;
|
|
|
|
+import com.google.android.gms.location.LocationResult;
|
|
|
|
+import com.google.android.gms.location.LocationServices;
|
|
|
|
+
|
|
|
|
+import org.xmlpull.v1.XmlPullParser;
|
|
|
|
+
|
|
|
|
+import java.io.DataOutputStream;
|
|
|
|
+import java.io.InputStream;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.net.HttpURLConnection;
|
|
|
|
+import java.net.URL;
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
+import java.util.Date;
|
|
|
|
+import java.util.Locale;
|
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
+
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.MyApplication;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.NoticeDialogFragment;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.R;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.models.busRoute_info;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.models.busRoute_infos;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.models.course_settings;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.models.drive_state;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.models.system_settings;
|
|
|
|
+import jp.co.ecosysnetwork.ccloca_app.service.DriveService;
|
|
|
|
+import jp.co.ecosysnetwork.universal.EsnDebugLog;
|
|
|
|
+import jp.co.ecosysnetwork.universal.EsnXmlParser;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * メインアクティビティ
|
|
|
|
+ */
|
|
|
|
+public class MainActivity
|
|
|
|
+ extends BaseActivity
|
|
|
|
+ implements View.OnClickListener,
|
|
|
|
+ NoticeDialogFragment.NoticeDialogListener {
|
|
|
|
+ //region 定数
|
|
|
|
+ /**
|
|
|
|
+ * 開始確認ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_START = "cfmStart";
|
|
|
|
+ /**
|
|
|
|
+ * 終了確認ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_EXIT = "cfmExit";
|
|
|
|
+ /**
|
|
|
|
+ * 運転条件エラーダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_DRIVE_CONDITION_ERROR = "errDriveCondition";
|
|
|
|
+ /**
|
|
|
|
+ * コース終了失敗ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_END_COURSE_ERROR = "cfmEndCourseError";
|
|
|
|
+ /**
|
|
|
|
+ * コース開始成功ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_START_COURSE_ERROR = "StartCourseError";
|
|
|
|
+ /**
|
|
|
|
+ * コース更新要求ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_RESET_COURSE = "ResetCourse";
|
|
|
|
+ /**
|
|
|
|
+ * コース設定要求ダイアログ
|
|
|
|
+ */
|
|
|
|
+ private static final String DIALOG_TAG_SET_COURSE = "SetCourse";
|
|
|
|
+ /**
|
|
|
|
+ * 表示更新間隔
|
|
|
|
+ */
|
|
|
|
+ private static final int REFRESH_DIPLAY_CYCLE_MSEC = 5 * 1000;
|
|
|
|
+ /**
|
|
|
|
+ * サーバ通信サービスが停止していると判断する、サーバとの不通時間
|
|
|
|
+ */
|
|
|
|
+ private static final int DISABLE_MSEC_COMM = 30 * 1000;
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得サービスが停止していると判断する、位置情報を取得していない時間
|
|
|
|
+ */
|
|
|
|
+ private static final int DISABLE_MSEC_LOLCATION = 30 * 1000;
|
|
|
|
+ /**
|
|
|
|
+ * コース開始,終了要求後の待機時間
|
|
|
|
+ */
|
|
|
|
+ private static final int WAIT_MSEC_REQ_COURSE_START_AND_END = 1000;
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報を採用する最小精度
|
|
|
|
+ */
|
|
|
|
+ private static final float MIN_ACC = 100;
|
|
|
|
+ /**
|
|
|
|
+ * 初期位置情報取得サイクル
|
|
|
|
+ */
|
|
|
|
+ private static final long INIT_MSEC_LOCATION_INTERVAL = 1000;
|
|
|
|
+ /**
|
|
|
|
+ * 初期位置情報取得サイクル
|
|
|
|
+ */
|
|
|
|
+ private static final long INIT_MSEC_LOCATION_FAST_INTERVAL = 1000;
|
|
|
|
+ //endregion
|
|
|
|
+ //region メンバ変数
|
|
|
|
+ /**
|
|
|
|
+ * シングルトンのアプリケーション参照
|
|
|
|
+ */
|
|
|
|
+ private final MyApplication _app = MyApplication.getInstance();
|
|
|
|
+ /**
|
|
|
|
+ * ヘッダ部のリニアレイアウト
|
|
|
|
+ */
|
|
|
|
+ private LinearLayout _lnlHeader;
|
|
|
|
+ /**
|
|
|
|
+ * コース名テキストビュー
|
|
|
|
+ */
|
|
|
|
+ private TextView _txvCourseName;
|
|
|
|
+ /**
|
|
|
|
+ * 運行状況テキストビュー
|
|
|
|
+ */
|
|
|
|
+ private TextView _txvOperationStatus;
|
|
|
|
+ /**
|
|
|
|
+ * サーバ通信状態アイコン
|
|
|
|
+ */
|
|
|
|
+ private ImageView _imvCommState;
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得状態アイコン
|
|
|
|
+ */
|
|
|
|
+ private ImageView _imvLocationState;
|
|
|
|
+ /**
|
|
|
|
+ * ボディ部のリニアレイアウト
|
|
|
|
+ */
|
|
|
|
+ private LinearLayout _lnlBody;
|
|
|
|
+ /**
|
|
|
|
+ * コース開始ボタン
|
|
|
|
+ */
|
|
|
|
+ private Button _btnStartDrive;
|
|
|
|
+ /**
|
|
|
|
+ * 電源管理
|
|
|
|
+ */
|
|
|
|
+ private PowerManager.WakeLock _wakeLock;
|
|
|
|
+ /**
|
|
|
|
+ * システム設定モデル
|
|
|
|
+ */
|
|
|
|
+ private system_settings _system_settings;
|
|
|
|
+ /**
|
|
|
|
+ * コース設定モデル
|
|
|
|
+ */
|
|
|
|
+ private course_settings _course_settings;
|
|
|
|
+ /**
|
|
|
|
+ * バス経路情報List
|
|
|
|
+ */
|
|
|
|
+ private busRoute_infos _busRoute_infos;
|
|
|
|
+ /**
|
|
|
|
+ * 表示更新ハンドラ
|
|
|
|
+ */
|
|
|
|
+ private Handler _refreshDisplayHandler;
|
|
|
|
+ /**
|
|
|
|
+ * 通信中フラグ
|
|
|
|
+ */
|
|
|
|
+ private boolean _communicating;
|
|
|
|
+ /**
|
|
|
|
+ * コース開始/終了プログレスバー
|
|
|
|
+ */
|
|
|
|
+ private ProgressBar _prgStartAndEndCourse;
|
|
|
|
+ /**
|
|
|
|
+ * 運行開始用位置情報コールバックハンドラ
|
|
|
|
+ */
|
|
|
|
+ private LocationCallback _startLocationCallback;
|
|
|
|
+ /**
|
|
|
|
+ * 運行終了用位置情報コールバックハンドラ
|
|
|
|
+ */
|
|
|
|
+ private LocationCallback _endLocationCallback;
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得中であるか否か
|
|
|
|
+ */
|
|
|
|
+ private boolean _isActiveUpdateLocation = false;
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報クライアント
|
|
|
|
+ */
|
|
|
|
+ private FusedLocationProviderClient _fusedLocationProviderClient;
|
|
|
|
+ //endregion
|
|
|
|
+ //region 内部メソッド
|
|
|
|
+ /**
|
|
|
|
+ * リフレッシュ(ボタン)
|
|
|
|
+ */
|
|
|
|
+ private void refreshButton() {
|
|
|
|
+ _btnStartDrive.setEnabled((!_course_settings.selected_busRoute_info.bus_route_no.equals("0")) &&
|
|
|
|
+ (!_communicating) &&
|
|
|
|
+ (!DriveService.isStarted()));
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 終了処理
|
|
|
|
+ */
|
|
|
|
+ private void terminate() {
|
|
|
|
+ finishAndRemoveTask();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 開始ボタン押下処理
|
|
|
|
+ */
|
|
|
|
+ private void clickBtnStart() {
|
|
|
|
+ EsnDebugLog.outputLog("開始ボタン押下", EsnDebugLog.DIV.INFO);
|
|
|
|
+
|
|
|
|
+ // 開始確認ダイアログ表示
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleCfm),
|
|
|
|
+ getString(R.string.msgConfStartCourse),
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.yes),
|
|
|
|
+ getString(R.string.no)
|
|
|
|
+ );
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_START);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 終了確認ダイアログ:はいボタン押下
|
|
|
|
+ */
|
|
|
|
+ private void clickPosCfmExit() {
|
|
|
|
+ // プログレスバー表示
|
|
|
|
+ _communicating = true;
|
|
|
|
+ _prgStartAndEndCourse.setVisibility(View.VISIBLE);
|
|
|
|
+ if (DriveService.isStarted()) {
|
|
|
|
+ startLocationUpdatesForCourseEnd(_endLocationCallback);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ terminate();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 運行終了呼出処理
|
|
|
|
+ */
|
|
|
|
+ private void callEndExec(final double lat, final double lon)
|
|
|
|
+ {
|
|
|
|
+ final Handler handler = new Handler(Looper.getMainLooper());
|
|
|
|
+ ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
+ executor.execute(new Runnable() {
|
|
|
|
+ /**
|
|
|
|
+ * 運行終了処理バックグラウンド処理
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ final String ret = startAndEndDriveExec(MyApplication.APIURL_END_BUS_COURSE, lat, lon);
|
|
|
|
+ handler.postDelayed(new Runnable() {
|
|
|
|
+ /**
|
|
|
|
+ * バックグラウンド終了後のUI処理
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ _communicating = false;
|
|
|
|
+ if (ret == null) {
|
|
|
|
+ _app.drive_state_model.setOperationState(drive_state.OPERATION_STATE.INACTIVE, true);
|
|
|
|
+ terminate();
|
|
|
|
+ } else {
|
|
|
|
+ // 認証失敗ダイアログ
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleError),
|
|
|
|
+ ret,
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.ok),
|
|
|
|
+ "");
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_END_COURSE_ERROR);
|
|
|
|
+ }
|
|
|
|
+ // プログレスバー非表示
|
|
|
|
+ _prgStartAndEndCourse.setVisibility(View.GONE);
|
|
|
|
+ }
|
|
|
|
+ }, 500);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 終了ボタン押下処理
|
|
|
|
+ */
|
|
|
|
+ private void clickBtnExit() {
|
|
|
|
+ EsnDebugLog.outputLog("終了ボタン押下", EsnDebugLog.DIV.INFO);
|
|
|
|
+
|
|
|
|
+ // 終了確認ダイアログ表示
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleCfm),
|
|
|
|
+ getString(R.string.msgAppExist),
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.yes),
|
|
|
|
+ getString(R.string.no)
|
|
|
|
+ );
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_EXIT);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 開始確認ダイアログ:はいボタン押下
|
|
|
|
+ */
|
|
|
|
+ private void clickPosCfmStart() {
|
|
|
|
+ // プログレスバー表示
|
|
|
|
+ _communicating = true;
|
|
|
|
+ _prgStartAndEndCourse.setVisibility(View.VISIBLE);
|
|
|
|
+ startLocationUpdates(_startLocationCallback);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 運行スタート呼出処理
|
|
|
|
+ */
|
|
|
|
+ private void callStartExec(final double lat, final double lon)
|
|
|
|
+ {
|
|
|
|
+ // 運転状態の初期化処理
|
|
|
|
+ _app.drive_state_model.init();
|
|
|
|
+ if(_course_settings.selected_busRoute_info.bus_route_no.equals("0"))
|
|
|
|
+ {
|
|
|
|
+ // コース設定要求ダイアログ
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleCfm),
|
|
|
|
+ getString(R.string.msgSetCourse),
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.ok),
|
|
|
|
+ "");
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_SET_COURSE);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 日替わり時、運行状態をクリアする
|
|
|
|
+ SimpleDateFormat fmtYYYYMMDD = new SimpleDateFormat("yyyyMMdd", Locale.JAPANESE);
|
|
|
|
+ String nowDate = fmtYYYYMMDD.format(new Date());
|
|
|
|
+ if ((_app.drive_state_model.getLastUpdateCourseDate() == null) || (_app.drive_state_model.getLastUpdateCourseDate().compareTo(nowDate) < 0)) {
|
|
|
|
+ _course_settings.initSelectedCourse();
|
|
|
|
+ _busRoute_infos.initBusRouteInfos();
|
|
|
|
+ _app.drive_state_model.setOperationState(drive_state.OPERATION_STATE.INACTIVE, false);
|
|
|
|
+ // コース更新要求ダイアログ
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleCfm),
|
|
|
|
+ getString(R.string.msgResetCourse),
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.ok),
|
|
|
|
+ "");
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_RESET_COURSE);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ final Handler handler = new Handler(Looper.getMainLooper());
|
|
|
|
+ ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
+ executor.execute(new Runnable() {
|
|
|
|
+ /**
|
|
|
|
+ * 運行開始処理バックグラウンド処理
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ final String ret = startAndEndDriveExec(MyApplication.APIURL_START_BUS_COURSE, lat, lon);
|
|
|
|
+ handler.postDelayed(new Runnable() {
|
|
|
|
+ /**
|
|
|
|
+ * バックグラウンド終了後のUI処理
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ _communicating = false;
|
|
|
|
+ if (ret == null) {
|
|
|
|
+ _app.drive_state_model.setOperationState(drive_state.OPERATION_STATE.ACTIVE, false);
|
|
|
|
+ EsnDebugLog.outputLog("正常に運行を開始しました", EsnDebugLog.DIV.WARN);
|
|
|
|
+ // エラーがない場合、運転制御開始
|
|
|
|
+ initExec();
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ EsnDebugLog.outputLog(ret, EsnDebugLog.DIV.WARN);
|
|
|
|
+ // 認証失敗ダイアログ
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleError),
|
|
|
|
+ ret,
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.ok),
|
|
|
|
+ "");
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_START_COURSE_ERROR);
|
|
|
|
+ }
|
|
|
|
+ // プログレスバー非表示
|
|
|
|
+ _prgStartAndEndCourse.setVisibility(View.GONE);
|
|
|
|
+ // リフレッシュ
|
|
|
|
+ refreshButton();
|
|
|
|
+ }
|
|
|
|
+ }, 500);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 運行開始,終了実行処理
|
|
|
|
+ * @return エラーメッセージ
|
|
|
|
+ */
|
|
|
|
+ private String startAndEndDriveExec(String url, double lat, double lon){
|
|
|
|
+ String ret = null;
|
|
|
|
+ // 日替わり時、運行状態をクリアする
|
|
|
|
+ SimpleDateFormat fmtYYYYMMDD = new SimpleDateFormat("yyyy-MM-dd", Locale.JAPANESE);
|
|
|
|
+ String nowDate = fmtYYYYMMDD.format(new Date());
|
|
|
|
+ SimpleDateFormat fmtHHiiss = new SimpleDateFormat("HH:mm:ss", Locale.JAPANESE);
|
|
|
|
+ String nowTime = fmtHHiiss.format(new Date());
|
|
|
|
+
|
|
|
|
+ HttpURLConnection con = null;
|
|
|
|
+ DataOutputStream os = null;
|
|
|
|
+ InputStream is = null;
|
|
|
|
+ try {
|
|
|
|
+ URL accUrl = new URL(_system_settings.server_url + url);
|
|
|
|
+ con = (HttpURLConnection)accUrl.openConnection();
|
|
|
|
+ con.setConnectTimeout(10 * 1000);
|
|
|
|
+ con.setRequestMethod("POST");
|
|
|
|
+ con.setDoOutput(true);
|
|
|
|
+ con.setDoInput(true);
|
|
|
|
+ con.setUseCaches(false);
|
|
|
|
+
|
|
|
|
+ // ヘッダ設定
|
|
|
|
+ con.setRequestProperty("ANDROID-API-KEY", MyApplication.API_KEY);
|
|
|
|
+ con.setRequestProperty("Connection", "Keep-Alive");
|
|
|
|
+ con.setRequestProperty("Charset", "UTF-8");
|
|
|
|
+ String boundary = "-----------------------------" + System.currentTimeMillis();
|
|
|
|
+ con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
|
|
|
+ con.connect();
|
|
|
|
+
|
|
|
|
+ // 送信データの設定
|
|
|
|
+ os = new DataOutputStream(con.getOutputStream());
|
|
|
|
+ append_string(os, boundary, "intFacilityPhoneNo", _system_settings.phone_id);
|
|
|
|
+ append_string(os, boundary, "intBusRouteNo", _course_settings.selected_busRoute_info.bus_route_no);
|
|
|
|
+ append_string(os, boundary, "decLatitude", BigDecimal.valueOf(lat).toPlainString());
|
|
|
|
+ append_string(os, boundary, "decLongitude", BigDecimal.valueOf(lon).toPlainString());
|
|
|
|
+ append_string(os, boundary, "dtDate", nowDate + nowTime);
|
|
|
|
+ append_final(os, boundary);
|
|
|
|
+ os = null;
|
|
|
|
+ // 携帯端末認証送信後のウェイト
|
|
|
|
+ MyApplication.sleep(WAIT_MSEC_REQ_COURSE_START_AND_END);
|
|
|
|
+
|
|
|
|
+ // 受信データを取得
|
|
|
|
+ is = con.getInputStream();
|
|
|
|
+ // 受信データのXMLパース
|
|
|
|
+ XmlPullParser parser = Xml.newPullParser();
|
|
|
|
+ parser.setInput(is, "UTF-8");
|
|
|
|
+
|
|
|
|
+ // 受信データのパース
|
|
|
|
+ EsnXmlParser esnParser = new EsnXmlParser(parser);
|
|
|
|
+ ret = esnParser.tryParse();
|
|
|
|
+ if (ret == null) {
|
|
|
|
+ // パース成功
|
|
|
|
+ for (EsnXmlParser.ParseItem item : esnParser.getParseItems()) {
|
|
|
|
+ if (item.tag.equals("errMsg")) {
|
|
|
|
+ ret = String.format(Locale.JAPAN, "開始処理要求が失敗しました。\n %s", item.value);
|
|
|
|
+ EsnDebugLog.outputLog(ret, EsnDebugLog.DIV.ERR);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e1) {
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "例外エラー1 %s", e1.toString()), EsnDebugLog.DIV.ERR);
|
|
|
|
+ ret = getString(R.string.msgCommunicationError);
|
|
|
|
+ } finally {
|
|
|
|
+ try {
|
|
|
|
+ if (is != null) is.close();
|
|
|
|
+ if (os != null) os.close();
|
|
|
|
+ if (con != null) con.disconnect();
|
|
|
|
+ } catch (Exception e2) {
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "例外エラー2 %s", e2.toString()), EsnDebugLog.DIV.ERR);
|
|
|
|
+ ret = getString(R.string.msgCommunicateCmpltError);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 表示更新
|
|
|
|
+ */
|
|
|
|
+ private void refreshDisplay() {
|
|
|
|
+ EsnDebugLog.outputLog("表示更新", EsnDebugLog.DIV.INFO);
|
|
|
|
+ // リフレッシュ
|
|
|
|
+ refreshButton();
|
|
|
|
+ if (_course_settings.selected_busRoute_info != null) {
|
|
|
|
+ _txvCourseName.setText(_course_settings.selected_busRoute_info.bus_route_name);
|
|
|
|
+ }
|
|
|
|
+ // 運行状態を表示
|
|
|
|
+ switch (_app.drive_state_model.getOperationState()) {
|
|
|
|
+ case INACTIVE:
|
|
|
|
+ _lnlHeader.setBackgroundColor(getColor(R.color.operationStateNeutral));
|
|
|
|
+ _txvCourseName.setTextColor(getColor(R.color.operationStateNeutralText));
|
|
|
|
+ _lnlBody.setBackgroundColor(getColor(R.color.operationStateNeutral));
|
|
|
|
+ _txvOperationStatus.setText(getString(R.string.driveStateEnd));
|
|
|
|
+ _txvOperationStatus.setTextColor(getColor(R.color.operationStateActiveText));
|
|
|
|
+ break;
|
|
|
|
+ case ACTIVE:
|
|
|
|
+ _lnlHeader.setBackgroundColor(getColor(R.color.operationStateActive));
|
|
|
|
+ _txvCourseName.setTextColor(getColor(R.color.operationStateActiveText));
|
|
|
|
+ _lnlBody.setBackgroundColor(getColor(R.color.operationStateActive));
|
|
|
|
+ _txvOperationStatus.setText(getString(R.string.driveStateStart));
|
|
|
|
+ _txvOperationStatus.setTextColor(getColor(R.color.approachColorArrial));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // サーバとの通信状態を表示
|
|
|
|
+ if ((System.currentTimeMillis() - _app.drive_state_model.getLastCommActiveMsec()) > DISABLE_MSEC_COMM) {
|
|
|
|
+ //_imvCommState.setBackgroundResource(R.drawable.ic_comm_disable);
|
|
|
|
+ _imvCommState.setVisibility(View.INVISIBLE);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ _imvCommState.setBackgroundResource(R.drawable.ic_comm_enable);
|
|
|
|
+ _imvCommState.setVisibility(View.VISIBLE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 位置情報取得状態を表示
|
|
|
|
+ if ((System.currentTimeMillis() - _app.drive_state_model.getLastLocationActiveMsec()) > DISABLE_MSEC_LOLCATION) {
|
|
|
|
+ _imvLocationState.setBackgroundResource(R.drawable.ic_location_disable);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ _imvLocationState.setBackgroundResource(R.drawable.ic_location_enable);
|
|
|
|
+ }
|
|
|
|
+ _imvLocationState.setVisibility(View.VISIBLE);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 表示更新ハンドラ
|
|
|
|
+ */
|
|
|
|
+ private Runnable _refreshDisplayRunnable = new Runnable() {
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ // 表示更新
|
|
|
|
+ refreshDisplay();
|
|
|
|
+
|
|
|
|
+ // タイマ指定
|
|
|
|
+ _refreshDisplayHandler.postDelayed(_refreshDisplayRunnable, REFRESH_DIPLAY_CYCLE_MSEC);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得の開始
|
|
|
|
+ */
|
|
|
|
+ @SuppressLint("MissingPermission")
|
|
|
|
+ private void startLocationUpdates(LocationCallback locationCallback) {
|
|
|
|
+ // 位置情報取得中の場合は一旦停止する
|
|
|
|
+ if (_isActiveUpdateLocation) {
|
|
|
|
+ stopLocationUpdates(locationCallback);
|
|
|
|
+ }
|
|
|
|
+ // 位置情報の取得を開始する
|
|
|
|
+ LocationRequest locReq = LocationRequest.create();
|
|
|
|
+ locReq.setInterval(MainActivity.INIT_MSEC_LOCATION_INTERVAL);
|
|
|
|
+ locReq.setFastestInterval(MainActivity.INIT_MSEC_LOCATION_FAST_INTERVAL);
|
|
|
|
+ locReq.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
|
|
|
+ _fusedLocationProviderClient.requestLocationUpdates(locReq, locationCallback, Looper.getMainLooper());
|
|
|
|
+ _isActiveUpdateLocation = true;
|
|
|
|
+
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "位置情報の取得開始 interval=%d fastestInterval=%d", MainActivity.INIT_MSEC_LOCATION_INTERVAL, MainActivity.INIT_MSEC_LOCATION_FAST_INTERVAL), EsnDebugLog.DIV.INFO);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得の終了
|
|
|
|
+ */
|
|
|
|
+ @SuppressLint("MissingPermission")
|
|
|
|
+ private void startLocationUpdatesForCourseEnd(LocationCallback locationCallback) {
|
|
|
|
+ // 位置情報の取得を開始する
|
|
|
|
+ LocationRequest locReq = LocationRequest.create();
|
|
|
|
+ locReq.setInterval(MainActivity.INIT_MSEC_LOCATION_INTERVAL);
|
|
|
|
+ locReq.setFastestInterval(MainActivity.INIT_MSEC_LOCATION_FAST_INTERVAL);
|
|
|
|
+ locReq.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
|
|
|
+ _fusedLocationProviderClient.requestLocationUpdates(locReq, locationCallback, Looper.getMainLooper());
|
|
|
|
+ _isActiveUpdateLocation = true;
|
|
|
|
+
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "位置情報の取得開始 interval=%d fastestInterval=%d", MainActivity.INIT_MSEC_LOCATION_INTERVAL, MainActivity.INIT_MSEC_LOCATION_FAST_INTERVAL), EsnDebugLog.DIV.INFO);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 位置情報取得の停止
|
|
|
|
+ */
|
|
|
|
+ private void stopLocationUpdates(LocationCallback locationCallback) {
|
|
|
|
+ if (_isActiveUpdateLocation) {
|
|
|
|
+ EsnDebugLog.outputLog("位置情報の更新を停止", EsnDebugLog.DIV.INFO);
|
|
|
|
+ _fusedLocationProviderClient.removeLocationUpdates(locationCallback);
|
|
|
|
+ _isActiveUpdateLocation = false;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ EsnDebugLog.outputLog("位置情報の更新は既に停止している", EsnDebugLog.DIV.WARN);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * 初期化処理
|
|
|
|
+ */
|
|
|
|
+ private void initExec() {
|
|
|
|
+ if (!DriveService.isStarted()) {
|
|
|
|
+ // 運転サービスの通知
|
|
|
|
+ NotificationChannel channel = new NotificationChannel(DriveService.CHANNEL_ID, getString(R.string.app_name), NotificationManager.IMPORTANCE_DEFAULT);
|
|
|
|
+ channel.setDescription(getString(R.string.driveNotifyDescription));
|
|
|
|
+ NotificationManager manager = getSystemService(NotificationManager.class);
|
|
|
|
+ manager.createNotificationChannel(channel);
|
|
|
|
+
|
|
|
|
+ // 運転サービスの開始
|
|
|
|
+ Intent intent = new Intent(this, DriveService.class);
|
|
|
|
+ startForegroundService(intent);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ EsnDebugLog.outputLog("メイン画面 既に運転サービス起動済のため、起動しない", EsnDebugLog.DIV.INFO);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 表示更新
|
|
|
|
+ refreshDisplay();
|
|
|
|
+
|
|
|
|
+ // 表示更新タイマ起動
|
|
|
|
+ _refreshDisplayHandler = new Handler(Looper.getMainLooper());
|
|
|
|
+ _refreshDisplayHandler.postDelayed(_refreshDisplayRunnable, REFRESH_DIPLAY_CYCLE_MSEC);
|
|
|
|
+ }
|
|
|
|
+ //endregion
|
|
|
|
+ //region イベントメソッド
|
|
|
|
+ /**
|
|
|
|
+ * アクティビティ作成イベント
|
|
|
|
+ *
|
|
|
|
+ * @param savedInstanceState アクティビティが以前にシャットダウンされた後に再初期化されている場合、このバンドルにはonSaveInstanceState(Bundle)で最後に提供されたデータが含まれます。 注:それ以外の場合はnullです。
|
|
|
|
+ */
|
|
|
|
+ @SuppressLint("WakelockTimeout")
|
|
|
|
+ @Override
|
|
|
|
+ protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
+ EsnDebugLog.outputLog("メイン画面 onCreate", EsnDebugLog.DIV.INFO);
|
|
|
|
+ super.onCreate(savedInstanceState);
|
|
|
|
+ setContentView(R.layout.activity_main);
|
|
|
|
+
|
|
|
|
+ // メンバ変数設定
|
|
|
|
+ _lnlHeader = findViewById(R.id.lnlHeader);
|
|
|
|
+ _txvCourseName = findViewById(R.id.txvSelectedCourseName);
|
|
|
|
+ _txvOperationStatus = findViewById(R.id.txvOperationStatus);
|
|
|
|
+ _imvCommState = findViewById(R.id.imvCommState);
|
|
|
|
+ _imvLocationState = findViewById(R.id.imvLocationState);
|
|
|
|
+ _lnlBody = findViewById(R.id.lnlBody);
|
|
|
|
+ _btnStartDrive = findViewById(R.id.btnStartDrive);
|
|
|
|
+ _prgStartAndEndCourse = findViewById(R.id.prgStartAndEndCourse);
|
|
|
|
+ _system_settings = new system_settings();
|
|
|
|
+ _course_settings = new course_settings();
|
|
|
|
+ _busRoute_infos = new busRoute_infos();
|
|
|
|
+ // 位置情報クライアント生成
|
|
|
|
+ _fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
|
|
|
|
+
|
|
|
|
+ // ボタンのリスナ登録
|
|
|
|
+ findViewById(R.id.btnExit).setOnClickListener(this);
|
|
|
|
+ _btnStartDrive.setOnClickListener(this);
|
|
|
|
+
|
|
|
|
+ // ボタンリフレッシュ
|
|
|
|
+ refreshButton();
|
|
|
|
+ // 運転状態の初期化処理
|
|
|
|
+ _app.drive_state_model.init();
|
|
|
|
+
|
|
|
|
+ // CPUを常にONにする
|
|
|
|
+ _wakeLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getPackageName());
|
|
|
|
+ _wakeLock.acquire();
|
|
|
|
+
|
|
|
|
+ // 携帯端末ID、コースが未設定の場合、エラー情報を表示し、プログラムを終了する
|
|
|
|
+ StringBuilder errMsg = new StringBuilder();
|
|
|
|
+ if ((_system_settings.phone_id == null) || (_system_settings.phone_id.length() == 0)) {
|
|
|
|
+ errMsg.append(getString(R.string.msgSetPhoneId)).append("\n");
|
|
|
|
+ }
|
|
|
|
+ if (_course_settings.selected_busRoute_info.bus_route_no.equals("0")) {
|
|
|
|
+ errMsg.append(getString(R.string.msgSetCourse)).append("\n");
|
|
|
|
+ }
|
|
|
|
+ if (errMsg.length() > 0) {
|
|
|
|
+ // 運転条件エラー
|
|
|
|
+ EsnDebugLog.outputLog(errMsg.toString(), EsnDebugLog.DIV.WARN);
|
|
|
|
+
|
|
|
|
+ DialogFragment newFragment = new NoticeDialogFragment(getString(R.string.titleError),
|
|
|
|
+ errMsg.toString(),
|
|
|
|
+ false,
|
|
|
|
+ false,
|
|
|
|
+ getString(R.string.ok),
|
|
|
|
+ "");
|
|
|
|
+ newFragment.show(getSupportFragmentManager(), DIALOG_TAG_DRIVE_CONDITION_ERROR);
|
|
|
|
+ }
|
|
|
|
+ // ロケーションコールバック定義
|
|
|
|
+ _startLocationCallback = new LocationCallback() {
|
|
|
|
+ /**
|
|
|
|
+ * ロケーション取得結果
|
|
|
|
+ *
|
|
|
|
+ * @param locationResult 位置情報の取得結果
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onLocationResult(LocationResult locationResult) {
|
|
|
|
+ stopLocationUpdates(_startLocationCallback);
|
|
|
|
+ if (locationResult != null) {
|
|
|
|
+ for (Location loc : locationResult.getLocations()) {
|
|
|
|
+ double lat = loc.getLatitude(); // 緯度
|
|
|
|
+ double lon = loc.getLongitude(); // 経度
|
|
|
|
+ float acc = loc.getAccuracy(); // 精度
|
|
|
|
+ // 取得値が最低精度を満たしている場合、位置情報制御を実施する
|
|
|
|
+ if ((acc < MIN_ACC) && (0 < lat) && (0 < lon)) {
|
|
|
|
+ callStartExec(lat, lon);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // リフレッシュ
|
|
|
|
+ refreshButton();
|
|
|
|
+ super.onLocationResult(locationResult);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ // ロケーションコールバック定義
|
|
|
|
+ _endLocationCallback = new LocationCallback() {
|
|
|
|
+ /**
|
|
|
|
+ * ロケーション取得結果
|
|
|
|
+ *
|
|
|
|
+ * @param locationResult 位置情報の取得結果
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onLocationResult(LocationResult locationResult) {
|
|
|
|
+ stopLocationUpdates(_endLocationCallback);
|
|
|
|
+ if (locationResult != null) {
|
|
|
|
+ for (Location loc : locationResult.getLocations()) {
|
|
|
|
+ double lat = loc.getLatitude(); // 緯度
|
|
|
|
+ double lon = loc.getLongitude(); // 経度
|
|
|
|
+ float acc = loc.getAccuracy(); // 精度
|
|
|
|
+ // 取得値が最低精度を満たしている場合、位置情報制御を実施する
|
|
|
|
+ if ((acc < MIN_ACC) && (0 < lat) && (0 < lon)) {
|
|
|
|
+ callEndExec(lat, lon);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ super.onLocationResult(locationResult);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ refreshDisplay();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * アクティビティの開始
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ protected void onStart() {
|
|
|
|
+ EsnDebugLog.outputLog("メイン画面 onStart", EsnDebugLog.DIV.INFO);
|
|
|
|
+ super.onStart();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * アクティビティの停止
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ protected void onStop() {
|
|
|
|
+ EsnDebugLog.outputLog("メイン画面 onStop", EsnDebugLog.DIV.INFO);
|
|
|
|
+ super.onStop();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * アクティビティの終了
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ protected void onDestroy() {
|
|
|
|
+ EsnDebugLog.outputLog("メイン画面 onDestroy", EsnDebugLog.DIV.INFO);
|
|
|
|
+ super.onDestroy();
|
|
|
|
+ // 表示更新の解除
|
|
|
|
+ if (_refreshDisplayRunnable != null) {
|
|
|
|
+ _refreshDisplayHandler.removeCallbacks(_refreshDisplayRunnable);
|
|
|
|
+ }
|
|
|
|
+ // サービスの停止
|
|
|
|
+ Intent intent = new Intent(this, DriveService.class);
|
|
|
|
+ stopService(intent);
|
|
|
|
+ // CPUロックの解除
|
|
|
|
+ _wakeLock.release();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * クリックリスナー
|
|
|
|
+ * @param view 対象のビュー
|
|
|
|
+ */
|
|
|
|
+ public void onClick(View view) {
|
|
|
|
+ Intent intent;
|
|
|
|
+ switch (view.getId()) {
|
|
|
|
+ case R.id.btnExit: clickBtnExit(); break; // 終了ボタン
|
|
|
|
+ case R.id.btnStartDrive: clickBtnStart(); break; // 終了ボタン
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * ダイアログのOKボタン押下イベント
|
|
|
|
+ * @param dialog ダイアログ
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onDialogPositiveClick(NoticeDialogFragment dialog) {
|
|
|
|
+ String tag = dialog.getTag();
|
|
|
|
+ if (tag == null) {
|
|
|
|
+ EsnDebugLog.outputLog("ダイアログタグが設定されていない", EsnDebugLog.DIV.ERR);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "POSSTIVEボタン押下 %s", tag), EsnDebugLog.DIV.INFO);
|
|
|
|
+
|
|
|
|
+ switch (tag) {
|
|
|
|
+ case DIALOG_TAG_EXIT:
|
|
|
|
+ // 終了確認ダイアログではいボタン押下
|
|
|
|
+ clickPosCfmExit();
|
|
|
|
+ break;
|
|
|
|
+ case DIALOG_TAG_DRIVE_CONDITION_ERROR:
|
|
|
|
+ case DIALOG_TAG_RESET_COURSE:
|
|
|
|
+ case DIALOG_TAG_SET_COURSE:
|
|
|
|
+ // 運転条件エラーでOKボタン押下
|
|
|
|
+ terminate();
|
|
|
|
+ break;
|
|
|
|
+ case DIALOG_TAG_START:
|
|
|
|
+ // 開始確認ダイアログではいボタン押下
|
|
|
|
+ clickPosCfmStart();
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * ダイアログのキャンセルボタン押下イベント
|
|
|
|
+ * @param dialog ダイアログ
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onDialogNegativeClick(NoticeDialogFragment dialog) {
|
|
|
|
+ String tag = dialog.getTag();
|
|
|
|
+ if (tag == null) {
|
|
|
|
+ EsnDebugLog.outputLog("ダイアログタグが設定されていない", EsnDebugLog.DIV.ERR);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "NEGATIVEボタン押下 %s", tag), EsnDebugLog.DIV.INFO);
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * ダイアログのニュートラルボタン押下イベント
|
|
|
|
+ * @param dialog ダイアログ
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void onDialogNeutralClick(NoticeDialogFragment dialog) {
|
|
|
|
+ String tag = dialog.getTag();
|
|
|
|
+ if (tag == null) {
|
|
|
|
+ EsnDebugLog.outputLog("ダイアログタグが設定されていない", EsnDebugLog.DIV.ERR);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ EsnDebugLog.outputLog(String.format(Locale.JAPAN, "NEUTRALボタン押下 %s", tag), EsnDebugLog.DIV.INFO);
|
|
|
|
+ }
|
|
|
|
+ //endregion
|
|
|
|
+}
|