--- /dev/null
+# A01c : Android Wear用 Olympus Air 撮影アプリ
+
+## はじめに
+本アプリは、Olympus Camera Kitを使用した、Android Wearで動作する Open Platform Camera (Olympus Air A01)用撮影アプリケーションです。
+AirA01bベースで開発しています。
+
+## 制約事項
+とりあえず動きはじめたところです。
+
+## 来歴
+- 0.0.1 初版作成
--- /dev/null
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.2"
+ defaultConfig {
+ applicationId "jp.sfjp.gokigen.a01c"
+ minSdkVersion 23
+ targetSdkVersion 25
+ versionCode 1
+ versionName "0.0.1"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+
+ provided 'com.google.android.wearable:wearable:2.0.0'
+ compile 'com.google.android.support:wearable:2.0.0'
+ compile 'com.google.android.gms:play-services-wearable:10.2.0'
+
+ compile 'com.android.support:animated-vector-drawable:25.2.0'
+ compile 'com.android.support:percent:25.2.0'
+ compile 'com.android.support:support-vector-drawable:25.2.0'
+ compile 'com.android.support:appcompat-v7:25.2.0'
+ compile 'com.android.support:preference-v7:25.2.0'
+ compile 'com.android.support:exifinterface:25.2.0'
+ compile 'com.android.support:support-v4:25.2.0'
+ compile files('libs/olycamerakit.jar')
+}
--- /dev/null
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\APL\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="jp.sfjp.gokigen.a01c">
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@android:style/Theme.DeviceDefault">
+ <uses-library android:name="com.google.android.wearable" android:required="false" />
+ <meta-data android:name="com.google.android.wearable.standalone" android:value="true" />
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="android.support.wearable.activity.ConfirmationActivity">
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+package jp.sfjp.gokigen.a01c;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+
+/**
+ * 確認ダイアログの表示
+ *
+ */
+public class ConfirmationDialog
+{
+ private final Context context;
+
+ public ConfirmationDialog(Context context)
+ {
+ this.context = context;
+ }
+
+ public void show(int titleResId, int messageResId, final Callback callback)
+ {
+ String title = "";
+ String message = "";
+
+ // タイトルとメッセージをのダイアログを表示する
+ if (context != null)
+ {
+ title = context.getString(titleResId);
+ message = context.getString(messageResId);
+ }
+ show(title, message, callback);
+ }
+
+ /**
+ *
+ * @param title ダイアログタイトル
+ * @param message ダイアログメッセージ
+ * @param callback 結果をコールバック
+ */
+ private void show(String title, String message, final Callback callback)
+ {
+ // 確認ダイアログの生成
+ final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
+ alertDialog.setTitle(title);
+ alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
+ alertDialog.setMessage(message);
+ alertDialog.setCancelable(true);
+
+ // ボタンを設定する(実行ボタン)
+ alertDialog.setPositiveButton(context.getString(R.string.dialog_positive_execute),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ callback.confirm();
+ dialog.dismiss();
+ }
+ });
+
+ // ボタンを設定する (キャンセルボタン)
+ alertDialog.setNegativeButton(context.getString(R.string.dialog_negative_cancel),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ dialog.cancel();
+ }
+ });
+
+ // 確認ダイアログを表示する
+ alertDialog.show();
+ }
+
+ // コールバックインタフェース
+ public interface Callback
+ {
+ void confirm(); // OKを選択したとき
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c;
+
+/**
+ *
+ */
+public interface IChangeScene
+{
+ void exitApplication();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c;
+
+import android.os.Bundle;
+import android.support.wearable.activity.WearableActivity;
+import android.util.Log;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+
+import jp.sfjp.gokigen.a01c.liveview.CameraLiveImageView;
+import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewListenerImpl;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
+import jp.sfjp.gokigen.a01c.liveview.OlyCameraLiveViewOnTouchListener;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IOlyCameraCoordinator;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.OlyCameraCoordinator;
+
+public class MainActivity extends WearableActivity implements IChangeScene, ICameraStatusReceiver
+{
+ private final String TAG = this.toString();
+ private final int REQUEST_NEED_PERMISSIONS = 1010;
+
+ private CameraLiveImageView liveView = null;
+ private IOlyCameraCoordinator coordinator = null;
+ private CameraLiveViewListenerImpl liveViewListener = null;
+
+ /**
+ *
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // 画面全体の設定
+ setContentView(R.layout.activity_main);
+/**/
+ // WiFIアクセス権のオプトイン
+ if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.WAKE_LOCK) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED))
+ {
+ ActivityCompat.requestPermissions(this,
+ new String[]{
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.ACCESS_WIFI_STATE,
+ Manifest.permission.CHANGE_WIFI_STATE,
+ Manifest.permission.CHANGE_NETWORK_STATE,
+ Manifest.permission.WRITE_SETTINGS,
+ Manifest.permission.WAKE_LOCK,
+ Manifest.permission.INTERNET,
+ },
+ REQUEST_NEED_PERMISSIONS);
+ }
+/**/
+ setupCameraCoodinator();
+ setupActionListener();
+
+ }
+
+
+ /**
+ *
+ */
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ Log.v(TAG, "onResume()");
+ }
+
+ /**
+ *
+ */
+ @Override
+ protected void onPause()
+ {
+ super.onPause();
+ Log.v(TAG, "onPause()");
+
+ //coordinator.stopLiveView();
+
+ //exitApplication();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onStart()
+ {
+ super.onStart();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onStop()
+ {
+ super.onStop();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onEnterAmbient(Bundle ambientDetails)
+ {
+ super.onEnterAmbient(ambientDetails);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onExitAmbient()
+ {
+ super.onExitAmbient();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onUpdateAmbient()
+ {
+ super.onUpdateAmbient();
+ }
+
+
+ private void setupActionListener()
+ {
+ final OlyCameraLiveViewOnTouchListener listener = new OlyCameraLiveViewOnTouchListener(this);
+
+ final ImageButton btn1 = (ImageButton) findViewById(R.id.btn_1);
+ btn1.setOnClickListener(listener);
+
+ final ImageButton btn2 = (ImageButton) findViewById(R.id.btn_2);
+ btn2.setOnClickListener(listener);
+
+ final ImageButton btn3 = (ImageButton) findViewById(R.id.btn_3);
+ btn3.setOnClickListener(listener);
+
+ final ImageButton btn4 = (ImageButton) findViewById(R.id.btn_4);
+ btn4.setOnClickListener(listener);
+
+ final ImageButton btn5 = (ImageButton) findViewById(R.id.btn_5);
+ btn5.setOnClickListener(listener);
+
+ final ImageButton btn6 = (ImageButton) findViewById(R.id.btn_6);
+ btn6.setOnClickListener(listener);
+
+ final TextView textArea1 = (TextView) findViewById(R.id.text_1);
+ textArea1.setOnClickListener(listener);
+
+ final TextView textArea2 = (TextView) findViewById(R.id.text_2);
+ textArea2.setOnClickListener(listener);
+
+ final TextView textArea3 = (TextView) findViewById(R.id.text_3);
+ textArea3.setOnClickListener(listener);
+
+ final TextView textArea4 = (TextView) findViewById(R.id.text_4);
+ textArea4.setOnClickListener(listener);
+
+ if (liveView == null)
+ {
+ liveView = (CameraLiveImageView) findViewById(R.id.liveview);
+ }
+ liveView.setOnTouchListener(listener);
+ listener.prepareInterfaces(coordinator, liveView, liveView);
+ }
+
+ private void setupCameraCoodinator()
+ {
+ if (liveView == null)
+ {
+ liveView = (CameraLiveImageView) findViewById(R.id.liveview);
+ }
+ coordinator = null;
+ coordinator = new OlyCameraCoordinator(this, liveView, liveView, this);
+ liveViewListener = new CameraLiveViewListenerImpl(liveView);
+ coordinator.setLiveViewListener(liveViewListener);
+ Thread thread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ coordinator.getConnectionInterface().connect();
+ }
+ });
+ try
+ {
+ thread.start();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void exitApplication()
+ {
+ Log.v(TAG, "exitApplication()");
+
+ // カメラの電源をOFFにしたうえで、アプリケーションを終了する。
+ coordinator.getConnectionInterface().disconnect(true);
+ finish();
+ //android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+ @Override
+ public void onStatusNotify(String message)
+ {
+
+ }
+
+ @Override
+ public void onCameraConnected()
+ {
+ Log.v(TAG, "onCameraConnected()");
+ coordinator.startLiveView();
+/*
+ Thread thread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ //coordinator.stopLiveView();
+ //coordinator.setLiveViewListener(new CameraLiveViewListenerImpl(liveView));
+ coordinator.startLiveView();
+ }
+ });
+ try
+ {
+ thread.start();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ */
+ }
+
+ @Override
+ public void onCameraDisconnected()
+ {
+
+ }
+
+ @Override
+ public void onCameraOccursException(String message, Exception e)
+ {
+
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+import android.os.Looper;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.liveview.gridframe.GridFrameFactory;
+import jp.sfjp.gokigen.a01c.liveview.gridframe.IGridFrameDrawer;
+import jp.sfjp.gokigen.a01c.preference.ICameraPropertyAccessor;
+
+/**
+ * CameraLiveImageView :
+ * (OLYMPUS の ImageCaptureSample をカスタマイズ)
+ *
+ */
+public class CameraLiveImageView extends View implements CameraLiveViewListenerImpl.IImageDataReceiver, IAutoFocusFrameDisplay, ILiveImageStatusNotify, ICameraStatusDisplay, IStatusViewDrawer
+{
+ private final String TAG = this.toString();
+
+ private static final String EXIF_ORIENTATION = "Orientation";
+
+ private boolean showGridFeature = false;
+ private ImageView.ScaleType imageScaleType;
+ private Bitmap imageBitmap;
+ private int imageRotationDegrees;
+ private boolean showingFocusFrame = false;
+ private IAutoFocusFrameDisplay.FocusFrameStatus focusFrameStatus;
+ private RectF focusFrameRect;
+ private Timer focusFrameHideTimer;
+
+ private IGridFrameDrawer gridFrameDrawer = null;
+ private ShowMessageHolder messageHolder;
+
+
+ /**
+ *
+ *
+ */
+ public CameraLiveImageView(Context context)
+ {
+ super(context);
+ initComponent(context);
+ }
+
+ /**
+ *
+ *
+ */
+ public CameraLiveImageView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ initComponent(context);
+ }
+
+ /**
+ *
+ *
+ */
+ public CameraLiveImageView(Context context, AttributeSet attrs, int defStyleAttr)
+ {
+ super(context, attrs, defStyleAttr);
+ initComponent(context);
+ }
+
+ /**
+ * 初期化ロジック (preferenceからデータを読み出す)
+ */
+ private void initComponent(Context context)
+ {
+ messageHolder = new ShowMessageHolder();
+
+ imageScaleType = ImageView.ScaleType.FIT_CENTER;
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+ showGridFeature = preferences.getBoolean(ICameraPropertyAccessor.SHOW_GRID_STATUS, true);
+
+ int framingGridStatus = Integer.parseInt(preferences.getString(ICameraPropertyAccessor.FRAME_GRID, ICameraPropertyAccessor.FRAME_GRID_DEFAULT_VALUE));
+ gridFrameDrawer = GridFrameFactory.getGridFrameDrawer(framingGridStatus);
+
+ // ダミーのビットマップデータ読み込み...画面表示のテスト用ロジック
+ try
+ {
+ imageBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.momonga);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ imageBitmap = null;
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ protected void onAttachedToWindow()
+ {
+ super.onAttachedToWindow();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ protected void onDetachedFromWindow()
+ {
+ super.onDetachedFromWindow();
+
+ imageBitmap = null;
+ if (focusFrameHideTimer != null)
+ {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ super.onDraw(canvas);
+ drawCanvas(canvas);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public float getContentSizeWidth() {
+ return getIntrinsicContentSizeWidth();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public float getContentSizeHeight() {
+ return getIntrinsicContentSizeHeight();
+ }
+
+ /**
+ *
+ *
+ */
+ private float getIntrinsicContentSizeWidth()
+ {
+ if (imageBitmap == null)
+ {
+ return (1.0f);
+ }
+ return (imageBitmap.getWidth());
+ }
+
+ /**
+ *
+ *
+ */
+ private float getIntrinsicContentSizeHeight()
+ {
+ if (imageBitmap == null)
+ {
+ return (1.0f);
+ }
+ return (imageBitmap.getHeight());
+ }
+
+ /**
+ * Sets a image to view.
+ * (CameraLiveViewListenerImpl.IImageDataReceiver の実装)
+ *
+ * @param data A image of live-view.
+ * @param metadata A metadata of the image.
+ */
+ public void setImageData(byte[] data, Map<String, Object> metadata)
+ {
+ Bitmap bitmap;
+ int rotationDegrees;
+
+ if (data != null && metadata != null)
+ {
+ // Create a bitmap.
+ try
+ {
+ bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+ }
+ catch (OutOfMemoryError e)
+ {
+ e.printStackTrace();
+ return;
+ }
+
+ // Acquire a rotation degree of image.
+ int orientation = ExifInterface.ORIENTATION_UNDEFINED;
+ if (metadata.containsKey(EXIF_ORIENTATION))
+ {
+ orientation = Integer.parseInt((String) metadata.get(EXIF_ORIENTATION));
+ }
+ switch (orientation)
+ {
+ case ExifInterface.ORIENTATION_NORMAL:
+ rotationDegrees = 0;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ rotationDegrees = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ rotationDegrees = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ rotationDegrees = 270;
+ break;
+ default:
+ rotationDegrees = 0;
+ break;
+ }
+ imageBitmap = bitmap;
+ imageRotationDegrees = rotationDegrees;
+ }
+ refreshCanvas();
+ }
+
+ /**
+ * Returns a point which is detected by a motion event.
+ *
+ * @param event A motion event.
+ * @return A point in the view finder. if a point is equal to null, the point is out of the view finder.
+ */
+ public PointF getPointWithEvent(MotionEvent event) {
+ if (event == null || imageBitmap == null) {
+ return null;
+ }
+
+ PointF pointOnView = new PointF(event.getX(), event.getY());
+ PointF pointOnImage = convertPointFromViewArea(pointOnView);
+ float imageWidth;
+ float imageHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ imageWidth = imageBitmap.getWidth();
+ imageHeight = imageBitmap.getHeight();
+ } else {
+ imageWidth = imageBitmap.getHeight();
+ imageHeight = imageBitmap.getWidth();
+ }
+ return (OLYCamera.convertPointOnLiveImageIntoViewfinder(pointOnImage, imageWidth, imageHeight, imageRotationDegrees));
+ }
+
+ /**
+ * Returns whether a image area contains a specified point.
+ *
+ * @param point The point to examine.
+ * @return true if the image is not null or empty and the point is located within the rectangle; otherwise, false.
+ */
+ public boolean isContainsPoint(PointF point) {
+ return ((point != null) && (new RectF(0, 0, 1, 1)).contains(point.x, point.y));
+ }
+
+ /**
+ * Hides the forcus frame.
+ */
+ public void hideFocusFrame() {
+ if (focusFrameHideTimer != null) {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+ showingFocusFrame = false;
+ refreshCanvas();
+ }
+
+ /**
+ * Shows the focus frame.
+ *
+ * @param rect A rectangle of the focus frame on view area.
+ * @param status A status of the focus frame.
+ * @param duration A duration of the focus frame showing.
+ */
+ @Override
+ public void showFocusFrame(RectF rect, FocusFrameStatus status, double duration) {
+ if (focusFrameHideTimer != null) {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+
+ showingFocusFrame = true;
+ focusFrameStatus = status;
+ focusFrameRect = rect;
+
+ refreshCanvas();
+
+ if (duration > 0) {
+ focusFrameHideTimer = new Timer();
+ focusFrameHideTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ hideFocusFrame();
+ }
+ }, (long) (duration * 1000));
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ private void refreshCanvas() {
+ if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
+ invalidate();
+ } else {
+ postInvalidate();
+ }
+ }
+
+ /**
+ * ビットマップの表示・画面表示の更新
+ *
+ * @param canvas キャンバス
+ */
+ private void drawCanvas(Canvas canvas)
+ {
+ // Clears the canvas.
+ canvas.drawARGB(255, 0, 0, 0);
+
+ // ビットマップの取得
+ Bitmap bitmapToShow = imageBitmap;
+ if (bitmapToShow == null)
+ {
+ // 表示するビットマップがないときは、メッセージ表示のみ行う
+ drawInformationMessages(canvas);
+ return;
+ }
+
+ // Rotates the image.
+ int centerX = canvas.getWidth() / 2;
+ int centerY = canvas.getHeight() / 2;
+ canvas.rotate(imageRotationDegrees, centerX, centerY);
+
+ RectF viewRect = null;
+
+ // Calculate the viewport of bitmap.
+ if (imageScaleType == ImageView.ScaleType.FIT_CENTER) {
+ viewRect = decideViewRect(canvas, bitmapToShow);
+
+ // Draws the bitmap.
+ Rect imageRect = new Rect(0, 0, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+ canvas.drawBitmap(bitmapToShow, imageRect, viewRect, null);
+ } else {
+ // Sorry, other scale types are not supported.
+ Log.v(TAG, "Sorry, other scale types are not supported. " + imageScaleType);
+ }
+
+ // Cancels rotation of the canvas.
+ canvas.rotate(-imageRotationDegrees, centerX, centerY);
+
+
+ // フォーカスフレームを表示する
+ if ((focusFrameRect != null) && (showingFocusFrame)) {
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ drawFocusFrame(canvas, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+ } else {
+ drawFocusFrame(canvas, bitmapToShow.getHeight(), bitmapToShow.getWidth());
+ }
+ }
+
+ // グリッド(撮影補助線)の表示
+ if ((viewRect != null) && (showGridFeature) && (gridFrameDrawer != null)) {
+ drawGridFrame(canvas, viewRect);
+ }
+
+ // メッセージの表示
+ drawInformationMessages(canvas);
+ }
+
+ /**
+ *
+ *
+ */
+ private RectF decideViewRect(Canvas canvas, Bitmap bitmapToShow) {
+ final int srcWidth;
+ final int srcHeight;
+ if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180)) {
+ srcWidth = bitmapToShow.getWidth();
+ srcHeight = bitmapToShow.getHeight();
+ } else {
+ // Replaces width and height.
+ srcWidth = bitmapToShow.getHeight();
+ srcHeight = bitmapToShow.getWidth();
+ }
+
+ int maxWidth = canvas.getWidth();
+ int maxHeight = canvas.getHeight();
+
+ int centerX = canvas.getWidth() / 2;
+ int centerY = canvas.getHeight() / 2;
+
+ float widthRatio = maxWidth / (float) srcWidth;
+ float heightRatio = maxHeight / (float) srcHeight;
+ float smallRatio = Math.min(widthRatio, heightRatio);
+
+ final int dstWidth;
+ final int dstHeight;
+ if (widthRatio < heightRatio) {
+ // Fits to maxWidth with keeping aspect ratio.
+ dstWidth = maxWidth;
+ dstHeight = (int) (smallRatio * srcHeight);
+ } else {
+ // Fits to maxHeight with keeping aspect ratio.
+ dstHeight = maxHeight;
+ dstWidth = (int) (smallRatio * srcWidth);
+ }
+
+ final float halfWidth = dstWidth * 0.5f;
+ final float halfHeight = dstHeight * 0.5f;
+ if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180)) {
+ return (new RectF(
+ centerX - halfWidth,
+ centerY - halfHeight,
+ centerX - halfWidth + dstWidth,
+ centerY - halfHeight + dstHeight));
+ }
+
+ // Replaces the width and height.
+ return (new RectF(
+ centerX - halfHeight,
+ centerY - halfWidth,
+ centerX - halfHeight + dstHeight,
+ centerY - halfWidth + dstWidth));
+ }
+
+ /**
+ * AF枠の表示
+ *
+ * @param canvas キャンバス
+ * @param imageWidth 幅
+ * @param imageHeight 高さ
+ */
+ private void drawFocusFrame(Canvas canvas, float imageWidth, float imageHeight) {
+ //Log.v(TAG, "drawFocusFrame() :" + focusFrameStatus);
+
+ // Calculate the rectangle of focus.
+ RectF focusRectOnImage = OLYCamera.convertRectOnViewfinderIntoLiveImage(focusFrameRect, imageWidth, imageHeight, imageRotationDegrees);
+ RectF focusRectOnView = convertRectFromImageArea(focusRectOnImage);
+
+ // Draw a rectangle to the canvas.
+ Paint focusFramePaint = new Paint();
+ focusFramePaint.setStyle(Paint.Style.STROKE);
+ switch (focusFrameStatus) {
+ case Running:
+ focusFramePaint.setColor(Color.WHITE);
+ break;
+
+ case Focused:
+ focusFramePaint.setColor(Color.GREEN);
+ break;
+
+ case Failed:
+ focusFramePaint.setColor(Color.RED);
+ break;
+
+ case Errored:
+ focusFramePaint.setColor(Color.YELLOW);
+ break;
+ }
+ float focusFrameStrokeWidth = 2.0f;
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, focusFrameStrokeWidth, dm);
+ focusFramePaint.setStrokeWidth(strokeWidth);
+ canvas.drawRect(focusRectOnView, focusFramePaint);
+ }
+
+ /**
+ * グリッドの表示
+ *
+ * @param canvas キャンバスエリア
+ * @param viewRect 表示領域
+ */
+ private void drawGridFrame(Canvas canvas, RectF viewRect) {
+ RectF gridRect;
+ if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180)) {
+ gridRect = new RectF(viewRect);
+ } else {
+ float height = viewRect.right - viewRect.left;
+ float width = viewRect.bottom - viewRect.top;
+ float left = (canvas.getWidth() / 2.0f) - (width / 2.0f);
+ float top = (canvas.getHeight() / 2.0f) - (height / 2.0f);
+ gridRect = new RectF(left, top, left + width, top + height);
+ }
+
+ Paint framePaint = new Paint();
+ framePaint.setStyle(Paint.Style.STROKE);
+
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.0f, dm);
+ framePaint.setStrokeWidth(strokeWidth);
+ framePaint.setColor(gridFrameDrawer.getDrawColor());
+ gridFrameDrawer.drawFramingGrid(canvas, gridRect, framePaint);
+ }
+
+ /**
+ * 画面にメッセージを表示する
+ */
+ private void drawInformationMessages(Canvas canvas)
+ {
+ String message;
+ Paint paint = new Paint();
+ float x = 5.0f; // margin
+ float y = 5.0f; // margin
+
+ // 画面の中心に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.CENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.CENTER));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.CENTER));
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ x = (canvas.getWidth() / 2.0f) - (paint.measureText(message) / 2.0f);
+ y = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+ canvas.drawText(message, x, y, paint);
+ }
+
+ // 画面上部に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UP);
+ if ((message != null)&&(message.length() > 0))
+ {
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UP));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UP));
+ canvas.drawText(message, x, y, paint);
+ }
+
+ // 画面下部に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOW);
+ if ((message != null)&&(message.length() > 0))
+ {
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOW));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOW));
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ y = canvas.getHeight() - (fontMetrics.ascent + fontMetrics.descent) - 5.0f;
+ canvas.drawText(message, x, y, paint);
+ }
+ }
+
+ /**
+ * Converts a point on image area to a point on view area.
+ *
+ * @param point A point on image area. (e.g. a live preview image)
+ * @return A point on view area. (e.g. a touch panel view)
+ */
+ private PointF convertPointFromImageArea(PointF point) {
+ if (imageBitmap == null) {
+ return new PointF();
+ }
+
+ float viewPointX = point.x;
+ float viewPointY = point.y;
+ float imageSizeWidth;
+ float imageSizeHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ imageSizeWidth = imageBitmap.getWidth();
+ imageSizeHeight = imageBitmap.getHeight();
+ } else {
+ imageSizeWidth = imageBitmap.getHeight();
+ imageSizeHeight = imageBitmap.getWidth();
+ }
+ float viewSizeWidth = this.getWidth();
+ float viewSizeHeight = this.getHeight();
+ float ratioX = viewSizeWidth / imageSizeWidth;
+ float ratioY = viewSizeHeight / imageSizeHeight;
+ float scale;
+
+ switch (imageScaleType) {
+ case FIT_XY:
+ viewPointX *= ratioX;
+ viewPointY *= ratioY;
+ break;
+ case FIT_CENTER: // go to next label.
+ case CENTER_INSIDE:
+ scale = Math.min(ratioX, ratioY);
+ viewPointX *= scale;
+ viewPointY *= scale;
+ viewPointX += (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ break;
+ case CENTER_CROP:
+ scale = Math.max(ratioX, ratioY);
+ viewPointX *= scale;
+ viewPointY *= scale;
+ viewPointX += (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ break;
+ case CENTER:
+ viewPointX += viewSizeWidth / 2.0 - imageSizeWidth / 2.0f;
+ viewPointY += viewSizeHeight / 2.0 - imageSizeHeight / 2.0f;
+ break;
+ default:
+ break;
+ }
+ return new PointF(viewPointX, viewPointY);
+ }
+
+ /**
+ * Converts a point on view area to a point on image area.
+ *
+ * @param point A point on view area. (e.g. a touch panel view)
+ * @return A point on image area. (e.g. a live preview image)
+ */
+ private PointF convertPointFromViewArea(PointF point) {
+ if (imageBitmap == null) {
+ return new PointF();
+ }
+
+ float imagePointX = point.x;
+ float imagePointY = point.y;
+ float imageSizeWidth;
+ float imageSizeHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ imageSizeWidth = imageBitmap.getWidth();
+ imageSizeHeight = imageBitmap.getHeight();
+ } else {
+ imageSizeWidth = imageBitmap.getHeight();
+ imageSizeHeight = imageBitmap.getWidth();
+ }
+ float viewSizeWidth = this.getWidth();
+ float viewSizeHeight = this.getHeight();
+ float ratioX = viewSizeWidth / imageSizeWidth;
+ float ratioY = viewSizeHeight / imageSizeHeight;
+ float scale;
+
+ switch (imageScaleType) {
+ case FIT_XY:
+ imagePointX /= ratioX;
+ imagePointY /= ratioY;
+ break;
+ case FIT_CENTER: // go to next label.
+ case CENTER_INSIDE:
+ scale = Math.min(ratioX, ratioY);
+ imagePointX -= (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ imagePointX /= scale;
+ imagePointY /= scale;
+ break;
+ case CENTER_CROP:
+ scale = Math.max(ratioX, ratioY);
+ imagePointX -= (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ imagePointX /= scale;
+ imagePointY /= scale;
+ break;
+ case CENTER:
+ imagePointX -= (viewSizeWidth - imageSizeWidth) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight) / 2.0f;
+ break;
+ default:
+ break;
+ }
+ return new PointF(imagePointX, imagePointY);
+ }
+
+ /**
+ * Converts a rectangle on image area to a rectangle on view area.
+ *
+ * @param rect A rectangle on image area. (e.g. a live preview image)
+ * @return A rectangle on view area. (e.g. a touch panel view)
+ */
+ private RectF convertRectFromImageArea(RectF rect)
+ {
+ if (imageBitmap == null)
+ {
+ return new RectF();
+ }
+
+ PointF imageTopLeft = new PointF(rect.left, rect.top);
+ PointF imageBottomRight = new PointF(rect.right, rect.bottom);
+
+ PointF viewTopLeft = convertPointFromImageArea(imageTopLeft);
+ PointF viewBottomRight = convertPointFromImageArea(imageBottomRight);
+
+ return (new RectF(viewTopLeft.x, viewTopLeft.y, viewBottomRight.x, viewBottomRight.y));
+ }
+
+ /**
+ *
+ *
+ */
+ public void setShowGridFrame(boolean isShowGridFeature) {
+ showGridFeature = isShowGridFeature;
+ SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(ICameraPropertyAccessor.SHOW_GRID_STATUS, showGridFeature);
+ editor.apply();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void toggleShowGridFrame() {
+ setShowGridFrame(!showGridFeature);
+ }
+
+ /**
+ *
+ *
+ */
+ public boolean isShowGrid() {
+ return (showGridFeature);
+ }
+
+ /**
+ *
+ *
+ */
+ public ShowMessageHolder getMessageHolder()
+ {
+ return (messageHolder);
+ }
+
+ /****************** ICameraStatusDisplayの 実装 *****************/
+
+ @Override
+ public void updateTakeMode()
+ {
+
+ }
+
+ @Override
+ public void updateDriveMode() {
+
+ }
+
+ @Override
+ public void updateWhiteBalance() {
+
+ }
+
+ @Override
+ public void updateBatteryLevel() {
+
+ }
+
+ @Override
+ public void updateAeMode() {
+
+ }
+
+ @Override
+ public void updateAeLockState() {
+
+ }
+
+ @Override
+ public void updateCameraStatus() {
+
+ }
+
+ @Override
+ public void updateCameraStatus(String message) {
+
+ }
+
+ @Override
+ public void updateStatusView(String message) {
+
+ }
+
+ @Override
+ public void updateGridFrameStatus() {
+
+ }
+
+ @Override
+ public void showFavoriteSettingDialog() {
+
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+import android.util.Log;
+
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraLiveViewListener;
+
+/**
+ * OLYCameraLiveViewListener の実装
+ * (LiveViewFragment用)
+ *
+ */
+public class CameraLiveViewListenerImpl implements OLYCameraLiveViewListener
+{
+ private final String TAG = toString();
+ private final IImageDataReceiver imageView;
+
+ /**
+ * コンストラクタ
+ */
+ public CameraLiveViewListenerImpl(IImageDataReceiver target)
+ {
+ Log.v(TAG, "CameraLiveViewListenerImpl is created. ; " + target.toString());
+ this.imageView = target;
+ //
+ }
+
+ /**
+ * LiveViewの画像データを更新する
+ *
+ */
+ @Override
+ public void onUpdateLiveView(OLYCamera camera, byte[] data, Map<String, Object> metadata)
+ {
+ //Log.v(TAG, "onUpdateLiveView()");
+ if (imageView != null)
+ {
+ imageView.setImageData(data, metadata);
+ }
+ }
+
+ /**
+ * CameraLiveImageView
+ */
+ interface IImageDataReceiver
+ {
+ void setImageData(byte[] data, Map<String, Object> metadata);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.view.MotionEvent;
+
+/**
+ * フォーカスフレームの表示クラス
+ *
+ */
+public interface IAutoFocusFrameDisplay
+{
+ // フォーカスフレームの状態
+ enum FocusFrameStatus
+ {
+ Running,
+ Focused,
+ Failed,
+ Errored,
+ }
+
+ float getContentSizeWidth();
+ float getContentSizeHeight();
+
+ PointF getPointWithEvent(MotionEvent event);
+ boolean isContainsPoint(PointF point);
+
+ void showFocusFrame(RectF rect, FocusFrameStatus status, double duration);
+ void hideFocusFrame();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+/**
+ *
+ */
+public interface ICameraStatusDisplay
+{
+ void updateTakeMode();
+ void updateDriveMode();
+ void updateWhiteBalance();
+ void updateBatteryLevel();
+ void updateAeMode();
+ void updateAeLockState();
+ void updateCameraStatus();
+ void updateCameraStatus(String message);
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+/**
+ *
+ *
+ */
+public interface ICameraStatusReceiver
+{
+ void onStatusNotify(String message);
+ void onCameraConnected();
+ void onCameraDisconnected();
+ void onCameraOccursException(String message, Exception e);
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+/**
+ *
+ *
+ */
+public interface ILiveImageStatusNotify
+{
+ void toggleShowGridFrame();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+public interface IStatusViewDrawer
+{
+ void updateStatusView(String message);
+ void updateGridFrameStatus();
+ void showFavoriteSettingDialog();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.v7.preference.PreferenceManager;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Toast;
+
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IOlyCameraCoordinator;
+import jp.sfjp.gokigen.a01c.preference.ICameraPropertyAccessor;
+
+/**
+ *
+ *
+ */
+public class OlyCameraLiveViewOnTouchListener implements View.OnClickListener, View.OnTouchListener
+{
+ private final String TAG = toString();
+ private final Context context;
+ private IOlyCameraCoordinator camera = null;
+ private IStatusViewDrawer statusDrawer = null;
+ private ILiveImageStatusNotify liveImageView = null;
+ private final SharedPreferences preferences;
+
+ public OlyCameraLiveViewOnTouchListener(Context context)
+ {
+ this.context = context;
+ preferences = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public void prepareInterfaces(IOlyCameraCoordinator cameraCoordinator, IStatusViewDrawer statusDrawer, ILiveImageStatusNotify liveImageView)
+ {
+ this.camera = cameraCoordinator;
+ this.statusDrawer = statusDrawer;
+ this.liveImageView = liveImageView;
+ }
+
+ @Override
+ public void onClick(View v)
+ {
+ int id = v.getId();
+ Log.v(TAG, "onClick() : " + id);
+ switch (id)
+ {
+ case R.id.btn_1:
+ //pushShutterButton();
+ break;
+
+ case R.id.btn_2:
+ //phoneShutter.onTouchedPreviewArea();
+ break;
+
+ case R.id.btn_3:
+ //camera.toggleManualFocus();
+ break;
+
+ case R.id.btn_4:
+ //camera.unlockAutoFocus();
+ break;
+
+ case R.id.btn_5:
+ //camera.toggleAutoExposure();
+ break;
+
+ case R.id.btn_6:
+ //camera.configure_expert();
+ pushShutterButton();
+ break;
+
+ case R.id.text_1:
+ //
+ break;
+
+ case R.id.text_2:
+ //
+ break;
+
+ case R.id.text_3:
+ //
+ break;
+
+ case R.id.text_4:
+ //
+ break;
+
+ default:
+ //
+ break;
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event)
+ {
+ int id = v.getId();
+ Log.v(TAG, "onTouch() : " + id);
+ if (id == R.id.liveview)
+ {
+ return (camera.driveAutoFocus(event));
+ }
+ return (false);
+ }
+
+ /**
+ * シャッターボタンが押された!
+ * (現在は、連続撮影モードやムービー撮影についてはまだ非対応)
+ */
+ private void pushShutterButton()
+ {
+ // カメラ側のシャッターを押す
+ camera.singleShot();
+ {
+ // パラメータが ON (ONLY CAMERA)の時は、スマートフォン側の撮影は行わない。
+ // (本体カメラのシャッターを切らない時だけ、Toastで通知する。)
+ Toast.makeText(context, R.string.shoot_camera, Toast.LENGTH_SHORT).show();
+ }
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview;
+
+import android.graphics.Color;
+
+/**
+ *
+ *
+ * Created by MRSa on 2017/03/01.
+ */
+public class ShowMessageHolder
+{
+ private String upperMessage = "";
+ private String centerMessage = "";
+ private String lowerMessage = "";
+
+ private int upperMessageColor = Color.BLUE;
+ private int centerMessageColor = Color.BLUE;
+ private int lowerMessageColor = Color.BLUE;
+
+ private int upperMessageTextSize = 8;
+ private int centerMessageTextSize = 16;
+ private int lowerMessageTextSize = 8;
+
+ // フォーカスフレームの状態
+ enum MessageArea
+ {
+ UP,
+ CENTER,
+ LOW
+ };
+
+ /**
+ *
+ *
+ */
+ public void setMessageToShow(MessageArea area, int color, int size, String message)
+ {
+ switch (area)
+ {
+ case CENTER:
+ centerMessageColor = color;
+ centerMessageTextSize = size;
+ centerMessage = message;
+ break;
+
+ case UP:
+ upperMessageColor = color;
+ upperMessageTextSize = size;
+ upperMessage = message;
+ break;
+
+ case LOW:
+ default:
+ lowerMessageColor = color;
+ lowerMessageTextSize = size;
+ lowerMessage = message;
+ break;
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ int getSize(MessageArea area)
+ {
+ int size;
+ switch (area)
+ {
+ case CENTER:
+ size = centerMessageTextSize;
+ break;
+
+ case UP:
+ size = upperMessageTextSize;
+ break;
+
+ case LOW:
+ default:
+ size = lowerMessageTextSize;
+ break;
+ }
+ return (size);
+ }
+
+ /**
+ *
+ *
+ */
+ int getColor(MessageArea area)
+ {
+ int color;
+ switch (area)
+ {
+ case CENTER:
+ color = centerMessageColor;
+ break;
+
+ case UP:
+ color = upperMessageColor;
+ break;
+
+ case LOW:
+ default:
+ color = lowerMessageColor;
+ break;
+ }
+ return (color);
+ }
+
+ /**
+ *
+ *
+ */
+ String getMessage(MessageArea area)
+ {
+ String message;
+ switch (area)
+ {
+ case CENTER:
+ message = centerMessage;
+ break;
+
+ case UP:
+ message = upperMessage;
+ break;
+
+ case LOW:
+ default:
+ message = lowerMessage;
+ break;
+ }
+ return (message);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 3x3 のグリッド表示
+ */
+class GridFrameDrawer0 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float w = (rect.right - rect.left) / 3.0f;
+ float h = (rect.bottom - rect.top) / 3.0f;
+
+ canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+ canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 4x3 のグリッド表示
+ */
+class GridFrameDrawer1 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float w = (rect.right - rect.left) / 4.0f;
+ float h = (rect.bottom - rect.top) / 3.0f;
+
+ canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 3.0f * w, rect.top, rect.left + 3.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+ canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.Log;
+
+/**
+ * 対角線のグリッド表示
+ */
+class GridFrameDrawer2 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ canvas.drawLine(rect.left, rect.top, rect.right, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.bottom, rect.right, rect.top, paint);
+
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 4x4 のグリッド表示
+ */
+class GridFrameDrawer3 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float w = (rect.right - rect.left) / 4.0f;
+ float h = (rect.bottom - rect.top) / 4.0f;
+
+ canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 3.0f * w, rect.top, rect.left + 3.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+ canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+ canvas.drawLine(rect.left, rect.top + 3.0f * h, rect.right, rect.top + 3.0f * h, paint);
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 4x4 のグリッドと対角線の表示
+ */
+class GridFrameDrawer4 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float w = (rect.right - rect.left) / 4.0f;
+ float h = (rect.bottom - rect.top) / 4.0f;
+
+ canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 3.0f * w, rect.top, rect.left + 3.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+ canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+ canvas.drawLine(rect.left, rect.top + 3.0f * h, rect.right, rect.top + 3.0f * h, paint);
+
+ canvas.drawLine(rect.left, rect.top, rect.right, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.bottom, rect.right, rect.top, paint);
+
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 3x3 のグリッドと対角線の表示
+ */
+class GridFrameDrawer5 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float cX = (rect.right + rect.left) / 2.0f;
+ float cY = (rect.bottom + rect.top) / 2.0f;
+
+ canvas.drawLine(rect.left, cY, rect.right, cY, paint);
+ canvas.drawLine(cX, rect.bottom, cX, rect.top, paint);
+
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 真ん中四角と中心線の表示
+ */
+class GridFrameDrawer6 implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float cX = (rect.right + rect.left) / 2.0f;
+ float cY = (rect.bottom + rect.top) / 2.0f;
+ float w = (rect.right - rect.left) / 4.0f;
+ float h = (rect.bottom - rect.top) / 4.0f;
+
+ canvas.drawRect(rect.left + w, rect.top + h, rect.right - w, rect.bottom - h, paint);
+
+ canvas.drawLine(rect.left, cY, rect.left + w, cY, paint);
+ canvas.drawLine(rect.right - w, cY, rect.right, cY, paint);
+
+ canvas.drawLine(cX, rect.top, cX, rect.top + h, paint);
+ canvas.drawLine(cX, rect.bottom - h, cX, rect.bottom, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+public class GridFrameDrawerStub implements IGridFrameDrawer
+{
+
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+/**
+ *
+ *
+ */
+public class GridFrameFactory
+{
+ private static final int GRID_FRAME_0 = 0;
+ private static final int GRID_FRAME_1 = 1;
+ private static final int GRID_FRAME_2 = 2;
+ private static final int GRID_FRAME_3 = 3;
+ private static final int GRID_FRAME_4 = 4;
+ private static final int GRID_FRAME_5 = 5;
+ private static final int GRID_FRAME_6 = 6;
+
+ public static IGridFrameDrawer getGridFrameDrawer(int id)
+ {
+ IGridFrameDrawer drawer;
+ switch (id)
+ {
+ case GRID_FRAME_2:
+ drawer = new GridFrameDrawer2();
+ break;
+ case GRID_FRAME_3:
+ drawer = new GridFrameDrawer3();
+ break;
+ case GRID_FRAME_4:
+ drawer = new GridFrameDrawer4();
+ break;
+ case GRID_FRAME_5:
+ drawer = new GridFrameDrawer5();
+ break;
+ case GRID_FRAME_6:
+ drawer = new GridFrameDrawer6();
+ break;
+ case GRID_FRAME_1:
+ drawer = new GridFrameDrawer1();
+ break;
+ case GRID_FRAME_0:
+ default:
+ drawer = new GridFrameDrawer0();
+ break;
+ }
+ return (drawer);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 撮影補助線の描画クラス
+ *
+ */
+public interface IGridFrameDrawer
+{
+ void drawFramingGrid(Canvas canvas, RectF rect, Paint paint);
+ int getDrawColor();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraAutoFocusResult;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay;
+
+/**
+ * オートフォーカス制御クラス
+ *
+ * 1. setAutoFocusFrameDisplay() で AFフレームの表示クラスを設定
+ * 2. lockAutoFocus() で AF-Lockを実行
+ * 3. unlockAutoFocus() で AF-Unlock を実行
+ *
+ */
+class AutoFocusControl implements OLYCamera.TakePictureCallback
+{
+ private final OLYCamera camera;
+ private final IIndicatorControl indicator;
+ private final IAutoFocusFrameDisplay focusFrameDrawer;
+ private RectF focusFrameRect = null;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ AutoFocusControl(OLYCamera camera, IAutoFocusFrameDisplay focusFrameDrawer, IIndicatorControl indicator)
+ {
+ this.camera = camera;
+ this.indicator = indicator;
+ this.focusFrameDrawer = focusFrameDrawer;
+ }
+
+ /**
+ * オートフォーカスを駆動させ、ロックする
+ *
+ * @param point ターゲットAF点
+ *
+ */
+ boolean lockAutoFocus(PointF point)
+ {
+ if (camera.isTakingPicture() || camera.isRecordingVideo())
+ {
+ // 撮影中の場合にはフォーカスロックはやらない。
+ return (false);
+ }
+
+ RectF preFocusFrameRect = getPreFocusFrameRect(point);
+ showFocusFrame(preFocusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Running, 0.0);
+
+ try
+ {
+ // Set auto-focus point.
+ camera.setAutoFocusPoint(point);
+
+ // Lock auto-focus.
+ focusFrameRect = preFocusFrameRect;
+ camera.lockAutoFocus(this);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ // Lock failed.
+ try
+ {
+ camera.clearAutoFocusPoint();
+ camera.unlockAutoFocus();
+ showFocusFrame(preFocusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Failed, 1.0);
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ return (false);
+ }
+ return (true);
+ }
+
+ /**
+ * AF-Lを解除する
+ *
+ */
+ void unlockAutoFocus()
+ {
+ if (camera.isTakingPicture() || camera.isRecordingVideo())
+ {
+ // 撮影中の場合には、フォーカスロック解除はやらない
+ return;
+ }
+
+ // Unlock auto-focus.
+ try
+ {
+ camera.unlockAutoFocus();
+ camera.clearAutoFocusPoint();
+ hideFocusFrame();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onProgress(OLYCamera olyCamera, OLYCamera.TakingProgress takingProgress, OLYCameraAutoFocusResult olyCameraAutoFocusResult)
+ {
+ if (takingProgress == OLYCamera.TakingProgress.EndFocusing)
+ {
+ if (olyCameraAutoFocusResult.getResult().equals("ok") && olyCameraAutoFocusResult.getRect() != null)
+ {
+ // Lock succeed.
+ RectF postFocusFrameRect = olyCameraAutoFocusResult.getRect();
+ showFocusFrame(postFocusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Focused, 0.0);
+
+ }
+ else if (olyCameraAutoFocusResult.getResult().equals("none"))
+ {
+ // Could not lock.
+ try
+ {
+ camera.clearAutoFocusPoint();
+ camera.unlockAutoFocus();
+ }
+ catch (OLYCameraKitException ee)
+ {
+ ee.printStackTrace();
+ }
+ hideFocusFrame();
+ }
+ else
+ {
+ // Lock failed.
+ try
+ {
+ camera.clearAutoFocusPoint();
+ camera.unlockAutoFocus();
+ }
+ catch (OLYCameraKitException ee)
+ {
+ ee.printStackTrace();
+ }
+ showFocusFrame(focusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Failed, 1.0);
+ }
+ }
+ }
+
+ @Override
+ public void onCompleted()
+ {
+ // フォーカスロック成功、なにもしない
+ }
+
+ @Override
+ public void onErrorOccurred(Exception e)
+ {
+ // フォーカスロック失敗 : 通知される
+ e.printStackTrace();
+ try
+ {
+ camera.clearAutoFocusPoint();
+ camera.unlockAutoFocus();
+ hideFocusFrame();
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ showFocusFrame(focusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Errored, 1.0);
+ }
+
+ private void showFocusFrame(RectF rect, IAutoFocusFrameDisplay.FocusFrameStatus status, double duration)
+ {
+ if (focusFrameDrawer != null)
+ {
+ focusFrameDrawer.showFocusFrame(rect, status, duration);
+ }
+ indicator.onAfLockUpdate(IAutoFocusFrameDisplay.FocusFrameStatus.Focused == status);
+ }
+
+ private void hideFocusFrame()
+ {
+ if (focusFrameDrawer != null)
+ {
+ focusFrameDrawer.hideFocusFrame();
+ }
+ indicator.onAfLockUpdate(false);
+ }
+
+ private RectF getPreFocusFrameRect(PointF point)
+ {
+ float imageWidth = 1.0f;
+ float imageHeight = 1.0f;
+ if (focusFrameDrawer != null)
+ {
+ imageWidth = focusFrameDrawer.getContentSizeWidth();
+ imageHeight = focusFrameDrawer.getContentSizeHeight();
+ }
+ // Display a provisional focus frame at the touched point.
+ float focusWidth = 0.125f; // 0.125 is rough estimate.
+ float focusHeight = 0.125f;
+ if (imageWidth > imageHeight)
+ {
+ focusHeight *= (imageWidth / imageHeight);
+ }
+ else
+ {
+ focusHeight *= (imageHeight / imageWidth);
+ }
+ return (new RectF(point.x - focusWidth / 2.0f, point.y - focusHeight / 2.0f,
+ point.x + focusWidth / 2.0f, point.y + focusHeight / 2.0f));
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+import android.util.Log;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
+
+/**
+ * Olympusカメラとの接続処理
+ *
+ */
+class CameraConnectSequence implements Runnable
+{
+ private final String TAG = this.toString();
+ private final Context context;
+ private final OLYCamera camera;
+ private final ICameraStatusReceiver cameraStatusReceiver;
+
+ /**
+ * コンストラクタ
+ */
+ CameraConnectSequence(Context context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+ {
+ Log.v(TAG, "CameraConnectSequence");
+ this.context = context;
+ this.camera =camera;
+ this.cameraStatusReceiver = statusReceiver;
+ }
+
+ /**
+ * カメラとの接続実処理
+ *
+ */
+ @Override
+ public void run()
+ {
+ String statusMessage = context.getString(R.string.connect_start);
+ try
+ {
+ statusMessage = context.getString(R.string.connect_check_wifi);
+ cameraStatusReceiver.onStatusNotify(statusMessage);
+ camera.connect(OLYCamera.ConnectionType.WiFi);
+
+ // ライブビューの自動スタート設定の場合、自動スタートをやめる
+ if (camera.isAutoStartLiveView())
+ {
+ camera.setAutoStartLiveView(false);
+ }
+
+ // 一度カメラの動作モードを確認する
+ OLYCamera.RunMode runMode = camera.getRunMode();
+ if (runMode == OLYCamera.RunMode.Unknown)
+ {
+ // UNKNOWNモードは動作しない、メッセージを作って応答する
+ statusMessage = context.getString(R.string.fatal_cannot_use_camera);
+ cameraStatusReceiver.onCameraOccursException(statusMessage, new IllegalStateException(context.getString(R.string.camera_reset_required)));
+ Log.w(TAG, "DETECT : OLYCamera.RunMode.Unknown");
+ }
+ if (runMode != OLYCamera.RunMode.Recording)
+ {
+ // Recordingモードでない場合は切り替える
+ statusMessage = context.getString(R.string.connect_change_run_mode);
+ cameraStatusReceiver.onStatusNotify(statusMessage);
+ camera.changeRunMode(OLYCamera.RunMode.Recording);
+ }
+ }
+ catch (OLYCameraKitException e)
+ {
+ cameraStatusReceiver.onCameraOccursException(statusMessage, e);
+ e.printStackTrace();
+ return;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return;
+ }
+ Log.v(TAG, "CameraConnectSequence:: connected.");
+
+ // カメラとの接続確立を通知する
+ cameraStatusReceiver.onStatusNotify(context.getString(R.string.connect_connected));
+ cameraStatusReceiver.onCameraConnected();
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.util.Log;
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ * Olympusカメラとの切断処理
+ *
+ */
+class CameraDisconnectSequence implements Runnable
+{
+ private final String TAG = this.toString();
+
+ private final OLYCamera camera;
+ private final boolean powerOff;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ CameraDisconnectSequence(OLYCamera camera, boolean isOff)
+ {
+ this.camera = camera;
+ this.powerOff = isOff;
+ }
+
+ @Override
+ public void run()
+ {
+ // カメラをPowerOffして接続を切る
+ try
+ {
+ camera.disconnectWithPowerOff(powerOff);
+ }
+ catch (OLYCameraKitException e)
+ {
+ // エラー情報をログに出力する
+ Log.w(TAG, "To disconnect from the camera is failed. : " + e.getLocalizedMessage());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import jp.sfjp.gokigen.a01c.ConfirmationDialog;
+import jp.sfjp.gokigen.a01c.IChangeScene;
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.preference.ICameraPropertyAccessor;
+
+/**
+ * Preferenceがクリックされた時に処理するクラス
+ *
+ */
+public class CameraPowerOff implements Preference.OnPreferenceClickListener, ConfirmationDialog.Callback
+{
+ private final Context context;
+ private final IChangeScene changeScene;
+ private String preferenceKey = null;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ public CameraPowerOff(Context context, IChangeScene changeScene)
+ {
+ this.context = context;
+ this.changeScene = changeScene;
+ }
+
+ /**
+ * クラスの準備
+ *
+ */
+ public void prepare()
+ {
+ // 何もしない
+ }
+
+ /**
+ *
+ *
+ * @param preference クリックしたpreference
+ * @return false : ハンドルしない / true : ハンドルした
+ */
+ @Override
+ public boolean onPreferenceClick(Preference preference)
+ {
+ if (!preference.hasKey())
+ {
+ return (false);
+ }
+
+ preferenceKey = preference.getKey();
+ if (preferenceKey.contains(ICameraPropertyAccessor.EXIT_APPLICATION))
+ {
+
+ // 確認ダイアログの生成と表示
+ ConfirmationDialog dialog = new ConfirmationDialog(context);
+ dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_power_off, this);
+ return (true);
+ }
+ return (false);
+ }
+
+ @Override
+ public void confirm()
+ {
+ if (preferenceKey.contains(ICameraPropertyAccessor.EXIT_APPLICATION))
+ {
+ // カメラの電源をOFFにしたうえで、アプリケーションを終了する。
+ changeScene.exitApplication();
+ }
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.util.Log;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraPropertyListener;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusDisplay;
+
+/**
+ * OLYCameraPropertyListenerの実装
+ * (LiveViewFragment用)
+ *
+ */
+public class CameraPropertyListenerImpl implements OLYCameraPropertyListener
+{
+ private final String TAG = this.toString();
+
+ private final ICameraStatusDisplay display;
+
+ public CameraPropertyListenerImpl(ICameraStatusDisplay parent)
+ {
+ this.display = parent;
+ }
+
+ @Override
+ public void onUpdateCameraProperty(OLYCamera camera, final String name)
+ {
+ switch (name)
+ {
+ case IOlyCameraProperty.TAKE_MODE:
+ display.updateTakeMode();
+ break;
+ case IOlyCameraProperty.DRIVE_MODE:
+ display.updateDriveMode();
+ break;
+ case IOlyCameraProperty.WB_MODE:
+ display.updateWhiteBalance();
+ break;
+ case IOlyCameraProperty.BATTERY_LEVEL:
+ display.updateBatteryLevel();
+ break;
+ case IOlyCameraProperty.AE_MODE:
+ display.updateAeMode();
+ break;
+ case IOlyCameraProperty.AE_LOCK_STATE:
+ display.updateAeLockState();
+ break;
+ default:
+ Log.v(TAG, "onUpdateCameraProperty() : " + name);
+ display.updateCameraStatus();
+ break;
+ }
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ * カメラプロパティに関する雑多な処理...
+ *
+ */
+class CameraPropertyUtilities
+{
+ /**
+ * toLiveViewSize() : スクリーンサイズの文字列から、OLYCamera.LiveViewSize型へ変換する
+ *
+ * @param quality スクリーンサイズ文字列
+ * @return OLYCamera.LiveViewSize型
+ */
+ public static OLYCamera.LiveViewSize toLiveViewSizeType(String quality)
+ {
+ if (quality == null)
+ {
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+ if (quality.equalsIgnoreCase("QVGA"))
+ {
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+ else if (quality.equalsIgnoreCase("VGA"))
+ {
+ return OLYCamera.LiveViewSize.VGA;
+ } else if (quality.equalsIgnoreCase("SVGA"))
+ {
+ return OLYCamera.LiveViewSize.SVGA;
+ } else if (quality.equalsIgnoreCase("XGA"))
+ {
+ return OLYCamera.LiveViewSize.XGA;
+ }
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+
+ public static String getPropertyValue(String value)
+ {
+ if (value == null)
+ {
+ return ("");
+ }
+ String[] keyValue = OLYCamera.decodeCameraPropertyValue(value);
+ return (keyValue[1]);
+ }
+ }
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.util.Map;
+import java.util.TreeSet;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraStatusListener;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusDisplay;
+import jp.sfjp.gokigen.a01c.R;
+
+/**
+ * OLYCameraStatusListenerの実装
+ * (LiveViewFragment用)
+ */
+public class CameraStatusListenerImpl implements OLYCameraStatusListener, ICameraStatusSummary
+{
+ private final String TAG = this.toString();
+
+ public static final String APERTURE_VALUE = "ActualApertureValue";
+ public static final String SHUTTER_SPEED = "ActualShutterSpeed";
+ public static final String EXPOSURE_COMPENSATION = "ActualExposureCompensation";
+ public static final String ISO_SENSITIVITY = "ActualIsoSensitivity";
+ public static final String RECORDABLEIMAGES = "RemainingRecordableImages";
+ public static final String MEDIA_BUSY = "MediaBusy";
+ public static final String MEDIA_ERROR = "MediaError";
+ public static final String DETECT_FACES = "DetectedHumanFaces";
+ public static final String FOCAL_LENGTH = "ActualFocalLength";
+ public static final String ACTUAL_ISO_SENSITIVITY_WARNING = "ActualIsoSensitivityWarning";
+ public static final String EXPOSURE_WARNING = "ExposureWarning";
+ public static final String EXPOSURE_METERING_WARNING = "ExposureMeteringWarning";
+ public static final String HIGH_TEMPERATURE_WARNING = "HighTemperatureWarning";
+ public static final String LEVEL_GAUGE = "LevelGauge";
+ public static final String LENS_MOUNT_STATUS = "LensMountStatus";
+ public static final String MEDIA_MOUNT_STATUS = "MediaMountStatus";
+ public static final String REMAINING_RECORDABLE_TIME = "RemainingRecordableTime";
+ public static final String MINIMUM_FOCAL_LENGTH = "MinimumFocalLength";
+ public static final String MAXIMUM_FOCAL_LENGTH = "MaximumFocalLength";
+
+ private final ICameraStatusDisplay display;
+ private final Context context;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ public CameraStatusListenerImpl(Context context, ICameraStatusDisplay parent)
+ {
+ this.context = context;
+ this.display = parent;
+ }
+
+ @Override
+ public void onUpdateStatus(OLYCamera camera, final String name)
+ {
+ if (name == null)
+ {
+ // name がないとき、何もしない
+ return;
+ }
+ switch (name)
+ {
+ case APERTURE_VALUE:
+ case SHUTTER_SPEED:
+ case ISO_SENSITIVITY:
+ case FOCAL_LENGTH:
+ case EXPOSURE_WARNING:
+ case EXPOSURE_METERING_WARNING:
+ case HIGH_TEMPERATURE_WARNING:
+ // ある一定の値が更新された時だけ
+ break;
+
+ default:
+ // 他の値が変わった場合には、ログだけ残して何もしない。
+ Log.v(TAG, "onUpdateStatus() : " + name);
+ return;
+ //break;
+ }
+ display.updateCameraStatus(geCameraStatusMessage(camera, name));
+ }
+
+ /**
+ * 表示用のメッセージを生成する
+ *
+ */
+ @Override
+ public String geCameraStatusMessage(OLYCamera camera, String name)
+ {
+ String message = name;
+ String warn = "";
+ try
+ {
+ // 警告メッセージを生成
+ if (camera.isHighTemperatureWarning())
+ {
+ warn = warn + " " + context.getString(R.string.high_temperature_warning);
+ }
+ if (camera.isExposureMeteringWarning())
+ {
+ warn = warn + " " + context.getString(R.string.exposure_metering_warning);
+ }
+ if (camera.isActualIsoSensitivityWarning())
+ {
+ warn = warn + " " + context.getString(R.string.iso_sensitivity_warning);
+ }
+
+ TreeSet<String> treeSet = new TreeSet<>();
+ treeSet.add(IOlyCameraProperty.TAKE_MODE);
+ treeSet.add(IOlyCameraProperty.WB_MODE);
+ treeSet.add(IOlyCameraProperty.AE_MODE);
+ treeSet.add(IOlyCameraProperty.EXPOSURE_COMPENSATION);
+ Map<String, String> values = camera.getCameraPropertyValues(treeSet);
+ //for (Map.Entry<String, String> entry : values.entrySet())
+ //{
+ // Log.v(TAG, "STATUS : " + entry.getKey() + " : " + entry.getValue());
+ //}
+ String takeMode = camera.getCameraPropertyValueTitle(values.get(IOlyCameraProperty.TAKE_MODE));
+ String wbMode = camera.getCameraPropertyValueTitle(values.get(IOlyCameraProperty.WB_MODE));
+ String aeMode = camera.getCameraPropertyValueTitle(values.get(IOlyCameraProperty.AE_MODE));
+ String aperture = camera.getCameraPropertyValueTitle(camera.getActualApertureValue());
+ String iso = camera.getCameraPropertyValueTitle(camera.getActualIsoSensitivity());
+ String shutter = camera.getCameraPropertyValueTitle(camera.getActualShutterSpeed());
+ message = " " + takeMode + " " + shutter + " F" + aperture + " ISO" + iso + " " + wbMode + " [" + aeMode + "]" + warn;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (message);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ */
+public interface ICameraHardwareStatus
+{
+ String getLensMountStatus();
+ String getMediaMountStatus();
+
+ float getMinimumFocalLength();
+ float getMaximumFocalLength();
+ float getActualFocalLength();
+
+ Map<String, Object> inquireHardwareInformation();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+public interface ICameraRunMode
+{
+ /** カメラの動作モード変更 **/
+ void changeRunMode(boolean isRecording);
+ boolean isRecordingMode();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+public interface ICameraStatusSummary
+{
+ String geCameraStatusMessage(OLYCamera camera, String name);
+
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+
+public interface IIndicatorControl
+{
+ void onAfLockUpdate(boolean isAfLocked);
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+public interface ILoadSaveCameraProperties
+{
+ void loadCameraSettings(final String id);
+ void saveCameraSettings(final String id, final String name);
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+public interface IOLYCameraObjectProvider
+{
+ OLYCamera getOLYCamera();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+
+/**
+ * カメラの接続/切断
+ *
+ * Created by MRSa on 2017/02/28.
+ */
+public interface IOlyCameraConnection
+{
+ // WIFI 接続系
+ void startWatchWifiStatus(Context context);
+ void stopWatchWifiStatus(Context context);
+ boolean isWatchWifiStatus();
+
+ /** カメラ接続系 **/
+ void disconnect(final boolean powerOff);
+ void connect();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+import android.view.MotionEvent;
+
+import jp.co.olympus.camerakit.OLYCameraLiveViewListener;
+import jp.co.olympus.camerakit.OLYCameraStatusListener;
+
+/**
+ *
+ *
+ */
+public interface IOlyCameraCoordinator
+{
+
+ /** ライブビュー関係 **/
+ void changeLiveViewSize(String size);
+ void setLiveViewListener(OLYCameraLiveViewListener listener);
+ void startLiveView();
+ void stopLiveView();
+
+ /** オートフォーカス機能の実行 **/
+ boolean driveAutoFocus(MotionEvent event);
+ void unlockAutoFocus();
+
+ /** シングル撮影機能の実行 **/
+ void singleShot();
+
+ /** AE Lockの設定・解除、 AF/MFの切替え **/
+ void toggleAutoExposure();
+ void toggleManualFocus();
+
+ /** カメラの状態取得 **/
+ boolean isManualFocus();
+ boolean isAFLock();
+ boolean isAELock();
+
+ /** カメラの状態変化リスナの設定 **/
+ void setCameraStatusListener(OLYCameraStatusListener listener);
+
+ /** カメラの状態サマリ(のテキスト情報)を取得する **/
+ String getCameraStatusSummary(ICameraStatusSummary decoder);
+
+ // カメラプロパティアクセスインタフェース
+ IOlyCameraPropertyProvider getCameraPropertyProvider();
+
+ // カメラプロパティのロード・セーブインタフェース
+ ILoadSaveCameraProperties getLoadSaveCameraProperties();
+
+ // カメラの動作モード変更インタフェース
+ ICameraRunMode getChangeRunModeExecutor();
+
+ IOlyCameraConnection getConnectionInterface();
+
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+/**
+ * 使用するカメラプロパティのキー一覧
+ *
+ *
+ */
+public interface IOlyCameraProperty
+{
+ String TAKE_MODE = "TAKEMODE";
+ String COLOR_TONE = "COLORTONE";
+ String AE_MODE = "AE";
+ String WB_MODE = "WB";
+ String EXPOSURE_COMPENSATION = "EXPREV";
+ String SHUTTER_SPEED = "SHUTTER";
+ String APERTURE ="APERTURE";
+ String ISO_SENSITIVITY = "ISO";
+ String SOUND_VOLUME_LEVEL = "SOUND_VOLUME_LEVEL";
+ String RAW = "RAW";
+ String DRIVE_MODE = "TAKE_DRIVE";
+ String BATTERY_LEVEL = "BATTERY_LEVEL";
+ String AE_LOCK_STATE = "AE_LOCK_STATE";
+
+ String FOCUS_STILL = "FOCUS_STILL";
+
+ String FOCUS_MF = "FOCUS_MF";
+ String FOCUS_SAF = "FOCUS_SAF";
+
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface IOlyCameraPropertyProvider
+{
+ // 現在利用可能なカメラプロパティ名のリスト
+ Set<String> getCameraPropertyNames();
+
+ // カメラプロパティに設定されている値を取得 : 戻りは "<WB/WB_AUTO>" な感じ
+ String getCameraPropertyValue(String name);
+
+ // カメラプロパティに設定されている値を一括取得
+ Map<String, String> getCameraPropertyValues (Set<String> names);
+
+ // カメラプロパティの名称
+ String getCameraPropertyTitle(String name);
+
+ // 設定可能なカメラプロパティ値のリストを取得する
+ List<String> getCameraPropertyValueList(String name);
+
+ // カメラプロパティの表示値
+ String getCameraPropertyValueTitle(String propertyValue);
+
+ // カメラプロパティに値を設定
+ void setCameraPropertyValue (String name, String value);
+
+ // カメラプロパティに値を一括設定
+ void setCameraPropertyValues(Map<String, String> values);
+
+ // カメラプロパティに値を設定できるかを検査
+ boolean canSetCameraProperty(String name);
+
+ // カメラに接続中かどうか
+ boolean isConnected();
+
+ // カメラのハードウェア状態のインタフェースを取得する
+ ICameraHardwareStatus getHardwareStatus();
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ * カメラプロパティを一括でバックアップしたり、リストアしたりするクラス
+ *
+ */
+public class LoadSaveCameraProperties implements ILoadSaveCameraProperties
+{
+ private final String TAG = toString();
+
+ public static final int MAX_STORE_PROPERTIES = 256; // お気に入り設定の最大記憶数...
+ public static final String TITLE_KEY = "CameraPropTitleKey";
+ public static final String DATE_KEY = "CameraPropDateTime";
+ private static final String TAKEMODE = "TAKEMODE";
+ private final Context parent;
+ private final OLYCamera camera;
+ private final IOlyCameraPropertyProvider propertyProvider;
+
+ LoadSaveCameraProperties(Context context, IOlyCameraPropertyProvider propertyProvider, IOLYCameraObjectProvider provider)
+ {
+ this.camera = provider.getOLYCamera();
+ this.parent = context;
+ this.propertyProvider = propertyProvider;
+ }
+
+ /**
+ * カメラの現在の設定を本体から読みだして記憶する
+ *
+ */
+ @Override
+ public void saveCameraSettings(String idHeader, String dataName)
+ {
+ // カメラから設定を一括で読みだして、Preferenceに記録する
+ if (propertyProvider.isConnected())
+ {
+ Map<String, String> values = null;
+ try
+ {
+ values = propertyProvider.getCameraPropertyValues(camera.getCameraPropertyNames());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ //Log.v(TAG, "CameraPropertyBackupRestore::storeCameraSettings() : " + idHeader);
+
+ if (values != null)
+ {
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+ SharedPreferences.Editor editor = preferences.edit();
+ for (String key : values.keySet())
+ {
+ editor.putString(idHeader + key, values.get(key));
+ //Log.v(TAG, "storeCameraSettings(): " + idHeader + key + " , " + values.get(key));
+ }
+ DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
+ editor.putString(idHeader + DATE_KEY, dateFormat.format(new Date()));
+ editor.putString(idHeader + TITLE_KEY, dataName);
+ //editor.commit();
+ editor.apply();
+
+ Log.v(TAG, "storeCameraSettings() COMMITED : " + idHeader + " [" + dataName + "]");
+ }
+ }
+ }
+
+ /**
+ * Preferenceにあるカメラの設定をカメラに登録する
+ * (注: Read Onlyなパラメータを登録しようとするとエラーになるので注意)
+ */
+ @Override
+ public void loadCameraSettings(String idHeader)
+ {
+ Log.v(TAG, "loadCameraSettings() : START [" + idHeader + "]");
+
+ // Restores my settings.
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
+ if (camera.isConnected())
+ {
+ String takeModeValue = preferences.getString(idHeader + TAKEMODE, null);
+ try
+ {
+ // TAKEMODE だけは先行して設定する(設定できないカメラプロパティもあるので...)
+ if (takeModeValue != null)
+ {
+ camera.setCameraPropertyValue(TAKEMODE, takeModeValue);
+ Log.v(TAG, "loadCameraSettings() TAKEMODE : " + takeModeValue);
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ Log.v(TAG, "loadCameraSettings() : setCameraPropertyValue() fail...");
+ }
+
+ Map<String, String> values = new HashMap<>();
+ Set<String> names = camera.getCameraPropertyNames();
+ for (String name : names)
+ {
+ String value = preferences.getString(idHeader + name, null);
+ if (value != null)
+ {
+ if (propertyProvider.canSetCameraProperty(name))
+ {
+ // Read Onlyのプロパティを除外して登録
+ values.put(name, value);
+ Log.v(TAG, "loadCameraSettings(): " + value);
+ }
+ }
+ }
+ if (values.size() > 0)
+ {
+ try
+ {
+ camera.setCameraPropertyValues(values);
+ }
+ catch (OLYCameraKitException e)
+ {
+ Log.w(TAG, "To change the camera properties is failed: " + e.getMessage());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ Log.v(TAG, "loadCameraSettings() : END [" + idHeader + "]" + " " + values.size());
+ }
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraConnectionListener;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
+
+/**
+ * カメラの接続・切断処理クラス
+ *
+ * https://github.com/googlesamples/android-WearHighBandwidthNetworking/blob/master/Wearable/src/main/java/com/example/android/wearable/wear/wearhighbandwidthnetworking/MainActivity.java
+ *
+ * Created by MRSa on 2017/02/28.
+ */
+class OlyCameraConnection implements IOlyCameraConnection, OLYCameraConnectionListener
+{
+ private final String TAG = toString();
+ private final Activity context;
+ private final OLYCamera camera;
+ private final Executor cameraExecutor = Executors.newFixedThreadPool(1);
+ private final BroadcastReceiver connectionReceiver;
+ private final ICameraStatusReceiver statusReceiver;
+
+ private boolean isWatchingWifiStatus = false;
+
+ private ConnectivityManager connectivityManager;
+ private ConnectivityManager.NetworkCallback networkCallback = null;
+
+ // Handler for dealing with network connection timeouts.
+ private Handler networkConnectionTimeoutHandler;
+
+
+ // Message to notify the network request timout handler that too much time has passed.
+ private static final int MESSAGE_CONNECTIVITY_TIMEOUT = 1;
+
+ // These constants are used by setUiState() to determine what information to display in the UI,
+ // as this app reuses UI components for the various states of the app, which is dependent on
+ // the state of the network.
+ static final int UI_STATE_REQUEST_NETWORK = 1;
+ static final int UI_STATE_REQUESTING_NETWORK = 2;
+ static final int UI_STATE_NETWORK_CONNECTED = 3;
+ static final int UI_STATE_CONNECTION_TIMEOUT = 4;
+ static final int MIN_BANDWIDTH_KBPS = 160;
+
+ // How long the app should wait trying to connect to a sufficient high-bandwidth network before
+ // asking the user to add a new Wi-Fi network.
+ private static final long NETWORK_CONNECTIVITY_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2000);
+
+ // The minimum network bandwidth required by the app for high-bandwidth operations.
+ private static final int MIN_NETWORK_BANDWIDTH_KBPS = 10000;
+
+ // Intent action for sending the user directly to the add Wi-Fi network activity.
+ private static final String ACTION_ADD_NETWORK_SETTINGS = "com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS";
+
+
+ /**
+ * コンストラクタ
+ *
+ */
+ OlyCameraConnection(Activity context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+ {
+ Log.v(TAG, "OlyCameraConnection()");
+ this.context = context;
+ this.camera = camera;
+ this.connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ this.networkConnectionTimeoutHandler = new Handler()
+ {
+ @Override
+ public void handleMessage(Message msg)
+ {
+ switch (msg.what)
+ {
+ case MESSAGE_CONNECTIVITY_TIMEOUT:
+ Log.d(TAG, "Network connection timeout");
+ //setUiState(UI_STATE_CONNECTION_TIMEOUT);
+ unregisterNetworkCallback();
+ break;
+ }
+ }
+ };
+ requestHighBandwidthNetwork();
+/*
+ Network activeNetwork = connectivityManager.getActiveNetwork();
+ if (activeNetwork != null)
+ {
+ int bandwidth = connectivityManager.getNetworkCapabilities(activeNetwork).getLinkDownstreamBandwidthKbps();
+ if (bandwidth < MIN_BANDWIDTH_KBPS)
+ {
+ // Request a high-bandwidth network
+ }
+ }
+ else
+ {
+ // You already are on a high-bandwidth network, so start your network request
+ }
+*/
+
+ this.statusReceiver = statusReceiver;
+ connectionReceiver = new BroadcastReceiver()
+ {
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ onReceiveBroadcastOfConnection(context, intent);
+ }
+ };
+
+ }
+
+ // Determine if there is a high-bandwidth network exists. Checks both the active
+ // and bound networks. Returns false if no network is available (low or high-bandwidth).
+ private boolean isNetworkHighBandwidth()
+ {
+ Network network = connectivityManager.getBoundNetworkForProcess();
+ network = network == null ? connectivityManager.getActiveNetwork() : network;
+ if (network == null)
+ {
+ return (false);
+ }
+
+ // requires android.permission.ACCESS_NETWORK_STATE
+ int bandwidth = connectivityManager.getNetworkCapabilities(network).getLinkDownstreamBandwidthKbps();
+ return (bandwidth >= MIN_NETWORK_BANDWIDTH_KBPS);
+ }
+
+
+
+ private void unregisterNetworkCallback()
+ {
+ if (networkCallback != null)
+ {
+ Log.d(TAG, "Unregistering network callback");
+ connectivityManager.unregisterNetworkCallback(networkCallback);
+ networkCallback = null;
+ }
+ }
+
+ private void releaseHighBandwidthNetwork()
+ {
+ connectivityManager.bindProcessToNetwork(null);
+ unregisterNetworkCallback();
+ }
+
+ private void addWifiNetwork()
+ {
+ // requires android.permission.CHANGE_WIFI_STATE
+ context.getApplicationContext().startActivity(new Intent(ACTION_ADD_NETWORK_SETTINGS));
+ }
+
+
+ /**
+ * Wifiが使える状態だったら、カメラと接続して動作するよ
+ *
+ */
+ private void onReceiveBroadcastOfConnection(Context context, Intent intent)
+ {
+ statusReceiver.onStatusNotify(context.getString(R.string.connect_check_wifi));
+ Log.v(TAG,context.getString(R.string.connect_check_wifi));
+
+ String action = intent.getAction();
+ if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
+ {
+ WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ WifiInfo info = wifiManager.getConnectionInfo();
+ if (wifiManager.isWifiEnabled() && info != null && info.getNetworkId() != -1)
+ {
+ // カメラとの接続処理を行う
+ connectToCamera();
+ }
+ }
+ }
+
+
+ /**
+ * Wifi接続状態の監視
+ * (接続の実処理は onReceiveBroadcastOfConnection() で実施)
+ */
+ @Override
+ public void startWatchWifiStatus(Context context)
+ {
+ Log.v(TAG, "startWatchWifiStatus()");
+ statusReceiver.onStatusNotify("prepare");
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ context.registerReceiver(connectionReceiver, filter);
+ isWatchingWifiStatus = true;
+ }
+
+ /**
+ * Wifi接続状態の監視終了
+ */
+ @Override
+ public void stopWatchWifiStatus(Context context)
+ {
+ Log.v(TAG, "stopWatchWifiStatus()");
+ context.unregisterReceiver(connectionReceiver);
+ isWatchingWifiStatus = false;
+ disconnect(false);
+ }
+
+ /**
+ * Wifi接続状態の監視処理を行っているかどうか
+ *
+ * @return true : 監視中 / false : 停止中
+ */
+ @Override
+ public boolean isWatchWifiStatus() {
+ return (isWatchingWifiStatus);
+ }
+
+ /**
+ * カメラとの接続を解除する
+ *
+ * @param powerOff 真ならカメラの電源オフを伴う
+ */
+ @Override
+ public void disconnect(final boolean powerOff)
+ {
+ Log.v(TAG, "disconnect()");
+ disconnectFromCamera(powerOff);
+ statusReceiver.onCameraDisconnected();
+ }
+
+ /**
+ * カメラとの再接続を指示する
+ */
+ @Override
+ public void connect() {
+ connectToCamera();
+ }
+
+ /**
+ * カメラの通信状態変化を監視するためのインターフェース
+ *
+ * @param camera 例外が発生した OLYCamera
+ * @param e カメラクラスの例外
+ */
+ @Override
+ public void onDisconnectedByError(OLYCamera camera, OLYCameraKitException e)
+ {
+ // カメラが切れた時に通知する
+ statusReceiver.onCameraDisconnected();
+ }
+
+ /**
+ * カメラとの切断処理
+ */
+ private void disconnectFromCamera(final boolean powerOff)
+ {
+ Log.v(TAG, "disconnectFromCamera()");
+ try
+ {
+ cameraExecutor.execute(new CameraDisconnectSequence(camera, powerOff));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * カメラとの接続処理
+ */
+ private void connectToCamera()
+ {
+ Log.v(TAG, "connectToCamera()");
+ try
+ {
+ cameraExecutor.execute(new CameraConnectSequence(context, camera, statusReceiver));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void requestHighBandwidthNetwork()
+ {
+ // Before requesting a high-bandwidth network, ensure prior requests are invalidated.
+ unregisterNetworkCallback();
+
+ Log.d(TAG, "requestHighBandwidthNetwork(): Requesting high-bandwidth network");
+
+ // Requesting an unmetered network may prevent you from connecting to the cellular
+ // network on the user's watch or phone; however, unless you explicitly ask for permission
+ // to a access the user's cellular network, you should request an unmetered network.
+ NetworkRequest request = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .build();
+
+ networkCallback = new ConnectivityManager.NetworkCallback()
+ {
+ @Override
+ public void onAvailable(final Network network)
+ {
+ networkConnectionTimeoutHandler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT);
+ context.runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run() {
+ // requires android.permission.INTERNET
+ if (!connectivityManager.bindProcessToNetwork(network))
+ {
+ Log.e(TAG, "ConnectivityManager.bindProcessToNetwork() requires android.permission.INTERNET");
+ }
+ else
+ {
+ Log.d(TAG, "Network available");
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)
+ {
+ context.runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ Log.d(TAG, "Network capabilities changed");
+ }
+ });
+ }
+
+ @Override
+ public void onLost(Network network)
+ {
+ Log.d(TAG, "Network lost");
+ }
+ };
+
+ // requires android.permission.CHANGE_NETWORK_STATE
+ connectivityManager.requestNetwork(request, networkCallback);
+
+ networkConnectionTimeoutHandler.sendMessageDelayed(networkConnectionTimeoutHandler.obtainMessage(MESSAGE_CONNECTIVITY_TIMEOUT), NETWORK_CONNECTIVITY_TIMEOUT_MS);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.app.Activity;
+import android.graphics.PointF;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraLiveViewListener;
+import jp.co.olympus.camerakit.OLYCameraStatusListener;
+
+import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusDisplay;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
+
+/**
+ * OlyCameraCoordinator : Olympus Air との接続、切断の間をとりもつクラス。
+ * (OLYCameraクラスの実体を保持する)
+ *
+ * 1. クラスを作成する
+ * 2. connectWifi() でカメラと接続する
+ * 3. disconnect() でカメラと切断する
+ *
+ * X. onDisconnectedByError() でカメラの通信状態が変更されたことを受信する
+ * o. CameraInteractionCoordinator.ICameraCallback でカメラとの接続状態を通知する
+ *
+ */
+public class OlyCameraCoordinator implements IOlyCameraCoordinator, IIndicatorControl, ICameraRunMode, IOLYCameraObjectProvider
+{
+ private final String TAG = toString();
+ private final IAutoFocusFrameDisplay focusFrameDisplay;
+ private final ICameraStatusDisplay cameraStatusDisplay;
+ private final OLYCamera camera;
+
+ // 本クラスの配下のカメラ制御クラス群
+ private final AutoFocusControl autoFocus;
+ private final SingleShotControl singleShot;
+ private final OlyCameraPropertyProxy propertyProxy;
+ private final LoadSaveCameraProperties loadSaveCameraProperties;
+ private final OlyCameraConnection cameraConnection;
+
+
+ private boolean isManualFocus = false;
+ private boolean isAutoFocusLocked = false;
+ private boolean isExposureLocked = false;
+
+ /**
+ * コンストラクタ
+ */
+ public OlyCameraCoordinator(Activity context, IAutoFocusFrameDisplay focusFrameDisplay, ICameraStatusDisplay cameraStatusDisplay, ICameraStatusReceiver receiver)
+ {
+ this.focusFrameDisplay = focusFrameDisplay;
+ this.cameraStatusDisplay = cameraStatusDisplay;
+
+ // OLYMPUS CAMERA クラスの初期化、リスナの設定
+ camera = new OLYCamera();
+ camera.setContext(context.getApplicationContext());
+
+ this.cameraConnection = new OlyCameraConnection(context, camera, receiver);
+ camera.setConnectionListener(cameraConnection);
+
+ // 本クラスの配下のカメラ制御クラス群の設定
+ autoFocus = new AutoFocusControl(camera, focusFrameDisplay, this); // AF制御
+ singleShot = new SingleShotControl(camera, focusFrameDisplay, this); // 撮影
+ propertyProxy = new OlyCameraPropertyProxy(camera); // カメラプロパティ
+
+ loadSaveCameraProperties = new LoadSaveCameraProperties(context, propertyProxy, this);
+ }
+
+ /**
+ * ライブビューの設定
+ */
+ public void setLiveViewListener(OLYCameraLiveViewListener listener)
+ {
+ Log.v(TAG, "setLiveViewListener()");
+ try
+ {
+ camera.setLiveViewListener(listener);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * ライブビューの解像度を設定する
+ *
+ */
+ @Override
+ public void changeLiveViewSize(String size)
+ {
+ Log.v(TAG, "changeLiveViewSize() : " + size);
+ try
+ {
+ camera.changeLiveViewSize(CameraPropertyUtilities.toLiveViewSizeType(size));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * ライブビューの開始
+ *
+ */
+ @Override
+ public void startLiveView()
+ {
+ Log.v(TAG, "startLiveView()");
+ try
+ {
+ camera.startLiveView();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * ライブビューの終了
+ *
+ */
+ @Override
+ public void stopLiveView()
+ {
+ Log.v(TAG, "stopLiveView()");
+ try
+ {
+ camera.stopLiveView();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * フォーカスロックの実行
+ */
+ public boolean driveAutoFocus(MotionEvent event)
+ {
+ if (event.getAction() != MotionEvent.ACTION_DOWN)
+ {
+ return (false);
+ }
+ PointF point = focusFrameDisplay.getPointWithEvent(event);
+ return ((focusFrameDisplay.isContainsPoint(point)) && autoFocus.lockAutoFocus(point));
+ }
+
+ /**
+ * フォーカスロックの解除
+ */
+ public void unlockAutoFocus()
+ {
+ autoFocus.unlockAutoFocus();
+ focusFrameDisplay.hideFocusFrame();
+ isAutoFocusLocked = false;
+ }
+
+ /**
+ * 画像を1枚撮影
+ */
+ public void singleShot() {
+ singleShot.singleShot();
+ }
+
+ @Override
+ public void toggleAutoExposure()
+ {
+ try
+ {
+ if (isExposureLocked)
+ {
+ Log.v(TAG, "toggleAutoExposure() : unlockAutoExposure()");
+ camera.unlockAutoExposure();
+ }
+ else
+ {
+ Log.v(TAG, "toggleAutoExposure() : lockAutoExposure()");
+ camera.lockAutoExposure();
+ }
+ updateIndicatorScreen(false);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * AF/MF の切り替えを行う
+ *
+ */
+ @Override
+ public void toggleManualFocus()
+ {
+ try
+ {
+ boolean isHideFocusFrame = false;
+ String property_name = IOlyCameraProperty.FOCUS_STILL;
+ String poverty_value = "<" + IOlyCameraProperty.FOCUS_STILL + "/";
+
+ // マニュアルフォーカス切替え
+ if (!isManualFocus)
+ {
+ // AF -> MF : オートフォーカスを解除して設定する
+ Log.v(TAG, "toggleManualFocus() : to " + IOlyCameraProperty.FOCUS_MF);
+ poverty_value = poverty_value + IOlyCameraProperty.FOCUS_MF + ">";
+ camera.unlockAutoFocus();
+ camera.setCameraPropertyValue(property_name, poverty_value);
+ isHideFocusFrame = true;
+ }
+ else
+ {
+ // MF -> AF
+ Log.v(TAG, "toggleManualFocus() : to " + IOlyCameraProperty.FOCUS_SAF);
+ poverty_value = poverty_value + IOlyCameraProperty.FOCUS_SAF + ">";
+ camera.setCameraPropertyValue(property_name, poverty_value);
+ }
+ updateIndicatorScreen(isHideFocusFrame);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void updateIndicatorScreen(boolean isHideFocusFrame)
+ {
+ isManualFocus();
+ if (isHideFocusFrame)
+ {
+ isAutoFocusLocked = false;
+ focusFrameDisplay.hideFocusFrame();
+ }
+ cameraStatusDisplay.updateCameraStatus();
+ }
+
+ @Override
+ public boolean isManualFocus()
+ {
+ isManualFocus = propertyProxy.isManualFocus();
+ return (isManualFocus);
+ }
+
+ @Override
+ public boolean isAFLock()
+ {
+ return (isAutoFocusLocked);
+ }
+
+ @Override
+ public boolean isAELock()
+ {
+ isExposureLocked = propertyProxy.isExposureLocked();
+ return (isExposureLocked);
+ }
+
+ @Override
+ public void setCameraStatusListener(OLYCameraStatusListener listener)
+ {
+ camera.setCameraStatusListener(listener);
+ }
+
+ @Override
+ public String getCameraStatusSummary(ICameraStatusSummary decoder)
+ {
+ return (decoder.geCameraStatusMessage(camera, ""));
+ }
+
+ @Override
+ public void changeRunMode(boolean isRecording)
+ {
+ OLYCamera.RunMode runMode = (isRecording) ? OLYCamera.RunMode.Recording : OLYCamera.RunMode.Playback;
+ Log.v(TAG, "changeRunMode() : " + runMode);
+ try
+ {
+ camera.changeRunMode(runMode);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean isRecordingMode()
+ {
+ boolean isRecordingMode = false;
+ try
+ {
+ OLYCamera.RunMode runMode = camera.getRunMode();
+ isRecordingMode = (runMode == OLYCamera.RunMode.Recording);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ return (isRecordingMode);
+ }
+
+ @Override
+ public IOlyCameraPropertyProvider getCameraPropertyProvider()
+ {
+ return (propertyProxy);
+ }
+
+ @Override
+ public ILoadSaveCameraProperties getLoadSaveCameraProperties()
+ {
+ return (loadSaveCameraProperties);
+ }
+
+ @Override
+ public ICameraRunMode getChangeRunModeExecutor()
+ {
+ return (this);
+ }
+
+ @Override
+ public IOlyCameraConnection getConnectionInterface()
+ {
+ return (cameraConnection);
+ }
+
+ @Override
+ public void onAfLockUpdate(boolean isAfLocked)
+ {
+ isAutoFocusLocked = isAfLocked;
+ updateIndicatorScreen(false);
+ }
+
+ @Override
+ public OLYCamera getOLYCamera()
+ {
+ return (camera);
+ }
+
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.util.Log;
+
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ *
+ */
+class OlyCameraHardwareStatus implements ICameraHardwareStatus
+{
+ private final String TAG = toString();
+ private final OLYCamera camera;
+
+ /**
+ *
+ */
+ OlyCameraHardwareStatus(OLYCamera camera)
+ {
+ this.camera = camera;
+ }
+
+ @Override
+ public String getLensMountStatus()
+ {
+ String message;
+ try
+ {
+ message = camera.getLensMountStatus();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ message = "[UNKNOWN]";
+ }
+ return (message);
+ }
+
+ @Override
+ public String getMediaMountStatus()
+ {
+ String message;
+ try
+ {
+ message = camera.getMediaMountStatus();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ message = "[UNKNOWN]";
+ }
+ return (message);
+ }
+
+ @Override
+ public float getMinimumFocalLength()
+ {
+ float value;
+ try
+ {
+ value = camera.getMinimumFocalLength();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ value = -1.0f;
+ }
+ return (value);
+ }
+
+ @Override
+ public float getMaximumFocalLength()
+ {
+ float value;
+ try
+ {
+ value = camera.getMaximumFocalLength();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ value = -1.0f;
+ }
+ return (value);
+ }
+
+ @Override
+ public float getActualFocalLength()
+ {
+ float value;
+ try
+ {
+ value = camera.getActualFocalLength();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ value = -1.0f;
+ }
+ return (value);
+ }
+
+ @Override
+ public Map<String, Object> inquireHardwareInformation()
+ {
+ try
+ {
+ return (camera.inquireHardwareInformation());
+ }
+ catch (Exception e)
+ {
+ Log.v(TAG, "EXCEPTION : " + e.toString());
+ e.printStackTrace();
+ }
+ return (null);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.util.Log;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ * カメラプロパティをやり取りするクラス (Wrapperクラス)
+ */
+class OlyCameraPropertyProxy implements IOlyCameraPropertyProvider
+{
+ private final String TAG = toString();
+ private final OLYCamera camera;
+ private final OlyCameraHardwareStatus hardwareStatusInterface;
+
+ /**
+ * コンストラクタ
+ *
+ * @param camera OLYCameraクラス
+ */
+ OlyCameraPropertyProxy(OLYCamera camera)
+ {
+ this.camera = camera;
+ this.hardwareStatusInterface = new OlyCameraHardwareStatus(camera);
+ }
+
+ /**
+ * フォーカス状態を知る(MF or AF)
+ * @return true : MF / false : AF
+ */
+ boolean isManualFocus()
+ {
+ boolean isManualFocus = false;
+ try
+ {
+ String value = camera.getCameraPropertyValue(IOlyCameraProperty.FOCUS_STILL);
+ Log.v(TAG, "OlyCameraPropertyProxy::isManualFocus() " + value);
+ isManualFocus = !(value.contains("AF"));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (isManualFocus);
+ }
+
+ /**
+ * AE ロック状態を知る
+ *
+ * @return true : AE Lock / false : AE Unlock
+ */
+ boolean isExposureLocked()
+ {
+ boolean isExposureLocked =false;
+ try
+ {
+ String value = camera.getCameraPropertyValue(IOlyCameraProperty.AE_LOCK_STATE);
+ Log.v(TAG, "OlyCameraPropertyProxy::isExposureLocked() " + value);
+ isExposureLocked = !(value.contains("UNLOCK"));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (isExposureLocked);
+ }
+
+ @Override
+ public Set<String> getCameraPropertyNames()
+ {
+ try
+ {
+ return (camera.getCameraPropertyNames());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public String getCameraPropertyValue(String name)
+ {
+ try
+ {
+ return (camera.getCameraPropertyValue(name));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public Map<String, String> getCameraPropertyValues(Set<String> names)
+ {
+ try
+ {
+ return (camera.getCameraPropertyValues(names));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public String getCameraPropertyTitle(String name)
+ {
+ try
+ {
+ return (camera.getCameraPropertyTitle(name));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public List<String> getCameraPropertyValueList(String name)
+ {
+ try
+ {
+ return (camera.getCameraPropertyValueList(name));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public String getCameraPropertyValueTitle(String propertyValue)
+ {
+ try
+ {
+ return (camera.getCameraPropertyValueTitle(propertyValue));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (null);
+ }
+
+ @Override
+ public void setCameraPropertyValue(String name, String value)
+ {
+ try
+ {
+ camera.setCameraPropertyValue(name, value);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void setCameraPropertyValues(Map<String, String> values)
+ {
+ try
+ {
+ camera.setCameraPropertyValues(values);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean canSetCameraProperty(String name)
+ {
+ try
+ {
+ return (camera.canSetCameraProperty(name));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (false);
+ }
+
+ @Override
+ public boolean isConnected()
+ {
+ try
+ {
+ return (camera.isConnected());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (false);
+ }
+
+ @Override
+ public ICameraHardwareStatus getHardwareStatus()
+ {
+ return (hardwareStatusInterface);
+ }
+
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.olycamerawrapper;
+
+import android.graphics.RectF;
+import android.util.Log;
+
+import java.util.HashMap;
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraAutoFocusResult;
+import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay;
+
+/**
+ * 一枚撮影用のクラス
+ *
+ * Created by MRSa on 2016/06/18.
+ */
+class SingleShotControl implements OLYCamera.TakePictureCallback
+{
+ private final String TAG = toString();
+ private final OLYCamera camera;
+ private final IIndicatorControl indicator;
+ private final IAutoFocusFrameDisplay frameDisplayer;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ SingleShotControl(OLYCamera camera, IAutoFocusFrameDisplay frameInfo, IIndicatorControl indicator)
+ {
+ this.camera = camera;
+ this.indicator = indicator;
+ this.frameDisplayer = frameInfo;
+ }
+
+ /**
+ * 1枚撮影する
+ *
+ */
+ void singleShot()
+ {
+ try
+ {
+ camera.takePicture(new HashMap<String, Object>(), this);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onProgress(OLYCamera olyCamera, OLYCamera.TakingProgress takingProgress, OLYCameraAutoFocusResult olyCameraAutoFocusResult)
+ {
+ if (takingProgress != OLYCamera.TakingProgress.EndFocusing)
+ {
+ return;
+ }
+
+ String result = olyCameraAutoFocusResult.getResult();
+ if (result == null)
+ {
+ Log.v(TAG, "FocusResult is null.");
+ }
+ else switch (result)
+ {
+ case "ok":
+ RectF postFocusFrameRect = olyCameraAutoFocusResult.getRect();
+ if (postFocusFrameRect != null)
+ {
+ showFocusFrame(postFocusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Focused, 0.0);
+ }
+ break;
+
+ case "none":
+ default:
+ hideFocusFrame();
+ break;
+ }
+ }
+
+ @Override
+ public void onCompleted()
+ {
+ try
+ {
+ camera.clearAutoFocusPoint();
+ hideFocusFrame();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onErrorOccurred(Exception e)
+ {
+ try
+ {
+ camera.clearAutoFocusPoint();
+ hideFocusFrame();
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ e.printStackTrace();
+ }
+
+ private void showFocusFrame(RectF rect, IAutoFocusFrameDisplay.FocusFrameStatus status, double duration)
+ {
+ if (frameDisplayer != null)
+ {
+ frameDisplayer.showFocusFrame(rect, status, duration);
+ }
+ indicator.onAfLockUpdate(IAutoFocusFrameDisplay.FocusFrameStatus.Focused == status);
+ }
+
+ private void hideFocusFrame()
+ {
+ if (frameDisplayer != null)
+ {
+ frameDisplayer.hideFocusFrame();
+ }
+ indicator.onAfLockUpdate(false);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.preference;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.util.Log;
+import android.widget.Toast;
+
+import jp.sfjp.gokigen.a01c.R;
+import jp.sfjp.gokigen.a01c.liveview.ICameraStatusDisplay;
+import jp.sfjp.gokigen.a01c.olycamerawrapper.ILoadSaveCameraProperties;
+import jp.sfjp.gokigen.a01c.preference.ICameraPropertyLoadSaveOperations;
+
+/**
+ * カメラプロパティの保存、展開を実行する
+ *
+ *
+ */
+public class CameraPropertyLoadSaveOperations implements ICameraPropertyLoadSaveOperations
+{
+ private final String TAG = toString();
+ private final ILoadSaveCameraProperties loadSaveProperties;
+ private final ICameraStatusDisplay cameraStatusDisplay;
+ private final Activity activity;
+
+ public CameraPropertyLoadSaveOperations(final Activity activity, ILoadSaveCameraProperties loadSaveProperties, ICameraStatusDisplay cameraStatusDisplay)
+ {
+ this.loadSaveProperties = loadSaveProperties;
+ this.cameraStatusDisplay = cameraStatusDisplay;
+ this.activity = activity;
+ }
+
+ @Override
+ public void loadProperties(final String id, final String name)
+ {
+ //Log.v(TAG, "PROPERTY RESTORE ENTER : (" + id + ") " + name);
+
+ //
+ // BUSYダイアログを表示する
+ //
+ final ProgressDialog busyDialog = new ProgressDialog(activity);
+ busyDialog.setMessage(activity.getString(R.string.dialog_start_load_property_message));
+ busyDialog.setTitle(activity.getString(R.string.dialog_start_load_property_title));
+ busyDialog.setIndeterminate(false);
+ busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ busyDialog.show();
+
+ try
+ {
+ Thread thread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ final boolean toast = restoreCameraSettings(id, name);
+ busyDialog.dismiss();
+
+ activity.runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ cameraStatusDisplay.updateCameraStatus();
+
+ // Toast で展開したよのメッセージを表示
+ if (toast)
+ {
+ String restoredMessage = activity.getString(R.string.restored_my_props) + name;
+ Toast.makeText(activity, restoredMessage, Toast.LENGTH_SHORT).show();
+ }
+
+ }
+ });
+
+ }
+ });
+ thread.start();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ //Log.v(TAG, "PROPERTY RESTORE EXIT : (" + id + ") " + name);
+ }
+
+ @Override
+ public void saveProperties(final String id, final String name)
+ {
+ //
+ // BUSYダイアログを表示する
+ //
+ final ProgressDialog busyDialog = new ProgressDialog(activity);
+ busyDialog.setMessage(activity.getString(R.string.dialog_start_save_property_message));
+ busyDialog.setTitle(activity.getString(R.string.dialog_start_save_property_title));
+ busyDialog.setIndeterminate(false);
+ busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ busyDialog.show();
+
+ try
+ {
+ Thread thread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ final boolean toast = storeCameraSettings(id, name);
+ busyDialog.dismiss();
+
+ activity.runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ cameraStatusDisplay.updateCameraStatus();
+
+ // Toast で保存したよのメッセージを表示
+ if (toast)
+ {
+ String storedMessage = activity.getString(R.string.saved_my_props) + name;
+ Toast.makeText(activity, storedMessage, Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ }
+ });
+ thread.start();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ Log.v(TAG, "PROPERTY STORED : " + id + " " + name);
+ }
+
+ private boolean storeCameraSettings(String itemId, String restoredDataName)
+ {
+ boolean toast = false;
+ //Log.v(TAG, "storeCameraSettings() : START");
+ try
+ {
+ if (loadSaveProperties != null)
+ {
+ if (itemId.contentEquals("000"))
+ {
+ Log.v(TAG, "AUTO SAVE DATA AREA...(NOT STORE PROPERTIES)");
+ }
+ else
+ {
+ // データを保管する
+ loadSaveProperties.saveCameraSettings(itemId, restoredDataName);
+ Log.v(TAG, "STORED : (" + itemId + ") " + restoredDataName);
+ toast = true;
+ }
+ }
+ else
+ {
+ Log.v(TAG, "STORE INTERFACE IS NULL...");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ Log.v(TAG, "STORE FAILED...");
+ }
+ //Log.v(TAG, "storeCameraSettings() : END");
+ return (toast);
+ }
+
+ private boolean restoreCameraSettings(String itemId, String restoredDataName)
+ {
+ boolean toast = false;
+ //Log.v(TAG, "restoreCameraSettings() : START");
+ try
+ {
+ if (loadSaveProperties != null)
+ {
+ if (itemId.contentEquals("000"))
+ {
+ loadSaveProperties.loadCameraSettings("");
+ Log.v(TAG, "RESTORED AUTO SAVE DATA...");
+ }
+ else
+ {
+ loadSaveProperties.loadCameraSettings(itemId);
+ Log.v(TAG, "RESTORED : (" + itemId + ") " + restoredDataName);
+ }
+ toast = true;
+ }
+ else
+ {
+ Log.v(TAG, "RESTORE INTERFACE IS NULL...");
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ Log.v(TAG, "RESTORE FAILED...");
+ }
+ //Log.v(TAG, "restoreCameraSettings() : END");
+ return (toast);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.preference;
+
+/**
+ *
+ *
+ *
+ */
+public interface ICameraPropertyAccessor
+{
+ String FRAME_GRID = "frame_grid";
+ String FRAME_GRID_DEFAULT_VALUE = "0";
+
+ String IMAGE_CONVERTER = "image_converter";
+ String IMAGE_CONVERTER_DEFAULT_VALUE = "0";
+
+ String TAKE_MODE = "take_mode";
+ String TAKE_MODE_DEFAULT_VALUE = "P";
+
+ String COLOR_TONE = "color_tone";
+ String COLOR_TONE_DEFAULT_VALUE = "I_FINISH";
+
+ String AE_MODE = "ae_mode";
+ String AE_MODE_DEFAULT_VALUE = "AE_ESP";
+
+ String WB_MODE = "wb_mode";
+ String WB_MODE_DEFAULT_VALUE = "WB_AUTO";
+
+ String EXPOSURE_COMPENSATION = "exposure_compensation";
+ String EXPOSURE_COMPENSATION_DEFAULT_VALUE = "0";
+
+ String SHUTTER_SPEED = "shutter_speed";
+ String SHUTTER_SPEED_DEFAULT_VALUE = "60";
+
+ String APERTURE = "aperture";
+ String APERTURE_DEFAULT_VALUE = "1";
+
+ String ISO_SENSITIVITY = "iso_sensitivity";
+ String ISO_SENSITIVITY_DEFAULT_VALUE = "Auto";
+
+ String LIVE_VIEW_QUALITY = "live_view_quality";
+ String LIVE_VIEW_QUALITY_DEFAULT_VALUE = "VGA";
+
+ String SOUND_VOLUME_LEVEL = "sound_volume_level";
+ String SOUND_VOLUME_LEVEL_DEFAULT_VALUE = "OFF";
+
+ String RAW = "raw";
+ String SHOOT_ONLY_CAMERA = "only_camera";
+
+ String PHONE_CAMERA_ID = "phone_camera_id";
+ String PHONE_CAMERA_ID_DEFAULT_VALUE = "0";
+
+ String PHONE_CAMERA_ROTATION = "camera_rotation";
+ String PHONE_CAMERA_ROTATION_DEFAULT_VALUE = "90";
+
+ String EXIT_APPLICATION = "exit_application";
+
+ String PLAYBACK_CAMERA = "playback_camera";
+ String PLAYBACK_PHONE = "playback_phone";
+
+ String SHOW_SAMPLE_IMAGE = "show_sample_image";
+ String SHOW_SAMPLE_IMAGE_DEFAULT_VALUE = "0";
+
+ String SELECT_SAMPLE_IMAGE = "select_sample_image";
+
+ String USE_CUSTOM_SPLASH = "use_custom_splash";
+ String SELECT_SPLASH_IMAGE = "select_splash_image";
+
+ String SCENE_MANIPULATE_IMAGE = "manipulate_image";
+
+ String SHOW_GRID_STATUS = "show_grid";
+ String SHOW_FOCUS_ASSIST_STATUS = "show_focus_assist";
+
+ int CHOICE_SPLASH_SCREEN = 10;
+ int SELECT_SAMPLE_IMAGE_CODE = 110;
+ int SELECT_SPLASH_IMAGE_CODE = 120;
+
+ String getLiveViewSize();
+ void restoreCameraSettings(Callback callback);
+ void storeCameraSettings(Callback callback);
+
+ interface Callback
+ {
+ void stored(boolean result);
+ void restored(boolean result);
+ }
+}
--- /dev/null
+package jp.sfjp.gokigen.a01c.preference;
+
+interface ICameraPropertyLoadSaveOperations
+{
+ void saveProperties(final String idHeader, final String dataName);
+ void loadProperties(final String idHeader, final String dataName);
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_enabled="false"
+ android:color="@android:color/darker_gray" />
+ <item
+ android:state_selected="true"
+ android:color="@android:color/holo_blue_light" />
+ <item
+ android:state_pressed="true"
+ android:color="@android:color/holo_blue_light" />
+ <item
+ android:color="@android:color/black" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_android_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_android_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_android_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_build_black_18dp" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_build_black_18dp" />
+ <item
+ android:drawable="@drawable/ic_build_white_18dp" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_check_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_check_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_check_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_collections_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_collections_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_collections_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_directions_run_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_directions_run_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_directions_run_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_done_all_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_done_all_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_done_all_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_exposure_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_exposure_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_exposure_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_filter_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_filter_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_filter_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_gavel_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_gavel_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_gavel_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_gps_fixed_white_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_gps_not_fixed_white_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_gps_off_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_book_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_book_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_book_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_burst_mode_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_burst_mode_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_burst_mode_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_camera_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_camera_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_camera_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_camera_alt_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_camera_alt_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_camera_alt_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_description_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_description_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_description_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_explore_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_explore_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_explore_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_grid_on_white_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_grid_on_white_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_grid_off_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_grid_off_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_grid_off_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_grid_off_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_grid_on_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_grid_on_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_grid_on_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_info_outline_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_info_outline_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_info_outline_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_linked_camera_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_linked_camera_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_linked_camera_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_one_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_one_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_one_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_two_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_two_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_two_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_3_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_3_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_3_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_4_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_4_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_4_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_5_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_5_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_5_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_looks_6_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_looks_6_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_looks_6_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_settings_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_settings_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_settings_white_18dp_1x" />
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_switch_camera_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_switch_camera_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_switch_camera_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_iso_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_iso_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_iso_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_motorcycle_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_motorcycle_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_motorcycle_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_pan_tool_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_pan_tool_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_pan_tool_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_pets_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_pets_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_pets_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_power_settings_new_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_power_settings_new_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_power_settings_new_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_radio_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_radio_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_radio_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_timer_white_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_timer_white_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_timer_off_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_timer_3_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_timer_3_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_timer_3_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_timer_off_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_timer_off_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_timer_off_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_timer_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_timer_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_timer_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_wb_sunny_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_wb_sunny_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_wb_sunny_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_wc_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_wc_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_wc_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_zoom_in_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_zoom_in_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_zoom_in_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_selected="true"
+ android:drawable="@drawable/ic_zoom_out_black_18dp_1x" />
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/ic_zoom_out_black_18dp_1x" />
+ <item
+ android:drawable="@drawable/ic_zoom_out_white_18dp_1x" />
+
+</selector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context="jp.sfjp.gokigen.a01c.MainActivity"
+ tools:deviceIds="wear_square">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="2dp"
+ app:layout_box="all">
+
+ <jp.sfjp.gokigen.a01c.liveview.CameraLiveImageView
+ android:id="@+id/liveview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:gravity="top"
+ >
+
+ <TextView
+ android:id="@+id/text_1"
+ android:layout_width="match_parent"
+ android:layout_height="16dp"
+ android:layout_weight="1"
+ android:text="@string/app_name"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_2"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_3"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_4"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/holo_orange_light"
+ android:clickable="true"
+ android:textSize="12sp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ImageButton
+ android:id="@+id/btn_1"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_1" />
+
+ <ImageButton
+ android:id="@+id/btn_2"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_2" />
+
+ <ImageButton
+ android:id="@+id/btn_3"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_3" />
+
+ <ImageButton
+ android:id="@+id/btn_4"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_4" />
+
+ <ImageButton
+ android:id="@+id/btn_5"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_5" />
+
+ <ImageButton
+ android:id="@+id/btn_6"
+ android:layout_width="30dp"
+ android:layout_height="15dp"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_camera_alt" />
+ </LinearLayout>
+ </FrameLayout>
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.wearable.view.BoxInsetLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="jp.sfjp.gokigen.a01c.MainActivity"
+ tools:deviceIds="wear_round">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="1dp"
+ app:layout_box="all">
+
+ <jp.sfjp.gokigen.a01c.liveview.CameraLiveImageView
+ android:id="@+id/liveview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:gravity="top"
+ >
+
+ <TextView
+ android:id="@+id/text_1"
+ android:layout_width="match_parent"
+ android:layout_height="16dp"
+ android:layout_weight="1"
+ android:text="@string/app_name"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_2"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_3"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/white"
+ android:clickable="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/text_4"
+ android:layout_width="match_parent"
+ android:layout_height="14dp"
+ android:layout_weight="1"
+ android:text="@string/text_message_blank"
+ android:textColor="@android:color/holo_orange_light"
+ android:clickable="true"
+ android:textSize="12sp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+ <ImageButton
+ android:background="@null"
+ android:id="@+id/btn_1"
+ android:layout_gravity="bottom"
+ android:layout_height="15dp"
+ android:layout_width="25dp"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_1" />
+ <ImageButton
+ android:background="@null"
+ android:id="@+id/btn_2"
+ android:layout_gravity="bottom"
+ android:layout_height="15dp"
+ android:layout_width="25dp"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_2" />
+ <ImageButton
+ android:background="@null"
+ android:id="@+id/btn_3"
+ android:layout_gravity="bottom"
+ android:layout_height="15dp"
+ android:layout_width="25dp"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_3" />
+ <ImageButton
+ android:background="@null"
+ android:id="@+id/btn_4"
+ android:layout_gravity="bottom"
+ android:layout_height="15dp"
+ android:layout_width="25dp"
+ android:clickable="true"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_4" />
+ <ImageButton
+ android:id="@+id/btn_5"
+ android:layout_width="25dp"
+ android:layout_height="15dp"
+ android:clickable="true"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_looks_5" />
+ <ImageButton
+ android:id="@+id/btn_6"
+ android:layout_width="25dp"
+ android:layout_height="15dp"
+ android:clickable="true"
+ android:layout_gravity="bottom"
+ android:background="@null"
+ android:contentDescription="@string/description_control_button"
+ android:src="@drawable/btn_ic_camera_alt" />
+ </LinearLayout>
+ </FrameLayout>
+
+</android.support.wearable.view.BoxInsetLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">A01c</string>
+ <string name="hello_round">Hello Round World!</string>
+ <string name="hello_square">Hello Square World</string>
+
+ <string name="connect_start">接続開始</string>
+ <string name="connect_check_wifi">Wifi準備中(OS待ち)</string>
+ <string name="connect_connect">接続開始</string>
+ <string name="connect_connected">接続完了!</string>
+ <string name="connect_change_run_mode">カメラ動作モード変更</string>
+ <string name="connect_restore_camera_settings">カメラ設定を展開</string>
+
+ <string name="fatal_cannot_use_camera">Olympus Camera Kitが動作しないモードのため、カメラのリセットが必要です。電源ボタンを8秒以上長押しして、カメラをリセットしてください。</string>
+ <string name="camera_reset_required">カメラ側のリセット操作をお願いします。</string>
+
+ <string name="dialog_title_confirmation">確認</string>
+ <string name="dialog_positive_execute">実行</string>
+ <string name="dialog_negative_cancel">Cancel</string>
+
+ <string name="dialog_message_power_off">カメラ電源断</string>
+
+ <string name="high_temperature_warning">TEMP</string>
+ <string name="exposure_metering_warning">EXP</string>
+ <string name="iso_sensitivity_warning">ISO</string>
+
+ <string name="dialog_start_load_property_message">Please Wait</string>
+ <string name="dialog_start_load_property_title">設定中…</string>
+
+ <string name="dialog_start_save_property_message">Please Wait</string>
+ <string name="dialog_start_save_property_title">保存中…</string>
+
+ <string name="restored_my_props">展開 : </string>
+ <string name="saved_my_props">保存 : </string>
+
+ <string name="description_control_button">ファンクションキー</string>
+ <string name="text_message_blank"> </string>
+
+ <string name="shoot_camera">撮影しました!</string>
+ <string name="message_none">---</string>
+</resources>
--- /dev/null
+<resources>
+ <string name="app_name">A01c</string>
+ <string name="hello_round">Hello Round World!</string>
+ <string name="hello_square">Hello Square World!</string>
+
+ <string name="connect_start">start</string>
+ <string name="connect_check_wifi">check WIFI</string>
+ <string name="connect_connect">connecting</string>
+ <string name="connect_connected">connected</string>
+ <string name="connect_change_run_mode">changeRunMode</string>
+ <string name="connect_restore_camera_settings">restoreCameraSettings</string>
+
+ <string name="fatal_cannot_use_camera">The CameraKit SDK can not work because the running mode of camera is UNKNOWN. So please long press the power button of camera more than 8 seconds. (This is the camera reset operation.) After that turn on the camera power again.</string>
+ <string name="camera_reset_required">The camera reset operation is required.</string>
+
+ <string name="dialog_title_confirmation">Confirmation</string>
+ <string name="dialog_positive_execute">Execute</string>
+ <string name="dialog_negative_cancel">Cancel</string>
+
+ <string name="dialog_message_power_off">Camera power off</string>
+
+ <string name="high_temperature_warning">TEMP</string>
+ <string name="exposure_metering_warning">EXP</string>
+ <string name="iso_sensitivity_warning">ISO</string>
+
+ <string name="dialog_start_load_property_message">Please Wait</string>
+ <string name="dialog_start_load_property_title">Setting Properties…</string>
+
+ <string name="dialog_start_save_property_message">Please Wait</string>
+ <string name="dialog_start_save_property_title">Storing Properties…</string>
+
+ <string name="restored_my_props">Restored Property : </string>
+ <string name="saved_my_props">Saved Property : </string>
+
+ <string name="description_control_button">Control Button</string>
+ <string name="text_message_blank"> </string>
+
+ <string name="shoot_camera">Captured</string>
+ <string name="message_none">---</string>
+</resources>
--- /dev/null
+<resources>
+ <string-array name="android_wear_capabilities">
+ <item>gokigen_wear_air_a01c</item>
+ </string-array>
+</resources>