OSDN Git Service

「ライブビュー画像を同時に保存」機能を作りこみ開始。
authorMRSa <mrsa@myad.jp>
Sat, 19 Sep 2020 14:36:04 +0000 (23:36 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 19 Sep 2020 14:36:04 +0000 (23:36 +0900)
15 files changed:
app/src/main/java/jp/osdn/gokigen/mangle/liveview/LiveImageViewFragment.kt
app/src/main/java/jp/osdn/gokigen/mangle/liveview/focusframe/FocusFrameDrawer.kt
app/src/main/java/jp/osdn/gokigen/mangle/liveview/image/CameraLiveViewListenerImpl.kt
app/src/main/java/jp/osdn/gokigen/mangle/liveview/storeimage/IStoreImage.kt
app/src/main/java/jp/osdn/gokigen/mangle/liveview/storeimage/StoreImage.kt
app/src/main/java/jp/osdn/gokigen/mangle/logcat/LogCatExporter.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/CameraControl.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/FileControl.kt
app/src/main/java/jp/osdn/gokigen/mangle/preference/IPreferencePropertyAccessor.kt
app/src/main/java/jp/osdn/gokigen/mangle/preference/MainPreferenceFragment.kt
app/src/main/java/jp/osdn/gokigen/mangle/preference/PreferenceValueInitializer.kt
app/src/main/java/jp/osdn/gokigen/mangle/preview/PreviewFragment.kt
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preference_main.xml

index f5a0d74..e860812 100644 (file)
@@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
 import jp.osdn.gokigen.mangle.R
 import jp.osdn.gokigen.mangle.operation.ICameraControl
 
-class LiveImageViewFragment(val contentLayoutId: Int = R.layout.liveimage_view) : Fragment(contentLayoutId)
+class LiveImageViewFragment(private val contentLayoutId: Int = R.layout.liveimage_view) : Fragment(contentLayoutId)
 {
     private val TAG = toString()
     private lateinit var liveviewView : View
index e7e7cc7..54918ad 100644 (file)
@@ -6,7 +6,7 @@ import android.util.DisplayMetrics
 import android.util.TypedValue
 
 
-class FocusFrameDrawer(val context : Context): IFocusFrameDrawer, IFocusFrameControl
+class FocusFrameDrawer(private val context : Context): IFocusFrameDrawer, IFocusFrameControl
 {
     override fun drawFocusFrame(canvas: Canvas)
     {
index af144e4..a0a57ed 100644 (file)
@@ -16,7 +16,7 @@ import java.io.ByteArrayOutputStream
 import java.util.*
 
 
-class CameraLiveViewListenerImpl(val context: Context) : IImageDataReceiver, IImageProvider, ImageAnalysis.Analyzer
+class CameraLiveViewListenerImpl(private val context: Context) : IImageDataReceiver, IImageProvider, ImageAnalysis.Analyzer
 {
     private var cachePics = ArrayList<ByteArray>()
     private var maxCachePics : Int = 0
@@ -184,7 +184,7 @@ class CameraLiveViewListenerImpl(val context: Context) : IImageDataReceiver, IIm
     private fun setupLiveviewCache()
     {
         val preference = PreferenceManager.getDefaultSharedPreferences(context)
-        if ((preference == null)||(!preference.getBoolean(IPreferencePropertyAccessor.CACHE_LIVEVIEW_PICTURES, false)))
+        if ((preference == null)||(!preference.getBoolean(IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES, false)))
         {
             return
         }
index 9a89459..5368927 100644 (file)
@@ -1,19 +1,35 @@
 package jp.osdn.gokigen.mangle.liveview.storeimage
 
+import android.app.Activity
 import android.app.ProgressDialog
 import android.content.Context
 import android.graphics.Bitmap
 import android.os.Environment
+import androidx.fragment.app.FragmentActivity
 import jp.osdn.gokigen.mangle.R
+import jp.osdn.gokigen.mangle.liveview.image.IImageProvider
 import java.io.File
 import java.io.FileOutputStream
 import java.text.SimpleDateFormat
 import java.util.*
 
-class StoreImage(private val context: Context) : IStoreImage
+class StoreImage(private val context: FragmentActivity, private val imageProvider : IImageProvider) : IStoreImage
 {
-    override fun doStore(target: Bitmap)
+    override fun doStore(target: Bitmap?)
     {
+        if (target != null)
+        {
+            storeImageImpl(target)
+        }
+        else
+        {
+            storeImageImpl(imageProvider.getImage())
+        }
+    }
+
+    private fun storeImageImpl(target : Bitmap)
+    {
+/*
         // 保存処理(プログレスダイアログ(「保存中...」)を表示して処理する)
         val saveDialog = ProgressDialog(context)
         saveDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER)
@@ -36,6 +52,15 @@ class StoreImage(private val context: Context) : IStoreImage
             t.printStackTrace()
             System.gc()
         }
+*/
+        try
+        {
+            saveImageImpl(target)
+        }
+        catch (t : Throwable)
+        {
+            t.printStackTrace()
+        }
     }
 
     private fun prepareLocalOutputDirectory(): File
@@ -54,7 +79,7 @@ class StoreImage(private val context: Context) : IStoreImage
     {
         try
         {
-            val fileName = "P" + SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(System.currentTimeMillis()) + ".jpg"
+            val fileName = "L" + SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(System.currentTimeMillis()) + ".jpg"
             val photoFile = File(prepareLocalOutputDirectory(), fileName)
             val outputStream = FileOutputStream(photoFile)
             targetImage.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
@@ -71,7 +96,6 @@ class StoreImage(private val context: Context) : IStoreImage
                 values.put(MediaStore.Images.Media.DATA, fileName)
             }
             resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
-
 */
         }
         catch (t: Throwable)
@@ -79,5 +103,4 @@ class StoreImage(private val context: Context) : IStoreImage
             t.printStackTrace()
         }
     }
-
-}
\ No newline at end of file
+}
index 8b2d67b..e309936 100644 (file)
@@ -9,7 +9,7 @@ import android.widget.AdapterView.OnItemLongClickListener
 import jp.osdn.gokigen.mangle.utils.ConfirmationDialog
 import jp.osdn.gokigen.mangle.R
 
-class LogCatExporter(val activity: Activity) : OnItemLongClickListener
+class LogCatExporter(private val activity: Activity) : OnItemLongClickListener
 {
     private val TAG = toString()
 
index 5285812..ec2028f 100644 (file)
@@ -1,7 +1,6 @@
 package jp.osdn.gokigen.mangle.operation
 
 import android.util.Log
-import android.util.Size
 import android.view.Surface
 import android.view.View
 import androidx.camera.core.CameraSelector
@@ -10,21 +9,21 @@ import androidx.camera.core.Preview
 import androidx.camera.lifecycle.ProcessCameraProvider
 import androidx.core.content.ContextCompat
 import androidx.fragment.app.FragmentActivity
-import androidx.preference.PreferenceManager
 import jp.osdn.gokigen.mangle.R
 import jp.osdn.gokigen.mangle.liveview.ILiveView
 import jp.osdn.gokigen.mangle.liveview.ILiveViewRefresher
 import jp.osdn.gokigen.mangle.liveview.image.CameraLiveViewListenerImpl
-import jp.osdn.gokigen.mangle.preference.IPreferencePropertyAccessor
+import jp.osdn.gokigen.mangle.liveview.storeimage.StoreImage
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
 
-class CameraControl(val activity : FragmentActivity) : ICameraControl
+class CameraControl(private val activity : FragmentActivity) : ICameraControl
 {
     private val TAG = toString()
     private lateinit var cameraExecutor: ExecutorService
-    private val fileControl : FileControl = FileControl(activity)
     private lateinit var liveViewListener : CameraLiveViewListenerImpl
+    private lateinit var fileControl : FileControl
+    private lateinit var storeImage : StoreImage
     private var cameraIsStarted = false
 
     init
@@ -37,6 +36,8 @@ class CameraControl(val activity : FragmentActivity) : ICameraControl
         Log.v(TAG, " initialize()")
         liveViewListener = CameraLiveViewListenerImpl(activity)
         cameraExecutor = Executors.newSingleThreadExecutor()
+        storeImage = StoreImage(activity, liveViewListener)
+        fileControl = FileControl(activity, storeImage)
     }
 
     override fun setRefresher(refresher: ILiveViewRefresher, imageView : ILiveView)
index c4f1b38..ed5da0a 100644 (file)
@@ -15,12 +15,13 @@ import androidx.fragment.app.FragmentActivity
 import androidx.preference.PreferenceManager
 import com.google.android.material.snackbar.Snackbar
 import jp.osdn.gokigen.mangle.R
+import jp.osdn.gokigen.mangle.liveview.storeimage.IStoreImage
 import jp.osdn.gokigen.mangle.preference.IPreferencePropertyAccessor
 import java.io.File
 import java.text.SimpleDateFormat
 import java.util.*
 
-class FileControl(private val context: FragmentActivity) : View.OnClickListener
+class FileControl(private val context: FragmentActivity, private val storeImage : IStoreImage) : View.OnClickListener
 {
     private val TAG = toString()
     private val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
@@ -31,7 +32,6 @@ class FileControl(private val context: FragmentActivity) : View.OnClickListener
 
     init
     {
-
     }
 
     fun prepare() : ImageCapture?
@@ -208,10 +208,28 @@ class FileControl(private val context: FragmentActivity) : View.OnClickListener
         Log.v(TAG, " takePhoto()")
         try
         {
-            val isLocalLocation  = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
+            val preference = PreferenceManager.getDefaultSharedPreferences(context)
+            val isLocalLocation  = preference.getBoolean(
                 IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION,
                 IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE
             )
+            val captureBothCamera  = preference.getBoolean(
+                IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW,
+                IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW_DEFAULT_VALUE
+            )
+            if (captureBothCamera)
+            {
+                val thread = Thread(Runnable { storeImage.doStore() })
+                try
+                {
+                    thread.start()
+                }
+                catch (e : Exception)
+                {
+                    e.printStackTrace()
+                }
+            }
+
             if (isLocalLocation)
             {
                 takePhotoLocal()
index 523807c..a760421 100644 (file)
@@ -13,12 +13,18 @@ interface IPreferencePropertyAccessor
         const val PREFERENCE_USE_CAMERA_X_PREVIEW = "use_camera_x_preview"
         const val PREFERENCE_USE_CAMERA_X_PREVIEW_DEFAULT_VALUE = false
 
-        const val CACHE_LIVEVIEW_PICTURES = "cache_liveview_pictures"
-        const val CACHE_LIVEVIEW_PICTURES_DEFAULT_VALUE = false
+        const val CACHE_LIVE_VIEW_PICTURES = "cache_live_view_pictures"
+        const val CACHE_LIVE_VIEW_PICTURES_DEFAULT_VALUE = false
 
         const val NUMBER_OF_CACHE_PICTURES = "nof_cache_pictures"
         const val NUMBER_OF_CACHE_PICTURES_DEFAULT_VALUE = "500"
 
+        const val CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW = "capture_both_camera_and_live_view"
+        const val CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW_DEFAULT_VALUE = false
+
+        const val CAPTURE_ONLY_LIVE_VIEW = "capture_only_live_view"
+        const val CAPTURE_ONLY_LIVE_VIEW_DEFAULT_VALUE = false
+
         // --- SCREEN TRANSACTION LABEL ---
         const val LABEL_EXIT_APPLICATION = "exit_application"
         const val LABEL_WIFI_SETTINGS = "wifi_settings"
@@ -26,11 +32,9 @@ interface IPreferencePropertyAccessor
         const val LABEL_PRIVACY_POLICY = "privacy_policy"
         const val LABEL_DEBUG_INFO = "debug_info"
 
-
         // --- HIDDEN
         const val SHOW_GRID_STATUS = "show_grid"
         const val SHOW_GRID_STATUS_DEFAULT_VALUE = false
-
     }
 
 }
index 2dce875..0b82037 100644 (file)
@@ -62,6 +62,9 @@ class MainPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceCha
             IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS_DEFAULT_VALUE)
             IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW_DEFAULT_VALUE)
             IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE)
+            IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW_DEFAULT_VALUE)
+            IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES_DEFAULT_VALUE)
+            IPreferencePropertyAccessor.CAPTURE_ONLY_LIVE_VIEW -> value = preferences.getBoolean(key, IPreferencePropertyAccessor.CAPTURE_ONLY_LIVE_VIEW_DEFAULT_VALUE)
             // else -> Log.v(TAG, " onSharedPreferenceChanged() : + $key ")
         }
         Log.v(TAG, " onSharedPreferenceChanged() : + $key, $value")
