Abstracted the MediaPlayer from the MainActivity and turned it into a service that has the ability to run regardless if an acitivity is present #28. Resolved issue where track display details was blank after switching from the settings view #26
This commit is contained in:
committed by
amazing-username
parent
971da4b9d2
commit
040544e630
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
@@ -15,15 +15,12 @@
|
||||
android:name=".activities.SettingsActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:parentActivityName=".activities.MainActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.example.mear.activities.MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.fdh"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:screenOrientation="portrait"></activity>
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
@@ -35,6 +32,8 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name=".playback.service.MusicService" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,50 +1,91 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import android.graphics.Color
|
||||
import android.app.ActivityManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.graphics.BitmapFactory
|
||||
import android.media.MediaPlayer
|
||||
import android.graphics.Color
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.IBinder
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.widget.Toast
|
||||
|
||||
import java.lang.Exception
|
||||
import java.lang.Runnable
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.io.*
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_play_controls.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_cover.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_details.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_elapsing.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_flow.*
|
||||
import kotlin.io.*
|
||||
import kotlin.random.Random
|
||||
|
||||
import org.jetbrains.anko.image
|
||||
import org.jetbrains.anko.imageBitmap
|
||||
|
||||
import com.example.mear.playback.service.MusicService
|
||||
import com.example.mear.R
|
||||
import com.example.mear.repositories.TrackRepository
|
||||
import com.example.mear.models.PlayControls
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private var musicService: MusicService? = null
|
||||
private var serviceBinded: Boolean? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
|
||||
initialize()
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
try {
|
||||
if (serviceBinded == null || serviceBinded!! == false) {
|
||||
unbindService(mConnection)
|
||||
serviceBinded = true
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
try {
|
||||
if (serviceBinded!!.equals(null) || serviceBinded!! == false ) {
|
||||
unbindService(mConnection)
|
||||
serviceBinded = true
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initialize() {
|
||||
songCount = TrackRepository(this).getSongCount()
|
||||
currentSong = fetchSongIndex(PlayTypes.PlaySong)
|
||||
TrackElapsing.progress = 0
|
||||
TrackElapsing.max = 100
|
||||
initializeMediaPlayer()
|
||||
|
||||
initializeClickListeners()
|
||||
initializeCompletionListener()
|
||||
try {
|
||||
initializeServices()
|
||||
initializeClickListeners()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
private fun initializeClickListeners() {
|
||||
PlayTrack.setOnClickListener {
|
||||
@@ -62,8 +103,6 @@ class MainActivity : AppCompatActivity() {
|
||||
SettingsLink.setOnClickListener {
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
try {
|
||||
|
||||
|
||||
startActivity(intent)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
@@ -72,19 +111,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun initializeCompletionListener() {
|
||||
trackPlayer!!.setOnCompletionListener {
|
||||
playNextSongTrack()
|
||||
}
|
||||
}
|
||||
private fun initializeMediaPlayer() {
|
||||
if (trackPlayer == null) {
|
||||
trackPlayer = MediaPlayer()
|
||||
playerInitialized = true
|
||||
val tr = TrackRepository(this).getTrack(currentSong!!)
|
||||
trackPlayer!!.setDataSource(tr.songPath)
|
||||
trackPlayer!!.prepare()
|
||||
}
|
||||
private fun initializeServices() {
|
||||
doBindService()
|
||||
}
|
||||
|
||||
private fun toggleShuffle() {
|
||||
@@ -108,12 +136,12 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun playSongTrack() {
|
||||
PlayTrack.isEnabled = true
|
||||
PlayTrack.isEnabled = false
|
||||
try {
|
||||
if (!trackPlayer!!.isPlaying) {
|
||||
trackPlayer!!.start()
|
||||
if (!musicService!!.isPlaying()) {
|
||||
musicService!!.playSongTrack()
|
||||
} else {
|
||||
trackPlayer!!.pause()
|
||||
musicService!!.pauseSongTrack()
|
||||
}
|
||||
configureTrackDisplay()
|
||||
}
|
||||
@@ -125,16 +153,9 @@ class MainActivity : AppCompatActivity() {
|
||||
private fun playNextSongTrack() {
|
||||
NextTrack.isEnabled = false
|
||||
try {
|
||||
currentSong = fetchSongIndex(PlayTypes.PlayNextSong)
|
||||
val controls = PlayControls(shuffleOn!!)
|
||||
musicService!!.playNextTrack(controls)
|
||||
|
||||
if (trackPlayer!!.isPlaying) {
|
||||
trackPlayer!!.stop()
|
||||
}
|
||||
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(TrackRepository(this).getTrack(currentSong!!).songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
configureTrackDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
@@ -146,16 +167,9 @@ class MainActivity : AppCompatActivity() {
|
||||
private fun playPreviousSongTrack() {
|
||||
PreviousTrack.isEnabled = false
|
||||
try {
|
||||
currentSong = fetchSongIndex(PlayTypes.PlayPreviousSong)
|
||||
val controls = PlayControls(shuffleOn!!)
|
||||
musicService!!.playPreviousTrack(controls)
|
||||
|
||||
if (trackPlayer!!.isPlaying) {
|
||||
trackPlayer!!.stop()
|
||||
}
|
||||
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(TrackRepository(this).getTrack(currentSong!!).songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
configureTrackDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
@@ -166,54 +180,60 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
private fun configureTrackDisplay() {
|
||||
try {
|
||||
configurePlayControlsDisplay()
|
||||
val currTrack = TrackRepository(this).getTrack(currentSong!!)
|
||||
val trackTitle = currTrack.title
|
||||
val artistTitle = currTrack.artist
|
||||
val albumTitle = currTrack.album
|
||||
val trackDuration = currTrack.length
|
||||
var trackCover: ByteArray? = null
|
||||
val dur = String.format(
|
||||
"%02d:%02d", TimeUnit.SECONDS.toMinutes(trackDuration.toLong()),
|
||||
(trackDuration % 60)
|
||||
)
|
||||
runOnUiThread {
|
||||
configurePlayControlsDisplay()
|
||||
val currTrack = musicService!!.getCurrentTrack()
|
||||
val trackTitle = currTrack.title
|
||||
val artistTitle = currTrack.artist
|
||||
val albumTitle = currTrack.album
|
||||
val trackDuration = currTrack.length
|
||||
var trackCover: ByteArray? = null
|
||||
val dur = String.format(
|
||||
"%02d:%02d", TimeUnit.SECONDS.toMinutes(trackDuration.toLong()),
|
||||
(trackDuration % 60)
|
||||
)
|
||||
|
||||
val mmr = MediaMetadataRetriever()
|
||||
mmr.setDataSource(currTrack.songPath)
|
||||
val mmr = MediaMetadataRetriever()
|
||||
mmr.setDataSource(currTrack.songPath)
|
||||
|
||||
if (mmr.embeddedPicture != null) {
|
||||
trackCover = mmr.embeddedPicture
|
||||
}
|
||||
updateTrackProgress()
|
||||
if (mmr.embeddedPicture != null) {
|
||||
trackCover = mmr.embeddedPicture
|
||||
}
|
||||
updateTrackProgress()
|
||||
|
||||
TrackTitle.text = null
|
||||
ArtistTitle.text = null
|
||||
AlbumTitle.text = null
|
||||
CurrentPosition.text = null
|
||||
TrackCover.setImageBitmap(null)
|
||||
resetControls()
|
||||
|
||||
TrackTitle.text = trackTitle
|
||||
ArtistTitle.text = artistTitle
|
||||
AlbumTitle.text = albumTitle
|
||||
TrackDuration.text = dur
|
||||
if (trackCover != null) {
|
||||
val songImage = BitmapFactory
|
||||
.decodeByteArray(trackCover, 0, trackCover.size)
|
||||
TrackCover.setImageBitmap(songImage)
|
||||
|
||||
TrackTitle.text = trackTitle
|
||||
ArtistTitle.text = artistTitle
|
||||
AlbumTitle.text = albumTitle
|
||||
TrackDuration.text = dur
|
||||
if (trackCover != null) {
|
||||
val songImage = BitmapFactory
|
||||
.decodeByteArray(trackCover, 0, trackCover.size)
|
||||
TrackCover.imageBitmap = songImage
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
private fun resetControls() {
|
||||
TrackTitle!!.text = null
|
||||
ArtistTitle!!.text = null
|
||||
AlbumTitle!!.text = null
|
||||
CurrentPosition!!.text = null
|
||||
TrackCover!!.imageBitmap = null
|
||||
}
|
||||
private fun updateTrackProgress() {
|
||||
musicHandler!!.postDelayed(musicTrackTimeUpdateTask, 100)
|
||||
musicHandler!!.postDelayed(musicTrackTimeUpdateTask, 250)
|
||||
}
|
||||
private fun configurePlayControlsDisplay() {
|
||||
PlayTrack.background = null
|
||||
PlayTrack.colorFilter = null
|
||||
|
||||
if (!trackPlayer!!.isPlaying) {
|
||||
if (!musicService!!.isPlaying()) {
|
||||
PlayTrack.setImageResource(android.R.drawable.ic_media_pause)
|
||||
PlayTrack.setColorFilter(Color.RED)
|
||||
}
|
||||
@@ -223,51 +243,25 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchSongIndex(playType: PlayTypes): Int {
|
||||
var songIndex: Int? = null
|
||||
|
||||
try {
|
||||
when (playType) {
|
||||
PlayTypes.PlayPreviousSong -> {
|
||||
songIndex = songCount
|
||||
if (currentSong!! != 0) {
|
||||
if (!shuffleOn!!) {
|
||||
songIndex = currentSong!!.dec()
|
||||
}
|
||||
else {
|
||||
songIndex = Random.nextInt(0, songCount!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayTypes.PlaySong -> {
|
||||
songIndex = Random.nextInt(0, songCount!!)
|
||||
}
|
||||
PlayTypes.PlayNextSong -> {
|
||||
songIndex = 0
|
||||
if (currentSong!! != songCount!!) {
|
||||
if (!shuffleOn!!) {
|
||||
songIndex = currentSong!!.inc()
|
||||
}
|
||||
else {
|
||||
songIndex = Random.nextInt(0, songCount!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||
|
||||
for (service in activityManager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (serviceClass.name == service.service.className) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
println(exMsg)
|
||||
}
|
||||
|
||||
return songIndex!!
|
||||
return false
|
||||
}
|
||||
|
||||
private var musicTrackTimeUpdateTask = object: Runnable {
|
||||
override fun run() {
|
||||
|
||||
try {
|
||||
var newPosition = 0
|
||||
val currentPosition = trackPlayer!!.currentPosition / 1000
|
||||
val totalDuration = trackPlayer!!.duration / 1000
|
||||
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
|
||||
val totalDuration = musicService!!.durationOfTrack() / 1000
|
||||
newPosition = (((currentPosition).toDouble() / totalDuration) * 100).toInt()
|
||||
val dur = String.format(
|
||||
"%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
|
||||
@@ -277,18 +271,69 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
TrackElapsing.progress = newPosition
|
||||
|
||||
musicHandler!!.postDelayed(this, 100)
|
||||
if (TrackCover.image == null && musicService!!.isPlaying()) {
|
||||
configureTrackDisplay()
|
||||
}
|
||||
|
||||
musicHandler!!.postDelayed(this, 250)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var musicHandler: Handler? = Handler()
|
||||
private var trackPlayer: MediaPlayer? = null
|
||||
private var currentSong: Int? = null
|
||||
private var playerInitialized: Boolean? = false
|
||||
private var shuffleOn: Boolean? = false
|
||||
private var songCount: Int? = null
|
||||
private val mConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
resetControls()
|
||||
|
||||
private enum class PlayTypes {
|
||||
PlayNextSong, PlaySong, PlayPreviousSong
|
||||
runBlocking {
|
||||
val demo = launch {
|
||||
musicService = (service as MusicService.LocalBinder).service
|
||||
}
|
||||
demo.start()
|
||||
}
|
||||
if (musicService != null) {
|
||||
if (musicService!!.isPlaying()) {
|
||||
configureTrackDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
Toast.makeText(
|
||||
this@MainActivity, "Music Service Started",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(className: ComponentName) {
|
||||
resetControls()
|
||||
Toast.makeText(
|
||||
this@MainActivity, "Music Service Stopped",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun doBindService() {
|
||||
val intent = Intent(this, MusicService::class.java)
|
||||
if (isServiceRunning(MusicService::class.java)) {
|
||||
val suc = "Service is already running"
|
||||
}
|
||||
else {
|
||||
startService(intent)
|
||||
}
|
||||
|
||||
var result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
|
||||
if (result) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private var musicHandler: Handler? = Handler()
|
||||
private var shuffleOn: Boolean? = false
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
try {
|
||||
TrackRepository(this).delete()
|
||||
val trackMgr = TrackManager(allSongs)
|
||||
trackMgr.configureTracks(this)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object DirectoryIgnore {
|
||||
const val Android_Root = "Android/"
|
||||
const val Notifications = "Notifications/"
|
||||
const val Ringtones = "Ringtones/"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object FileTypes {
|
||||
const val Mp3 = "mp3"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class PlayControls(val shuffleOn: Boolean) {
|
||||
}
|
||||
@@ -1,45 +1,274 @@
|
||||
package com.example.mear.playback.service
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.media.MediaPlayer
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.R
|
||||
import android.R.string.cancel
|
||||
import android.os.Looper
|
||||
import android.widget.Toast
|
||||
|
||||
import java.lang.Exception
|
||||
import kotlin.random.Random
|
||||
|
||||
import com.example.mear.models.Track
|
||||
import com.example.mear.management.DatabaseManager
|
||||
import com.example.mear.management.MusicFiles
|
||||
import com.example.mear.management.TrackManager
|
||||
import com.example.mear.models.PlayControls
|
||||
import com.example.mear.models.Track
|
||||
import com.example.mear.repositories.TrackRepository
|
||||
|
||||
|
||||
class MusicService: Service() {
|
||||
|
||||
private var trackPlayer: MediaPlayer? = null
|
||||
private var currentSongIndex: Int? = null
|
||||
private var shuffleOn: Boolean? = false
|
||||
private val mBinder = LocalBinder()
|
||||
private val seconds = 4
|
||||
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
internal val service: MusicService
|
||||
get() = this@MusicService
|
||||
}
|
||||
|
||||
|
||||
private enum class PlayTypes {
|
||||
PlayNextSong, PlaySong, PlayPreviousSong
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
initializeMediaPlayer()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
return Service.START_NOT_STICKY
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
val intent = Intent(this, mBinder.javaClass)
|
||||
onUnbind(intent)
|
||||
|
||||
Toast.makeText(this, "Music Service Stopped", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return mBinder
|
||||
}
|
||||
|
||||
override fun onUnbind(intent: Intent?): Boolean {
|
||||
return super.onUnbind(intent)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun playSongTrack() {
|
||||
try {
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception ) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun pauseSongTrack() {
|
||||
try {
|
||||
trackPlayer!!.pause()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun playPreviousTrack() {
|
||||
try {
|
||||
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun playNextTrack() {
|
||||
try {
|
||||
trackPlayer!!.reset()
|
||||
var nextTrack = fetchSongIndex(PlayTypes.PlayNextSong)
|
||||
val track = TrackRepository(this).getTrack(nextTrack)
|
||||
trackPlayer!!.setDataSource(track.songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun playPreviousTrack(controls: PlayControls) {
|
||||
try {
|
||||
configureControl(controls)
|
||||
val duration = trackPlayer!!.currentPosition / 1000
|
||||
if (duration > seconds) {
|
||||
|
||||
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(TrackRepository(this).getTrack(currentSongIndex!!).songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
var previousTrack = fetchSongIndex(PlayTypes.PlayPreviousSong)
|
||||
val track = TrackRepository(this).getTrack(previousTrack)
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(track.songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun configureControl(controls: PlayControls) {
|
||||
shuffleOn = controls.shuffleOn
|
||||
}
|
||||
fun playNextTrack(controls: PlayControls) {
|
||||
try {
|
||||
configureControl(controls)
|
||||
val nextTrack = fetchSongIndex(PlayTypes.PlayNextSong)
|
||||
|
||||
val track = TrackRepository(this).getTrack(nextTrack)
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(track.songPath)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentTrack(): Track {
|
||||
var track: Track? = null
|
||||
|
||||
track = TrackRepository(this).getTrack(currentSongIndex!!)
|
||||
|
||||
return track!!
|
||||
}
|
||||
|
||||
|
||||
private fun fetchSongIndex(playType: PlayTypes): Int {
|
||||
var songIndex: Int? = currentSongIndex
|
||||
val songCount = retrieveSongCount()
|
||||
|
||||
try {
|
||||
when (playType) {
|
||||
PlayTypes.PlayPreviousSong -> {
|
||||
if (currentSongIndex!! != 0) {
|
||||
if (!shuffleOn!!) {
|
||||
currentSongIndex = currentSongIndex!!.dec()
|
||||
songIndex = currentSongIndex!!
|
||||
}
|
||||
else {
|
||||
currentSongIndex = Random.nextInt(0, songCount!!)
|
||||
songIndex = currentSongIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayTypes.PlaySong -> {
|
||||
if (shuffleOn!!) {
|
||||
songIndex = Random.nextInt(0, songCount!!)
|
||||
}
|
||||
else {
|
||||
songIndex = 0
|
||||
}
|
||||
}
|
||||
PlayTypes.PlayNextSong -> {
|
||||
if (currentSongIndex!! != songCount!!) {
|
||||
if (!shuffleOn!!) {
|
||||
currentSongIndex = currentSongIndex!!.inc()
|
||||
songIndex = currentSongIndex!!
|
||||
}
|
||||
else {
|
||||
currentSongIndex = Random.nextInt(0, songCount!!)
|
||||
songIndex = currentSongIndex!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
println(exMsg)
|
||||
}
|
||||
|
||||
return songIndex!!
|
||||
}
|
||||
fun currentPositionOfTrack(): Int {
|
||||
return trackPlayer!!.currentPosition
|
||||
}
|
||||
fun durationOfTrack(): Int {
|
||||
return trackPlayer!!.duration
|
||||
}
|
||||
|
||||
fun isPlaying(): Boolean {
|
||||
return trackPlayer!!.isPlaying
|
||||
}
|
||||
|
||||
|
||||
private fun initializeMediaPlayer() {
|
||||
if (trackPlayer == null) {
|
||||
trackPlayer = MediaPlayer()
|
||||
}
|
||||
if (trackRepositoryEmpty()!!) {
|
||||
populateTrackRepository()
|
||||
}
|
||||
|
||||
currentSongIndex = Random.nextInt(0, TrackRepository(this).getSongCount())
|
||||
val trackToPlay = TrackRepository(this).getTrack(currentSongIndex!!)
|
||||
trackPlayer!!.setDataSource(trackToPlay.songPath)
|
||||
trackPlayer!!.prepareAsync()
|
||||
trackPlayer!!.setOnCompletionListener {
|
||||
playNextTrack()
|
||||
}
|
||||
}
|
||||
private fun populateTrackRepository() {
|
||||
var mp3Paths = MusicFiles(android.os.Environment.getExternalStorageDirectory())
|
||||
mp3Paths.searchForMp3Songs()
|
||||
val paths = mp3Paths.allSongs
|
||||
val trackMgr = TrackManager(paths!!)
|
||||
trackMgr.configureTracks(this)
|
||||
}
|
||||
|
||||
|
||||
private fun trackRepositoryEmpty(): Boolean? {
|
||||
val trackCount = retrieveSongCount()
|
||||
|
||||
when (trackCount) {
|
||||
null -> {
|
||||
return true
|
||||
}
|
||||
0 -> {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun retrieveSongCount(): Int? {
|
||||
|
||||
try {
|
||||
var db = DatabaseManager(this)
|
||||
var trackDb = TrackRepository(this)
|
||||
val count = trackDb.getSongCount()
|
||||
|
||||
return count
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,15 @@ import org.jetbrains.anko.db.*
|
||||
import com.example.mear.database
|
||||
import com.example.mear.models.Track
|
||||
|
||||
class TrackRepository(val context: Context) {
|
||||
class TrackRepository {
|
||||
private var context: Context? = null
|
||||
|
||||
fun getAll(): List<Track> = context.database.use {
|
||||
constructor(context: Context)
|
||||
{
|
||||
this.context = context
|
||||
}
|
||||
|
||||
fun getAll(): List<Track> = context!!.database.use {
|
||||
val tracks = mutableListOf<Track>()
|
||||
|
||||
select("Track" )
|
||||
@@ -31,7 +37,7 @@ class TrackRepository(val context: Context) {
|
||||
})
|
||||
tracks
|
||||
}
|
||||
fun getTrack(id: Int): Track = context.database.use {
|
||||
fun getTrack(id: Int): Track = context!!.database.use {
|
||||
select("Track").where("Id = $id")
|
||||
.parseSingle(object: MapRowParser<Track>{
|
||||
override fun parseRow(columns: Map<String, Any?>): Track {
|
||||
@@ -49,7 +55,7 @@ class TrackRepository(val context: Context) {
|
||||
}
|
||||
})
|
||||
}
|
||||
fun getSongCount(): Int = context.database.use {
|
||||
fun getSongCount(): Int = context!!.database.use {
|
||||
select("TrackCount").limit(1)
|
||||
.parseSingle(object : MapRowParser<Int>{
|
||||
override fun parseRow(columns: Map<String, Any?>): Int {
|
||||
@@ -59,7 +65,7 @@ class TrackRepository(val context: Context) {
|
||||
})
|
||||
}
|
||||
|
||||
fun insertTrack(track: Track) = context.database.use {
|
||||
fun insertTrack(track: Track) = context!!.database.use {
|
||||
insert("Track",
|
||||
"Id" to track.id,
|
||||
"Title" to track.title,
|
||||
@@ -68,16 +74,25 @@ class TrackRepository(val context: Context) {
|
||||
"Duration" to track.length,
|
||||
"FilePath" to track.songPath)
|
||||
}
|
||||
fun createSongCount(songCount: Int) = context.database.use {
|
||||
fun createSongCount(songCount: Int) = context!!.database.use {
|
||||
delete("TrackCount")
|
||||
insert("TrackCount",
|
||||
"Id" to 0,
|
||||
"TotalSongs" to songCount)
|
||||
}
|
||||
|
||||
fun delete(table: Any?) = context.database.use {
|
||||
delete("Track", whereClause = "id = {$table.id}")
|
||||
}
|
||||
fun delete() = context.database.use {
|
||||
fun delete() = context!!.database.use {
|
||||
delete("Track")
|
||||
}
|
||||
|
||||
fun getLibraryCount(): Int? {
|
||||
context!!.database.use {
|
||||
select("TrackCount").limit(1)
|
||||
.parseList (object : MapRowParser<Int> {
|
||||
override fun parseRow(columns: Map<String, Any?>): Int {
|
||||
return columns.getValue("TotalSongs").toString().toInt()
|
||||
}
|
||||
})
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,4 @@ import android.content.Context
|
||||
import com.example.mear.management.DatabaseManager
|
||||
|
||||
val Context.database: DatabaseManager
|
||||
get() = DatabaseManager.getInstance(applicationContext)
|
||||
get() = DatabaseManager.getInstance(applicationContext)
|
||||
Reference in New Issue
Block a user