根据Service及BroadcastReceiver的知识讲解和案例使用,实现一个Android音乐播放器。要求能实现音乐的播放,暂停,上一首,下一首等功能。Kotlin
时间: 2023-12-28 13:03:33 浏览: 112
Android使用Service及BroadcastReceiver实现音乐播放器
好的,我们可以按照以下步骤来实现一个基本的Android音乐播放器:
1. 创建一个新的Android项目,并在Gradle文件中添加以下依赖项:
```groovy
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.squareup.picasso:picasso:2.71828'
```
2. 在项目中创建一个包名为`service`,并在其中创建一个名为`MusicService`的服务类,用于管理音乐的播放、暂停和停止等操作。以下是服务类的基本代码:
```kotlin
class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {
private lateinit var mediaPlayer: MediaPlayer
private lateinit var audioList: ArrayList<Audio>
private var audioIndex = -1
override fun onCreate() {
super.onCreate()
mediaPlayer = MediaPlayer()
mediaPlayer.setOnPreparedListener(this)
mediaPlayer.setOnCompletionListener(this)
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val action = intent?.action
when (action) {
ACTION_PLAY -> {
val index = intent.getIntExtra(EXTRA_AUDIO_INDEX, 0)
if (index != audioIndex) {
audioIndex = index
playAudio()
} else {
resumeAudio()
}
}
ACTION_PAUSE -> pauseAudio()
ACTION_STOP -> stopAudio()
ACTION_NEXT -> nextAudio()
ACTION_PREVIOUS -> previousAudio()
}
return START_NOT_STICKY
}
override fun onPrepared(mp: MediaPlayer?) {
mp?.start()
}
override fun onCompletion(mp: MediaPlayer?) {
nextAudio()
}
private fun playAudio() {
try {
mediaPlayer.reset()
mediaPlayer.setDataSource(audioList[audioIndex].data)
mediaPlayer.prepareAsync()
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun resumeAudio() {
mediaPlayer.start()
}
private fun pauseAudio() {
mediaPlayer.pause()
}
private fun stopAudio() {
mediaPlayer.stop()
audioIndex = -1
}
private fun nextAudio() {
if (audioIndex < audioList.size - 1) {
audioIndex++
} else {
audioIndex = 0
}
playAudio()
}
private fun previousAudio() {
if (audioIndex > 0) {
audioIndex--
} else {
audioIndex = audioList.size - 1
}
playAudio()
}
companion object {
const val ACTION_PLAY = "com.example.musicplayer.ACTION_PLAY"
const val ACTION_PAUSE = "com.example.musicplayer.ACTION_PAUSE"
const val ACTION_STOP = "com.example.musicplayer.ACTION_STOP"
const val ACTION_NEXT = "com.example.musicplayer.ACTION_NEXT"
const val ACTION_PREVIOUS = "com.example.musicplayer.ACTION_PREVIOUS"
const val EXTRA_AUDIO_INDEX = "com.example.musicplayer.EXTRA_AUDIO_INDEX"
}
}
```
3. 创建一个名为`Audio`的数据类,用于存储音乐的信息,例如标题、艺术家、专辑和文件路径等。以下是数据类的基本代码:
```kotlin
data class Audio(
val id: Long,
val title: String,
val artist: String,
val album: String,
val data: String,
val duration: Long
)
```
4. 在项目中创建一个名为`adapter`的包,并在其中创建一个名为`AudioAdapter`的适配器类,用于将音乐列表显示在RecyclerView中。以下是适配器类的基本代码:
```kotlin
class AudioAdapter(private val audioList: ArrayList<Audio>, private val onItemClick: (position: Int) -> Unit) : RecyclerView.Adapter<AudioAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_audio, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val audio = audioList[position]
holder.titleText.text = audio.title
holder.artistText.text = audio.artist
Picasso.get().load(getAlbumArtUri(audio.album)).into(holder.albumImage)
holder.itemView.setOnClickListener {
onItemClick(position)
}
}
override fun getItemCount(): Int {
return audioList.size
}
private fun getAlbumArtUri(album: String): Uri? {
val uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Audio.Albums.ALBUM_ART)
val selection = MediaStore.Audio.Albums.ALBUM + "=?"
val selectionArgs = arrayOf(album)
val cursor = MediaStore.Images.Media.query(
holder.itemView.context.contentResolver,
uri,
projection,
selection,
selectionArgs,
null
)
var albumArtUri: Uri? = null
if (cursor.moveToFirst()) {
val albumArt = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART))
albumArtUri = Uri.parse(albumArt)
}
cursor.close()
return albumArtUri
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val titleText: TextView = itemView.findViewById(R.id.title_text)
val artistText: TextView = itemView.findViewById(R.id.artist_text)
val albumImage: ImageView = itemView.findViewById(R.id.album_image)
}
}
```
5. 在项目中创建一个名为`receiver`的包,并在其中创建一个名为`MusicReceiver`的广播接收器类,用于接收来自通知栏的音乐控制操作。以下是广播接收器类的基本代码:
```kotlin
class MusicReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.action
when (action) {
MusicService.ACTION_PLAY -> {
val serviceIntent = Intent(context, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PLAY
serviceIntent.putExtra(MusicService.EXTRA_AUDIO_INDEX, intent.getIntExtra(MusicService.EXTRA_AUDIO_INDEX, 0))
context?.startService(serviceIntent)
}
MusicService.ACTION_PAUSE -> {
val serviceIntent = Intent(context, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PAUSE
context?.startService(serviceIntent)
}
MusicService.ACTION_STOP -> {
val serviceIntent = Intent(context, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_STOP
context?.startService(serviceIntent)
}
MusicService.ACTION_NEXT -> {
val serviceIntent = Intent(context, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_NEXT
context?.startService(serviceIntent)
}
MusicService.ACTION_PREVIOUS -> {
val serviceIntent = Intent(context, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PREVIOUS
context?.startService(serviceIntent)
}
}
}
}
```
6. 在项目中创建一个名为`ui`的包,并在其中创建一个名为`MainActivity`的活动类,用于显示音乐列表和控制音乐的操作。以下是活动类的基本代码:
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var audioList: ArrayList<Audio>
private lateinit var audioAdapter: AudioAdapter
private lateinit var musicReceiver: MusicReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
audioList = loadAudioList()
audioAdapter = AudioAdapter(audioList) {
playAudio(it)
}
audio_recycler_view.adapter = audioAdapter
musicReceiver = MusicReceiver()
val filter = IntentFilter().apply {
addAction(MusicService.ACTION_PLAY)
addAction(MusicService.ACTION_PAUSE)
addAction(MusicService.ACTION_STOP)
addAction(MusicService.ACTION_NEXT)
addAction(MusicService.ACTION_PREVIOUS)
}
registerReceiver(musicReceiver, filter)
play_button.setOnClickListener {
if (audioList.isNotEmpty()) {
val index = if (MusicService.audioIndex != -1) MusicService.audioIndex else 0
playAudio(index)
}
}
pause_button.setOnClickListener {
val serviceIntent = Intent(this, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PAUSE
startService(serviceIntent)
}
stop_button.setOnClickListener {
val serviceIntent = Intent(this, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_STOP
startService(serviceIntent)
}
next_button.setOnClickListener {
val serviceIntent = Intent(this, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_NEXT
startService(serviceIntent)
}
previous_button.setOnClickListener {
val serviceIntent = Intent(this, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PREVIOUS
startService(serviceIntent)
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(musicReceiver)
}
private fun loadAudioList(): ArrayList<Audio> {
val audioList = ArrayList<Audio>()
val resolver = contentResolver
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION
)
val selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"
val sortOrder = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
val cursor = resolver.query(uri, projection, selection, null, sortOrder)
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID))
val title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE))
val artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
val album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM))
val data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
val duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
val audio = Audio(id, title, artist, album, data, duration)
audioList.add(audio)
}
cursor.close()
}
return audioList
}
private fun playAudio(index: Int) {
val serviceIntent = Intent(this, MusicService::class.java)
serviceIntent.action = MusicService.ACTION_PLAY
serviceIntent.putExtra(MusicService.EXTRA_AUDIO_INDEX, index)
startService(serviceIntent)
}
}
```
7. 在项目的AndroidManifest.xml文件中声明服务和广播接收器:
```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.musicplayer">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher_background"
android:label="@string/app_name"
android:roundIcon="@drawable/ic_launcher_foreground"
android:supportsRtl="true"
android:theme="@style/Theme.MusicPlayer">
<activity android:name=".ui.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".service.MusicService" />
<receiver android:name=".receiver.MusicReceiver" />
</application>
</manifest>
```
8. 运行应用程序并测试音乐播放器是否正常工作。
以上就是一个基本的Android音乐播放器的实现步骤,希望对你有所帮助!
阅读全文