index ed2b0a2..de8c4ff 100644 (file)
@@ -4,30 +4,66 @@ import android.content.SharedPreferences
 
 class PreferenceValueInitializer
 {
-    fun initializePreferences(preferences : SharedPreferences)
+    fun initializePreferences(preferences: SharedPreferences)
     {
         val items : Map<String, *> = preferences.all
         val editor : SharedPreferences.Editor = preferences.edit()
 
         if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS))
         {
-            editor.putBoolean(IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS, IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS_DEFAULT_VALUE)
+            editor.putBoolean(
+                IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS,
+                IPreferencePropertyAccessor.PREFERENCE_NOTIFICATIONS_DEFAULT_VALUE
+            )
         }
         if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW))
         {
-            editor.putBoolean(IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW, IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW_DEFAULT_VALUE)
+            editor.putBoolean(
+                IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW,
+                IPreferencePropertyAccessor.PREFERENCE_USE_CAMERA_X_PREVIEW_DEFAULT_VALUE
+            )
         }
         if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION))
         {
-            editor.putBoolean(IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION, IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE)
+            editor.putBoolean(
+                IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION,
+                IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE
+            )
         }
         if (!items.containsKey(IPreferencePropertyAccessor.SHOW_GRID_STATUS))
         {
-            editor.putBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, IPreferencePropertyAccessor.SHOW_GRID_STATUS_DEFAULT_VALUE)
+            editor.putBoolean(
+                IPreferencePropertyAccessor.SHOW_GRID_STATUS,
+                IPreferencePropertyAccessor.SHOW_GRID_STATUS_DEFAULT_VALUE
+            )
         }
-        if (!items.containsKey(IPreferencePropertyAccessor.CACHE_LIVEVIEW_PICTURES))
+        if (!items.containsKey(IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES))
         {
-            editor.putBoolean(IPreferencePropertyAccessor.CACHE_LIVEVIEW_PICTURES, IPreferencePropertyAccessor.CACHE_LIVEVIEW_PICTURES_DEFAULT_VALUE)
+            editor.putBoolean(
+                IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES,
+                IPreferencePropertyAccessor.CACHE_LIVE_VIEW_PICTURES_DEFAULT_VALUE
+            )
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.NUMBER_OF_CACHE_PICTURES))
+        {
+            editor.putString(
+                IPreferencePropertyAccessor.NUMBER_OF_CACHE_PICTURES,
+                IPreferencePropertyAccessor.NUMBER_OF_CACHE_PICTURES_DEFAULT_VALUE
+            )
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW))
+        {
+            editor.putBoolean(
+                IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW,
+                IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW_DEFAULT_VALUE
+            )
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_ONLY_LIVE_VIEW))
+        {
+            editor.putBoolean(
+                IPreferencePropertyAccessor.CAPTURE_ONLY_LIVE_VIEW,
+                IPreferencePropertyAccessor.CAPTURE_ONLY_LIVE_VIEW_DEFAULT_VALUE
+            )
         }
         editor.apply()
     }
