OSDN Git Service

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