diff --git a/.gitignore b/.gitignore
index 3a2358d3..9721712b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,20 @@
+<<<<<<< HEAD
+*/.gitignore
+.gradle
+.DS_Store
+
+=======
+>>>>>>> ee3fc3113323afc9bd4b22252aab337033d65f47
# built application files
*.apk
*.ap_
+<<<<<<< HEAD
+=======
# Mac files
.DS_Store
+>>>>>>> ee3fc3113323afc9bd4b22252aab337033d65f47
# files for the dex VM
*.dex
@@ -13,6 +23,34 @@
# generated files
bin/
+<<<<<<< HEAD
+out/
+gen/
+
+# Libraries used by the app
+/libs
+
+# Build stuff (auto-generated by android update project ...)
+build.xml
+ant.properties
+local.properties
+project.properties
+
+# Eclipse project files
+.classpath
+.project
+
+# idea project files
+.idea/
+.idea/.name
+*.iml
+*.ipr
+*.iws
+
+# Gradle-based build
+build/
+
+=======
gen/
# Ignore gradle files
@@ -33,4 +71,5 @@ proguard-project.txt
# Android Studio/IDEA
*.iml
-.idea
\ No newline at end of file
+.idea
+>>>>>>> ee3fc3113323afc9bd4b22252aab337033d65f47
diff --git a/app/build.gradle b/app/build.gradle
index 489ec986..206ae4c3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,16 +17,17 @@ plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
+ id 'androidx.navigation.safeargs.kotlin'
}
android {
- compileSdkVersion 30
- buildToolsVersion "30.0.2"
+ compileSdkVersion 32
+ buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.wordsapp"
minSdkVersion 19
- targetSdkVersion 30
+ targetSdkVersion 32
versionCode 1
versionName "1.0"
@@ -59,4 +60,7 @@ dependencies {
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "com.google.android.material:material:$material_version"
implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version"
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
+ implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index de8ddd12..4588a9f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,16 +24,13 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Words">
-
-
+
-
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/wordsapp/DetailActivity.kt b/app/src/main/java/com/example/wordsapp/DetailActivity.kt
deleted file mode 100644
index 54497552..00000000
--- a/app/src/main/java/com/example/wordsapp/DetailActivity.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.example.wordsapp
-
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
-import com.example.wordsapp.databinding.ActivityDetailBinding
-
-
-class DetailActivity : AppCompatActivity() {
- /**
- * Provides global access to these variables from anywhere in the app
- * via DetailActivity. without needing to create
- * a DetailActivity instance.
- */
- companion object {
- const val LETTER = "letter"
- const val SEARCH_PREFIX = "https://www.google.com/search?q="
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- // Retrieve a binding object that allows you to refer to views by id name
- // Names are converted from snake case to camel case.
- // For example, a View with the id word_one is referenced as binding.wordOne
- val binding = ActivityDetailBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- // Retrieve the LETTER from the Intent extras
- // intent.extras.getString returns String? (String or null)
- // so toString() guarantees that the value will be a String
- val letterId = intent?.extras?.getString(LETTER).toString()
-
- val recyclerView = binding.recyclerView
- recyclerView.layoutManager = LinearLayoutManager(this)
- recyclerView.adapter = WordAdapter(letterId, this)
-
- // Adds a [DividerItemDecoration] between items
- recyclerView.addItemDecoration(
- DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
- )
-
- title = getString(R.string.detail_prefix) + " " + letterId
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/wordsapp/LetterAdapter.kt b/app/src/main/java/com/example/wordsapp/LetterAdapter.kt
index 9243ed04..bfc8c295 100644
--- a/app/src/main/java/com/example/wordsapp/LetterAdapter.kt
+++ b/app/src/main/java/com/example/wordsapp/LetterAdapter.kt
@@ -23,6 +23,7 @@ import android.view.ViewGroup
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.Button
import androidx.annotation.RequiresApi
+import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
@@ -51,9 +52,9 @@ class LetterAdapter :
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LetterViewHolder {
val layout = LayoutInflater
- .from(parent.context)
- .inflate(R.layout.item_view, parent, false)
-
+ .from(parent.context)
+ .inflate(R.layout.item_view, parent, false)
+
// Setup custom accessibility delegate to set the text read
layout.accessibilityDelegate = Accessibility
return LetterViewHolder(layout)
@@ -66,17 +67,10 @@ class LetterAdapter :
val item = list.get(position)
holder.button.text = item.toString()
- // Assigns a [OnClickListener] to the button contained in the [ViewHolder]
holder.button.setOnClickListener {
- val context = holder.view.context
- // Create an intent with a destination of DetailActivity
- val intent = Intent(context, DetailActivity::class.java)
- // Add the selected letter to the intent as extra data
- // The text of Buttons are [CharSequence], a list of characters,
- // so it must be explicitly converted into a [String].
- intent.putExtra(DetailActivity.LETTER, holder.button.text.toString())
- // Start an activity using the data and destination from the Intent.
- context.startActivity(intent)
+ val action = LetterListFragmentDirections
+ .actionLetterListFragmentToWordListFragment(letter = holder.button.text.toString())
+ holder.view.findNavController().navigate(action)
}
}
diff --git a/app/src/main/java/com/example/wordsapp/LetterListFragment.kt b/app/src/main/java/com/example/wordsapp/LetterListFragment.kt
new file mode 100644
index 00000000..da1a388a
--- /dev/null
+++ b/app/src/main/java/com/example/wordsapp/LetterListFragment.kt
@@ -0,0 +1,110 @@
+package com.example.wordsapp
+
+import android.os.Bundle
+import android.view.*
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.example.wordsapp.databinding.FragmentLetterListBinding
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [LetterListFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class LetterListFragment : Fragment() {
+ private var _binding: FragmentLetterListBinding? = null
+ private val binding get() = _binding!!
+ private lateinit var recyclerView: RecyclerView
+ private var isLinearLayoutManager = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setHasOptionsMenu(true)
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ _binding = FragmentLetterListBinding.inflate(inflater, container, false)
+ val view = binding.root
+ return view
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ recyclerView = binding.recyclerView
+ chooseLayout()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ _binding = null
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ inflater.inflate(R.menu.layout_menu, menu)
+
+ val layoutButton = menu.findItem(R.id.action_switch_layout)
+ setIcon(layoutButton)
+ }
+
+ private fun chooseLayout() {
+ when (isLinearLayoutManager) {
+ true -> {
+ recyclerView.layoutManager = LinearLayoutManager(context)
+ recyclerView.adapter = LetterAdapter()
+ }
+ false -> {
+ recyclerView.layoutManager = GridLayoutManager(context, 4)
+ recyclerView.adapter = LetterAdapter()
+ }
+ }
+ }
+
+ private fun setIcon(menuItem: MenuItem?) {
+ if (menuItem == null)
+ return
+
+ // Set the drawable for the menu icon based on which LayoutManager is currently in use
+
+ // An if-clause can be used on the right side of an assignment if all paths return a value.
+ // The following code is equivalent to
+ // if (isLinearLayoutManager)
+ // menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
+ // else menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
+ menuItem.icon =
+ if (isLinearLayoutManager)
+ ContextCompat.getDrawable(this.requireContext(), R.drawable.ic_grid_layout)
+ else ContextCompat.getDrawable(this.requireContext(), R.drawable.ic_linear_layout)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.action_switch_layout -> {
+ // Sets isLinearLayoutManager (a Boolean) to the opposite value
+ isLinearLayoutManager = !isLinearLayoutManager
+ // Sets layout and icon
+ chooseLayout()
+ setIcon(item)
+
+ return true
+ }
+ // Otherwise, do nothing and use the core event handling
+
+ // when clauses require that all possible paths be accounted for explicitly,
+ // for instance both the true and false cases if the value is a Boolean,
+ // or an else to catch all unhandled cases.
+ else -> super.onOptionsItemSelected(item)
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/wordsapp/MainActivity.kt b/app/src/main/java/com/example/wordsapp/MainActivity.kt
index 50c924d2..b93904da 100644
--- a/app/src/main/java/com/example/wordsapp/MainActivity.kt
+++ b/app/src/main/java/com/example/wordsapp/MainActivity.kt
@@ -20,6 +20,9 @@ import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
+import androidx.navigation.NavController
+import androidx.navigation.fragment.NavHostFragment
+import androidx.navigation.ui.setupActionBarWithNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -28,10 +31,10 @@ import com.example.wordsapp.databinding.ActivityMainBinding
/**
* Main Activity and entry point for the app. Displays a RecyclerView of letters.
*/
+
class MainActivity : AppCompatActivity() {
- private lateinit var recyclerView: RecyclerView
- // Keeps track of which LayoutManager is in use for the [RecyclerView]
- private var isLinearLayoutManager = true
+
+ private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -39,73 +42,15 @@ class MainActivity : AppCompatActivity() {
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
- recyclerView = binding.recyclerView
- // Sets the LinearLayoutManager of the recyclerview
- chooseLayout()
- }
-
- /**
- * Sets the LayoutManager for the [RecyclerView] based on the desired orientation of the list.
- */
- private fun chooseLayout() {
- if (isLinearLayoutManager) {
- recyclerView.layoutManager = LinearLayoutManager(this)
- } else {
- recyclerView.layoutManager = GridLayoutManager(this, 4)
- }
- recyclerView.adapter = LetterAdapter()
- }
-
- private fun setIcon(menuItem: MenuItem?) {
- if (menuItem == null)
- return
+ val navHostFragment = supportFragmentManager
+ .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
+ navController = navHostFragment.navController
- // Set the drawable for the menu icon based on which LayoutManager is currently in use
+ setupActionBarWithNavController(navController)
- // An if-clause can be used on the right side of an assignment if all paths return a value.
- // The following code is equivalent to
- // if (isLinearLayoutManager)
- // menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
- // else menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
- menuItem.icon =
- if (isLinearLayoutManager)
- ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
- else ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
}
- /**
- * Initializes the [Menu] to be used with the current [Activity]
- */
- override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.layout_menu, menu)
-
- val layoutButton = menu?.findItem(R.id.action_switch_layout)
- // Calls code to set the icon based on the LinearLayoutManager of the RecyclerView
- setIcon(layoutButton)
-
- return true
- }
-
- /**
- * Determines how to handle interactions with the selected [MenuItem]
- */
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- R.id.action_switch_layout -> {
- // Sets isLinearLayoutManager (a Boolean) to the opposite value
- isLinearLayoutManager = !isLinearLayoutManager
- // Sets layout and icon
- chooseLayout()
- setIcon(item)
-
- return true
- }
- // Otherwise, do nothing and use the core event handling
-
- // when clauses require that all possible paths be accounted for explicitly,
- // for instance both the true and false cases if the value is a Boolean,
- // or an else to catch all unhandled cases.
- else -> super.onOptionsItemSelected(item)
- }
+ override fun onSupportNavigateUp(): Boolean {
+ return navController.navigateUp() || super.onSupportNavigateUp()
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/wordsapp/WordAdapter.kt b/app/src/main/java/com/example/wordsapp/WordAdapter.kt
index fc74f2cd..df2bd907 100644
--- a/app/src/main/java/com/example/wordsapp/WordAdapter.kt
+++ b/app/src/main/java/com/example/wordsapp/WordAdapter.kt
@@ -28,7 +28,7 @@ import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.RecyclerView
/**
- * Adapter for the [RecyclerView] in [DetailActivity].
+ * Adapter for the [RecyclerView] in [WordListFragment].
*/
class WordAdapter(private val letterId: String, context: Context) :
RecyclerView.Adapter() {
@@ -83,15 +83,13 @@ class WordAdapter(private val letterId: String, context: Context) :
// Set the text of the WordViewHolder
holder.button.text = item
-
- // Assigns a [OnClickListener] to the button contained in the [ViewHolder]
holder.button.setOnClickListener {
- val queryUrl: Uri = Uri.parse("${DetailActivity.SEARCH_PREFIX}${item}")
+ val queryUrl: Uri = Uri.parse("${WordListFragment.SEARCH_PREFIX}${item}")
val intent = Intent(Intent.ACTION_VIEW, queryUrl)
context.startActivity(intent)
}
- }
+ }
// Setup custom accessibility delegate to set the text read with
// an accessibility service
companion object Accessibility : View.AccessibilityDelegate() {
diff --git a/app/src/main/java/com/example/wordsapp/WordListFragment.kt b/app/src/main/java/com/example/wordsapp/WordListFragment.kt
new file mode 100644
index 00000000..8bf9319a
--- /dev/null
+++ b/app/src/main/java/com/example/wordsapp/WordListFragment.kt
@@ -0,0 +1,65 @@
+package com.example.wordsapp
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.example.wordsapp.databinding.FragmentLetterListBinding
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+// private const val ARG_PARAM1 = "param1"
+// private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [WordListFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class WordListFragment : Fragment() {
+
+ companion object {
+ const val LETTER = "letter"
+ const val SEARCH_PREFIX = "https://www.google.com/search?q="
+ }
+
+ private var _binding: FragmentLetterListBinding? = null
+ private val binding get() = _binding!!
+
+ private lateinit var letterId: String
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ arguments?.let {
+ letterId = it.getString(LETTER).toString()
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentLetterListBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ val recyclerView = binding.recyclerView
+ recyclerView.layoutManager = LinearLayoutManager(requireContext())
+ recyclerView.adapter = WordAdapter(letterId, requireContext())
+
+ recyclerView.addItemDecoration(
+ DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
+ )
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+}
diff --git a/app/src/main/res/drawable/ic_grid_layout.xml b/app/src/main/res/drawable/ic_grid_layout.xml
index 60a42149..78298cd2 100644
--- a/app/src/main/res/drawable/ic_grid_layout.xml
+++ b/app/src/main/res/drawable/ic_grid_layout.xml
@@ -1,26 +1,9 @@
-
-
-
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
diff --git a/app/src/main/res/drawable/ic_linear_layout.xml b/app/src/main/res/drawable/ic_linear_layout.xml
index a01e25a9..9884aeb8 100644
--- a/app/src/main/res/drawable/ic_linear_layout.xml
+++ b/app/src/main/res/drawable/ic_linear_layout.xml
@@ -1,27 +1,10 @@
-
-
-
-
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 884928d8..a462c3f7 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -15,14 +15,17 @@
-->
-
+ app:defaultNavHost="true"
+ app:navGraph="@navigation/nav_graph"
+ />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_letter_list.xml b/app/src/main/res/layout/fragment_letter_list.xml
new file mode 100644
index 00000000..74978bed
--- /dev/null
+++ b/app/src/main/res/layout/fragment_letter_list.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/fragment_word_list.xml
similarity index 96%
rename from app/src/main/res/layout/activity_detail.xml
rename to app/src/main/res/layout/fragment_word_list.xml
index 93074c8e..6cf10f97 100644
--- a/app/src/main/res/layout/activity_detail.xml
+++ b/app/src/main/res/layout/fragment_word_list.xml
@@ -18,7 +18,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".DetailActivity">
+ tools:context=".WordListFragment">
-
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
new file mode 100644
index 00000000..a9fddcf5
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b3e4004c..bd95c23c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,4 @@
-
-
Words
+ Words That Start With {letter}
Words That Start With
Switch Layout
Look up word in a Browser Search
Show Stored Words
+
+
+ Hello blank fragment
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index c7ead94e..56d39017 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,19 +16,23 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
- appcompat_version = "1.2.0"
- constraintlayout_version = "2.0.2"
- core_ktx_version = "1.3.2"
- kotlin_version = "1.3.72"
- material_version = "1.2.1"
+
+ appcompat_version = "1.4.1"
+ constraintlayout_version = "2.1.3"
+ core_ktx_version = "1.7.0"
+ kotlin_version = "1.6.21"
+ material_version = "1.5.0"
+ nav_version = '2.4.2'
+
}
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4f04f629..c3af661f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip