diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f2c6a58..b84e54d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,8 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) - id("kotlin-kapt") + id("org.jetbrains.kotlin.kapt") + id("androidx.room") } android { @@ -34,6 +35,13 @@ android { kotlinOptions { jvmTarget = "11" } + + buildFeatures { + //noinspection WrongGradleMethod + room { + schemaDirectory("$projectDir/schemas") + } + } } dependencies { @@ -46,13 +54,13 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) - implementation("androidx.room:room-runtime:2.7.1") - implementation("androidx.room:room-ktx:2.7.1") - kapt ("androidx.room:room-compiler:2.7.1") - implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") - implementation ("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0") + // Room dependencies + implementation("androidx.room:room-runtime:2.7.1") // Замените на вашу версию + implementation("androidx.room:room-ktx:2.7.1") // Замените на вашу версию + kapt("androidx.room:room-compiler:2.7.1") // Замените на вашу версию - - -} \ No newline at end of file + // Lifecycle dependencies + implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0") // Замените на вашу версию + implementation ("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0") // Замените на вашу версию +} diff --git a/app/schemas/com.example.timert.AppDatabase/1.json b/app/schemas/com.example.timert.AppDatabase/1.json new file mode 100644 index 0000000..15d2a28 --- /dev/null +++ b/app/schemas/com.example.timert.AppDatabase/1.json @@ -0,0 +1,77 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "87cf8dcd07bc0b2c0a8d52dbb0eca913", + "entities": [ + { + "tableName": "workouts", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `numApproaches` INTEGER NOT NULL, `numExercises` INTEGER NOT NULL, `restBetweenExercises` INTEGER NOT NULL, `restBetweenApproaches` INTEGER NOT NULL, `exerciseDuration` INTEGER NOT NULL, `startTime` INTEGER, `endTime` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "numApproaches", + "columnName": "numApproaches", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "numExercises", + "columnName": "numExercises", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "restBetweenExercises", + "columnName": "restBetweenExercises", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "restBetweenApproaches", + "columnName": "restBetweenApproaches", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exerciseDuration", + "columnName": "exerciseDuration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "startTime", + "columnName": "startTime", + "affinity": "INTEGER" + }, + { + "fieldPath": "endTime", + "columnName": "endTime", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '87cf8dcd07bc0b2c0a8d52dbb0eca913')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 65a73a0..b4f691b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> ) : RecyclerView.Adapter() { + + class WorkoutViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val textViewName: TextView = itemView.findViewById(R.id.textViewName) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkoutViewHolder { + val itemView = LayoutInflater.from(parent.context) + .inflate(R.layout.workout_item, parent, false) + return WorkoutViewHolder(itemView) + } + + override fun onBindViewHolder(holder: WorkoutViewHolder, position: Int) { + val currentItem = workouts[position] + holder.textViewName.text = currentItem.name + } + + override fun getItemCount() = workouts.size +} \ No newline at end of file diff --git a/app/src/main/java/WorkoutDao.kt b/app/src/main/java/WorkoutDao.kt new file mode 100644 index 0000000..26a43f6 --- /dev/null +++ b/app/src/main/java/WorkoutDao.kt @@ -0,0 +1,22 @@ +package com.example.timert + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update + +@Dao +interface WorkoutDao { + @Insert(onConflict = OnConflictStrategy.IGNORE) + suspend fun insertWorkout(workout: Workout): Long + + @Query("SELECT * FROM workouts") + suspend fun getAllWorkouts(): List + + @Query("SELECT * FROM workouts WHERE id = :workoutId") + suspend fun getWorkoutById(workoutId: Int): Workout? + + @Update + suspend fun updateWorkout(workout: Workout) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/timert/History.kt b/app/src/main/java/com/example/timert/History.kt index 2bfbb68..6642667 100644 --- a/app/src/main/java/com/example/timert/History.kt +++ b/app/src/main/java/com/example/timert/History.kt @@ -7,27 +7,24 @@ import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat -import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.example.timert.data.adapter.ExerciseAdapter -import com.example.timert.data.viewModel.ExerciseViewModel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers class History : AppCompatActivity() { + private lateinit var recyclerViewHistory: RecyclerView + private val coroutineScope = CoroutineScope(Dispatchers.IO) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() + setContentView(R.layout.activity_history) + + recyclerViewHistory = findViewById(R.id.recyclerViewHistory) + recyclerViewHistory.layoutManager = LinearLayoutManager(this) + - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - val button_on_main: Button = findViewById(R.id.btn_on_main) - button_on_main.setOnClickListener { - val intent = Intent(this, MainActivity::class.java) - startActivity(intent) - } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/timert/MainActivity.kt b/app/src/main/java/com/example/timert/MainActivity.kt index 2f485c1..b607269 100644 --- a/app/src/main/java/com/example/timert/MainActivity.kt +++ b/app/src/main/java/com/example/timert/MainActivity.kt @@ -2,7 +2,7 @@ package com.example.timert import android.content.Intent import android.os.Bundle -import android.view.View +import android.util.Log import android.widget.Button import android.widget.Toast import androidx.activity.enableEdgeToEdge @@ -10,7 +10,11 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat + class MainActivity : AppCompatActivity() { + + + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -50,9 +54,8 @@ class MainActivity : AppCompatActivity() { //TODO: Intent для открытия Activity создания шаблона (форма 7) val intent = Intent(this, History::class.java) startActivity(intent) - - } + // ---- ROOM TEST ---- } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/timert/MyApplication.kt b/app/src/main/java/com/example/timert/MyApplication.kt new file mode 100644 index 0000000..1606441 --- /dev/null +++ b/app/src/main/java/com/example/timert/MyApplication.kt @@ -0,0 +1,20 @@ +package com.example.timert + +import android.app.Application +import androidx.room.Room +import com.example.timert.AppDatabase + +class MyApplication : Application() { + companion object { + lateinit var database: AppDatabase + } + + override fun onCreate() { + super.onCreate() + database = Room.databaseBuilder( + applicationContext, + AppDatabase::class.java, + "workout_database" + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/timert/timer.kt b/app/src/main/java/com/example/timert/timer.kt index 26277ba..bd6e7dd 100644 --- a/app/src/main/java/com/example/timert/timer.kt +++ b/app/src/main/java/com/example/timert/timer.kt @@ -2,10 +2,9 @@ package com.example.timert import android.app.AlertDialog import android.content.Intent -import android.media.Image +import android.media.MediaPlayer import android.os.Bundle import android.os.CountDownTimer -import android.widget.Button import android.widget.ImageButton import android.widget.TextView import androidx.activity.enableEdgeToEdge @@ -28,6 +27,14 @@ class timer : AppCompatActivity() { private var exerciseDuration = 45 // например, 45 секунд упражнение private var currentTimer: CountDownTimer? = null private var timeLeftInMillis: Long = 0 + + // Объявляем переменные для MediaPlayer + private var startWorkoutSound: MediaPlayer? = null + private var workSound: MediaPlayer? = null + private var startRestSound: MediaPlayer? = null + private var restSound: MediaPlayer? = null + + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -47,6 +54,12 @@ class timer : AppCompatActivity() { restBetweenApproaches = intent.getIntExtra("restBetweenApproaches", restBetweenApproaches) exerciseDuration = intent.getIntExtra("exerciseDuration", exerciseDuration) + // Инициализируем MediaPlayer + startWorkoutSound = MediaPlayer.create(this, R.raw.sound1) + workSound = MediaPlayer.create(this, R.raw.sound1) + startRestSound = MediaPlayer.create(this, R.raw.sound2) + restSound = MediaPlayer.create(this, R.raw.sound3) + startTraining() val button: ImageButton = findViewById(R.id.stop) @@ -106,15 +119,18 @@ class timer : AppCompatActivity() { statusText.text = "Тренировка завершена!" rootLayout.setBackgroundResource(R.drawable.blue_gradient) timerText.text = "00:00" + // Здесь должен быть звук завершения тренировки, если нужно return } - + statusSet.text = "Подход № $currentApproach" var currentExercise = 1 fun nextExercise() { if (currentExercise > numExercises) { statusText.text = "Отдых между подходами" rootLayout.setBackgroundResource(R.drawable.green_gradient) + // Звук перед началом отдыха между подходами + startRestSound?.start() startRest(restBetweenApproaches) { currentApproach++ nextApproach() @@ -122,23 +138,28 @@ class timer : AppCompatActivity() { return } rootLayout.setBackgroundResource(R.drawable.gradient_pink) - statusText.text="Работа" - + statusText.text = "Работа" statusExercise.text = "$currentExercise / $numExercises" - statusSet.text="$currentApproach" + statusSet.text = "$currentApproach" + + // Звук перед началом упражнения + workSound?.start() + startTimer(exerciseDuration) { statusText.text = "Отдых" rootLayout.setBackgroundResource(R.drawable.green_gradient) + // Звук перед началом отдыха между упражнениями + restSound?.start() startRest(restBetweenExercises) { currentExercise++ nextExercise() } } } - + // Звук перед началом подхода + startWorkoutSound?.start() nextExercise() } - nextApproach() } @@ -162,7 +183,6 @@ class timer : AppCompatActivity() { override fun onTick(millisUntilFinished: Long) { timerText.text = "${millisUntilFinished / 1000}" statusText.text = "Отдых" - } override fun onFinish() { @@ -170,5 +190,18 @@ class timer : AppCompatActivity() { } }.start() } + override fun onDestroy() { + super.onDestroy() + currentTimer?.cancel() + // Освобождаем ресурсы MediaPlayer + startWorkoutSound?.release() + workSound?.release() + startRestSound?.release() + restSound?.release() + startWorkoutSound = null + workSound = null + startRestSound = null + restSound = null + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_history.xml b/app/src/main/res/layout/activity_history.xml index d18ee74..99c53a9 100644 --- a/app/src/main/res/layout/activity_history.xml +++ b/app/src/main/res/layout/activity_history.xml @@ -8,6 +8,15 @@ android:background="@drawable/gradient_purpure" tools:context=".History"> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/raw/sound1.mp3 b/app/src/main/res/raw/sound1.mp3 new file mode 100644 index 0000000..825b1da Binary files /dev/null and b/app/src/main/res/raw/sound1.mp3 differ diff --git a/app/src/main/res/raw/sound2.mp3 b/app/src/main/res/raw/sound2.mp3 new file mode 100644 index 0000000..b6562a7 Binary files /dev/null and b/app/src/main/res/raw/sound2.mp3 differ diff --git a/app/src/main/res/raw/sound3.mp3 b/app/src/main/res/raw/sound3.mp3 new file mode 100644 index 0000000..8362c2b Binary files /dev/null and b/app/src/main/res/raw/sound3.mp3 differ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2693823..6361eed 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.9.2" +agp = "8.10.0" kotlin = "2.0.21" coreKtx = "1.16.0" junit = "4.13.2" diff --git a/settings.gradle.kts b/settings.gradle.kts index 7bb073d..5b0b124 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,6 +10,12 @@ pluginManagement { mavenCentral() gradlePluginPortal() } + plugins { + id("com.android.application") version "8.3.2" apply false // Замените на вашу версию + id("org.jetbrains.kotlin.android") version "1.9.0" apply false // Замените на вашу версию Kotlin + id("org.jetbrains.kotlin.kapt") version "1.9.0" apply false // замените на вашу версию Kotlin + id("androidx.room") version "2.7.1" apply false // Добавьте эту строку, заменив на вашу версию Room + } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) @@ -20,5 +26,4 @@ dependencyResolutionManagement { } rootProject.name = "TimerT" -include(":app") - \ No newline at end of file +include(":app") \ No newline at end of file