OSDN Git Service

4画面同時撮影の準備。
authorMRSa <mrsa@myad.jp>
Sat, 20 Mar 2021 13:34:21 +0000 (22:34 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 20 Mar 2021 13:34:21 +0000 (22:34 +0900)
16 files changed:
app/build.gradle
app/src/main/java/jp/osdn/gokigen/mangle/liveview/LiveImageViewFragment.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/operation/CameraControl.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/ICameraControl.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/imagefile/FileControl.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/imagefile/IImageStore.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/imagefile/ImageStoreExternal.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/imagefile/ImageStoreExternalLegacy.kt
app/src/main/java/jp/osdn/gokigen/mangle/operation/imagefile/ImageStoreLocal.kt
app/src/main/java/jp/osdn/gokigen/mangle/scene/IChangeScene.kt
app/src/main/java/jp/osdn/gokigen/mangle/scene/MainButtonHandler.kt
app/src/main/java/jp/osdn/gokigen/mangle/scene/SceneChanger.kt
app/src/main/res/layout/liveimage_view.xml
build.gradle

index 6847f49..9f97fd1 100644 (file)
@@ -35,16 +35,16 @@ dependencies {
     implementation 'androidx.appcompat:appcompat:1.2.0'
     implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
     implementation 'androidx.preference:preference-ktx:1.1.1'
-    implementation 'com.google.android.material:material:1.2.1'
+    implementation 'com.google.android.material:material:1.3.0'
 
-    testImplementation 'junit:junit:4.12'
+    testImplementation 'junit:junit:4.13.1'
     androidTestImplementation 'androidx.test.ext:junit:1.1.2'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
 
-    def camerax_version = "1.0.0-rc01"
+    def camerax_version = "1.1.0-alpha02"
     implementation "androidx.camera:camera-camera2:$camerax_version"
     implementation "androidx.camera:camera-lifecycle:$camerax_version"
 
-    implementation "androidx.camera:camera-view:1.0.0-alpha20"
-    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha05"
+    implementation "androidx.camera:camera-view:1.0.0-alpha22"
+    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha08"
 }
index e860812..0a6f78f 100644 (file)
@@ -10,36 +10,105 @@ import androidx.fragment.app.Fragment
 import jp.osdn.gokigen.mangle.R
 import jp.osdn.gokigen.mangle.operation.ICameraControl
 
-class LiveImageViewFragment(private val contentLayoutId: Int = R.layout.liveimage_view) : Fragment(contentLayoutId)
+class LiveImageViewFragment(private val contentLayoutId: Int = R.layout.liveimage_view) : Fragment(contentLayoutId), View.OnClickListener
 {
-    private val TAG = toString()
     private lateinit var liveviewView : View
-    private lateinit var cameraControl: ICameraControl
+
+    private lateinit var cameraControl0: ICameraControl
+    private lateinit var cameraControl1: ICameraControl
+    private lateinit var cameraControl2: ICameraControl
+    private lateinit var cameraControl3: ICameraControl
+
+    private var isCameraControl0 = false
+    private var isCameraControl1 = false
+    private var isCameraControl2 = false
+    private var isCameraControl3 = false
 
     companion object
     {
+        private val TAG = LiveImageViewFragment::class.java.simpleName
         fun newInstance() = LiveImageViewFragment().apply { }
     }
 
-    fun setCameraControl(cameraControl : ICameraControl)
+    fun setCameraControl(isCameraControl0 : Boolean, cameraControl0 : ICameraControl, isCameraControl1 : Boolean, cameraControl1 : ICameraControl, isCameraControl2 : Boolean, cameraControl2 : ICameraControl, isCameraControl3 : Boolean, cameraControl3 : ICameraControl)
     {
-        this.cameraControl = cameraControl
+        this.isCameraControl0 = isCameraControl0
+        this.cameraControl0 = cameraControl0
+
+        this.isCameraControl1 = isCameraControl1
+        this.cameraControl1 = cameraControl1
+
+        this.isCameraControl2 = isCameraControl2
+        this.cameraControl2 = cameraControl2
+
+        this.isCameraControl3 = isCameraControl3
+        this.cameraControl3 = cameraControl3
     }
 
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
     {
         if (::liveviewView.isInitialized)
         {
             return (liveviewView)
         }
         liveviewView = inflater.inflate(contentLayoutId, null, false)
-        val imageView = liveviewView.findViewById<LiveImageView>(R.id.liveViewFinder0)
-        if (::cameraControl.isInitialized)
+        liveviewView.findViewById<ImageButton>(R.id.button_camera)?.setOnClickListener(this)
+
+        try
         {
-            liveviewView.findViewById<ImageButton>(R.id.button_camera)?.setOnClickListener(cameraControl.captureButtonReceiver())
+            if (::cameraControl0.isInitialized)
+            {
+                val imageView0 = liveviewView.findViewById<LiveImageView>(R.id.liveViewFinder0)
+                if (isCameraControl0)
+                {
+                    cameraControl0.setRefresher(imageView0, imageView0)
+                }
+                else
+                {
+                    imageView0.visibility = View.GONE
+                }
+            }
+            if (::cameraControl1.isInitialized)
+            {
+                val imageView1 = liveviewView.findViewById<LiveImageView>(R.id.liveViewFinder1)
+                if (isCameraControl1)
+                {
+                    cameraControl1.setRefresher(imageView1, imageView1)
+                }
+                else
+                {
+                    imageView1.visibility = View.GONE
+                }
+            }
+            if (::cameraControl2.isInitialized)
+            {
+                val imageView2 = liveviewView.findViewById<LiveImageView>(R.id.liveViewFinder2)
+                if (isCameraControl2)
+                {
+                    cameraControl2.setRefresher(imageView2, imageView2)
+                }
+                else
+                {
+                    imageView2.visibility = View.GONE
+                }
+            }
+            if (::cameraControl3.isInitialized)
+            {
+                val imageView3 = liveviewView.findViewById<LiveImageView>(R.id.liveViewFinder3)
+                if (isCameraControl3)
+                {
+                    cameraControl3.setRefresher(imageView3, imageView3)
+                }
+                else
+                {
+                    imageView3.visibility = View.GONE
+                }
+            }
+        }
+        catch (e : Exception)
+        {
+            e.printStackTrace()
         }
-        cameraControl.setRefresher(imageView, imageView)
-
         return (liveviewView)
     }
 
@@ -54,4 +123,31 @@ class LiveImageViewFragment(private val contentLayoutId: Int = R.layout.liveimag
         super.onPause()
         Log.v(TAG, " onPause() : ")
     }
+
+    override fun onClick(v: View?)
+    {
+        try
+        {
+            if (::cameraControl0.isInitialized)
+            {
+                cameraControl0.captureButtonReceiver(0).onClick(v)
+            }
+            if (::cameraControl1.isInitialized)
+            {
+                cameraControl1.captureButtonReceiver(1).onClick(v)
+            }
+            if (::cameraControl2.isInitialized)
+            {
+                cameraControl2.captureButtonReceiver(2).onClick(v)
+            }
+            if (::cameraControl3.isInitialized)
+            {
+                cameraControl3.captureButtonReceiver(3).onClick(v)
+            }
+        }
+        catch (e : Exception)
+        {
+            e.printStackTrace()
+        }
+    }
 }
index 033f191..0747f76 100644 (file)
@@ -4,5 +4,5 @@ import android.graphics.Bitmap
 
 interface IStoreImage
 {
-    fun doStore(target: Bitmap? = null)
+    fun doStore(id : Int = 0, target: Bitmap? = null)
 }
index 563776e..3cd8aa5 100644 (file)
@@ -1,6 +1,5 @@
 package jp.osdn.gokigen.mangle.liveview.storeimage
 
-
 import android.content.ContentValues
 import android.database.DatabaseUtils
 import android.graphics.Bitmap
@@ -22,7 +21,7 @@ import java.util.*
 class StoreImage(private val context: FragmentActivity, private val imageProvider: IImageProvider, private val dumpLog : Boolean = false) : IStoreImage
 {
 
-    override fun doStore(target: Bitmap?)
+    override fun doStore(id : Int, target: Bitmap?)
     {
         try
         {
@@ -32,11 +31,11 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
             val isLocalLocation  = PreferenceAccessWrapper(context).getBoolean(IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION, IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE)
             if (isLocalLocation)
             {
-                saveImageLocal(bitmapToStore)
+                saveImageLocal(id, bitmapToStore)
             }
             else
             {
-                saveImageExternal(bitmapToStore)
+                saveImageExternal(id, bitmapToStore)
             }
 
             // 保存処理(プログレスダイアログ(「保存中...」)を削除
@@ -47,7 +46,7 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
         }
     }
 
-    private fun storeImageImpl(target: Bitmap)
+    private fun storeImageImpl(id : Int, target: Bitmap)
     {
 /*
         // 保存処理(プログレスダイアログ(「保存中...」)を表示して処理する)
@@ -78,11 +77,11 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
             val isLocalLocation  = PreferenceAccessWrapper(context).getBoolean(IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION, IPreferencePropertyAccessor.PREFERENCE_SAVE_LOCAL_LOCATION_DEFAULT_VALUE)
             if (isLocalLocation)
             {
-                saveImageLocal(target)
+                saveImageLocal(id, target)
             }
             else
             {
-                saveImageExternal(target)
+                saveImageExternal(id, target)
             }
         }
         catch (t: Throwable)
@@ -103,11 +102,11 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
      *
      * @param targetImage  出力するビットマップイメージ
      */
-    private fun saveImageLocal(targetImage: Bitmap)
+    private fun saveImageLocal(id : Int, targetImage: Bitmap)
     {
         try
         {
-            val fileName = "L" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + ".jpg"
+            val fileName = "L" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + "_" + id + ".jpg"
             val photoFile = File(prepareLocalOutputDirectory(), fileName)
             val outputStream = FileOutputStream(photoFile)
             targetImage.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
@@ -122,7 +121,7 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
 
     private fun getExternalOutputDirectory(): File
     {
-        val directoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path + "/" + context.getString(R.string.app_location) + "/"
+        @Suppress("DEPRECATION") val directoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path + "/" + context.getString(R.string.app_location) + "/"
         val target = File(directoryPath)
         try
         {
@@ -144,14 +143,14 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
      *
      * @param targetImage  出力するビットマップイメージ
      */
-    private fun saveImageExternal(targetImage: Bitmap)
+    private fun saveImageExternal(id : Int, targetImage: Bitmap)
     {
         try
         {
             if (!isExternalStorageWritable())
             {
 
-                saveImageLocal(targetImage)
+                saveImageLocal(id, targetImage)
                 return
             }
 
@@ -160,7 +159,7 @@ class StoreImage(private val context: FragmentActivity, private val imageProvide
             val mimeType = "image/jpeg"
             val now = System.currentTimeMillis()
             val path = Environment.DIRECTORY_DCIM + File.separator + context.getString(R.string.app_location) // Environment.DIRECTORY_PICTURES  + File.separator + "gokigen" //"DCIM/aira01a/"
-            val fileName = "L" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(now) + ".jpg"
+            val fileName = "L" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(now) + "_" + id + ".jpg"
 
             val extStorageUri : Uri
             val values = ContentValues()
index da7e1b9..938c929 100644 (file)
@@ -167,8 +167,16 @@ class CameraControl(private val activity : FragmentActivity, private val accessP
         fileControl.finish()
     }
 
-    override fun captureButtonReceiver() : View.OnClickListener
+    override fun captureButtonReceiver(id : Int) : View.OnClickListener
     {
+        try
+        {
+            fileControl.setId(id)
+        }
+        catch (e : Exception)
+        {
+            e.printStackTrace()
+        }
         return (fileControl)
     }
 
index d8c7372..4523bb0 100644 (file)
@@ -11,5 +11,5 @@ interface ICameraControl
     fun finishCamera()
 
     fun setRefresher(refresher : ILiveViewRefresher, imageView : ILiveView)
-    fun captureButtonReceiver() : View.OnClickListener
+    fun captureButtonReceiver(id : Int = 0) : View.OnClickListener
 }
index 817aa60..d076569 100644 (file)
@@ -16,6 +16,7 @@ class FileControl(private val context: FragmentActivity, private val storeImage
     private val storeLocal = ImageStoreLocal(context)
     private val storeExternal = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { ImageStoreExternal(context, accessRequest) } else { ImageStoreExternalLegacy(context) }
     private var imageCapture: ImageCapture? = null
+    private var addId : Int = 0
 
     fun prepare() : ImageCapture?
     {
@@ -35,6 +36,11 @@ class FileControl(private val context: FragmentActivity, private val storeImage
 
     }
 
+    fun setId(id : Int)
+    {
+        addId = id
+    }
+
     private fun takePhoto()
     {
         Log.v(TAG, " takePhoto()")
@@ -53,7 +59,7 @@ class FileControl(private val context: FragmentActivity, private val storeImage
             if (captureBothCamera)
             {
                 // ライブビュー画像を保管する場合...
-                val thread = Thread { storeImage.doStore() }
+                val thread = Thread { storeImage.doStore(addId) }
                 try
                 {
                     thread.start()
@@ -75,12 +81,12 @@ class FileControl(private val context: FragmentActivity, private val storeImage
             if (!isLocalLocation)
             {
                 // 共用フォルダに保存
-                isStoreLocal = !storeExternal.takePhoto(imageCapture)
+                isStoreLocal = !storeExternal.takePhoto(addId, imageCapture)
             }
             if (isStoreLocal)
             {
                 // アプリ専用フォルダに登録
-                storeLocal.takePhoto(imageCapture)
+                storeLocal.takePhoto(addId, imageCapture)
             }
         }
         catch (e: Exception)
index 462d22b..1dcad5d 100644 (file)
@@ -4,5 +4,5 @@ import androidx.camera.core.ImageCapture
 
 interface IImageStore
 {
-    fun takePhoto(imageCapture : ImageCapture?) : Boolean
+    fun takePhoto(id : Int, imageCapture : ImageCapture?) : Boolean
 }
index b025601..c7f6cfb 100644 (file)
@@ -70,7 +70,7 @@ class ImageStoreExternal(private val context: FragmentActivity, private val acce
         return (uriString)
     }
 
-    override fun takePhoto(imageCapture : ImageCapture?) : Boolean {
+    override fun takePhoto(id : Int, imageCapture : ImageCapture?) : Boolean {
         if ((!isExternalStorageWritable()) || (imageCapture == null)) {
             Log.v(TAG, " takePhotoExternal() : cannot write image to external.")
             return (false)
@@ -88,7 +88,7 @@ class ImageStoreExternal(private val context: FragmentActivity, private val acce
         val now = System.currentTimeMillis()
         val path =
             Environment.DIRECTORY_DCIM + File.separator + context.getString(R.string.app_location) // Environment.DIRECTORY_PICTURES  + File.separator + "gokigen" //"DCIM/aira01a/"
-        val photoFile = "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(now) + ".jpg"
+        val photoFile = "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(now) + "_" + id + ".jpg"
 
         val extStorageUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
         val values = ContentValues()
index 09b0531..278634d 100644 (file)
@@ -32,7 +32,7 @@ class ImageStoreExternalLegacy(private val context: FragmentActivity) : IImageSt
         return (target)
     }
 
-    override fun takePhoto(imageCapture : ImageCapture?) : Boolean
+    override fun takePhoto(id : Int, imageCapture : ImageCapture?) : Boolean
     {
         if ((!isExternalStorageWritable())||(imageCapture == null))
         {
@@ -46,7 +46,7 @@ class ImageStoreExternalLegacy(private val context: FragmentActivity) : IImageSt
             val outputDir = getExternalOutputDirectory()
 
             val mimeType = "image/jpeg"
-            val photoFile = "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + ".jpg"
+            val photoFile = "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + "_" + id + ".jpg"
 
             val extStorageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
 
index cd5eeeb..d579296 100644 (file)
@@ -27,7 +27,7 @@ class ImageStoreLocal(private val context: FragmentActivity)
         return (if (mediaDir != null && mediaDir.exists()) mediaDir else context.filesDir)
     }
 
-    fun takePhoto(imageCapture : ImageCapture?)
+    fun takePhoto(id : Int, imageCapture : ImageCapture?)
     {
         if (imageCapture == null)
         {
@@ -37,7 +37,7 @@ class ImageStoreLocal(private val context: FragmentActivity)
         Log.v(TAG, " takePhotoLocal()")
         try
         {
-            val photoFile = File(prepareLocalOutputDirectory(), "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + ".jpg")
+            val photoFile = File(prepareLocalOutputDirectory(), "P" + SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) + "_" + id + ".jpg")
             val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
             imageCapture.takePicture(
                 outputOptions,
index 16bce4f..779c442 100644 (file)
@@ -4,7 +4,7 @@ interface IChangeScene
 {
     fun initializeFragment()
     fun changeToLiveView()
-    fun changeToPreview()
+    fun connectToCamera()
     fun changeToConfiguration()
     fun changeToDebugInformation()
     fun exitApplication()
index 99655ab..080cead 100644 (file)
@@ -39,7 +39,7 @@ class MainButtonHandler(private val activity : AppCompatActivity) : View.OnClick
     private fun connect()
     {
         Log.v(TAG, " - - - - - - - - - CONNECT - - - - - - - - -")
-        sceneChanger.changeToPreview()
+        sceneChanger.connectToCamera()
     }
 
     private fun camera()
index 8c64d7b..42d89f2 100644 (file)
@@ -51,7 +51,7 @@ class SceneChanger(private val activity: FragmentActivity, private val informati
         if (!::liveviewFragment.isInitialized)
         {
             liveviewFragment = LiveImageViewFragment.newInstance()
-            liveviewFragment.setCameraControl(cameraControl)
+            liveviewFragment.setCameraControl(true, cameraControl,true, cameraControl,true, cameraControl,true, cameraControl)
         }
         setDefaultFragment(liveviewFragment)
         cameraControl.startCamera(false)
@@ -85,13 +85,13 @@ class SceneChanger(private val activity: FragmentActivity, private val informati
         if (!::liveviewFragment.isInitialized)
         {
             liveviewFragment = LiveImageViewFragment.newInstance()
-            liveviewFragment.setCameraControl(cameraControl)
+            liveviewFragment.setCameraControl(true, cameraControl,true, cameraControl,true, cameraControl,true, cameraControl)
         }
         changeFragment(liveviewFragment)
     }
 
 
-    override fun changeToPreview()
+    override fun connectToCamera()
     {
         if (!::previewFragment.isInitialized)
         {
index f94363e..72dda30 100644 (file)
         android:visibility="visible"/>
 
     <view
-        class="jp.osdn.gokigen.mangle.liveview.LiveImageView"
         android:id="@+id/liveViewFinder0"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        class="jp.osdn.gokigen.mangle.liveview.LiveImageView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:scaleType="fitCenter"
+        android:visibility="visible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintLeft_toLeftOf="@id/liveViewFinder1"
+        app:layout_constraintTop_toTopOf="@id/liveViewFinder2" />
+
+    <view
+        class="jp.osdn.gokigen.mangle.liveview.LiveImageView"
+        android:id="@+id/liveViewFinder1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+
+        app:layout_constraintRight_toRightOf="@id/liveViewFinder0"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="@id/liveViewFinder3"
+        app:layout_constraintBottom_toBottomOf="parent"
+
+        android:gravity="center"
+        android:scaleType="fitCenter"
+        android:visibility="visible" />
+
+    <view
+        class="jp.osdn.gokigen.mangle.liveview.LiveImageView"
+        android:id="@+id/liveViewFinder2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintLeft_toLeftOf="@id/liveViewFinder3"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="@id/liveViewFinder0"
+
+        android:gravity="center"
+        android:scaleType="fitCenter"
+        android:visibility="visible" />
+
+    <view
+        class="jp.osdn.gokigen.mangle.liveview.LiveImageView"
+        android:id="@+id/liveViewFinder3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+
+        app:layout_constraintRight_toRightOf="@id/liveViewFinder2"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="@id/liveViewFinder1"
+
+
         android:gravity="center"
         android:scaleType="fitCenter"
         android:visibility="visible" />
index 59f630a..0d9d5d5 100644 (file)
@@ -1,12 +1,12 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 buildscript {
-    ext.kotlin_version = "1.4.21"
+    ext.kotlin_version = "1.4.31"
     repositories {
         google()
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:4.1.1'
+        classpath 'com.android.tools.build:gradle:4.1.3'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
         // NOTE: Do not place your application dependencies here; they belong