<option value="$PROJECT_DIR$/app" />
</set>
</option>
- <option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
--- /dev/null
+package net.osdn.gokigen.objectdetection.a01f.liaison
+
+import android.graphics.Canvas
+import android.graphics.RectF
+import android.util.Log
+import jp.osdn.gokigen.gokigenassets.liveview.IAnotherDrawer
+import java.util.ArrayList
+
+class AnotherDrawerHolder : IAnotherDrawer
+{
+ private val drawers = ArrayList<IAnotherDrawer>()
+
+ fun addAnotherDrawer(anotherDrawer: IAnotherDrawer)
+ {
+ try
+ {
+ Log.v(TAG, "add Drawer : ${drawers.size}")
+ drawers.add(anotherDrawer)
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ override fun onDraw(canvas: Canvas?, imageRectF: RectF, rotationDegrees: Int)
+ {
+ try
+ {
+ for (d in drawers)
+ {
+ d.onDraw(canvas, imageRectF, rotationDegrees)
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ companion object
+ {
+ private val TAG = AnotherDrawerHolder::class.java.simpleName
+ }
+}
class CameraLiaison(private val activity: AppCompatActivity, private val informationNotify: IInformationReceiver, private val vibrator : IVibrator, statusReceiver : ICameraStatusReceiver)
{
- private val objectDetectionModel = ObjectDetectionModelReader(activity, 10, 0.5f)
+ private val drawers = AnotherDrawerHolder()
private val cameraProvider = CameraProvider(activity, informationNotify, vibrator, statusReceiver)
private lateinit var cameraControl: ICameraControl // = cameraProvider.getCameraXControl()
+ private lateinit var objectDetectionModel: ObjectDetectionModelReader
+ private lateinit var objectDetectionModel2nd : ObjectDetectionModelReader
init
{
try
{
val preference = PreferenceManager.getDefaultSharedPreferences(activity)
- val connectionIndex = try {
- (preference.getString(
- IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX,
- IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX_DEFAULT_VALUE
- ))?.toInt() ?: 2
+ val connectionIndex =
+ try
+ {
+ (preference.getString(
+ IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX,
+ IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX_DEFAULT_VALUE
+ ))?.toInt() ?: 2
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ 3
+ }
+ val is2ndDetection: Boolean =
+ try
+ {
+ preference.getBoolean(IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL, IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL_DEFAULT_VALUE)
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ false
+ }
+ try
+ {
+ initializeObjectDetectionModel(0)
+ if (is2ndDetection)
+ {
+ initializeObjectDetectionModel(1)
+ }
}
catch (e: Exception)
{
e.printStackTrace()
- 3
}
+
cameraControl = try
{
val items = activity.resources.getStringArray(R.array.connection_method_value)
e.printStackTrace()
cameraProvider.getCameraXControl()
}
+ Log.v(TAG, " setImageProvider... [2nd:$is2ndDetection]")
cameraProvider.setRefresher(objectDetectionModel)
objectDetectionModel.setImageProvider(cameraProvider.getImageProvider())
+ if ((is2ndDetection)&&(::objectDetectionModel2nd.isInitialized))
+ {
+ cameraProvider.setRefresher(objectDetectionModel2nd)
+ objectDetectionModel2nd.setImageProvider(cameraProvider.getImageProvider())
+ }
cameraControl.initialize()
}
catch (e: Exception)
}
}
- fun initialize()
+ private fun initializeObjectDetectionModel(number: Int = 0)
{
try
{
val preference = PreferenceManager.getDefaultSharedPreferences(activity)
- val modelUri = (preference.getString(
- IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE,
- IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE) ?: "").toUri()
- if (!objectDetectionModel.readObjectModel(modelUri))
+ val key =
+ if (number == 0)
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0
+ }
+ else
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1
+ }
+ val defaultValue =
+ if (number == 0)
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_0
+ }
+ else
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_1
+ }
+
+ val maxObjectKey =
+ if (number == 0)
+ {
+ IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_0
+ }
+ else
+ {
+ IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_1
+ }
+ val maxObjectDefaultValue =
+ if (number == 0)
+ {
+ IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_0
+ }
+ else
+ {
+ IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_1
+ }
+ var maxObject: Int = (preference.getString(maxObjectKey, maxObjectDefaultValue) ?: "10").toInt()
+ if ((maxObject <= 0)||(maxObject >= 100))
+ {
+ // オブジェクトの検出数は 1~99 までにする、その範囲を逸脱していた場合は 10 にする
+ maxObject = 10
+ }
+ val modelUri = (preference.getString(key, defaultValue) ?: "").toUri()
+ if (number == 0)
{
- Log.v(TAG, " -=-=-=-=-=-=-=-=-=-=-=-=- Object Detection Model Read Failure... $modelUri -=-=-=-=-=-=-=-=-=-=-=-=- ")
+ if (!::objectDetectionModel.isInitialized)
+ {
+ objectDetectionModel = ObjectDetectionModelReader(activity, id = 0, maxObject, 0.5f)
+ drawers.addAnotherDrawer(objectDetectionModel)
+ }
+ if (!objectDetectionModel.readObjectModel(modelUri))
+ {
+ Log.v(TAG, " -=-=-=-=-=-=-=-=-=-=-=-=- Object Detection Model Read Failure... $modelUri -=-=-=-=-=-=-=-=-=-=-=-=- ")
+ }
+ }
+ else
+ {
+ if (!::objectDetectionModel2nd.isInitialized)
+ {
+ objectDetectionModel2nd = ObjectDetectionModelReader(activity, id = 1, maxObject, 0.5f)
+ drawers.addAnotherDrawer(objectDetectionModel2nd)
+ }
+ if (!objectDetectionModel2nd.readObjectModel(modelUri))
+ {
+ Log.v(TAG, " -=-=-=-=-=-=-=-=-=-=-=-=- Object Detection Model(2nd) Read Failure... $modelUri -=-=-=-=-=-=-=-=-=-=-=-=- ")
+ }
}
}
catch (e: Exception)
{
e.printStackTrace()
}
+ }
+
+
+
+
+ fun initialize()
+ {
try
{
val msg = activity.getString(R.string.app_name)
fun getCameraControl() : ICameraControl { return (cameraControl) }
fun getVibrator() : IVibrator { return (vibrator) }
- fun getAnotherDrawer() : IAnotherDrawer { return (objectDetectionModel) }
+ fun getAnotherDrawer() : IAnotherDrawer { return (drawers) }
fun handleKeyDown(keyCode: Int, event: KeyEvent): Boolean
{
private val cameraConnectionMethodIndex : MutableLiveData<Int> by lazy { MutableLiveData<Int>() }
private val connectionStatus : MutableLiveData<ICameraConnectionStatus.CameraConnectionStatus> by lazy { MutableLiveData<ICameraConnectionStatus.CameraConnectionStatus>() }
+ private val useSecondObjectDetectionModel : MutableLiveData<Boolean> by lazy { MutableLiveData<Boolean>() }
+
val captureBothLvAndCamera: LiveData<Boolean> = captureLiveViewImage
val isCameraConnectionMethodExpanded: LiveData<Boolean> = cameraConnectionMethodExpanded
val cameraConnectionMethodSelectionIndex: LiveData<Int> = cameraConnectionMethodIndex
val cameraConnectionStatus: LiveData<ICameraConnectionStatus.CameraConnectionStatus> = connectionStatus
+ val useSecondObjectDetection: LiveData<Boolean> = useSecondObjectDetectionModel
fun initializePreferences(activity: AppCompatActivity)
{
IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX,
IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX_DEFAULT_VALUE
))?.toInt()
+ useSecondObjectDetectionModel.value = preference.getBoolean(
+ IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL,
+ IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL_DEFAULT_VALUE
+ )
}
catch (e: Exception)
{
}
}
+ fun setUseSecondObjectDetection(value: Boolean)
+ {
+ useSecondObjectDetectionModel.value = value
+ try
+ {
+ val editor: SharedPreferences.Editor = preference.edit()
+ editor.putBoolean(IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL, value)
+ editor.apply()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
fun setIsCameraConnectionMethodExpanded(value: Boolean)
{
cameraConnectionMethodExpanded.value = value
//connectionStatus.value = value
}
- fun getObjectDetectionFileName() : String
+ fun getObjectDetectionFileName(number: Int = 0) : String
{
if (::preference.isInitialized)
{
try
{
- val modeFileString = preference.getString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE) ?: ""
+ val modeFileString =
+ if (number == 0)
+ {
+ preference.getString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_0) ?: ""
+ }
+ else
+ {
+ preference.getString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_1) ?: ""
+ }
val fileName = modeFileString.substring(modeFileString.lastIndexOf("%2F") + "%2f".length)
if (fileName.isNotEmpty())
{
return (" (aohina)")
}
- fun setObjectDetectionFileModel(uri: Uri)
+ fun setObjectDetectionFileModel(uri: Uri, number: Int = 0)
{
if (::preference.isInitialized)
{
try
{
val editor: SharedPreferences.Editor = preference.edit()
- editor.putString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE, uri.toString())
+ val key =
+ if (number == 0)
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0
+ }
+ else
+ {
+ IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1
+ }
+ editor.putString(key, uri.toString())
editor.apply()
}
catch (e: Exception)
const val PREFERENCE_CAMERA_METHOD_INDEX_DEFAULT_VALUE = "1"
// --- PREFERENCE FOR OBJECT DETECTION MODEL FILE
- const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE = "object_detection_model_file"
- const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE = ""
+ const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0 = "object_detection_model_file"
+ const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_0 = ""
+
+ // --- PREFERENCE NUMBER OF OBJECT DETECTION
+ const val PREFERENCE_NUMBER_OF_OBJECT_DETECTION_0 = "number_of_object_detection"
+ const val PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_0 = "10"
+
+ // --- PREFERENCE FOR OBJECT DETECTION MODEL FILE (2nd)
+ const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1 = "object_detection_model_file1"
+ const val PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_1 = ""
+
+ // --- PREFERENCE NUMBER OF OBJECT DETECTION (2nd)
+ const val PREFERENCE_NUMBER_OF_OBJECT_DETECTION_1 = "number_of_object_detection1"
+ const val PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_1 = "10"
+
+ // --- USE SECOND OBJECT DETECTION MODEL
+ const val PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL = "use_second_object_detection_model"
+ const val PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL_DEFAULT_VALUE = false
// --- CAMERA 1 PREFERENCES
const val PREFERENCE_CAMERA_METHOD_1 = "camera_method1"
editor.putString(IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX, IPreferencePropertyAccessor.PREFERENCE_CAMERA_METHOD_INDEX_DEFAULT_VALUE)
}
- if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE))
+ if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0))
{
- editor.putString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE)
+ editor.putString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_0, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_0)
+ }
+
+ if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_0))
+ {
+ editor.putString(IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_0, IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_0)
+ }
+
+ if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1))
+ {
+ editor.putString(IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_1, IPreferencePropertyAccessor.PREFERENCE_OBJECT_DETECTION_MODEL_FILE_DEFAULT_VALUE_1)
+ }
+
+ if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_1))
+ {
+ editor.putString(IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_1, IPreferencePropertyAccessor.PREFERENCE_NUMBER_OF_OBJECT_DETECTION_DEFAULT_VALUE_1)
+ }
+
+ if (!items.containsKey(IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL))
+ {
+ editor.putBoolean(
+ IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL,
+ IPreferencePropertyAccessor.PREFERENCE_USE_SECOND_OBJECT_DETECTION_MODEL_DEFAULT_VALUE
+ )
}
editor.apply()
import java.nio.ByteOrder
import kotlin.math.abs
-class ObjectDetectionModelReader(private val activity: AppCompatActivity, private val max_detect_objects: Int = 10, private val confidence_level: Float = 0.5f) : IAnotherDrawer, ILiveViewRefresher
+class ObjectDetectionModelReader(private val activity: AppCompatActivity, private val id: Int = 0, private val max_detect_objects: Int = 10, private val confidence_level: Float = 0.5f) : IAnotherDrawer, ILiveViewRefresher
{
private val contentResolver = activity.contentResolver
private lateinit var objectDetector: ObjectDetector
readInternalObjectModel()
return (true)
}
- Log.v(TAG, " Requested URI : $uri")
+ Log.v(TAG, " $id Requested URI : $uri")
var size = 0
val cursor = contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE), null, null, null)
//objectDetector = ObjectDetector.createFromBufferAndOptions(ByteBuffer.wrap(data), options)
}
isObjectModelReady = true
- Log.v(TAG, " ----- ObjectDetector is Ready! -----")
+ Log.v(TAG, " ----- ObjectDetector($id) is Ready! -----")
return (true)
}
catch (e: Exception)
if (canvas != null)
{
- Log.v(TAG, "onDraw...")
+ Log.v(TAG, "onDraw($id)...")
val paintText = Paint()
paintText.strokeWidth = 1.0f
}
}
}
- Log.v(TAG, " ----- DETECTED OBJECT : $count")
+ Log.v(TAG, " ----- DETECTED OBJECT($id) : $count")
}
}
catch (e: Throwable)
{
val bitmap = imageProvider.getImage()
targetRectF = RectF(0.0f, 0.0f, (bitmap.width).toFloat(), (bitmap.height).toFloat())
- Log.v(TAG, " - - - - Object Detection (${targetRectF})")
+ Log.v(TAG, " - - - - Object Detection[$id] (${targetRectF})")
detectResults = objectDetector.detect(TensorImage.fromBitmap(bitmap))
- Log.v(TAG, " - - - - Object Detection (results: ${detectResults.size})")
+ Log.v(TAG, " - - - - Object Detection[$id] (results: ${detectResults.size})")
}
else
{
- Log.v(TAG, " - - - - The object detection model is not ready...")
+ Log.v(TAG, " - - - - The object detection model($id) is not ready...")
}
}
catch (e: Throwable)
Spacer(Modifier.size(padding))
Divider(color = Color.LightGray, thickness = 1.dp)
Spacer(Modifier.size(padding))
+ FilePickerForObjectDetectionModel2(prefsModel)
+ Spacer(Modifier.size(padding))
+ Divider(color = Color.LightGray, thickness = 1.dp)
+ Spacer(Modifier.size(padding))
CameraConnectionMethodDropdown(prefsModel, vibrator)
Spacer(Modifier.size(padding))
Divider(color = Color.LightGray, thickness = 1.dp)
val filePickerLauncher = rememberLauncherForActivityResult(GetPickFilePermission()) { modelUri ->
if (modelUri != null)
{
- Log.v("File Pick", "Picked file URI: $modelUri")
+ Log.v("File Pick", "Picked file URI: $modelUri")
+ scope.launch {
+ prefsModel.setObjectDetectionFileModel(modelUri, 0)
+ }
+ }
+ }
+
+ Row (verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(all = 10.dp)) {
+ Text(stringResource(id = R.string.pref_for_object_detection_model_file) + " " + prefsModel.getObjectDetectionFileName(0), modifier = Modifier.clickable { filePickerLauncher.launch("*/*") }, fontSize = with(density) { 18.dp.toSp() })
+ }
+}
+
+@Composable
+fun FilePickerForObjectDetectionModel2(prefsModel: A01fPrefsModel)
+{
+ val density = LocalDensity.current
+ val scope = rememberCoroutineScope()
+ val useSecondObjectDetection = prefsModel.useSecondObjectDetection.observeAsState(initial = prefsModel.useSecondObjectDetection.value ?: false)
+
+ val filePickerLauncher = rememberLauncherForActivityResult(GetPickFilePermission()) { modelUri ->
+ if (modelUri != null)
+ {
+ Log.v("File Pick", "Picked file (2nd) URI: $modelUri")
scope.launch {
- prefsModel.setObjectDetectionFileModel(modelUri)
+ prefsModel.setObjectDetectionFileModel(modelUri, 1)
}
}
}
Row (verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(all = 10.dp)) {
- Text(" " + stringResource(id = R.string.pref_for_object_detection_model_file) + " " + prefsModel.getObjectDetectionFileName(), modifier = Modifier.clickable { filePickerLauncher.launch("*/*") }, fontSize = with(density) { 18.dp.toSp() })
+ Checkbox(
+ checked = useSecondObjectDetection.value,
+ onCheckedChange = {
+ scope.launch {
+ prefsModel.setUseSecondObjectDetection(!useSecondObjectDetection.value)
+ }
+ })
+ Spacer(modifier = Modifier.height(4.dp))
+ Text(stringResource(id = R.string.pref_for_object_detection_model_file2) + " " + prefsModel.getObjectDetectionFileName(1), modifier = Modifier.clickable { filePickerLauncher.launch("*/*") }, fontSize = with(density) { 18.dp.toSp() })
}
}
<string name="pref_instruction_manual_url">https://osdn.net/projects/gokigen/wiki/A01f</string>
<string name="pref_privacy_policy_url">https://osdn.net/projects/gokigen/wiki/PrivacyPolicy</string>
- <string name="pref_for_object_detection_model_file">オブジェクト検出モデル : </string>
+ <string name="pref_for_object_detection_model_file">オブジェクト検出モデル:</string>
+ <string name="pref_for_object_detection_model_file2">オブジェクト検出モデル(2):</string>
<string name="object_detection_model_load_failure">オブジェクト検出モデルが読み込めませんでした。</string>
<!-- Use for jp.osdn.gokigen.constants.IApplicationConstantConvert -->
<string name="pref_instruction_manual_url">https://osdn.net/projects/gokigen/wiki/A01f</string>
<string name="pref_privacy_policy_url">https://osdn.net/projects/gokigen/wiki/PrivacyPolicy</string>
- <string name="pref_for_object_detection_model_file"> Object Detection Model : </string>
+ <string name="pref_for_object_detection_model_file">Object Detection Model:</string>
+ <string name="pref_for_object_detection_model_file2">ObjectDetection Model(2):</string>
<string name="object_detection_model_load_failure">Object Detection Model is not Ready…</string>
<!-- Use for jp.osdn.gokigen.constants.IApplicationConstantConvert -->
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '7.1.3' apply false
- id 'com.android.library' version '7.1.3' apply false
+ id 'com.android.application' version '7.2.0' apply false
+ id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.6.20' apply false
}
#Wed Feb 23 09:24:21 JST 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME