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.annotation.NonNull;
19 import androidx.appcompat.app.AppCompatActivity;
20 import androidx.core.app.ActivityCompat;
21 import androidx.core.content.ContextCompat;
23 import jp.sfjp.gokigen.a01c.liveview.CameraLiveImageView;
24 import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewListenerImpl;
25 import jp.sfjp.gokigen.a01c.liveview.dialog.FavoriteSettingSelectionDialog;
26 import jp.sfjp.gokigen.a01c.liveview.dialog.IDialogDismissedNotifier;
27 import jp.sfjp.gokigen.a01c.olycamerawrapper.dispatcher.FeatureDispatcher;
28 import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
29 import jp.sfjp.gokigen.a01c.liveview.IMessageDrawer;
30 import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewOnTouchListener;
31 import jp.sfjp.gokigen.a01c.olycamerawrapper.OlyCameraCoordinator;
32 import jp.sfjp.gokigen.a01c.preference.IPreferenceCameraPropertyAccessor;
33 import jp.sfjp.gokigen.a01c.preference.PreferenceAccessWrapper;
34 import jp.sfjp.gokigen.a01c.thetacamerawrapper.ThetaCameraController;
40 public class MainActivity extends AppCompatActivity implements IChangeScene, IShowInformation, ICameraStatusReceiver, IDialogDismissedNotifier
42 private final String TAG = toString();
43 static final int REQUEST_NEED_PERMISSIONS = 1010;
44 //static final int COMMAND_MY_PROPERTY = 0x00000100;
46 private PreferenceAccessWrapper preferences = null;
47 private PowerManager powerManager = null;
48 private CameraLiveImageView liveView = null;
49 private ICameraController currentCoordinator = null;
50 private ICameraController olyAirCoordinator = null;
51 private ICameraController thetaCoordinator = null;
52 private IMessageDrawer messageDrawer = null;
53 private CameraLiveViewOnTouchListener listener = null;
54 private FavoriteSettingSelectionDialog selectionDialog = null;
55 private Vibrator vibrator = null;
56 private boolean cameraDisconnectedHappened = false;
57 //private boolean ambientMode = false;
63 protected void onCreate(Bundle savedInstanceState)
65 super.onCreate(savedInstanceState);
66 Log.v(TAG, "onCreate()");
68 // Ambientモードを許してみる...
69 //setAmbientEnabled();
72 setContentView(R.layout.activity_main);
75 if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
76 (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
77 (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
78 (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
79 (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED)||
80 (ContextCompat.checkSelfPermission(this, Manifest.permission.WAKE_LOCK) != PackageManager.PERMISSION_GRANTED)||
81 (ContextCompat.checkSelfPermission(this, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED)||
82 (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED))
84 ActivityCompat.requestPermissions(this,
86 Manifest.permission.ACCESS_NETWORK_STATE,
87 Manifest.permission.ACCESS_WIFI_STATE,
88 Manifest.permission.CHANGE_WIFI_STATE,
89 Manifest.permission.CHANGE_NETWORK_STATE,
90 Manifest.permission.WRITE_SETTINGS,
91 Manifest.permission.WAKE_LOCK,
92 Manifest.permission.INTERNET,
94 REQUEST_NEED_PERMISSIONS);
101 // GPS機能が搭載されていない場合...
102 Log.d(TAG, "This hardware doesn't have GPS.");
103 // Fall back to functionality that does not use location or
104 // warn the user that location function is not available.
108 vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
111 powerManager = (PowerManager) getSystemService(POWER_SERVICE);
113 setupCameraCoordinator();
114 setupInitialButtonIcons();
115 setupActionListener();
127 protected void onResume()
130 Log.v(TAG, "onResume()");
137 protected void onPause()
140 Log.v(TAG, "onPause()");
148 public void onStart()
151 Log.v(TAG, "onStart()");
162 Log.v(TAG, "onStop()");
168 public void onEnterAmbient(Bundle ambientDetails)
170 super.onEnterAmbient(ambientDetails);
171 Log.v(TAG, "onEnterAmbient()");
176 public void onExitAmbient()
178 super.onExitAmbient();
179 Log.v(TAG, "onExitAmbient()");
184 public void onUpdateAmbient()
186 super.onUpdateAmbient();
187 Log.v(TAG, "onUpdateAmbient()");
192 * ボタンが押された、画面がタッチされた、、は、リスナクラスで処理するよう紐づける
195 private void setupActionListener()
199 final ImageButton btn1 = findViewById(R.id.btn_1);
200 btn1.setOnClickListener(listener);
201 btn1.setOnLongClickListener(listener);
203 final ImageButton btn2 = findViewById(R.id.btn_2);
204 btn2.setOnClickListener(listener);
205 btn2.setOnLongClickListener(listener);
207 final ImageButton btn3 = findViewById(R.id.btn_3);
208 btn3.setOnClickListener(listener);
209 btn3.setOnLongClickListener(listener);
211 final ImageButton btn4 = findViewById(R.id.btn_4);
212 btn4.setOnClickListener(listener);
213 btn4.setOnLongClickListener(listener);
215 final ImageButton btn5 = findViewById(R.id.btn_5);
216 btn5.setOnClickListener(listener);
217 btn5.setOnLongClickListener(listener);
219 final ImageButton btn6 = findViewById(R.id.btn_6);
220 btn6.setOnClickListener(listener);
221 btn6.setOnLongClickListener(listener);
223 final TextView textArea1 = findViewById(R.id.text_1);
224 textArea1.setOnClickListener(listener);
225 textArea1.setOnLongClickListener(listener);
227 final TextView textArea2 = findViewById(R.id.text_2);
228 textArea2.setOnClickListener(listener);
229 textArea2.setOnLongClickListener(listener);
231 final TextView textArea3 = findViewById(R.id.text_3);
232 textArea3.setOnClickListener(listener);
233 textArea3.setOnLongClickListener(listener);
235 final TextView textArea4 = findViewById(R.id.text_4);
236 textArea4.setOnClickListener(listener);
237 textArea4.setOnLongClickListener(listener);
239 if (liveView == null)
241 liveView = findViewById(R.id.liveview);
243 liveView.setOnTouchListener(listener);
244 messageDrawer = liveView.getMessageDrawer();
245 messageDrawer.setLevelGauge(currentCoordinator.getLevelGauge());
257 private void setupInitialButtonIcons()
261 if (currentCoordinator != null)
264 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
265 if (preferences.getBoolean(IPreferenceCameraPropertyAccessor.SHOW_GRID_STATUS, true)) {
266 // ボタンをGrid OFFアイコンにする
267 resId = R.drawable.btn_ic_grid_off;
269 // ボタンをGrid ONアイコンにする
270 resId = R.drawable.btn_ic_grid_on;
272 setButtonDrawable(IShowInformation.BUTTON_1, resId);
282 * Intentを使ってWiFi設定画面を開く
285 private boolean launchWifiSettingScreen()
287 Log.v(TAG, "launchWifiSettingScreen()");
290 // Wifi 設定画面を表示する... (SONY Smart Watch 3では開かないけど...)
291 startActivity(new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"));
298 Log.v(TAG, "launchWifiSettingScreen() : ACTION_WIFI_SETTINGS");
299 startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
304 Log.v(TAG, "android.content.ActivityNotFoundException... " + "com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS");
307 // SONY Smart Watch 3で開く場合のIntent...
308 Intent intent = new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS");
309 intent.setClassName("com.google.android.apps.wearable.settings", "com.google.android.clockwork.settings.wifi.WifiSettingsActivity");
310 startActivity(intent);
313 catch (Exception ex2)
317 // Wifi 設定画面を表示する...普通のAndroidの場合
318 startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
323 ee.printStackTrace();
326 // LG G Watch Rで開く場合のIntent...
327 Intent intent = new Intent("android.intent.action.MAIN");
328 intent.setClassName("com.google.android.apps.wearable.settings", "com.google.android.clockwork.settings.MainSettingsActivity");
329 startActivity(intent);
332 catch (android.content.ActivityNotFoundException ex3)
334 ex3.printStackTrace();
344 * Olympus Cameraクラスとのやりとりをするクラスを準備する
345 * (カメラとの接続も、ここでスレッドを起こして開始する)
347 private void setupCameraCoordinator()
351 preferences = new PreferenceAccessWrapper(this);
352 preferences.initialize();
353 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
354 if (liveView == null)
356 liveView = findViewById(R.id.liveview);
358 olyAirCoordinator = new OlyCameraCoordinator(this, liveView, this, this);
359 thetaCoordinator = new ThetaCameraController(this, liveView, this, this, preferences);
360 currentCoordinator = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? thetaCoordinator : olyAirCoordinator;
361 currentCoordinator.setLiveViewListener(new CameraLiveViewListenerImpl(liveView));
362 listener = new CameraLiveViewOnTouchListener(this, currentCoordinator.getFeatureDispatcher(this, this, currentCoordinator, preferences, liveView), this);
363 selectionDialog = new FavoriteSettingSelectionDialog(this, currentCoordinator.getCameraPropertyLoadSaveOperations(), this);
376 private void connectToCamera()
378 Thread thread = new Thread(new Runnable()
383 currentCoordinator.getConnectionInterface().connect();
397 * カメラの電源をOFFいして、アプリを抜ける処理
401 public void exitApplication()
405 Log.v(TAG, "exitApplication()");
409 // アンビエントモードの時(≒自分でアプリを終了しなかったとき)は、何もしない
411 Log.v(TAG, "keep liveview.");
416 // パワーマネージャを確認し、interactive modeではない場合は、ライブビューも止めず、カメラの電源も切らない
417 if ((powerManager != null) && (!powerManager.isInteractive()))
419 Log.v(TAG, "not interactive, keep liveview.");
424 currentCoordinator.stopLiveView();
426 // パラメータを確認し、カメラの電源を切る
427 if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(IPreferenceCameraPropertyAccessor.EXIT_APPLICATION_WITH_DISCONNECT, true))
429 Log.v(TAG, "Shutdown camera...");
432 currentCoordinator.getConnectionInterface().disconnect(true);
435 //finishAndRemoveTask();
436 //android.os.Process.killProcess(android.os.Process.myPid());
448 public boolean checkConnectionFeature(int id, int btnId)
454 ret = launchWifiSettingScreen();
459 changeConnectionMethod();
467 * @param posX X座標位置 (0.0f - 1.0f)
468 * @param posY Y座標位置 (0.0f - 1.0f)
469 * @return true / false
472 public boolean touchedPosition(float posX, float posY)
474 Log.v(TAG, "touchedPosition (" + posX + ", " + posY);
475 return ((liveView != null)&&(liveView.touchedPosition(posX, posY)));
482 public boolean showConnectionStatus()
486 if ((listener.isEnabledOperation() == IShowInformation.operation.ONLY_CONNECT) && (cameraDisconnectedHappened)) {
487 // カメラが切断されたとき、再接続を指示する
489 cameraDisconnectedHappened = false;
504 public void onStatusNotify(String message)
506 setMessage(IShowInformation.AREA_C, Color.WHITE, message);
513 public void onCameraConnected()
515 Log.v(TAG, "onCameraConnected()");
518 // ライブビューの開始 & タッチ/ボタンの操作を可能にする
519 currentCoordinator.connectFinished();
520 currentCoordinator.startLiveView();
521 currentCoordinator.setRecViewMode(false);
522 listener.setEnableOperation(operation.ENABLE);
523 setMessage(IShowInformation.AREA_C, Color.WHITE, "");
524 currentCoordinator.updateStatusAll();
533 * カメラとの接続が切れたとき...何もしない
537 public void onCameraDisconnected()
539 Log.v(TAG, "onCameraDisconnected()");
542 setMessage(IShowInformation.AREA_C, Color.YELLOW, getString(R.string.camera_disconnected));
543 listener.setEnableOperation(operation.ONLY_CONNECT);
544 cameraDisconnectedHappened = true;
556 public void onCameraConnectError(@NonNull String message)
558 Log.v(TAG, "onCameraOccursException()");
561 setMessage(IShowInformation.AREA_C, Color.YELLOW, message);
562 listener.setEnableOperation(operation.ONLY_CONNECT);
563 cameraDisconnectedHappened = true;
567 ee.printStackTrace();
575 public void onCameraOccursException(@NonNull String message, Exception e)
577 Log.v(TAG, "onCameraOccursException()");
580 setMessage(IShowInformation.AREA_C, Color.YELLOW, message);
581 listener.setEnableOperation(operation.ONLY_CONNECT);
582 cameraDisconnectedHappened = true;
587 ee.printStackTrace();
594 * @param area 表示エリア (AREA_1 ~ AREA_6, AREA_C)
596 * @param message 表示するメッセージ
599 public void setMessage(final int area, final int color, final String message)
604 case IShowInformation.AREA_1:
607 case IShowInformation.AREA_2:
610 case IShowInformation.AREA_3:
613 case IShowInformation.AREA_4:
616 case IShowInformation.AREA_NONE:
621 if (messageDrawer != null)
623 if (area == IShowInformation.AREA_C)
625 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTER, color, IMessageDrawer.SIZE_LARGE, message);
628 if (area == IShowInformation.AREA_5)
630 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPLEFT, color, IMessageDrawer.SIZE_STD, message);
633 if (area == IShowInformation.AREA_6)
635 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWLEFT, color, IMessageDrawer.SIZE_STD, message);
638 if (area == IShowInformation.AREA_7)
640 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPRIGHT, color, IMessageDrawer.SIZE_STD, message);
643 if (area == IShowInformation.AREA_8)
645 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, color, IMessageDrawer.SIZE_STD, message);
648 if (area == IShowInformation.AREA_9)
650 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPCENTER, color, IMessageDrawer.SIZE_STD, message);
653 if (area == IShowInformation.AREA_A)
655 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWCENTER, color, IMessageDrawer.SIZE_STD, message);
658 if (area == IShowInformation.AREA_B)
660 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERLEFT, color, IMessageDrawer.SIZE_STD, message);
663 if (area == IShowInformation.AREA_D)
665 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERRIGHT, color, IMessageDrawer.SIZE_STD, message);
676 final int areaId = id;
677 runOnUiThread(new Runnable()
682 final TextView textArea = findViewById(areaId);
683 if (textArea != null)
685 textArea.setTextColor(color);
686 textArea.setText(message);
687 textArea.invalidate();
696 * @param button ボタンの場所
697 * @param labelId 変更する内容
700 public void setButtonDrawable(final int button, final int labelId)
705 case IShowInformation.BUTTON_1:
708 case IShowInformation.BUTTON_2:
711 case IShowInformation.BUTTON_3:
714 case IShowInformation.BUTTON_4:
717 case IShowInformation.BUTTON_5:
720 case IShowInformation.BUTTON_6:
726 final int areaId = id;
727 runOnUiThread(new Runnable()
734 final ImageButton button = findViewById(areaId);
735 final Drawable drawTarget = ContextCompat.getDrawable(getApplicationContext(), labelId);
738 button.setImageDrawable(drawTarget);
752 * @return true GPS搭載, false GPS非搭載
754 private boolean hasGps()
756 return (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS));
764 public void vibrate(final int vibratePattern)
768 if ((vibrator == null)||(!vibrator.hasVibrator()))
773 Thread thread = new Thread(new Runnable() {
776 switch (vibratePattern)
778 case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONGLONG:
779 vibrator.vibrate(300);
781 case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONG:
782 vibrator.vibrate(150);
784 case IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE:
785 vibrator.vibrate(80);
787 case IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT:
788 vibrator.vibrate(30);
790 case IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE:
791 long[] pattern = { 10, 35, 30, 35, 0 };
792 vibrator.vibrate(pattern, -1);
794 case IShowInformation.VIBRATE_PATTERN_NONE:
810 public void setEnabledOperation(IShowInformation.operation operation)
812 if (listener != null)
814 listener.setEnableOperation(operation);
823 public void showFavoriteSettingsDialog()
825 if ((liveView != null)&&(listener != null)&&(listener.isEnabledOperation() != operation.ONLY_CONNECT))
827 listener.setEnableOperation(operation.ENABLE_ONLY_TOUCHED_POSITION);
828 liveView.showDialog(selectionDialog);
837 public void dialogDismissed(boolean isExecuted)
841 if ((liveView != null) && (listener != null))
843 liveView.hideDialog();
844 listener.setEnableOperation(operation.ENABLE);
853 private void updateConnectionMethodMessage()
857 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
858 int methodId = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? R.string.connection_method_theta : R.string.connection_method_opc;
859 setMessage(IShowInformation.AREA_7, Color.MAGENTA, getString(methodId));
860 if (liveView == null)
862 liveView = findViewById(R.id.liveview);
864 liveView.setupInitialBackgroundImage(this);
865 liveView.invalidate();
873 private void updateConnectionMethod(String parameter, ICameraController method)
877 currentCoordinator = method;
878 preferences.putString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, parameter);
879 vibrate(IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE);
888 * 接続方式を変更するか確認する (OPC ⇔ THETA)
891 private void changeConnectionMethod()
893 final AppCompatActivity activity = this;
894 runOnUiThread(new Runnable() {
899 int titleId = R.string.change_title_from_opc_to_theta;
900 int messageId = R.string.change_message_from_opc_to_theta;
901 boolean method = false;
902 String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
903 if (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA))
905 titleId = R.string.change_title_from_theta_to_opc;
906 messageId = R.string.change_message_from_theta_to_opc;
909 final boolean isTheta = method;
910 ConfirmationDialog confirmation = new ConfirmationDialog(activity);
911 confirmation.show(titleId, messageId, new ConfirmationDialog.Callback() {
913 public void confirm() {
914 Log.v(TAG, " --- CONFIRMED! --- (theta:" + isTheta + ")");
918 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_OPC, olyAirCoordinator);
922 // 接続方式を Theta に切り替える
923 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA, thetaCoordinator);
925 updateConnectionMethodMessage();