41 Commits

Author SHA1 Message Date
Michachatz
ae16b12d28 Merge pull request #44 from Michatec/renovate/com.android.application-9.x
Update plugin com.android.application to v9.0.1
2026-02-15 20:39:40 +01:00
renovate[bot]
0697ee0dca Update plugin com.android.application to v9.0.1 2026-02-15 19:39:32 +00:00
Michachatz
27e324decc Merge pull request #43 from Michatec/renovate/androidx.activity-activity-ktx-1.x
Update dependency androidx.activity:activity-ktx to v1.12.4
2026-02-15 20:39:24 +01:00
Michachatz
618914617e Merge pull request #45 from Michatec/renovate/com.android.library-9.x
Update plugin com.android.library to v9.0.1
2026-02-15 20:39:12 +01:00
renovate[bot]
e81aa10125 Update plugin com.android.library to v9.0.1 2026-02-13 22:32:52 +00:00
renovate[bot]
44d25f92a0 Update dependency androidx.activity:activity-ktx to v1.12.4 2026-02-11 18:14:29 +00:00
Michachatz
95bf0e5c56 Merge pull request #38 from Michatec/renovate/kotlin-monorepo
Update plugin org.jetbrains.kotlin.android to v2.3.10
2026-02-08 12:52:02 +01:00
Michachatz
dddd180136 Merge pull request #39 from Michatec/renovate/androidx.media3-media3-datasource-okhttp-1.x
Update dependency androidx.media3:media3-datasource-okhttp to v1.9.2
2026-02-08 12:51:50 +01:00
Michachatz
46ddd4feca Merge pull request #40 from Michatec/renovate/androidx.media3-media3-exoplayer-1.x
Update dependency androidx.media3:media3-exoplayer to v1.9.2
2026-02-08 12:51:37 +01:00
renovate[bot]
e10c8ed68f Update dependency androidx.media3:media3-exoplayer to v1.9.2 2026-02-08 11:51:24 +00:00
Michachatz
6563820a00 Merge pull request #41 from Michatec/renovate/androidx.media3-media3-exoplayer-hls-1.x
Update dependency androidx.media3:media3-exoplayer-hls to v1.9.2
2026-02-08 12:51:04 +01:00
renovate[bot]
594801238a Update dependency androidx.media3:media3-exoplayer-hls to v1.9.2 2026-02-08 11:50:10 +00:00
renovate[bot]
8a1e0ef6c2 Update dependency androidx.media3:media3-datasource-okhttp to v1.9.2 2026-02-08 11:50:07 +00:00
Michachatz
053db2abaa Merge pull request #42 from Michatec/renovate/androidx.media3-media3-session-1.x
Update dependency androidx.media3:media3-session to v1.9.2
2026-02-08 12:49:48 +01:00
renovate[bot]
7e5d5eb6c1 Update dependency androidx.media3:media3-session to v1.9.2 2026-02-06 13:11:45 +00:00
renovate[bot]
1e1efd422c Update plugin org.jetbrains.kotlin.android to v2.3.10 2026-02-05 10:55:36 +00:00
Michachatz
2c1913896d Merge pull request #29 from Michatec/renovate/androidx.media3-media3-datasource-okhttp-1.x
Update dependency androidx.media3:media3-datasource-okhttp to v1.9.1
2026-01-30 18:56:34 +01:00
Michachatz
026e18ae22 Merge pull request #30 from Michatec/renovate/androidx.media3-media3-exoplayer-1.x
Update dependency androidx.media3:media3-exoplayer to v1.9.1
2026-01-30 18:56:18 +01:00
renovate[bot]
3b6ebe5e1b Update dependency androidx.media3:media3-exoplayer to v1.9.1 2026-01-30 17:55:55 +00:00
Michachatz
26eab4c64c Merge pull request #31 from Michatec/renovate/androidx.media3-media3-exoplayer-hls-1.x
Update dependency androidx.media3:media3-exoplayer-hls to v1.9.1
2026-01-30 18:55:43 +01:00
renovate[bot]
75b3deb210 Update dependency androidx.media3:media3-exoplayer-hls to v1.9.1 2026-01-30 17:55:23 +00:00
renovate[bot]
96389a5c81 Update dependency androidx.media3:media3-datasource-okhttp to v1.9.1 2026-01-30 17:55:19 +00:00
Michachatz
1544c07938 Merge pull request #32 from Michatec/renovate/androidx.media3-media3-session-1.x
Update dependency androidx.media3:media3-session to v1.9.1
2026-01-30 18:54:56 +01:00
Michachatz
65e9d1fed4 Merge pull request #33 from Michatec/renovate/androidx.navigation-navigation-fragment-ktx-2.x
Update dependency androidx.navigation:navigation-fragment-ktx to v2.9.7
2026-01-30 18:54:45 +01:00
renovate[bot]
9bfc1661b8 Update dependency androidx.navigation:navigation-fragment-ktx to v2.9.7 2026-01-30 17:54:21 +00:00
Michachatz
9a379675bf Merge pull request #34 from Michatec/renovate/androidx.navigation-navigation-ui-ktx-2.x
Update dependency androidx.navigation:navigation-ui-ktx to v2.9.7
2026-01-30 18:53:49 +01:00
renovate[bot]
529e359f7f Update dependency androidx.navigation:navigation-ui-ktx to v2.9.7 2026-01-30 17:52:58 +00:00
Michachatz
fc3a1f767a Merge pull request #35 from Michatec/renovate/androidx.activity-activity-ktx-1.x
Update dependency androidx.activity:activity-ktx to v1.12.3
2026-01-30 18:52:45 +01:00
Michachatz
9197e5c2a9 Merge pull request #36 from Michatec/renovate/androidx.work-work-runtime-ktx-2.x
Update dependency androidx.work:work-runtime-ktx to v2.11.1
2026-01-30 18:52:34 +01:00
Michachatz
5920327283 Merge pull request #37 from Michatec/renovate/gradle-9.x
Update Gradle to v9.3.1
2026-01-30 18:52:22 +01:00
renovate[bot]
769cbb505f Update Gradle to v9.3.1 2026-01-29 16:34:13 +00:00
renovate[bot]
1f5d61759c Update dependency androidx.work:work-runtime-ktx to v2.11.1 2026-01-29 04:41:58 +00:00
renovate[bot]
5b1d6d96c7 Update dependency androidx.activity:activity-ktx to v1.12.3 2026-01-29 04:41:54 +00:00
renovate[bot]
606154cfb3 Update dependency androidx.media3:media3-session to v1.9.1 2026-01-26 17:46:05 +00:00
Michatec
9b5c7e3c04 - New version Initialized 2026-01-25 17:07:30 +01:00
Michatec
4466654e92 - Fix unused import 2026-01-25 16:33:45 +01:00
Michatec
b2de7bd534 - Progress Bar added
- CollectionAdapter.kt updated
- File download optimized
- Housekeeping updated
2026-01-25 16:33:17 +01:00
Michatec
d3dfcb98f9 - Layout Changes
- HLS media extraction
2026-01-25 16:08:22 +01:00
Michachatz
0adb906438 Aktualisieren von provider_paths.xml 2026-01-22 06:55:40 +01:00
Michachatz
49e63d3aaa Aktualisieren von shortcuts.xml 2026-01-22 06:55:08 +01:00
Michatec
f892a137ce - Fix .yml 2026-01-21 18:14:38 +01:00
14 changed files with 142 additions and 71 deletions

