OSDN Git Service

83c4f5d01601a19be6295ddb58ff03c6fa74988f
[gokigen/A01c.git] / wear / src / main / java / jp / sfjp / gokigen / a01c / MainActivity.java
1 package jp.sfjp.gokigen.a01c;
2
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;
17
18 import androidx.annotation.NonNull;
19 import androidx.appcompat.app.AppCompatActivity;
20 import androidx.core.app.ActivityCompat;
21 import androidx.core.content.ContextCompat;
22
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;
35
36 /**
37  *   メインのActivity
38  *
39  */
40 public class MainActivity extends AppCompatActivity implements  IChangeScene, IShowInformation, ICameraStatusReceiver, IDialogDismissedNotifier
41 {
42     private final String TAG = toString();
43     static final int REQUEST_NEED_PERMISSIONS = 1010;
44     //static final int COMMAND_MY_PROPERTY = 0x00000100;
45
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;
58
59     /**
60      *
61      */
62     @Override
63     protected void onCreate(Bundle savedInstanceState)
64     {
65         super.onCreate(savedInstanceState);
66         Log.v(TAG, "onCreate()");
67
68         // Ambientモードを許してみる...
69         //setAmbientEnabled();
70
71         //  画面全体の設定
72         setContentView(R.layout.activity_main);
73
74         // WiFIアクセス権のオプトイン
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))
83         {
84             ActivityCompat.requestPermissions(this,
85                     new String[]{
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,
93                     },
94                     REQUEST_NEED_PERMISSIONS);
95         }
96
97         try
98         {
99             if (!hasGps())
100             {
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.
105             }
106
107             // バイブレータをつかまえる
108             vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
109
110             // パワーマネージャをつかまえる
111             powerManager = (PowerManager) getSystemService(POWER_SERVICE);
112
113             setupCameraCoordinator();
114             setupInitialButtonIcons();
115             setupActionListener();
116         }
117         catch (Exception e)
118         {
119             e.printStackTrace();
120         }
121     }
122
123     /**
124      *
125      */
126     @Override
127     protected void onResume()
128     {
129         super.onResume();
130         Log.v(TAG, "onResume()");
131     }
132
133     /**
134      *
135      */
136     @Override
137     protected void onPause()
138     {
139         super.onPause();
140         Log.v(TAG, "onPause()");
141     }
142
143     /**
144      *
145      *
146      */
147     @Override
148     public void onStart()
149     {
150         super.onStart();
151         Log.v(TAG, "onStart()");
152     }
153
154     /**
155      *
156      *
157      */
158     @Override
159     public void onStop()
160     {
161         super.onStop();
162         Log.v(TAG, "onStop()");
163         exitApplication();
164     }
165
166 /*
167      @Override
168      public void onEnterAmbient(Bundle ambientDetails)
169      {
170          super.onEnterAmbient(ambientDetails);
171          Log.v(TAG, "onEnterAmbient()");
172          ambientMode =true;
173      }
174
175     @Override
176     public void onExitAmbient()
177     {
178         super.onExitAmbient();
179         Log.v(TAG, "onExitAmbient()");
180         ambientMode = false;
181     }
182
183     @Override
184     public void onUpdateAmbient()
185     {
186         super.onUpdateAmbient();
187         Log.v(TAG, "onUpdateAmbient()");
188     }
189 */
190
191     /**
192      *   ボタンが押された、画面がタッチされた、、は、リスナクラスで処理するよう紐づける
193      *
194      */
195     private void setupActionListener()
196     {
197         try
198         {
199             final ImageButton btn1 = findViewById(R.id.btn_1);
200             btn1.setOnClickListener(listener);
201             btn1.setOnLongClickListener(listener);
202
203             final ImageButton btn2 = findViewById(R.id.btn_2);
204             btn2.setOnClickListener(listener);
205             btn2.setOnLongClickListener(listener);
206
207             final ImageButton btn3 = findViewById(R.id.btn_3);
208             btn3.setOnClickListener(listener);
209             btn3.setOnLongClickListener(listener);
210
211             final ImageButton btn4 = findViewById(R.id.btn_4);
212             btn4.setOnClickListener(listener);
213             btn4.setOnLongClickListener(listener);
214
215             final ImageButton btn5 = findViewById(R.id.btn_5);
216             btn5.setOnClickListener(listener);
217             btn5.setOnLongClickListener(listener);
218
219             final ImageButton btn6 = findViewById(R.id.btn_6);
220             btn6.setOnClickListener(listener);
221             btn6.setOnLongClickListener(listener);
222
223             final TextView textArea1 = findViewById(R.id.text_1);
224             textArea1.setOnClickListener(listener);
225             textArea1.setOnLongClickListener(listener);
226
227             final TextView textArea2 = findViewById(R.id.text_2);
228             textArea2.setOnClickListener(listener);
229             textArea2.setOnLongClickListener(listener);
230
231             final TextView textArea3 = findViewById(R.id.text_3);
232             textArea3.setOnClickListener(listener);
233             textArea3.setOnLongClickListener(listener);
234
235             final TextView textArea4 = findViewById(R.id.text_4);
236             textArea4.setOnClickListener(listener);
237             textArea4.setOnLongClickListener(listener);
238
239             if (liveView == null)
240             {
241                 liveView = findViewById(R.id.liveview);
242             }
243             liveView.setOnTouchListener(listener);
244             messageDrawer = liveView.getMessageDrawer();
245             messageDrawer.setLevelGauge(currentCoordinator.getLevelGauge());
246         }
247         catch (Exception e)
248         {
249             e.printStackTrace();
250         }
251     }
252
253     /**
254      *   ボタンアイコンの初期設定
255      *
256      */
257     private void setupInitialButtonIcons()
258     {
259         try
260         {
261             if (currentCoordinator != null)
262             {
263                 int resId;
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;
268                 } else {
269                     // ボタンをGrid ONアイコンにする
270                     resId = R.drawable.btn_ic_grid_on;
271                 }
272                 setButtonDrawable(IShowInformation.BUTTON_1, resId);
273             }
274         }
275         catch (Exception e)
276         {
277             e.printStackTrace();
278         }
279     }
280
281     /**
282      *   Intentを使ってWiFi設定画面を開く
283      *
284      */
285     private boolean launchWifiSettingScreen()
286     {
287         Log.v(TAG, "launchWifiSettingScreen()");
288         try
289         {
290             // Wifi 設定画面を表示する... (SONY Smart Watch 3では開かないけど...)
291             startActivity(new Intent("com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"));
292             return (true);
293         }
294         catch (Exception ex)
295         {
296             try
297             {
298                 Log.v(TAG, "launchWifiSettingScreen() : ACTION_WIFI_SETTINGS");
299                 startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
300                 return (true);
301             }
302             catch (Exception e)
303             {
304                 Log.v(TAG, "android.content.ActivityNotFoundException... " + "com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS");
305                 try
306                 {
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);
311                     return (true);
312                 }
313                 catch (Exception ex2)
314                 {
315                     try
316                     {
317                         // Wifi 設定画面を表示する...普通のAndroidの場合
318                         startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
319                         return (true);
320                     }
321                     catch (Exception ee)
322                     {
323                         ee.printStackTrace();
324                         try
325                         {
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);
330                             return (true);
331                         }
332                         catch (android.content.ActivityNotFoundException ex3)
333                         {
334                             ex3.printStackTrace();
335                         }
336                     }
337                 }
338             }
339         }
340         return (false);
341     }
342
343     /**
344      *   Olympus Cameraクラスとのやりとりをするクラスを準備する
345      *   (カメラとの接続も、ここでスレッドを起こして開始する)
346      */
347     private void setupCameraCoordinator()
348     {
349         try
350         {
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)
355             {
356                 liveView = findViewById(R.id.liveview);
357             }
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);
364             connectToCamera();
365         }
366         catch (Exception e)
367         {
368             e.printStackTrace();
369         }
370     }
371
372     /**
373      *   カメラと接続する
374      *
375      */
376     private void connectToCamera()
377     {
378         Thread thread = new Thread(new Runnable()
379         {
380             @Override
381             public void run()
382             {
383                 currentCoordinator.getConnectionInterface().connect();
384             }
385         });
386         try
387         {
388             thread.start();
389         }
390         catch (Exception e)
391         {
392             e.printStackTrace();
393         }
394     }
395
396     /**
397      *   カメラの電源をOFFいして、アプリを抜ける処理
398      *
399      */
400     @Override
401     public void exitApplication()
402     {
403         try
404         {
405             Log.v(TAG, "exitApplication()");
406 /*
407             if (ambientMode)
408             {
409                 // アンビエントモードの時(≒自分でアプリを終了しなかったとき)は、何もしない
410                 // (接続したままとする)
411                 Log.v(TAG, "keep liveview.");
412                 return;
413             }
414 */
415
416             // パワーマネージャを確認し、interactive modeではない場合は、ライブビューも止めず、カメラの電源も切らない
417             if ((powerManager != null) && (!powerManager.isInteractive()))
418             {
419                 Log.v(TAG, "not interactive, keep liveview.");
420                 return;
421             }
422
423             // ライブビューを停止させる
424             currentCoordinator.stopLiveView();
425
426             //  パラメータを確認し、カメラの電源を切る
427             if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(IPreferenceCameraPropertyAccessor.EXIT_APPLICATION_WITH_DISCONNECT, true))
428             {
429                 Log.v(TAG, "Shutdown camera...");
430
431                 // カメラの電源をOFFにする
432                 currentCoordinator.getConnectionInterface().disconnect(true);
433             }
434             //finish();
435             //finishAndRemoveTask();
436             //android.os.Process.killProcess(android.os.Process.myPid());
437         }
438         catch (Exception e)
439         {
440             e.printStackTrace();
441         }
442     }
443
444     /**
445      *   接続機能を確認する
446      */
447     @Override
448     public boolean checkConnectionFeature(int id, int btnId)
449     {
450         boolean ret = false;
451         if (id == 0)
452         {
453             // Wifi 設定画面を開く
454             ret = launchWifiSettingScreen();
455         }
456         else if (id == 1)
457         {
458             // 接続の変更を確認する
459             changeConnectionMethod();
460         }
461         return (ret);
462     }
463
464     /**
465      *   画面をタッチした場所を受信する
466      *
467      * @param posX  X座標位置 (0.0f - 1.0f)
468      * @param posY  Y座標位置 (0.0f - 1.0f)
469      * @return true / false
470      */
471     @Override
472     public boolean touchedPosition(float posX, float posY)
473     {
474         Log.v(TAG, "touchedPosition (" + posX + ", " + posY);
475         return ((liveView != null)&&(liveView.touchedPosition(posX, posY)));
476     }
477
478     /**
479      *   接続状態を見る or 再接続する
480      */
481     @Override
482     public boolean showConnectionStatus()
483     {
484         try
485         {
486             if ((listener.isEnabledOperation() == IShowInformation.operation.ONLY_CONNECT) && (cameraDisconnectedHappened)) {
487                 // カメラが切断されたとき、再接続を指示する
488                 connectToCamera();
489                 cameraDisconnectedHappened = false;
490                 return (true);
491             }
492         }
493         catch (Exception e)
494         {
495             e.printStackTrace();
496         }
497         return (false);
498     }
499
500     /**
501      *
502      */
503     @Override
504     public void onStatusNotify(String message)
505     {
506         setMessage(IShowInformation.AREA_C, Color.WHITE, message);
507     }
508
509     /**
510      *
511      */
512     @Override
513     public void onCameraConnected()
514     {
515         Log.v(TAG, "onCameraConnected()");
516         try
517         {
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();
525         }
526         catch (Exception e)
527         {
528             e.printStackTrace();
529         }
530     }
531
532     /**
533      *   カメラとの接続が切れたとき...何もしない
534      *
535      */
536     @Override
537     public void onCameraDisconnected()
538     {
539         Log.v(TAG, "onCameraDisconnected()");
540         try
541         {
542             setMessage(IShowInformation.AREA_C, Color.YELLOW, getString(R.string.camera_disconnected));
543             listener.setEnableOperation(operation.ONLY_CONNECT);
544             cameraDisconnectedHappened = true;
545         }
546         catch (Exception e)
547         {
548             e.printStackTrace();
549         }
550     }
551
552     /**
553      *  カメラと接続失敗
554      */
555     @Override
556     public void onCameraConnectError(@NonNull String message)
557     {
558         Log.v(TAG, "onCameraOccursException()");
559         try
560         {
561             setMessage(IShowInformation.AREA_C, Color.YELLOW, message);
562             listener.setEnableOperation(operation.ONLY_CONNECT);
563             cameraDisconnectedHappened = true;
564         }
565         catch (Exception ee)
566         {
567             ee.printStackTrace();
568         }
569     }
570
571     /**
572      *  カメラに例外発生
573      */
574     @Override
575     public void onCameraOccursException(@NonNull String message, Exception e)
576     {
577         Log.v(TAG, "onCameraOccursException()");
578         try
579         {
580             setMessage(IShowInformation.AREA_C, Color.YELLOW, message);
581             listener.setEnableOperation(operation.ONLY_CONNECT);
582             cameraDisconnectedHappened = true;
583         }
584         catch (Exception ee)
585         {
586             e.printStackTrace();
587             ee.printStackTrace();
588         }
589     }
590
591     /**s
592      *   メッセージの表示
593      *
594      * @param area    表示エリア (AREA_1 ~ AREA_6, AREA_C)
595      * @param color  表示色
596      * @param message 表示するメッセージ
597      */
598     @Override
599     public void setMessage(final int area, final int color, final String message)
600     {
601         int id = 0;
602         switch (area)
603         {
604             case IShowInformation.AREA_1:
605                 id = R.id.text_1;
606                 break;
607             case IShowInformation.AREA_2:
608                 id = R.id.text_2;
609                 break;
610             case IShowInformation.AREA_3:
611                 id = R.id.text_3;
612                 break;
613             case IShowInformation.AREA_4:
614                 id = R.id.text_4;
615                 break;
616             case IShowInformation.AREA_NONE:
617             default:
618                 // unknown
619                 break;
620         }
621         if (messageDrawer != null)
622         {
623             if (area == IShowInformation.AREA_C)
624             {
625                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTER, color, IMessageDrawer.SIZE_LARGE, message);
626                 return;
627             }
628             if (area == IShowInformation.AREA_5)
629             {
630                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPLEFT, color, IMessageDrawer.SIZE_STD, message);
631                 return;
632             }
633             if (area == IShowInformation.AREA_6)
634             {
635                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWLEFT, color, IMessageDrawer.SIZE_STD, message);
636                 return;
637             }
638             if (area == IShowInformation.AREA_7)
639             {
640                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPRIGHT, color, IMessageDrawer.SIZE_STD, message);
641                 return;
642             }
643             if (area == IShowInformation.AREA_8)
644             {
645                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, color, IMessageDrawer.SIZE_STD, message);
646                 return;
647             }
648             if (area == IShowInformation.AREA_9)
649             {
650                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.UPCENTER, color, IMessageDrawer.SIZE_STD, message);
651                 return;
652             }
653             if (area == IShowInformation.AREA_A)
654             {
655                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.LOWCENTER, color, IMessageDrawer.SIZE_STD, message);
656                 return;
657             }
658             if (area == IShowInformation.AREA_B)
659             {
660                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERLEFT, color, IMessageDrawer.SIZE_STD, message);
661                 return;
662             }
663             if (area == IShowInformation.AREA_D)
664             {
665                 messageDrawer.setMessageToShow(IMessageDrawer.MessageArea.CENTERRIGHT, color, IMessageDrawer.SIZE_STD, message);
666                 return;
667             }
668
669             if (id == 0)
670             {
671                 // 描画エリアが不定の場合...
672                 return;
673             }
674         }
675
676         final int areaId = id;
677         runOnUiThread(new Runnable()
678         {
679              @Override
680              public void run()
681              {
682                  final TextView textArea = findViewById(areaId);
683                  if (textArea != null)
684                  {
685                      textArea.setTextColor(color);
686                      textArea.setText(message);
687                      textArea.invalidate();
688                  }
689              }
690         });
691     }
692
693     /**
694      *   ボタンの表示イメージを変更する
695      *
696      * @param button  ボタンの場所
697      * @param labelId 変更する内容
698      */
699     @Override
700     public void setButtonDrawable(final int button, final int labelId)
701     {
702         int id;
703         switch (button)
704         {
705             case IShowInformation.BUTTON_1:
706                 id = R.id.btn_1;
707                 break;
708             case IShowInformation.BUTTON_2:
709                 id = R.id.btn_2;
710                 break;
711             case IShowInformation.BUTTON_3:
712                 id = R.id.btn_3;
713                 break;
714             case IShowInformation.BUTTON_4:
715                 id = R.id.btn_4;
716                 break;
717             case IShowInformation.BUTTON_5:
718                 id = R.id.btn_5;
719                 break;
720             case IShowInformation.BUTTON_6:
721             default:
722                 id = R.id.btn_6;
723                 break;
724         }
725
726         final int areaId = id;
727         runOnUiThread(new Runnable()
728         {
729             @Override
730             public void run()
731             {
732                 try
733                 {
734                     final ImageButton button = findViewById(areaId);
735                     final Drawable drawTarget = ContextCompat.getDrawable(getApplicationContext(), labelId);
736                     if (button != null)
737                     {
738                         button.setImageDrawable(drawTarget);
739                         button.invalidate();
740                     }
741                 }
742                 catch (Exception e)
743                 {
744                     e.printStackTrace();
745                 }
746             }
747         });
748     }
749
750     /**
751      *
752      * @return true GPS搭載, false GPS非搭載
753      */
754     private boolean hasGps()
755     {
756         return (getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS));
757     }
758
759     /**
760      *
761      *
762      */
763     @Override
764     public void vibrate(final int vibratePattern)
765     {
766         try
767         {
768             if ((vibrator == null)||(!vibrator.hasVibrator()))
769             {
770                 return;
771             }
772
773             Thread thread = new Thread(new Runnable() {
774                 @Override
775                 public void run() {
776                     switch (vibratePattern)
777                     {
778                         case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONGLONG:
779                             vibrator.vibrate(300);
780                             break;
781                         case IShowInformation.VIBRATE_PATTERN_SIMPLE_LONG:
782                             vibrator.vibrate(150);
783                             break;
784                         case IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE:
785                             vibrator.vibrate(80);
786                             break;
787                         case IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT:
788                             vibrator.vibrate(30);
789                             break;
790                         case IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE:
791                             long[] pattern = { 10, 35, 30, 35, 0 };
792                             vibrator.vibrate(pattern, -1);
793                             break;
794                         case IShowInformation.VIBRATE_PATTERN_NONE:
795                         default:
796                             // ぶるぶるしない
797                             break;
798                     }
799                 }
800             });
801             thread.start();
802         }
803         catch (Exception e)
804         {
805             e.printStackTrace();
806         }
807     }
808
809     @Override
810     public void setEnabledOperation(IShowInformation.operation operation)
811     {
812         if (listener != null)
813         {
814             listener.setEnableOperation(operation);
815         }
816     }
817
818     /**
819      *   「お気に入り設定」表示画面を開く
820      *
821      */
822     @Override
823     public void showFavoriteSettingsDialog()
824     {
825         if ((liveView != null)&&(listener != null)&&(listener.isEnabledOperation() != operation.ONLY_CONNECT))
826         {
827             listener.setEnableOperation(operation.ENABLE_ONLY_TOUCHED_POSITION);
828             liveView.showDialog(selectionDialog);
829         }
830     }
831
832     /**
833      *   「お気に入り設定」表示画面を閉じる
834      *
835      */
836     @Override
837     public void dialogDismissed(boolean isExecuted)
838     {
839         try
840         {
841             if ((liveView != null) && (listener != null))
842             {
843                 liveView.hideDialog();
844                 listener.setEnableOperation(operation.ENABLE);
845             }
846         }
847         catch (Exception e)
848         {
849             e.printStackTrace();
850         }
851     }
852
853     private void updateConnectionMethodMessage()
854     {
855         try
856         {
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)
861             {
862                 liveView = findViewById(R.id.liveview);
863             }
864             liveView.setupInitialBackgroundImage(this);
865             liveView.invalidate();
866         }
867         catch (Exception e)
868         {
869             e.printStackTrace();
870         }
871     }
872
873     private void updateConnectionMethod(String parameter, ICameraController method)
874     {
875         try
876         {
877             currentCoordinator = method;
878             preferences.putString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, parameter);
879             vibrate(IShowInformation.VIBRATE_PATTERN_SHORT_DOUBLE);
880         }
881         catch (Exception e)
882         {
883             e.printStackTrace();
884         }
885     }
886
887     /**
888      *   接続方式を変更するか確認する (OPC ⇔ THETA)
889      *
890      */
891     private void changeConnectionMethod()
892     {
893         final AppCompatActivity activity = this;
894         runOnUiThread(new Runnable() {
895             @Override
896             public void run() {
897                 try
898                 {
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))
904                     {
905                         titleId = R.string.change_title_from_theta_to_opc;
906                         messageId = R.string.change_message_from_theta_to_opc;
907                         method = true;
908                     }
909                     final boolean isTheta = method;
910                     ConfirmationDialog confirmation = new ConfirmationDialog(activity);
911                     confirmation.show(titleId, messageId, new ConfirmationDialog.Callback() {
912                         @Override
913                         public void confirm() {
914                             Log.v(TAG, " --- CONFIRMED! --- (theta:" + isTheta + ")");
915                             if (isTheta)
916                             {
917                                 // 接続方式を OPC に切り替える
918                                 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_OPC, olyAirCoordinator);
919                             }
920                             else
921                             {
922                                 // 接続方式を Theta に切り替える
923                                 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA, thetaCoordinator);
924                             }
925                             updateConnectionMethodMessage();
926                         }
927                     });
928                 }
929                 catch (Exception e)
930                 {
931                     e.printStackTrace();
932                 }
933             }
934         });
935     }
936 }