1 package jp.sfjp.gokigen.a01c;
3 import android.content.Intent;
4 import android.content.SharedPreferences;
5 import android.graphics.Color;
6 import android.graphics.drawable.Drawable;
7 import android.os.Bundle;
8 import android.os.PowerManager;
9 import android.os.Vibrator;
10 import android.preference.PreferenceManager;
11 import android.provider.Settings;
12 import android.util.Log;
13 import android.widget.ImageButton;
14 import android.widget.TextView;
15 import android.Manifest;
16 import android.content.pm.PackageManager;
18 import androidx.appcompat.app.AppCompatActivity;
19 import androidx.core.app.ActivityCompat;
20 import androidx.core.content.ContextCompat;
22 import jp.sfjp.gokigen.a01c.liveview.CameraLiveImageView;
23 import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewListenerImpl;
24 import jp.sfjp.gokigen.a01c.liveview.dialog.FavoriteSettingSelectionDialog;
25 import jp.sfjp.gokigen.a01c.liveview.dialog.IDialogDismissedNotifier;
26 import jp.sfjp.gokigen.a01c.olycamerawrapper.dispatcher.FeatureDispatcher;
27 import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
28 import jp.sfjp.gokigen.a01c.liveview.IMessageDrawer;
29 import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewOnTouchListener;
30 import jp.sfjp.gokigen.a01c.olycamerawrapper.OlyCameraCoordinator;
31 import jp.sfjp.gokigen.a01c.preference.IPreferenceCameraPropertyAccessor;
32 import jp.sfjp.gokigen.a01c.preference.PreferenceAccessWrapper;
33 import jp.sfjp.gokigen.a01c.thetacamerawrapper.ThetaCameraController;
39 public class MainActivity extends AppCompatActivity implements IChangeScene, IShowInformation, ICameraStatusReceiver, IDialogDismissedNotifier
41 private final String TAG = toString();
42 static final int REQUEST_NEED_PERMISSIONS = 1010;
43 //static final int COMMAND_MY_PROPERTY = 0x00000100;
45 private PreferenceAccessWrapper preferences = null;
46 private PowerManager powerManager = null;
47 private CameraLiveImageView liveView = null;
48 private ICameraController currentCoordinator = null;
49 private ICameraController olyAirCoordinator = null;
50 private ICameraController thetaCoordinator = null;
51 private IMessageDrawer messageDrawer = null;
52 private CameraLiveViewOnTouchListener listener = null;
53 private FavoriteSettingSelectionDialog selectionDialog = null;
54 private Vibrator vibrator = null;
55 private boolean cameraDisconnectedHappened = false;
56 //private boolean ambientMode = false;
62 protected void onCreate(Bundle savedInstanceState)
64 super.onCreate(savedInstanceState);
65 Log.v(TAG, "onCreate()");
67 // Ambientモードを許してみる...
68 //setAmbientEnabled();
71 setContentView(R.layout.activity_main);
74 if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
75 (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
76 (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
77 (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
78 (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED)||
79 (ContextCompat.checkSelfPermission(this, Manifest.permission.WAKE_LOCK) != PackageManager.PERMISSION_GRANTED)||
80 (ContextCompat.checkSelfPermission(this, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED)||
81 (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED))
83 ActivityCompat.requestPermissions(this,
85 Manifest.permission.ACCESS_NETWORK_STATE,
86 Manifest.permission.ACCESS_WIFI_STATE,
87 Manifest.permission.CHANGE_WIFI_STATE,
88 Manifest.permission.CHANGE_NETWORK_STATE,
89 Manifest.permission.WRITE_SETTINGS,
90 Manifest.permission.WAKE_LOCK,
91 Manifest.permission.INTERNET,
93 REQUEST_NEED_PERMISSIONS);
100 // GPS機能が搭載されていない場合...
101 Log.d(TAG, "This hardware doesn't have GPS.");
102 // Fall back to functionality that does not use location or
103 // warn the user that location function is not available.
107 vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
110 powerManager = (PowerManager) getSystemService(POWER_SERVICE);
112 setupCameraCoordinator();
113 setupInitialButtonIcons();
114 setupActionListener();
126 protected void onResume()
129 Log.v(TAG, "onResume()");
136 protected void onPause()
139 Log.v(TAG, "onPause()");
147 public void onStart()
150 Log.v(TAG, "onStart()");
161 Log.v(TAG, "onStop()");
167 public void onEnterAmbient(Bundle ambientDetails)
169 super.onEnterAmbient(ambientDetails);
170 Log.v(TAG, "onEnterAmbient()");
175 public void onExitAmbient()
177 super.onExitAmbient();
178 Log.v(TAG, "onExitAmbient()");
183 public void onUpdateAmbient()
185 super.onUpdateAmbient();
186 Log.v(TAG, "onUpdateAmbient()");
191 * ボタンが押された、画面がタッチされた、、は、リスナクラスで処理するよう紐づける
194 private void setupActionListener()
198 final ImageButton btn1 = findViewById(R.id.btn_1);
199 btn1.setOnClickListener(listener);
200 btn1.setOnLongClickListener(listener);
202 final ImageButton btn2 = findViewById(R.id.btn_2);
203 btn2.setOnClickListener(listener);
204 btn2.setOnLongClickListener(listener);
206 final ImageButton btn3 = findViewById(R.id.btn_3);
207 btn3.setOnClickListener(listener);
208 btn3.setOnLongClickListener(listener);
210 final ImageButton btn4 = findViewById(R.id.btn_4);
211 btn4.setOnClickListener(listener);
212 btn4.setOnLongClickListener(listener);
214 final ImageButton btn5 = findViewById(R.id.btn_5);
215 btn5.setOnClickListener(listener);
216 btn5.setOnLongClickListener(listener);
218 final ImageButton btn6 = findViewById(R.id.btn_6);
219 btn6.setOnClickListener(listener);
220 btn6.setOnLongClickListener(listener);
222 final TextView textArea1 = findViewById(R.id.text_1);
223 textArea1.setOnClickListener(listener);
224 textArea1.setOnLongClickListener(listener);
226 final TextView textArea2 = findViewById(R.id.text_2);
227 textArea2.setOnClickListener(listener);
228 textArea2.setOnLongClickListener(listener);
230 final TextView textArea3 = findViewById(R.id.text_3);
231 textArea3.setOnClickListener(listener);
232 textArea3.setOnLongClickListener(listener);
234 final TextView textArea4 = findViewById(R.id.text_4);
235 textArea4.setOnClickListener(listener);
236 textArea4.setOnLongClickListener(listener);
238 if (liveView == null)
240 liveView = findViewById(R.id.liveview);
242 liveView.setOnTouchListener(listener);
243 messageDrawer = liveView.getMessageDrawer();
244 messageDrawer.setLevelGauge(currentCoordinator.getLevelGauge());
256 private void setupInitialButtonIcons()
260 if (currentCoordinator != null)
263 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
264 if (preferences.getBoolean(IPreferenceCameraPropertyAccessor.SHOW_GRID_STATUS, true)) {
265 // ボタンをGrid OFFアイコンにする
266 resId = R.drawable.btn_ic_grid_off;
268 // ボタンをGrid ONアイコンにする
269 resId = R.drawable.btn_ic_grid_on;
271 setButtonDrawable(IShowInformation.BUTTON_1, resId);
281 * Intentを使ってWiFi設定画面を開く
284 private boolean launchWifiSettingScreen()
286 Log.v(TAG, "launchWifiSettingScreen()");
289 // Wifi 設定画面を表示する... (SONY Smart Watch 3では開かないけど...)
290 startActivity(new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"));
297 Log.v(TAG, "launchWifiSettingScreen() : ACTION_WIFI_SETTINGS");
298 startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
303 Log.v(TAG, "android.content.ActivityNotFoundException... " + "com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS");
306 // SONY Smart Watch 3で開く場合のIntent...
307 Intent intent = new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS");
308 intent.setClassName("com.google.android.apps.wearable.settings", "com.google.android.clockwork.settings.wifi.WifiSettingsActivity");
309 startActivity(intent);
312 catch (Exception ex2)
316 // Wifi 設定画面を表示する...普通のAndroidの場合
317 startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
322 ee.printStackTrace();
325 // LG G Watch Rで開く場合のIntent...
326 Intent intent = new Intent("android.intent.action.MAIN");
327 intent.setClassName("com.google.android.apps.wearable.settings", "com.google.android.clockwork.settings.MainSettingsActivity");
328 startActivity(intent);
331 catch (android.content.ActivityNotFoundException ex3)
333 ex3.printStackTrace();
343 * Olympus Cameraクラスとのやりとりをするクラスを準備する
344 * (カメラとの接続も、ここでスレッドを起こして開始する)
346 private void setupCameraCoordinator()
350 preferences = new PreferenceAccessWrapper(this);
351 preferences.initialize();
352 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
353 if (liveView == null)
355 liveView = findViewById(R.id.liveview);
357 olyAirCoordinator = new OlyCameraCoordinator(this, liveView, this, this);
358 thetaCoordinator = new ThetaCameraController(this, liveView, this, this);
359 currentCoordinator = olyAirCoordinator; // (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? thetaCoordinator : olyAirCoordinator;
360 currentCoordinator.setLiveViewListener(new CameraLiveViewListenerImpl(liveView));
361 listener = new CameraLiveViewOnTouchListener(this, new FeatureDispatcher(this, this, currentCoordinator, preferences, liveView), this);
362 selectionDialog = new FavoriteSettingSelectionDialog(this, currentCoordinator.getCameraPropertyLoadSaveOperations(), this);
375 private void connectToCamera()
377 Thread thread = new Thread(new Runnable()
382 currentCoordinator.getConnectionInterface().connect();
396 * カメラの電源をOFFいして、アプリを抜ける処理
400 public void exitApplication()
404 Log.v(TAG, "exitApplication()");
408 // アンビエントモードの時(≒自分でアプリを終了しなかったとき)は、何もしない
410 Log.v(TAG, "keep liveview.");
415 // パワーマネージャを確認し、interactive modeではない場合は、ライブビューも止めず、カメラの電源も切らない
416 if ((powerManager != null) && (!powerManager.isInteractive()))
418 Log.v(TAG, "not interactive, keep liveview.");
423 currentCoordinator.stopLiveView();
425 // パラメータを確認し、カメラの電源を切る
426 if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(IPreferenceCameraPropertyAccessor.EXIT_APPLICATION_WITH_DISCONNECT, true))
428 Log.v(TAG, "Shutdown camera...");
431 currentCoordinator.getConnectionInterface().disconnect(true);
434 //finishAndRemoveTask();
435 //android.os.Process.killProcess(android.os.Process.myPid());
447 public boolean checkConnectionFeature(int id, int btnId)
453 ret = launchWifiSettingScreen();
458 changeConnectionMethod();
466 * @param posX X座標位置 (0.0f - 1.0f)
467 * @param posY Y座標位置 (0.0f - 1.0f)
468 * @return true / false
471 public boolean touchedPosition(float posX, float posY)
473 Log.v(TAG, "touchedPosition (" + posX + ", " + posY);
474 return ((liveView != null)&&(liveView.touchedPosition(posX, posY)));
481 public boolean showConnectionStatus()
485 if ((listener.isEnabledOperation() == IShowInformation.operation.ONLY_CONNECT) && (cameraDisconnectedHappened)) {
486 // カメラが切断されたとき、再接続を指示する
488 cameraDisconnectedHappened = false;
503 public void onStatusNotify(String message)
505 setMessage(IShowInformation.AREA_C, Color.WHITE, message);
512 public void onCameraConnected()
514 Log.v(TAG, "onCameraConnected()");
517 // ライブビューの開始 & タッチ/ボタンの操作を可能にする
518 currentCoordinator.startLiveView();
519 currentCoordinator.setRecViewMode(false);
520 listener.setEnableOperation(operation.ENABLE);
521 setMessage(IShowInformation.AREA_C, Color.WHITE, "");
522 currentCoordinator.updateStatusAll();
531 * カメラとの接続が切れたとき...何もしない
535 public void onCameraDisconnected()
537 Log.v(TAG, "onCameraDisconnected()");
540 setMessage(IShowInformation.AREA_C, Color.YELLOW, getString(R.string.camera_disconnected));
541 listener.setEnableOperation(operation.ONLY_CONNECT);
542 cameraDisconnectedHappened = true;
554 public void onCameraOccursException(String message, Exception e)
556 Log.v(TAG, "onCameraOccursException()");
559 setMessage(IShowInformation.AREA_C, Color.YELLOW, message);
560 listener.setEnableOperation(operation.ONLY_CONNECT);
561 cameraDisconnectedHappened = true;
566 ee.printStackTrace();
573 * @param area 表示エリア (AREA_1 ~ AREA_6, AREA_C)
575 * @param message 表示するメッセージ
578 public void setMessage(final int area, final int color, final String message)
583 case IShowInformation.AREA_1:
586 case IShowInformation.AREA_2:
589 case IShowInformation.AREA_3:
592 case IShowInformation.AREA_4:
595 case IShowInformation.AREA_NONE:
600 if (messageDrawer != null)
602 if (area == IShowInformation.AREA_C)
604 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTER, color, IMessageDrawer.SIZE_LARGE, message);
607 if (area == IShowInformation.AREA_5)
609 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPLEFT, color, IMessageDrawer.SIZE_STD, message);
612 if (area == IShowInformation.AREA_6)
614 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWLEFT, color, IMessageDrawer.SIZE_STD, message);
617 if (area == IShowInformation.AREA_7)
619 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPRIGHT, color, IMessageDrawer.SIZE_STD, message);
622 if (area == IShowInformation.AREA_8)
624 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, color, IMessageDrawer.SIZE_STD, message);
627 if (area == IShowInformation.AREA_9)
629 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPCENTER, color, IMessageDrawer.SIZE_STD, message);
632 if (area == IShowInformation.AREA_A)
634 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWCENTER, color, IMessageDrawer.SIZE_STD, message);
637 if (area == IShowInformation.AREA_B)
639 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERLEFT, color, IMessageDrawer.SIZE_STD, message);
642 if (area == IShowInformation.AREA_D)
644 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERRIGHT, color, IMessageDrawer.SIZE_STD, message);
655 final int areaId = id;
656 runOnUiThread(new Runnable()
661 final TextView textArea = findViewById(areaId);
662 if (textArea != null)
664 textArea.setTextColor(color);
665 textArea.setText(message);
666 textArea.invalidate();
675 * @param button ボタンの場所
676 * @param labelId 変更する内容
679 public void setButtonDrawable(final int button, final int labelId)
684 case IShowInformation.BUTTON_1:
687 case IShowInformation.BUTTON_2:
690 case IShowInformation.BUTTON_3:
693 case IShowInformation.BUTTON_4:
696 case IShowInformation.BUTTON_5:
699 case IShowInformation.BUTTON_6:
705 final int areaId = id;
706 runOnUiThread(new Runnable()
713 final ImageButton button = findViewById(areaId);
714 final Drawable drawTarget = ContextCompat.getDrawable(getApplicationContext(), labelId);
717 button.setImageDrawable(drawTarget);
731 * @return true GPS搭載, false GPS非搭載
733 private boolean hasGps()
735 return (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS));
743 public void vibrate(final int vibratePattern)
747 if ((vibrator == null)||(!vibrator.hasVibrator()))
752 Thread thread = new Thread(new Runnable() {
755 switch (vibratePattern)
757 case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONGLONG:
758 vibrator.vibrate(300);
760 case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONG:
761 vibrator.vibrate(150);
763 case IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE:
764 vibrator.vibrate(80);
766 case IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT:
767 vibrator.vibrate(30);
769 case IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE:
770 long[] pattern = { 10, 35, 30, 35, 0 };
771 vibrator.vibrate(pattern, -1);
773 case IShowInformation.VIBRATE_PATTERN_NONE:
789 public void setEnabledOperation(IShowInformation.operation operation)
791 if (listener != null)
793 listener.setEnableOperation(operation);
802 public void showFavoriteSettingsDialog()
804 if ((liveView != null)&&(listener != null)&&(listener.isEnabledOperation() != operation.ONLY_CONNECT))
806 listener.setEnableOperation(operation.ENABLE_ONLY_TOUCHED_POSITION);
807 liveView.showDialog(selectionDialog);
816 public void dialogDismissed(boolean isExecuted)
820 if ((liveView != null) && (listener != null))
822 liveView.hideDialog();
823 listener.setEnableOperation(operation.ENABLE);
832 private void updateConnectionMethodMessage()
836 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
837 int methodId = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? R.string.connection_method_theta : R.string.connection_method_opc;
838 setMessage(IShowInformation.AREA_5, Color.MAGENTA, getString(methodId));
846 private void updateConnectionMethod(String parameter, ICameraController method)
850 currentCoordinator = method;
851 preferences.putString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, parameter);
852 vibrate(IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE);
861 * 接続方式を変更するか確認する (OPC ⇔ THETA)
864 private void changeConnectionMethod()
866 final AppCompatActivity activity = this;
867 runOnUiThread(new Runnable() {
872 int titleId = R.string.change_title_from_opc_to_theta;
873 int messageId = R.string.change_message_from_opc_to_theta;
874 boolean method = false;
875 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
876 if (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA))
878 titleId = R.string.change_title_from_theta_to_opc;
879 messageId = R.string.change_message_from_theta_to_opc;
882 final boolean isTheta = method;
883 ConfirmationDialog confirmation = new ConfirmationDialog(activity);
884 confirmation.show(titleId, messageId, new ConfirmationDialog.Callback() {
886 public void confirm() {
887 Log.v(TAG, " --- CONFIRMED! --- (theta:" + isTheta + ")");
891 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_OPC, olyAirCoordinator);
895 // 接続方式を Theta に切り替える
896 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA, olyAirCoordinator); // thetaCoordinator
898 updateConnectionMethodMessage();