View File

@@ -51,6 +51,10 @@ jobs:
- name: Check APK path
run: ls -R app/build/outputs/apk
- name: Zipalign APK
run: |
/usr/local/lib/android/sdk/build-tools/34.0.0/zipalign -v -p 4 ${{ env.APK_PATH }} app-release-aligned.apk
- name: Sign APK
env:
SIGN_CERT: ${{ secrets.SIGN_CERT }}
@@ -58,15 +62,10 @@ jobs:
run: |
echo "$SIGN_CERT" | base64 -d > cert.der
echo "$SIGN_KEY" | base64 -d > key.der
mv ${{ env.APK_PATH }} app-release.apk
${{ env.APKSIGNER }} sign --key key.der --cert cert.der app-release.apk
${{ env.APKSIGNER }} sign --key key.der --cert cert.der app-release-aligned.apk
rm cert.der key.der
- name: Zipalign APK
run: |
/usr/local/lib/android/sdk/build-tools/34.0.0/zipalign -v -p 4 app-release.apk app-release-aligned.apk
mv app-release-aligned.apk app-release.apk
- name: Upload artifact
uses: actions/upload-artifact@v6
with:

View File

@@ -19,8 +19,8 @@ android {
applicationId 'com.michatec.radio'
minSdk 28
targetSdk 36
versionCode 140
versionName '14'
versionCode 141
versionName '14.1'
resourceConfigurations += ['en', 'de', 'el', 'nl', 'pl', 'ru','uk', 'ja', 'da', 'fr']
}
@@ -60,17 +60,17 @@ dependencies {
// AndroidX Stuff //
implementation 'androidx.core:core-ktx:1.17.0'
implementation 'androidx.activity:activity-ktx:1.12.2'
implementation 'androidx.activity:activity-ktx:1.12.4'
implementation 'androidx.palette:palette-ktx:1.0.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.media:media:1.7.1'
implementation 'androidx.media3:media3-exoplayer:1.9.0'
implementation 'androidx.media3:media3-exoplayer-hls:1.9.0'
implementation 'androidx.media3:media3-session:1.9.0'
implementation 'androidx.media3:media3-datasource-okhttp:1.9.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.9.6'
implementation 'androidx.navigation:navigation-ui-ktx:2.9.6'
implementation 'androidx.work:work-runtime-ktx:2.11.0'
implementation 'androidx.media3:media3-exoplayer:1.9.2'
implementation 'androidx.media3:media3-exoplayer-hls:1.9.2'
implementation 'androidx.media3:media3-session:1.9.2'
implementation 'androidx.media3:media3-datasource-okhttp:1.9.2'
implementation 'androidx.navigation:navigation-fragment-ktx:2.9.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.9.7'
implementation 'androidx.work:work-runtime-ktx:2.11.1'
// Volley HTTP request //
implementation 'com.android.volley:volley:1.2.1'

View File

@@ -24,7 +24,6 @@ import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.navigateUp
import com.michatec.radio.helpers.AppThemeHelper
import com.michatec.radio.helpers.FileHelper
import com.michatec.radio.helpers.ImportHelper
import com.michatec.radio.helpers.PreferencesHelper
@@ -41,18 +40,6 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// house-keeping: determine if edit stations is enabled by default todo: remove in 2023
if (PreferencesHelper.isHouseKeepingNecessary()) {
// house-keeping 1: remove hard coded default image
ImportHelper.removeDefaultStationImageUris(this)
// house-keeping 2: if existing user detected, enable Edit Stations by default
if (PreferencesHelper.loadCollectionSize() != -1) {
// existing user detected - enable Edit Stations by default
PreferencesHelper.saveEditStationsEnabled(true)
}
PreferencesHelper.saveHouseKeepingNecessaryState()
}
// set up views
setContentView(R.layout.activity_main)

View File

@@ -24,6 +24,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
@@ -193,6 +194,8 @@ class CollectionAdapter(
setStationImage(stationViewHolder, station)
setStationButtons(stationViewHolder, station)
setEditViews(stationViewHolder, station)
setPlaybackProgress(stationViewHolder, station)
setDownloadProgress(stationViewHolder, station)
// show / hide edit views
when (expandedStationPosition) {
@@ -248,6 +251,28 @@ class CollectionAdapter(
}
/* Sets the playback progress view */
private fun setPlaybackProgress(stationViewHolder: StationViewHolder, station: Station) {
if (station.bufferingProgress > 0) {
stationViewHolder.bufferingProgress.progress = station.bufferingProgress
stationViewHolder.bufferingProgress.isVisible = true
} else {
stationViewHolder.bufferingProgress.isGone = true
}
}
/* Sets the download progress view */
private fun setDownloadProgress(stationViewHolder: StationViewHolder, station: Station) {
if (station.downloadProgress > 0) {
stationViewHolder.downloadProgress.progress = station.downloadProgress
stationViewHolder.downloadProgress.isVisible = true
} else {
stationViewHolder.downloadProgress.isGone = true
}
}
/* Sets the edit views */
private fun setEditViews(stationViewHolder: StationViewHolder, station: Station) {
stationViewHolder.stationNameEditView.setText(station.name, TextView.BufferType.EDITABLE)
@@ -471,24 +496,25 @@ class CollectionAdapter(
} else if (holder is StationViewHolder) {
// get station from position
collection.stations[holder.bindingAdapterPosition]
val station: Station = collection.stations[holder.bindingAdapterPosition]
for (data in payloads) {
when (data as Int) {
Keys.HOLDER_UPDATE_COVER -> {
// todo implement
setStationImage(holder, station)
setStarredIcon(holder, station)
}
Keys.HOLDER_UPDATE_NAME -> {
// todo implement
setStationName(holder, station)
}
Keys.HOLDER_UPDATE_PLAYBACK_STATE -> {
// todo implement
setStationButtons(holder, station)
}
Keys.HOLDER_UPDATE_PLAYBACK_PROGRESS -> {
// todo implement
setPlaybackProgress(holder, station)
}
Keys.HOLDER_UPDATE_DOWNLOAD_STATE -> {
// todo implement
setDownloadProgress(holder, station)
}
}
}
@@ -575,21 +601,6 @@ class CollectionAdapter(
}
// /* Initiates update of a station's information */ // todo move to CollectionHelper
// private fun updateStation(context: Context, station: Station) {
// if (station.radioBrowserStationUuid.isNotEmpty()) {
// // get updated station from radio browser - results are handled by onRadioBrowserSearchResults
// val radioBrowserSearch: RadioBrowserSearch = RadioBrowserSearch(context, this)
// radioBrowserSearch.searchStation(context, station.radioBrowserStationUuid, Keys.SEARCH_TYPE_BY_UUID)
// } else if (station.remoteStationLocation.isNotEmpty()) {
// // download playlist // todo check content type detection is necessary here
// DownloadHelper.downloadPlaylists(context, arrayOf(station.remoteStationLocation))
// } else {
// Log.w(TAG, "Unable to update station: ${station.name}.")
// }
// }
/* Determines if position is last */
private fun isPositionFooter(position: Int): Boolean {
return position == collection.stations.size
@@ -600,7 +611,7 @@ class CollectionAdapter(
@SuppressLint("NotifyDataSetChanged")
private fun updateRecyclerView(oldCollection: Collection, newCollection: Collection) {
collection = newCollection
if (oldCollection.stations.size == 0 && newCollection.stations.size > 0) {
if (oldCollection.stations.isEmpty() && newCollection.stations.isNotEmpty()) {
// data set has been initialized - redraw the whole list
notifyDataSetChanged()
} else {
@@ -672,6 +683,8 @@ class CollectionAdapter(
val stationImageView: ImageView = stationCardLayout.findViewById(R.id.station_icon)
val stationNameView: TextView = stationCardLayout.findViewById(R.id.station_name)
val stationStarredView: ImageView = stationCardLayout.findViewById(R.id.starred_icon)
val bufferingProgress: ProgressBar = stationCardLayout.findViewById(R.id.buffering_progress)
val downloadProgress: ProgressBar = stationCardLayout.findViewById(R.id.download_progress)
// val menuButtonView: ImageView = stationCardLayout.findViewById(R.id.menu_button)
val playButtonView: ImageView = stationCardLayout.findViewById(R.id.playback_button)

View File

@@ -48,7 +48,9 @@ data class Station(
@Expose var radioBrowserStationUuid: String = String(),
@Expose var radioBrowserChangeUuid: String = String(),
@Expose var bitrate: Int = 0,
@Expose var codec: String = String()
@Expose var codec: String = String(),
@Expose var bufferingProgress: Int = 0,
@Expose var downloadProgress: Int = 0
) : Parcelable {
@@ -79,6 +81,12 @@ data class Station(
}
/* Getter for media type */
fun getMediaType(): String {
return streamContent
}
/* Creates a deep copy of a Station */
fun deepCopy(): Station {
return Station(
@@ -101,7 +109,9 @@ data class Station(
radioBrowserStationUuid = radioBrowserStationUuid,
radioBrowserChangeUuid = radioBrowserChangeUuid,
bitrate = bitrate,
codec = codec
codec = codec,
bufferingProgress = bufferingProgress,
downloadProgress = downloadProgress
)
}
}

View File

@@ -20,6 +20,8 @@ import androidx.media3.common.Metadata
import androidx.media3.common.util.UnstableApi
import androidx.media3.extractor.metadata.icy.IcyHeaders
import androidx.media3.extractor.metadata.icy.IcyInfo
import androidx.media3.extractor.metadata.id3.Id3Frame
import androidx.media3.extractor.metadata.id3.TextInformationFrame
import com.michatec.radio.Keys
import kotlin.math.min
@@ -37,28 +39,51 @@ object AudioHelper {
/* Extract audio stream metadata */
@OptIn(UnstableApi::class)
fun getMetadataString(metadata: Metadata): String {
var metadataString = String()
var title = ""
var artist = ""
var album = ""
for (i in 0 until metadata.length()) {
// extract IceCast metadata
when (val entry = metadata.get(i)) {
is IcyInfo -> {
metadataString = entry.title.toString()
title = entry.title.toString()
}
is IcyHeaders -> {
Log.i(TAG, "icyHeaders:" + entry.name + " - " + entry.genre)
}
is Id3Frame -> {
when (entry) {
is TextInformationFrame -> {
when (entry.id) {
"TIT2" -> title = entry.values.getOrNull(0) ?: "" // Title
"TPE1" -> artist = entry.values.getOrNull(0) ?: "" // Artist
"TALB" -> album = entry.values.getOrNull(0) ?: "" // Album
}
}
else -> {
Log.d(TAG, "Unhandled ID3 frame: ${entry.javaClass.simpleName}")
}
}
}
else -> {
Log.w(TAG, "Unsupported metadata received (type = ${entry.javaClass.simpleName})")
}
}
// TODO implement HLS metadata extraction (Id3Frame / PrivFrame)
// https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/metadata/Metadata.Entry.html
}
// Build metadata string
var metadataString = title
if (artist.isNotEmpty() && title.isNotEmpty()) {
metadataString = "$artist - $title"
}
if (album.isNotEmpty() && metadataString.isNotEmpty()) {
metadataString += " ($album)"
}
// ensure a max length of the metadata string
if (metadataString.isNotEmpty()) {
metadataString = metadataString.substring(0, min(metadataString.length, Keys.DEFAULT_MAX_LENGTH_OF_METADATA_ENTRY))
metadataString = metadataString.take(min(metadataString.length, Keys.DEFAULT_MAX_LENGTH_OF_METADATA_ENTRY))
}
return metadataString
}

View File

@@ -688,7 +688,6 @@ object CollectionHelper {
/* Creates a MediaItem with MediaMetadata for a single radio station - used to prepare player */
fun buildMediaItem(context: Context, station: Station): MediaItem {
// todo implement HLS MediaItems
// put uri in RequestMetadata - credit: https://stackoverflow.com/a/70103460
val requestMetadata = MediaItem.RequestMetadata.Builder().apply {
setMediaUri(station.getStreamUri().toUri())
@@ -713,7 +712,7 @@ object CollectionHelper {
setMediaId(station.uuid)
setRequestMetadata(requestMetadata)
setMediaMetadata(mediaMetadata)
//setMimeType(station.getMediaType())
setMimeType(station.getMediaType())
setUri(station.getStreamUri().toUri())
}.build()
}

View File

@@ -417,16 +417,14 @@ object FileHelper {
/* Reads InputStream from file uri and returns it as String */
private fun readTextFileFromFile(context: Context): String {
// todo read https://commonsware.com/blog/2016/03/15/how-consume-content-uri.html
// https://developer.android.com/training/secure-file-sharing/retrieve-info
// check if file exists
val file = File(context.getExternalFilesDir(Keys.FOLDER_COLLECTION), Keys.COLLECTION_FILE)
if (!file.exists() || !file.canRead()) {
return String()
}
// read until last line reached
val stream: InputStream = file.inputStream()
val uri = Uri.fromFile(file)
val stream: InputStream = context.contentResolver.openInputStream(uri) ?: return String()
val reader = BufferedReader(InputStreamReader(stream))
val builder: StringBuilder = StringBuilder()
reader.forEachLine {

View File

@@ -14,6 +14,7 @@
package com.michatec.radio.ui
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
@@ -131,6 +132,7 @@ data class LayoutHolder(var rootView: View) {
/* Updates the player views */
@SuppressLint("DefaultLocale")
fun updatePlayerViews(context: Context, station: Station, isPlaying: Boolean) {
// set default metadata views, when playback has stopped
@@ -164,12 +166,20 @@ data class LayoutHolder(var rootView: View) {
// show only the codec when the bitrate is at "0" from radio-browser.info API
station.codec
} else {
val kiloBytesPerSecond = station.bitrate / 8F
val dataRateString = if (kiloBytesPerSecond >= 1000) {
String.format("%.2f mb/s", kiloBytesPerSecond / 1000F)
} else {
String.format("%.0f kb/s", kiloBytesPerSecond)
}
// show the bitrate and codec if the result is available in the radio-browser.info API
buildString {
append(station.codec)
append(" | ")
append(station.bitrate)
append("kbps")
append(" | ")
append(dataRateString)
}
}
} else {

View File

@@ -31,6 +31,21 @@
app:shapeAppearanceOverlay="@style/RoundedCorners"
app:srcCompat="@drawable/ic_default_station_image_72dp" />
<ProgressBar
android:id="@+id/download_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="4dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:progressTint="@color/player_button_background"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@+id/station_icon"
app:layout_constraintStart_toStartOf="@+id/station_icon"
app:layout_constraintTop_toTopOf="@+id/station_icon"
tools:visibility="visible" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/change_image_view"
android:layout_width="0dp"
@@ -155,6 +170,21 @@
app:layout_constraintEnd_toStartOf="@+id/save_button"
app:layout_constraintTop_toTopOf="@+id/save_button" />
<ProgressBar
android:id="@+id/buffering_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="4dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:progressTint="@color/player_button_background"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group
android:id="@+id/default_edit_views"
android:layout_width="0dp"

View File

@@ -2,7 +2,7 @@
<paths>
<external-files-path
name="my_images"
path="Android/data/com.michatec.urlradio/files/Pictures" />
path="Android/data/com.michatec.radio/files/Pictures" />
<external-path
name="external_files"
path="." />

View File

@@ -10,7 +10,7 @@
android:shortcutShortLabel="@string/shortcut_last_station_short_label">
<intent
android:action="com.jamal2367.urlradio.action.START"
android:action="com.michatec.radio.action.START"
android:targetClass="com.michatec.radio.MainActivity"
android:targetPackage="com.michatec.radio">
<extra

View File

@@ -1,9 +1,9 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '9.0.0' apply false
id 'com.android.library' version '9.0.0' apply false
id 'org.jetbrains.kotlin.android' version "2.3.0" apply false
id 'com.android.application' version '9.0.1' apply false
id 'com.android.library' version '9.0.1' apply false
id 'org.jetbrains.kotlin.android' version "2.3.10" apply false
}
tasks.register('clean', Delete) {

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME