换A 资源
@ -80,6 +80,16 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".service.LocalPlaybackService"
|
||||
android:exported="true"
|
||||
android:foregroundServiceType="mediaPlayback">
|
||||
<intent-filter>
|
||||
<action android:name="androidx.media3.session.MediaSessionService" />
|
||||
<action android:name="android.media.browse.MediaBrowserService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".service.MyDownloadService"
|
||||
android:exported="false"
|
||||
|
||||
|
Before Width: | Height: | Size: 810 KiB |
|
Before Width: | Height: | Size: 728 KiB |
|
Before Width: | Height: | Size: 453 KiB |
BIN
app/src/main/assets/Sound of instrument data/Big Ben.mp3
Normal file
BIN
app/src/main/assets/Sound of instrument data/Guitar sound.mp3
Normal file
BIN
app/src/main/assets/Sound of instrument data/Piano.mp3
Normal file
BIN
app/src/main/assets/Sound of instrument/Big Ben.jpg
Normal file
|
After Width: | Height: | Size: 360 KiB |
BIN
app/src/main/assets/Sound of instrument/Guitar sound.jpg
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
app/src/main/assets/Sound of instrument/Piano.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 552 KiB |
|
Before Width: | Height: | Size: 718 KiB |
|
Before Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 829 KiB |
|
Before Width: | Height: | Size: 515 KiB |
|
Before Width: | Height: | Size: 750 KiB |
|
Before Width: | Height: | Size: 450 KiB |
|
Before Width: | Height: | Size: 860 KiB |
|
Before Width: | Height: | Size: 563 KiB |
|
Before Width: | Height: | Size: 525 KiB |
|
Before Width: | Height: | Size: 379 KiB |
|
Before Width: | Height: | Size: 594 KiB |
BIN
app/src/main/assets/Voice of Nature data/Flowing water.mp3
Normal file
BIN
app/src/main/assets/Voice of Nature data/High -speed stream.mp3
Normal file
BIN
app/src/main/assets/Voice of Nature data/Wind blow.mp3
Normal file
BIN
app/src/main/assets/Voice of Nature/Flowing water.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
app/src/main/assets/Voice of Nature/High -speed stream.jpg
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
app/src/main/assets/Voice of Nature/Hundred Birds Calling.png
Normal file
|
After Width: | Height: | Size: 345 KiB |
BIN
app/src/main/assets/Voice of Nature/Rain falls in the leaves.png
Normal file
|
After Width: | Height: | Size: 428 KiB |
BIN
app/src/main/assets/Voice of Nature/Wind blow.jpg
Normal file
|
After Width: | Height: | Size: 796 KiB |
BIN
app/src/main/assets/White noise data/High -speed car.mp3
Normal file
BIN
app/src/main/assets/White noise data/High -voltage wire.mp3
Normal file
BIN
app/src/main/assets/White noise data/Mechanical failure.mp3
Normal file
BIN
app/src/main/assets/White noise data/Rhythm.mp3
Normal file
BIN
app/src/main/assets/White noise/High -speed car.png
Normal file
|
After Width: | Height: | Size: 588 KiB |
BIN
app/src/main/assets/White noise/High -voltage wire.jpg
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
app/src/main/assets/White noise/Mechanical failure.png
Normal file
|
After Width: | Height: | Size: 804 KiB |
BIN
app/src/main/assets/White noise/Rhythm.jpg
Normal file
|
After Width: | Height: | Size: 321 KiB |
@ -1,99 +1,84 @@
|
||||
{
|
||||
"categories": [
|
||||
{
|
||||
"name": "Real human voice",
|
||||
"name": "Sound of instrument",
|
||||
"audios": [
|
||||
{
|
||||
"name": "Breathe",
|
||||
"file": "Real human voice/Breathe.mp3",
|
||||
"image": "Real human voice pic/Breathe.png"
|
||||
"name": "Big Ben",
|
||||
"file": "Sound of instrument data/Big Ben.mp3",
|
||||
"image": "Sound of instrument/Big Ben.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Shh Shh",
|
||||
"file": "Real human voice/Shh Shh.mp3",
|
||||
"image": "Real human voice pic/Shh Shh.png"
|
||||
"name": "Guitar sound",
|
||||
"file": "Sound of instrument data/Guitar sound.mp3",
|
||||
"image": "Sound of instrument/Guitar sound.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Shhh...",
|
||||
"file": "Real human voice/Shhh….mp3",
|
||||
"image": "Real human voice pic/Shhh….png"
|
||||
"name": "Piano",
|
||||
"file": "Sound of instrument data/Piano.mp3",
|
||||
"image": "Sound of instrument/Piano.png"
|
||||
},
|
||||
{
|
||||
"name": "Mixing cup",
|
||||
"file": "Sound of instrument data/The sound of mixing cup.mp3",
|
||||
"image": "Sound of instrument/The sound of mixing cup.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sounds of appliances",
|
||||
"name": "White noise",
|
||||
"audios": [
|
||||
{
|
||||
"name": "Fireplace",
|
||||
"file": "Sounds of appliances/Fireplace.mp3",
|
||||
"image": "Sounds of appliances pic/Fireplace.png"
|
||||
"name": "High -speed car",
|
||||
"file": "White noise data/High -speed car.mp3",
|
||||
"image": "White noise/High -speed car.png"
|
||||
},
|
||||
{
|
||||
"name": "Mountain stream",
|
||||
"file": "Sounds of appliances/Mountain stream.mp3",
|
||||
"image": "Sounds of appliances pic/Mountain stream.png"
|
||||
"name": "High -voltage wire",
|
||||
"file": "White noise data/High -voltage wire.mp3",
|
||||
"image": "White noise/High -voltage wire.jpg"
|
||||
},
|
||||
{
|
||||
"name": "TV",
|
||||
"file": "Sounds of appliances/TV.mp3",
|
||||
"image": "Sounds of appliances pic/TV.png"
|
||||
"name": "Mechanical failure",
|
||||
"file": "White noise data/Mechanical failure.mp3",
|
||||
"image": "White noise/Mechanical failure.png"
|
||||
},
|
||||
{
|
||||
"name": "Water droplet",
|
||||
"file": "Sounds of appliances/Water droplet.mp3",
|
||||
"image": "Sounds of appliances pic/Water droplet.png"
|
||||
"name": "Rhythm",
|
||||
"file": "White noise data/Rhythm.mp3",
|
||||
"image": "White noise/Rhythm.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sounds of nature",
|
||||
"name": "Voice of Nature",
|
||||
"audios": [
|
||||
{
|
||||
"name": "Beach",
|
||||
"file": "Sounds of nature/Beach.mp3",
|
||||
"image": "Sounds of nature pic/Beach.png"
|
||||
"name": "Flowing water",
|
||||
"file": "Voice of Nature data/Flowing water.mp3",
|
||||
"image": "Voice of Nature/Flowing water.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Call of Seagulls",
|
||||
"file": "Sounds of nature/Call of Seagulls.mp3",
|
||||
"image": "Sounds of nature pic/Call of Seagulls.png"
|
||||
"name": "High -speed stream",
|
||||
"file": "Voice of Nature data/High -speed stream.mp3",
|
||||
"image": "Voice of Nature/High -speed stream.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Chirping of Birds",
|
||||
"file": "Sounds of nature/Chirping of Birds.mp3",
|
||||
"image": "Sounds of nature pic/Chirping of Birds.png"
|
||||
"name": "Hundred Birds Calling",
|
||||
"file": "Voice of Nature data/Hundred Birds Calling.mp3",
|
||||
"image": "Voice of Nature/Hundred Birds Calling.png"
|
||||
},
|
||||
{
|
||||
"name": "Cicada Chirping",
|
||||
"file": "Sounds of nature/Cicada Chirping.mp3",
|
||||
"image": "Sounds of nature pic/Cicada Chirping.png"
|
||||
"name": "Rain falls in the leaves",
|
||||
"file": "Voice of Nature data/Rain falls in the leaves.mp3",
|
||||
"image": "Voice of Nature/Rain falls in the leaves.png"
|
||||
},
|
||||
{
|
||||
"name": "Howling Wind",
|
||||
"file": "Sounds of nature/Howling Wind.mp3",
|
||||
"image": "Sounds of nature pic/Howling Wind.png"
|
||||
},
|
||||
{
|
||||
"name": "Nocturnal Insects",
|
||||
"file": "Sounds of nature/Nocturnal Insects.mp3",
|
||||
"image": "Sounds of nature pic/Nocturnal Insects.png"
|
||||
},
|
||||
{
|
||||
"name": "Seawater Surging",
|
||||
"file": "Sounds of nature/Seawater Surging.mp3",
|
||||
"image": "Sounds of nature pic/Seawater Surging.png"
|
||||
},
|
||||
{
|
||||
"name": "Summer Insects",
|
||||
"file": "Sounds of nature/Summer Insects.mp3",
|
||||
"image": "Sounds of nature pic/Summer Insects.png"
|
||||
},
|
||||
{
|
||||
"name": "waterfall",
|
||||
"file": "Sounds of nature/waterfall.mp3",
|
||||
"image": "Sounds of nature pic/waterfall.png"
|
||||
"name": "Wind blow",
|
||||
"file": "Voice of Nature data/Wind blow.mp3",
|
||||
"image": "Voice of Nature/Wind blow.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ import com.player.musicoo.database.AppOfflineDBManager
|
||||
import com.player.musicoo.database.CurrentAudioDatabase
|
||||
import com.player.musicoo.database.CurrentAudioManager
|
||||
import com.player.musicoo.database.DatabaseManager
|
||||
import com.player.musicoo.media.LocalMediaControllerManager
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
import com.player.musicoo.util.CacheManager
|
||||
import com.player.musicoo.util.DownloadUtil
|
||||
@ -93,9 +94,9 @@ class App : Application() {
|
||||
|
||||
for (category in resourcesList.categories) {
|
||||
when (category.name) {
|
||||
"Real human voice" -> realHumanVoiceList = category.audios
|
||||
"Sounds of appliances" -> soundsOfAppliancesList = category.audios
|
||||
"Sounds of nature" -> soundsOfNatureList = category.audios
|
||||
"Sound of instrument" -> realHumanVoiceList = category.audios
|
||||
"White noise" -> soundsOfAppliancesList = category.audios
|
||||
"Voice of Nature" -> soundsOfNatureList = category.audios
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,6 +107,7 @@ class App : Application() {
|
||||
app = this
|
||||
initialize(this)
|
||||
MediaControllerManager.init(this)
|
||||
LocalMediaControllerManager.init(this)
|
||||
appOfflineDBManager = AppOfflineDBManager.getInstance(this)
|
||||
currentAudioManager = CurrentAudioManager.getInstance(this)
|
||||
databaseManager = DatabaseManager.getInstance(this)
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package com.player.musicoo.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
|
||||
open class BaseActivity : AppCompatActivity() {
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ class LaunchActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun toMainActivity() {
|
||||
startActivity(Intent(this, PrimaryActivity::class.java))
|
||||
startActivity(Intent(this, MainActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -19,8 +18,7 @@ import com.player.musicoo.bean.Audio
|
||||
import com.player.musicoo.databinding.ActivityMainBinding
|
||||
import com.player.musicoo.fragment.HomeFragment
|
||||
import com.player.musicoo.fragment.ImportFragment
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
||||
import com.player.musicoo.media.LocalMediaControllerManager
|
||||
import com.player.musicoo.util.getAudioDurationFromAssets
|
||||
|
||||
|
||||
@ -52,7 +50,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
|
||||
if (App.currentPlayingAudio == null) {
|
||||
binding.playingStatusLayout.visibility = View.GONE
|
||||
@ -121,7 +119,7 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
binding.playBlackBtn.setOnClickListener {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null) {
|
||||
if (currentPlayer.playbackState == Player.STATE_READY) {
|
||||
if (currentPlayer.isPlaying) {
|
||||
@ -133,7 +131,7 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
updateProgressState()
|
||||
} else {
|
||||
MediaControllerManager.setupMedia(this@MainActivity, App.currentPlayingAudio!!,
|
||||
LocalMediaControllerManager.setupMedia(this@MainActivity, App.currentPlayingAudio!!,
|
||||
object : Player.Listener {
|
||||
override fun onPlayWhenReadyChanged(
|
||||
playWhenReady: Boolean,
|
||||
@ -209,7 +207,7 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun updateProgressState() {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
|
||||
progressHandler.removeCallbacksAndMessages(null)
|
||||
updatePlayState(currentPlayer.isPlaying)
|
||||
@ -221,7 +219,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
private val progressHandler = object : Handler(Looper.myLooper()!!) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
|
||||
val currentPosition = currentPlayer.currentPosition
|
||||
binding.progressBar.setProgress(currentPosition)
|
||||
|
||||
@ -157,8 +157,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
||||
val id = meController.currentMediaItem?.mediaId
|
||||
LogD(TAG, "initDownloadFlow id ->${id}")
|
||||
val currentScreenDownloads = downloads[id]
|
||||
LogD(TAG, "currentScreenDownloads->${currentScreenDownloads}")
|
||||
if (currentScreenDownloads != null) {
|
||||
LogD(TAG, "initDownloadFlow Download id->${currentScreenDownloads?.request?.id}")
|
||||
updateDownloadUI(currentScreenDownloads)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,9 +13,9 @@ import android.renderscript.Allocation
|
||||
import android.renderscript.Element
|
||||
import android.renderscript.RenderScript
|
||||
import android.renderscript.ScriptIntrinsicBlur
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import com.bumptech.glide.Glide
|
||||
@ -24,7 +24,8 @@ import com.gyf.immersionbar.ktx.immersionBar
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.bean.Audio
|
||||
import com.player.musicoo.databinding.ActivityPlayDetailsBinding
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
import com.player.musicoo.media.LocalMediaControllerManager
|
||||
import com.player.musicoo.util.LogTag
|
||||
import com.player.musicoo.util.containsContent
|
||||
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
||||
import com.player.musicoo.util.getAudioDurationFromAssets
|
||||
@ -53,7 +54,6 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
Toast.makeText(this, getString(R.string.data_error), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
initView()
|
||||
|
||||
}
|
||||
|
||||
private fun initImmersionBar() {
|
||||
@ -97,7 +97,7 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
binding.backBtn.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
currentPlayer?.addListener(object : Player.Listener {
|
||||
override fun onPlayWhenReadyChanged(
|
||||
playWhenReady: Boolean,
|
||||
@ -123,9 +123,12 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
updateProgressState()
|
||||
}
|
||||
}
|
||||
MediaControllerManager.setupMedia(this,
|
||||
LocalMediaControllerManager.setupMedia(this,
|
||||
audio!!,
|
||||
object : Player.Listener {
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
LogTag.LogD("ocean","error->${error}")
|
||||
}
|
||||
override fun onPlayWhenReadyChanged(
|
||||
playWhenReady: Boolean,
|
||||
reason: Int
|
||||
@ -154,7 +157,7 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY) {
|
||||
val isPlaying = currentPlayer.isPlaying
|
||||
updatePlayState(isPlaying, "onResume")
|
||||
@ -236,7 +239,7 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun updateProgressState() {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
|
||||
updatePlayState(currentPlayer.isPlaying, "playWhenReady")
|
||||
progressHandler.removeCallbacksAndMessages(null)
|
||||
@ -248,7 +251,7 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
|
||||
private val progressHandler = object : Handler(Looper.myLooper()!!) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
val currentPlayer = LocalMediaControllerManager.getController()
|
||||
if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
|
||||
val currentPosition = currentPlayer.currentPosition
|
||||
val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
|
||||
|
||||
@ -0,0 +1,169 @@
|
||||
package com.player.musicoo.media
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.MediaController
|
||||
import androidx.media3.session.SessionToken
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.common.util.concurrent.MoreExecutors
|
||||
import com.player.musicoo.App
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.bean.Audio
|
||||
import com.player.musicoo.bean.CurrentPlayingAudio
|
||||
import com.player.musicoo.service.LocalPlaybackService
|
||||
import com.player.musicoo.util.containsContent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@UnstableApi
|
||||
object LocalMediaControllerManager {
|
||||
private var mediaController: MediaController? = null
|
||||
private var controllerFuture: ListenableFuture<MediaController>? = null
|
||||
private var currentAudioFile = ""
|
||||
|
||||
fun init(context: Context) {
|
||||
val sessionToken =
|
||||
SessionToken(context, ComponentName(context, LocalPlaybackService::class.java))
|
||||
controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
|
||||
controllerFuture?.addListener({
|
||||
mediaController = controllerFuture?.get()
|
||||
}, MoreExecutors.directExecutor())
|
||||
}
|
||||
|
||||
fun getController(): MediaController? {
|
||||
return if (mediaController != null && mediaController!!.isConnected) {
|
||||
mediaController
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun setupMedia(context: Context, audio: Audio, listener: Player.Listener) {
|
||||
if (currentAudioFile != audio.file) {
|
||||
currentAudioFile = audio.file
|
||||
|
||||
val uri: Uri? = if (containsContent(audio.file)) {
|
||||
Uri.parse(audio.file)
|
||||
} else {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
Uri.parse("file:///android_asset/${audio.image}")
|
||||
} else {
|
||||
Uri.parse("android.resource://${context.packageName}/$resourceId")
|
||||
}
|
||||
|
||||
val mediaItem =
|
||||
MediaItem.Builder()
|
||||
.setUri(uri)
|
||||
.setMediaMetadata(
|
||||
MediaMetadata.Builder()
|
||||
.setArtist(audio.name)
|
||||
.setTitle(audio.name)
|
||||
.setArtworkUri(imgUri)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
if (isConnected()) {
|
||||
mediaController?.let {
|
||||
it.addListener(listener)
|
||||
it.setMediaItem(mediaItem)
|
||||
it.repeatMode = Player.REPEAT_MODE_ALL
|
||||
it.prepare()
|
||||
it.play()
|
||||
val currentPlayingAudio =
|
||||
CurrentPlayingAudio(
|
||||
audio.id,
|
||||
audio.name,
|
||||
audio.file,
|
||||
audio.image,
|
||||
audio.duration,
|
||||
false
|
||||
)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
App.currentAudioManager.setCurrentPlayingAudio(currentPlayingAudio)
|
||||
withContext(Dispatchers.Main) {
|
||||
App.initCurrentPlayingAudio()//更新到入口变量中
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setupMedia(context: Context, audio: CurrentPlayingAudio, listener: Player.Listener) {
|
||||
if (currentAudioFile != audio.file) {
|
||||
currentAudioFile = audio.file
|
||||
|
||||
val uri: Uri? = if (containsContent(audio.file)) {
|
||||
Uri.parse(audio.file)
|
||||
} else {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
Uri.parse("file:///android_asset/${audio.image}")
|
||||
} else {
|
||||
Uri.parse("android.resource://${context.packageName}/$resourceId")
|
||||
}
|
||||
|
||||
// val uri = Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
//// val mediaItem = MediaItem.fromUri(uri)
|
||||
// val imgUri = Uri.parse("file:///android_asset/${audio.image}")
|
||||
val mediaItem =
|
||||
MediaItem.Builder()
|
||||
.setUri(uri)
|
||||
.setMediaMetadata(
|
||||
MediaMetadata.Builder()
|
||||
.setArtist(audio.name)
|
||||
.setTitle(audio.name)
|
||||
.setArtworkUri(imgUri)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
if (isConnected()) {
|
||||
mediaController?.let {
|
||||
it.addListener(listener)
|
||||
it.setMediaItem(mediaItem)
|
||||
it.repeatMode = Player.REPEAT_MODE_ALL
|
||||
it.prepare()
|
||||
it.play()
|
||||
val currentPlayingAudio =
|
||||
CurrentPlayingAudio(
|
||||
audio.id,
|
||||
audio.name,
|
||||
audio.file,
|
||||
audio.image,
|
||||
audio.duration,
|
||||
false
|
||||
)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
App.currentAudioManager.setCurrentPlayingAudio(currentPlayingAudio)
|
||||
withContext(Dispatchers.Main) {
|
||||
App.initCurrentPlayingAudio()//更新到入口变量中
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isConnected(): Boolean {
|
||||
mediaController?.let {
|
||||
return it.isConnected
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import android.os.Binder
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.MediaController
|
||||
import androidx.media3.session.SessionToken
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
@ -22,10 +23,10 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@UnstableApi
|
||||
object MediaControllerManager {
|
||||
private var mediaController: MediaController? = null
|
||||
private var controllerFuture: ListenableFuture<MediaController>? = null
|
||||
private var currentAudioFile = ""
|
||||
|
||||
fun init(context: Context) {
|
||||
val sessionToken =
|
||||
@ -44,129 +45,6 @@ object MediaControllerManager {
|
||||
}
|
||||
}
|
||||
|
||||
fun setupMedia(context: Context, audio: Audio, listener: Player.Listener) {
|
||||
if (currentAudioFile != audio.file) {
|
||||
currentAudioFile = audio.file
|
||||
|
||||
val uri: Uri? = if (containsContent(audio.file)) {
|
||||
Uri.parse(audio.file)
|
||||
} else {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
Uri.parse("file:///android_asset/${audio.image}")
|
||||
} else {
|
||||
Uri.parse("android.resource://${context.packageName}/$resourceId")
|
||||
}
|
||||
|
||||
val mediaItem =
|
||||
MediaItem.Builder()
|
||||
.setUri(uri)
|
||||
.setMediaMetadata(
|
||||
MediaMetadata.Builder()
|
||||
.setArtist(audio.name)
|
||||
.setTitle(audio.name)
|
||||
.setArtworkUri(imgUri)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
if (isConnected()) {
|
||||
mediaController?.let {
|
||||
it.addListener(listener)
|
||||
it.setMediaItem(mediaItem)
|
||||
it.repeatMode = Player.REPEAT_MODE_ALL
|
||||
it.prepare()
|
||||
it.play()
|
||||
val currentPlayingAudio =
|
||||
CurrentPlayingAudio(
|
||||
audio.id,
|
||||
audio.name,
|
||||
audio.file,
|
||||
audio.image,
|
||||
audio.duration,
|
||||
false
|
||||
)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
App.currentAudioManager.setCurrentPlayingAudio(currentPlayingAudio)
|
||||
withContext(Dispatchers.Main) {
|
||||
App.initCurrentPlayingAudio()//更新到入口变量中
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setupMedia(context: Context, audio: CurrentPlayingAudio, listener: Player.Listener) {
|
||||
if (currentAudioFile != audio.file) {
|
||||
currentAudioFile = audio.file
|
||||
|
||||
val uri: Uri? = if (containsContent(audio.file)) {
|
||||
Uri.parse(audio.file)
|
||||
} else {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
Uri.parse("file:///android_asset/${audio.image}")
|
||||
} else {
|
||||
Uri.parse("android.resource://${context.packageName}/$resourceId")
|
||||
}
|
||||
|
||||
// val uri = Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
//// val mediaItem = MediaItem.fromUri(uri)
|
||||
// val imgUri = Uri.parse("file:///android_asset/${audio.image}")
|
||||
val mediaItem =
|
||||
MediaItem.Builder()
|
||||
.setUri(uri)
|
||||
.setMediaMetadata(
|
||||
MediaMetadata.Builder()
|
||||
.setArtist(audio.name)
|
||||
.setTitle(audio.name)
|
||||
.setArtworkUri(imgUri)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
if (isConnected()) {
|
||||
mediaController?.let {
|
||||
it.addListener(listener)
|
||||
it.setMediaItem(mediaItem)
|
||||
it.repeatMode = Player.REPEAT_MODE_ALL
|
||||
it.prepare()
|
||||
it.play()
|
||||
val currentPlayingAudio =
|
||||
CurrentPlayingAudio(
|
||||
audio.id,
|
||||
audio.name,
|
||||
audio.file,
|
||||
audio.image,
|
||||
audio.duration,
|
||||
false
|
||||
)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
App.currentAudioManager.setCurrentPlayingAudio(currentPlayingAudio)
|
||||
withContext(Dispatchers.Main) {
|
||||
App.initCurrentPlayingAudio()//更新到入口变量中
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isConnected(): Boolean {
|
||||
mediaController?.let {
|
||||
return it.isConnected
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getDuration(): Long {
|
||||
mediaController?.let {
|
||||
if (it.duration > 0) {
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package com.player.musicoo.service
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.session.MediaSessionService
|
||||
import com.player.musicoo.R
|
||||
|
||||
|
||||
@UnstableApi
|
||||
class LocalPlaybackService : MediaSessionService() {
|
||||
|
||||
private var mediaSession: MediaSession? = null
|
||||
|
||||
// Create your player and media session in the onCreate lifecycle event
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
val player = ExoPlayer.Builder(this).build()
|
||||
mediaSession = MediaSession.Builder(this, player)
|
||||
.setId(getString(R.string.app_name) + "LocalPlay")
|
||||
.build()
|
||||
|
||||
|
||||
// setMediaNotificationProvider(MyMediaNotificationProvider(this))
|
||||
|
||||
}
|
||||
|
||||
// The user dismissed the app from the recent tasks
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
val player = mediaSession?.player!!
|
||||
if (!player.playWhenReady
|
||||
|| player.mediaItemCount == 0
|
||||
|| player.playbackState == Player.STATE_ENDED
|
||||
) {
|
||||
// Stop the service if not playing, continue playing in the background
|
||||
// otherwise.
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? =
|
||||
mediaSession
|
||||
|
||||
// Remember to release the player and media session in onDestroy
|
||||
override fun onDestroy() {
|
||||
mediaSession?.run {
|
||||
player.release()
|
||||
release()
|
||||
mediaSession = null
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@ -92,6 +92,7 @@ class PlaybackService : MediaSessionService(), Player.Listener {
|
||||
player.addListener(this)
|
||||
|
||||
mediaSession = MediaSession.Builder(this, player)
|
||||
.setId(getString(R.string.app_name) + "OnlinePlay")
|
||||
.build()
|
||||
|
||||
|
||||
|
||||
@ -6,8 +6,8 @@ import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import com.player.musicoo.R
|
||||
|
||||
const val PRIVACY_POLICY_URL = "https://musicoo.app/privacy"
|
||||
const val TERMS_OF_SERVICE_URL = "https://musicoo.app/terms"
|
||||
const val PRIVACY_POLICY_URL = "https://sites.google.com/view/musiclax-privacy/home"
|
||||
const val TERMS_OF_SERVICE_URL = "https://sites.google.com/view/musiclax-terms/home"
|
||||
|
||||
fun openPrivacyPolicy(context: Context, privacyPolicyUrl: String) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(privacyPolicyUrl))
|
||||
|
||||
@ -14,12 +14,26 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/splash_bg_img" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="98dp"
|
||||
android:layout_height="98dp"
|
||||
android:src="@mipmap/musicoo_logo_img"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:textColor="@color/white_60"
|
||||
android:textSize="32dp"
|
||||
android:text="@string/app_name"
|
||||
android:fontFamily="@font/bold_font_italic"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -31,7 +45,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/listen_music_anytime"
|
||||
android:text="@string/resource_loading"
|
||||
android:textColor="#CCFFFFFF"
|
||||
android:textSize="16dp" />
|
||||
|
||||
@ -41,13 +55,6 @@
|
||||
android:layout_height="6dp"
|
||||
android:layout_marginTop="10dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/resource_loading"
|
||||
android:textColor="#99FFFFFF"
|
||||
android:textSize="12dp" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@ -4,13 +4,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/main_bg_color">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/settings_bg_img" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Musicoo</string>
|
||||
<string name="app_name">Musiclax</string>
|
||||
<string name="ready_to_sleep">Ready to sleep</string>
|
||||
<string name="home_top_desc">We\'ve carefully prepared sounds for you </string>
|
||||
<string name="data_error">Data Error</string>
|
||||
|
||||