index dea6fed..37957ae 100644 (file)
@@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment
 import jp.osdn.gokigen.mangle.R
 import jp.osdn.gokigen.mangle.operation.ICameraControl
 
-class PreviewFragment(val contentLayoutId: Int = R.layout.camera_capture) : Fragment(contentLayoutId)
+class PreviewFragment(private val contentLayoutId: Int = R.layout.camera_capture) : Fragment(contentLayoutId)
 {
     private lateinit var previewView : View
     private lateinit var cameraControl: ICameraControl
index 74378e1..8f918d3 100644 (file)
     <string name="data_saving">保存中、お待ちください&#8230;</string>
     <string name="save_image_failure">画像保存に失敗しました。</string>
 
+    <string name="pref_cat_camera">カメラ設定</string>
+    <string name="pref_capture_both_camera_and_live_view">ライブビュー画像を撮影する</string>
+    <string name="pref_summary_capture_both_live_view">シャッターボタンを押すとライブビュー画像を保存します。</string>
+    <string name="pref_capture_only_live_view">カメラのシャッターを使用しない</string>
+    <string name="pref_summary_capture_only_live_view">チェックを入れると、シャッターを押してもカメラ側で撮影を行いません。</string>
+    <string name="pref_cache_live_view_pictures">ライブビュー画像の表示を遅延</string>
+    <string name="pref_summary_cache_live_view_pictures">ライブビュー画像を溜めて表示します。(再起動後に有効)</string>
+    <string name="pref_number_of_cache_pictures">ライブビュー画像の遅延最大数</string>
+    <string name="pref_summary_number_of_cache_pictures">ライブビューを遅らせる画像の最大枚数を指定します。(初期値:500、再起動後に有効)</string>
+
+
 </resources>
index 8c3a41f..0d3e71c 100644 (file)
     <string name="data_saving">Saving&#8230;</string>
     <string name="save_image_failure">Save image is failed.</string>
 
+    <string name="pref_cat_camera">Camera</string>
+    <string name="pref_capture_both_camera_and_live_view">Capture LiveView Image</string>
+    <string name="pref_summary_capture_both_live_view">Captures a LiveView image.</string>
+    <string name="pref_capture_only_live_view">DO NOT USE REMOTE SHUTTER</string>
+    <string name="pref_summary_capture_only_live_view"> </string>
+    <string name="pref_cache_live_view_pictures">Delay live view picture</string>
+    <string name="pref_summary_cache_live_view_pictures">This switch effects after restart. </string>
+    <string name="pref_number_of_cache_pictures">Max number of cache pictures</string>
+    <string name="pref_summary_number_of_cache_pictures">Set number of cache pictures. (Default:500, enables after restart.)</string>
+
 </resources>
\ No newline at end of file
index 02fa612..b67a22a 100644 (file)
     </PreferenceCategory>
 
     <PreferenceCategory
+        android:title="@string/pref_cat_camera">
+        <SwitchPreferenceCompat
+            android:key="capture_both_camera_and_live_view"
+            android:title="@string/pref_capture_both_camera_and_live_view"
+            android:summary="@string/pref_summary_capture_both_live_view"/>
+<!--
+        <SwitchPreferenceCompat
+            android:key="capture_only_live_view"
+            android:title="@string/pref_capture_only_live_view"
+            android:summary="@string/pref_summary_capture_only_live_view" />
+
+        <SwitchPreferenceCompat
+            android:key="cache_live_view_pictures"
+            android:title="@string/pref_cache_live_view_pictures"
+            android:summary="@string/pref_summary_cache_live_view_pictures" />
+
+        <EditTextPreference
+            android:key="number_of_cache_pictures"
+            android:title="@string/pref_number_of_cache_pictures"
+            android:defaultValue="500"
+            android:inputType="numberDecimal"
+            android:digits="0123456789"
+            android:summary="@string/pref_summary_number_of_cache_pictures" />
+-->
+    </PreferenceCategory>
+
+    <PreferenceCategory
         app:title="@string/pref_cat_gokigen">
         <Preference
             android:key="instruction_link"