Skip to content

Commit

Permalink
Allow to pick different songs
Browse files Browse the repository at this point in the history
  • Loading branch information
Théophile Delmas committed Feb 5, 2024
1 parent c89d6f7 commit 30513fe
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 27 deletions.
22 changes: 15 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />


<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -29,25 +28,33 @@
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">

<receiver android:name=".AlarmclockReceiver"
android:exported="false"
android:enabled="true">
<receiver
android:name=".AlarmclockReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.rooster.rooster.ALARM_INTENT" />
<action android:name="android.intent.action.ALARM" />

<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

<activity
android:name=".RingtoneActivity"
android:exported="false"
android:parentActivityName=".AlarmListActivity"
android:theme="@style/AppTheme.FullScreen"/>

<activity
android:name=".AlarmActivity"
android:enabled="true"
android:exported="true"
android:launchMode="singleInstance"
android:showOnLockScreen="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:enabled="true"/>
android:turnScreenOn="true" />
<activity
android:name=".AlarmListActivity"
android:exported="true" />
Expand All @@ -68,6 +75,7 @@
android:theme="@style/Theme.MyApplication">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Expand All @@ -79,10 +87,10 @@
android:theme="@style/Theme.MyApplication">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>

</application>

</manifest>
2 changes: 2 additions & 0 deletions app/src/main/java/com/rooster/rooster/Alarm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class AlarmCreation(
val label: String,
val enabled: Boolean,
val mode: String,
var ringtoneUri: String,
var relative1: String,
var relative2: String,
var time1: Long,
Expand All @@ -22,6 +23,7 @@ class Alarm(
var label: String,
var enabled: Boolean,
var mode: String,
var ringtoneUri: String,
var relative1: String,
var relative2: String,
var time1: Long,
Expand Down
24 changes: 19 additions & 5 deletions app/src/main/java/com/rooster/rooster/AlarmActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,23 @@ import java.util.Calendar
import java.util.Date

class AlarmActivity : FragmentActivity() {
private var alarmId: Long = 0
private var alarmIsRunning = false
private var isVibrating = false

private var vibrator: Vibrator? = null
private var mediaPlayer: MediaPlayer? = null
private var wakeLock: PowerManager.WakeLock? = null

val alarmDbHelper = AlarmDbHelper(this)


override fun onCreate(savedInstanceState: Bundle?) {
Log.e("Alarm", "Alarm Activity Start")
val alarm = alarmDbHelper.getAlarm(alarmId)
Log.e("Alarm", "Alarm Activity Start\n" + "Alarm id: $alarmId")
alarmId = intent.getStringExtra("alarm_id")!!
.toLong() // -1 is a default value if "alarm_id" is not found
Log.e("Alarmclock Reciever", "Alarm id: $alarmId")
alarmIsRunning = true
super.setShowWhenLocked(true)
super.setTurnScreenOn(true)
Expand All @@ -55,7 +63,9 @@ class AlarmActivity : FragmentActivity() {
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
refreshCycle()
alarmRing()
if (alarm != null) {
alarmRing(alarm.ringtoneUri)
}
//TODO Release wake lock
val alarmHandler = AlarmHandler()
alarmHandler.setNextAlarm(applicationContext)
Expand Down Expand Up @@ -93,7 +103,7 @@ class AlarmActivity : FragmentActivity() {
handler.post(updateRunnable)
}

private fun alarmRing() {
private fun alarmRing(ringtoneUri: String) {
// Wake Phone
val powerManager: PowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
Expand All @@ -108,9 +118,13 @@ class AlarmActivity : FragmentActivity() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// it is safe to cancel other vibrations currently taking place
vibrator!!.cancel()
val soundUri =
val soundUri = if (ringtoneUri == "default") {
// Fallback to a default sound if the URI is null or empty
Uri.parse("android.resource://${applicationContext.packageName}/raw/alarmclock")

} else {
// Use the provided URI
Uri.parse(ringtoneUri)
}
mediaPlayer = MediaPlayer().apply {
setDataSource(applicationContext, soundUri)
setAudioAttributes(
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/com/rooster/rooster/AlarmAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package com.rooster.rooster
import android.app.AlertDialog
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
Expand Down Expand Up @@ -126,6 +131,21 @@ class AlarmAdapter(private val alarmList: List<Alarm>, val alarmDbHelper: AlarmD
setButtonState(dynamicButton, dynamicButton.isSelected)
}

val ringtoneTitle = holder.alarmContainer.findViewById<TextView>(R.id.ringtoneTitle)
val title = getRingtoneTitleFromUri(holder.alarmContainer.context, alarm.ringtoneUri)
ringtoneTitle.text = title
val ringtoneButton = holder.alarmContainer.findViewById<LinearLayout>(R.id.layoutRingtone)
ringtoneButton.setOnClickListener {
val ringtoneActivity = Intent(context, RingtoneActivity::class.java)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M || Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
ringtoneActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
val b = Bundle()
b.putLong("alarm_id", alarm.id)
ringtoneActivity.putExtras(b);
context.applicationContext.startActivity(ringtoneActivity);
}

// Vibrate
var vibrateButton = holder.alarmContainer.findViewById<CheckBox>(R.id.checkBoxVibrate)
vibrateButton.setOnClickListener{
Expand Down Expand Up @@ -474,4 +494,16 @@ class AlarmAdapter(private val alarmList: List<Alarm>, val alarmDbHelper: AlarmD
}
button?.setBackgroundResource(bgDrawable)
}
fun getRingtoneTitleFromUri(context: Context, ringtoneUri: String?): String {
if (ringtoneUri == null) return "Default Ringtone" // Return a default or an indication that no custom ringtone is set

try {
val uri = Uri.parse(ringtoneUri)
val ringtone = RingtoneManager.getRingtone(context, uri)
return ringtone.getTitle(context)
} catch (e: Exception) {
e.printStackTrace()
return "Unknown Ringtone" // In case of any error, return a default name
}
}
}
15 changes: 13 additions & 2 deletions app/src/main/java/com/rooster/rooster/AlarmDbHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import androidx.appcompat.app.AppCompatActivity
import java.util.Date

class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", null, 1) {
companion object {
const val DATABASE_VERSION = 2 // Increment database version
const val DATABASE_NAME = "alarm_db"
}

private val alarmHandler = AlarmHandler()
val context = context
Expand All @@ -27,6 +31,7 @@ class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", nu
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
label TEXT,
mode TEXT,
ringtoneUri TEXT,
relative1 TEXT,
relative2 TEXT,
time1 INTEGER,
Expand All @@ -45,14 +50,17 @@ class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", nu
}

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// TODO: Implement database migration if needed
if (oldVersion < 2) {
db.execSQL("ALTER TABLE alarms ADD COLUMN ringtoneUri TEXT")
}
}

fun insertAlarm(alarm: AlarmCreation) {
val db = writableDatabase
val values = ContentValues().apply {
put("label", alarm.label)
put("mode", alarm.mode)
put("ringtoneUri", alarm.ringtoneUri)
put("relative1", alarm.relative1)
put("relative2", alarm.relative2)
put("time1", alarm.time1)
Expand Down Expand Up @@ -89,6 +97,7 @@ class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", nu
id = cursor.getLong(cursor.getColumnIndex("id")),
label = cursor.getString(cursor.getColumnIndex("label")),
mode = cursor.getString(cursor.getColumnIndex("mode")),
ringtoneUri = cursor.getString(cursor.getColumnIndex("ringtoneUri")),
relative1 = cursor.getString(cursor.getColumnIndex("relative1")),
relative2 = cursor.getString(cursor.getColumnIndex("relative2")),
time1 = cursor.getLong(cursor.getColumnIndex("time1")),
Expand Down Expand Up @@ -123,6 +132,7 @@ class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", nu
val values = ContentValues().apply {
put("label", alarm.label)
put("mode", alarm.mode)
put("ringtoneUri", alarm.ringtoneUri)
put("relative1", alarm.relative1)
put("relative2", alarm.relative2)
put("time1", alarm.time1)
Expand Down Expand Up @@ -285,13 +295,14 @@ class AlarmDbHelper(context: Context) : SQLiteOpenHelper(context, "alarm_db", nu

fun getAllAlarms(): List<Alarm> {
val db = readableDatabase
val cursor = db.query("alarms", arrayOf("id", "label", "mode", "relative1", "relative2", "time1", "time2", "calculated_time", "enabled", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"), null, null, null, null, null)
val cursor = db.query("alarms", arrayOf("id", "label", "mode", "ringtoneUri", "relative1", "relative2", "time1", "time2", "calculated_time", "enabled", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"), null, null, null, null, null)
val alarms = mutableListOf<Alarm>()
while (cursor.moveToNext()) {
alarms.add(Alarm(
id = cursor.getLong(cursor.getColumnIndex("id")),
label = cursor.getString(cursor.getColumnIndex("label")),
mode = cursor.getString(cursor.getColumnIndex("mode")),
ringtoneUri = cursor.getString(cursor.getColumnIndex("ringtoneUri")),
relative1 = cursor.getString(cursor.getColumnIndex("relative1")),
relative2 = cursor.getString(cursor.getColumnIndex("relative2")),
time1 = cursor.getLong(cursor.getColumnIndex("time1")),
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/rooster/rooster/AlarmListActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class AlarmListActivity() : ComponentActivity() {
private fun linkButtons() {
val addAlarmButton = findViewById<Button>(R.id.addAlarmButton)
addAlarmButton.setOnClickListener {
val alarm = AlarmCreation("Alarm",false, "At", "Pick Time", "Pick Time", 0, 0, 0)
val alarm = AlarmCreation("Alarm",false, "At","Default", "Pick Time", "Pick Time", 0, 0, 0)
alarmDbHelper.insertAlarm(alarm)
reloadAlarmList()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class AlarmclockReceiver : BroadcastReceiver() {
notificationManager.createNotificationChannel(notificationChannel)


// Set the notification's intent.
val alarmActivityIntent = Intent(context, AlarmActivity::class.java)
alarmActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
alarmActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
alarmActivityIntent.putExtra("alarm_id", alarmId.toString())
val alarmActivityPendingIntent = PendingIntent.getActivity(
context,
0,
Expand Down
3 changes: 0 additions & 3 deletions app/src/main/java/com/rooster/rooster/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ import android.net.Uri
import android.os.Build
import android.os.Looper
import android.provider.Settings
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import com.google.android.datatransport.Priority
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
Expand Down
76 changes: 76 additions & 0 deletions app/src/main/java/com/rooster/rooster/RingtoneActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.rooster.rooster

import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.Manifest
import android.content.pm.PackageManager
import android.util.Log
import android.widget.Toast

class RingtoneActivity : AppCompatActivity() {
private var alarmId: Long = 0
private val RINGTONE_PICKER_REQUEST = 999

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ringtone)

// Check and request permission
checkPermission()

// Get alarm ID from intent
intent.extras?.let {
alarmId = it.getLong("alarm_id")
Log.i("RingtoneActivity", "Alarm ID: $alarmId")
}

// Open ringtone picker
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM)
putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Select Alarm Ringtone")
}
startActivityForResult(intent, RINGTONE_PICKER_REQUEST)
}

private fun checkPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
}
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1 && grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show()
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RINGTONE_PICKER_REQUEST) {
val ringtoneUri: Uri? = data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
ringtoneUri?.let {
// Here you should update the alarm in your database with the URI
updateAlarmRingtone(alarmId, it.toString())
Toast.makeText(this, "Ringtone selected!", Toast.LENGTH_SHORT).show()
}
}
}

private fun updateAlarmRingtone(alarmId: Long, ringtoneUri: String) {
val alarmDbHelper = AlarmDbHelper(this)
val alarm = alarmDbHelper.getAlarm(alarmId)
Log.w("Update", "Ringtone update Intent for alarm $alarmId")
alarm?.let {
it.ringtoneUri = ringtoneUri
alarmDbHelper.updateAlarm(it)
Log.i("Update", "Ringtone updated for alarm $alarmId")
}
finish()
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/layout/activity_ringtone.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RingtoneActivity">

</RelativeLayout>
Loading

0 comments on commit 30513fe

Please sign in to comment.