OSDN Git Service

c25d6483a5e1bf9ebf60aa136b4c8ce388790b8b
[gokigen/mangle.git] / app / src / main / java / jp / osdn / gokigen / gokigenassets / utils / imagefile / ImageStoreExternal.kt
1 package jp.osdn.gokigen.gokigenassets.utils.imagefile
2
3 import android.content.ContentValues
4 import android.database.DatabaseUtils
5 import android.net.Uri
6 import android.os.Build
7 import android.os.Environment
8 import android.provider.MediaStore
9 import android.util.Log
10 import android.widget.Toast
11 import androidx.annotation.RequiresApi
12 import androidx.camera.core.ImageCapture
13 import androidx.camera.core.ImageCaptureException
14 import androidx.core.content.ContextCompat
15 import androidx.fragment.app.FragmentActivity
16 import jp.osdn.gokigen.gokigenassets.constants.IStringResourceConstantConvert.Companion.ID_LABEL_APP_LOCATION
17 import jp.osdn.gokigen.gokigenassets.constants.IStringResourceConstantConvert.Companion.ID_MESSAGE_LABEL_CAPTURE_SUCCESS
18 import jp.osdn.gokigen.gokigenassets.constants.IPreferenceConstantConvert.Companion.ID_PREFERENCE_EXTERNAL_STORAGE_LOCATION
19 import jp.osdn.gokigen.gokigenassets.constants.IPreferenceConstantConvert.Companion.ID_PREFERENCE_EXTERNAL_STORAGE_LOCATION_DEFAULT_VALUE
20 import jp.osdn.gokigen.gokigenassets.preference.PreferenceAccessWrapper
21 import java.io.File
22 import java.io.OutputStream
23 import java.text.SimpleDateFormat
24 import java.util.*
25
26 @RequiresApi(api = Build.VERSION_CODES.Q)
27 class ImageStoreExternal(private val context: FragmentActivity) : IImageStore, IImageStoreGrant
28 {
29     private fun getExternalOutputDirectory(): String
30     {
31         var uriString = ""
32         var prefString : String? = ""
33         try
34         {
35             prefString = PreferenceAccessWrapper(context).getString(ID_PREFERENCE_EXTERNAL_STORAGE_LOCATION, ID_PREFERENCE_EXTERNAL_STORAGE_LOCATION_DEFAULT_VALUE)
36             uriString = Uri.decode(prefString)
37             if (uriString.isEmpty())
38             {
39                 // 設定がない場合はデフォルトの場所に...
40                 @Suppress("DEPRECATION")
41                 uriString = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path + "/" + context.getString(ID_LABEL_APP_LOCATION) + "/"
42             }
43         }
44         catch (e : Exception)
45         {
46             e.printStackTrace()
47         }
48
49         try
50         {
51             File(uriString).mkdirs()
52         }
53         catch (e: Exception)
54         {
55             e.printStackTrace()
56         }
57         Log.v(TAG, "  ----- RECORD Directory PATH : ${uriString} : ${prefString} -----")
58         return (uriString)
59     }
60
61     override fun takePhoto(id : Int, imageCapture : ImageCapture?) : Boolean {
62         if ((!isExternalStorageWritable()) || (imageCapture == null)) {
63             Log.v(TAG, " takePhotoExternal() : cannot write image to external.")
64             return (false)
65         }
66         Log.v(TAG, " takePhotoExternal()")
67
68         val outputDirString = getExternalOutputDirectory()
69         if (outputDirString.isEmpty()) {
70             return (false)
71         }
72         val outputDir = File(outputDirString)
73         val resolver = context.contentResolver
74
75         val mimeType = "image/jpeg"
76         val now = System.currentTimeMillis()
77         val path =
78             Environment.DIRECTORY_DCIM + File.separator + context.getString(ID_LABEL_APP_LOCATION) // Environment.DIRECTORY_PICTURES  + File.separator + "gokigen" //"DCIM/aira01a/"
79         val photoFile = "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(now) + "_" + id + ".jpg"
80
81         val extStorageUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
82         val values = ContentValues()
83         values.put(MediaStore.Images.Media.TITLE, photoFile)
84         values.put(MediaStore.Images.Media.DISPLAY_NAME, photoFile)
85         values.put(MediaStore.Images.Media.MIME_TYPE, mimeType)
86         values.put(MediaStore.Images.Media.RELATIVE_PATH, path)
87         values.put(MediaStore.Images.Media.IS_PENDING, true)
88         @Suppress("DEPRECATION")
89         values.put(MediaStore.Images.Media.DATA, outputDir.absolutePath + File.separator + photoFile)
90
91         var imageUri: Uri? = null
92         try
93         {
94             imageUri = resolver.insert(extStorageUri, values)
95         }
96         catch (e: Exception)
97         {
98             e.printStackTrace()
99         }
100         if (imageUri == null)
101         {
102             return (false)
103         }
104
105         /////////////////////////////
106         Log.v(TAG, "  ===== imageUri : $imageUri =====")
107         val cursor = resolver.query(imageUri, null, null, null, null)
108         DatabaseUtils.dumpCursor(cursor)
109         cursor!!.close()
110         /////////////////////////////
111
112         var openStream : OutputStream? = null
113         try
114         {
115             openStream = resolver.openOutputStream(imageUri)
116         }
117         catch (e : Exception)
118         {
119             values.put(MediaStore.Images.Media.IS_PENDING, false)
120             resolver.update(imageUri, values, null, null)
121             e.printStackTrace()
122         }
123
124         try
125         {
126             if (openStream != null)
127             {
128                 val outputOptions = ImageCapture.OutputFileOptions.Builder(openStream).build()
129                 imageCapture.takePicture(
130                     outputOptions,
131                     ContextCompat.getMainExecutor(context),
132                     object : ImageCapture.OnImageSavedCallback {
133                         override fun onError(e: ImageCaptureException) {
134                             Log.e(TAG, "Photo capture failed: ${e.message} ", e)
135                             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
136                                 //values.clear()
137                                 values.put(MediaStore.Images.Media.IS_PENDING, false)
138                                 resolver.update(imageUri, values, null, null)
139                             }
140                             e.printStackTrace()
141                         }
142
143                         override fun onImageSaved(output: ImageCapture.OutputFileResults) {
144                             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
145                                 //values.clear()
146                                 values.put(MediaStore.Images.Media.IS_PENDING, false)
147                                 resolver.update(imageUri, values, null, null)
148                             }
149                             val msg = context.getString(ID_MESSAGE_LABEL_CAPTURE_SUCCESS) + " $path/$photoFile"
150                             Toast.makeText(context.baseContext, msg, Toast.LENGTH_SHORT).show()
151                             //Snackbar.make(
152                             //    context.findViewById<androidx.constraintlayout.widget.ConstraintLayout>(
153                             //        ID_MAIN_ACTIVITY_LAYOUT
154                             //    ), msg, Snackbar.LENGTH_SHORT
155                             //).show()
156                             Log.v(TAG, msg)
157                         }
158                     })
159             }
160             else
161             {
162                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
163                 {
164                     //values.clear()
165                     values.put(MediaStore.Images.Media.IS_PENDING, false)
166                     resolver.update(imageUri, values, null, null)
167                 }
168             }
169         }
170         catch (e : Exception)
171         {
172             e.printStackTrace()
173         }
174          return (true)
175     }
176
177     override fun grantStoreImage()
178     {
179
180     }
181
182     private fun isExternalStorageWritable(): Boolean
183     {
184         return (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED)
185     }
186
187 /*
188     private fun isExternalStorageReadable(): Boolean
189     {
190         return (Environment.getExternalStorageState() in setOf(
191             Environment.MEDIA_MOUNTED,
192             Environment.MEDIA_MOUNTED_READ_ONLY
193         ))
194     }
195 */
196
197     companion object
198     {
199         private val TAG = ImageStoreExternal::class.java.simpleName
200         private const val FILENAME_FORMAT = "yyyyMMdd_HHmmss"
201     }
202
203 }