基于存储卡音乐播放器05

本文详细介绍了创建安卓音乐播放器应用【SDCardMusicPlayerV0.5】的步骤,包括拷贝图片素材、创建按钮背景图片选择器、在项目清单文件授权及注册相关类、创建布局和资源文件、划分不同子包并创建音乐实体类、适配器、服务类等。

1、创建安卓应用【SDCardMusicPlayerV0.5】
2、将图片素材拷贝到drawable目录与mipmap目录
3、创建按钮背景图片选择器
(1)播放按钮背景图片选择器 - play_button_selector.xml
(2)暂停按钮背景图片选择器 - pause_button_selector.xml
(3)上一首按钮背景图片选择器 - previous_button_selector.xml
(4)下一首按钮背景图片选择器 - next_button_selector.xml
4、在项目清单文件里授权访问外置存储卡,设置应用程序图标
5、主布局资源文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:background="@drawable/background"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".ui.MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pbScanMusic"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:visibility="gone" />

        <TextView
            android:id="@+id/tvScanMusic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/scan_music"
            android:textColor="#0000ff"
            android:textSize="25sp"
            android:visibility="gone" />
    </LinearLayout>

    <ListView
        android:id="@+id/lvMusicName"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="16dp"
        android:layout_weight="8" />

    <TextView
        android:id="@+id/tvMusicName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:textColor="#0000ff"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_weight="0.5"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tvCurrentPosition"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="#ff0000" />

        <ProgressBar
            android:id="@+id/pbMusicProgress"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="6" />

        <TextView
            android:id="@+id/tvDuration"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="#ff00ff" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnPrevious"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/previous_button_selector"
            android:onClick="doPrevious" />

        <Button
            android:id="@+id/btnPlayOrPause"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/play_button_selector"
            android:onClick="doPlayOrPause" />

        <Button
            android:id="@+id/btnNext"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/next_button_selector"
            android:onClick="doNext" />
    </LinearLayout>
</LinearLayout>

6、字符串资源文件strings.xml
7、创建音乐名列表项模板music_name_list_item.xml
8、创建ui子包,将MainActivity拖进ui子包
9、创建entity子包,在里面创建音乐实体类 - Music
10、创建app子包,在里面创建音乐播放器应用程序类 - MusicPlayerApplication
11、在项目清单文件里给音乐播放器应用程序类注册
12、创建adapter子包,在里面创建音乐适配器 - MusicAdapter
13、在app子包常见应用程序常量接口 - AppConstants
14、创建service子包,在里面创建音乐播放服务类 - MusicPlayService

package net.qyk.sdcard_musicplayer_05.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.IBinder;

import androidx.annotation.Nullable;

import net.qyk.sdcard_musicplayer_05.R;
import net.qyk.sdcard_musicplayer_05.app.AppConstants;
import net.qyk.sdcard_musicplayer_05.app.MusicPlayerApplication;
import net.qyk.sdcard_musicplayer_05.entity.Music;

import java.io.IOException;
import java.util.List;

public class MusicPlayService extends Service implements AppConstants {
    private MediaPlayer mp; // 媒体播放器
    private String musicName; // 音乐文件名
    private Thread thread; // 线程
    private boolean isRunning; // 线程循环控制变量
    private List<Music> musicList; // 音乐列表(数据源)
    private MusicPlayerApplication app; // 音乐播放器应用程序对象
    private MusicReceiver receiver;
    @Override
    public void onCreate() {
        super.onCreate();
        app =(MusicPlayerApplication) getApplication();
        musicList=app.getMusicList();
        mp =new MediaPlayer();
        mp=new MediaPlayer();
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
            @Override
            public void onCompletion(MediaPlayer mp) {
                nextMusic();
            }

        });

        isRunning=true;
        thread = new Thread((Runnable)()->{
            while (isRunning){
                if (mp.isPlaying()){
                    Intent intent=new Intent();
                    intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);
                    app.setCurrentPosition(mp.getCurrentPosition());
                    intent.putExtra(DURATION,mp.getDuration());
                    intent.putExtra(CONTROL,R.drawable.pause_button_selector);
                    sendBroadcast(intent);
                    try {
                        Thread.sleep(500);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        });
        thread.start();
        receiver=new MusicReceiver();
        IntentFilter filter=new IntentFilter();
        filter.addAction(INTENT_ACTION_PLAY_OR_PAUSE);
        filter.addAction(INTENT_ACTION_PLAY);
        filter.addAction(INTENT_ACTION_PREVIOUS);
        filter.addAction(INTENT_ACTION_NEXT);
        registerReceiver(receiver,filter);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        musicName=musicList.get(app.getCurrentMusicIndex()).getMusicName();
        try {
            mp.setDataSource(musicName);
            mp.prepare();
            app.setCurrentPosition(0);
            Intent intent1=new Intent();
            intent1.setAction(INTENT_ACTION_UPDATE_PROGRESS);
            intent1.putExtra(DURATION,mp.getDuration());
            sendBroadcast(intent1);
        }catch (IOException e){
            e.printStackTrace();
        }
        return Service.START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mp!=null){
            mp.release();
            mp=null;
        }
        unregisterReceiver(receiver);
        isRunning=false;
        thread=null;
    }
    //播放
    private void play()  {
        try {


            mp.reset();
            musicName = musicList.get(app.getCurrentMusicIndex()).getMusicName();
            mp.setDataSource(musicName);
            mp.prepare();
            mp.seekTo(app.getCurrentPosition());
            mp.start();
        }catch (IOException e){
            e.printStackTrace();
        }

    }

    private void previousMusic() {

        if (app.getCurrentMusicIndex() > 0) {
            app.setCurrentMusicIndex(app.getCurrentPosition()-1);
        } else {
            app.setCurrentMusicIndex(musicList.size() - 1);
        }

        app.setCurrentPosition(0);
        play();
    }
    private void nextMusic() {

        if (app.getCurrentMusicIndex() < musicList.size() - 1) {
            app.setCurrentMusicIndex(app.getCurrentPosition()-1);
        } else {
           app.setCurrentMusicIndex(0);
        }
        app.setCurrentPosition(0);

        play();
    }
    private void pause(){
        mp.pause();
        app.setCurrentPosition(mp.getCurrentPosition());
        Intent intent=new Intent();
        intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);
        intent.putExtra(DURATION,mp.getDuration());
        intent.putExtra(CONTROL, R.drawable.pause_button_selector);
        sendBroadcast(intent);
        
    }

    private class MusicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String action =intent.getAction();
            if (action!=null){
                switch (action){
                    case INTENT_ACTION_PLAY:
                        app.setCurrentPosition(0);
                        play();
                        break;
                    case INTENT_ACTION_PLAY_OR_PAUSE:
                        if (mp.isPlaying()){
                            pause();
                        }else {
                            play();
                        }
                        break;
                    case INTENT_ACTION_PREVIOUS:
                        previousMusic();
                        break;
                    case  INTENT_ACTION_NEXT:
                        nextMusic();
                        break;
                }
            }
        }
    }
}

15、在项目清单文件里注册音乐播放服务
16、主界面类 - MainActivity

package net.qyk.sdcard_musicplayer_05.ui;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import net.qyk.sdcard_musicplayer_05.R;
import net.qyk.sdcard_musicplayer_05.adapter.MusicAdapter;
import net.qyk.sdcard_musicplayer_05.app.AppConstants;
import net.qyk.sdcard_musicplayer_05.app.MusicPlayerApplication;
import net.qyk.sdcard_musicplayer_05.entity.Music;
import net.qyk.sdcard_musicplayer_05.service.MusicPlayService;

import java.util.List;

public class MainActivity extends AppCompatActivity implements AppConstants {
    private String musicName;
    private TextView tvMusicName;
    private Button btnPlayOrPause; // 播放|暂停按钮
    private MusicReceiver receiver;
    private TextView tvCurrentPosition; // 显示当前播放位置的标签
    private TextView tvDuration; // 显示音乐播放时长的标签
    private ProgressBar pbMusicProgress; // 音乐播放进度条
    private ListView lvMusicName; // 音乐名列表控件
    private List<Music> musicList; // 音乐列表(数据源)
    private MusicAdapter adapter; // 音乐适配器
    private MusicPlayerApplication app; // 音乐播放器应用程序对象
    private ProgressBar pbScanMusic; // 扫描存储卡音乐进度条
    private TextView tvScanMusic; // 扫描存储卡音乐标签(提示用户耐心等待)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvMusicName=findViewById(R.id.lvMusicName);
        tvMusicName=findViewById(R.id.tvMusicName);
        btnPlayOrPause=findViewById(R.id.btnPlayOrPause);
        tvCurrentPosition=findViewById(R.id.tvCurrentPosition);
        tvDuration=findViewById(R.id.tvDuration);
        pbMusicProgress=findViewById(R.id.pbMusicProgress);
        pbScanMusic=findViewById(R.id.pbScanMusic);
        tvScanMusic=findViewById(R.id.tvScanMusic);
        app =(MusicPlayerApplication)getApplication();
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        final int permission = ActivityCompat.checkSelfPermission(this, PERMISSIONS_STORAGE[0]);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 0);
            return;
        }
        new FillMusicListTask().execute();
        lvMusicName.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                app.setCurrentMusicIndex(position);
                app.setCurrentPosition(0);
                musicName=app.getMusicList().get(position).getMusicName();
                tvMusicName.setText("No."+(app.getCurrentMusicIndex()+1)+""+musicName.substring(
                        musicName.lastIndexOf("/")+1,musicName.lastIndexOf(".")));
                Intent intent=new Intent();
                intent.setAction(INTENT_ACTION_PLAY);
                sendBroadcast(intent);
            }
        });
        receiver=new MusicReceiver();
        IntentFilter filter=new IntentFilter();
        filter.addAction(INTENT_ACTION_UPDATE_PROGRESS);
        registerReceiver(receiver,filter);

    }
    private class MusicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {

        }
    }
    private class FillMusicListTask extends AsyncTask<Void ,Integer,Void>{
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pbMusicProgress.setVisibility(View.VISIBLE);
            tvScanMusic.setVisibility(View.VISIBLE);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            musicList=app.getMusicList();
            for(long i=0;i<2000000000;i++){

            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            pbScanMusic.setVisibility(View.GONE);
            tvScanMusic.setVisibility(View.GONE);
            if (musicList.size()>0){
                adapter=new MusicAdapter(MainActivity.this,musicList);
                lvMusicName.setAdapter(adapter);
                musicName=musicList.get(0).getMusicName();
                tvScanMusic.setText("No."+(app.getCurrentMusicIndex()+1)+""+musicName.substring(
                        musicName.lastIndexOf("/")+1,musicName.lastIndexOf(".")
                ));
                Intent intent=new Intent(MainActivity.this,MusicReceiver.class);
                startService(intent);

            }else {
                Toast.makeText(MainActivity.this,"没有音乐文件",Toast.LENGTH_SHORT);
            }
        }
        private class MusicReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent) {
                String action=intent.getAction();
                if (action!=null){
                    if (INTENT_ACTION_UPDATE_PROGRESS.equals(action)){
                        int duration=intent.getIntExtra(DURATION,0);
                        int controlIcon=intent.getByteExtra(CONTROL, (byte) R.drawable.pause_button_selector);
                        int progress=app.getCurrentPosition()*100/duration;
                        musicName=app.getMusicList().get(app.getCurrentMusicIndex()).getMusicName();
                        tvMusicName.setText("No."+(app.getCurrentMusicIndex()+1)+" "
                        +musicName.substring(musicName.lastIndexOf("/")+1,musicName.lastIndexOf(".")));
                        tvCurrentPosition.setText(app.getFormatTime(app.getCurrentPosition()));
                        tvDuration.setText(app.getFormatTime(duration));
                        pbMusicProgress.setProgress(progress);
                        btnPlayOrPause.setBackgroundResource(controlIcon);
                    }
                }
            }
        }
    }
    public void doPrevious(View view){
        Intent intent=new Intent();
        intent.setAction(INTENT_ACTION_PREVIOUS);
        sendBroadcast(intent);
    }
    public void doNext(View view){
        Intent intent=new Intent();
        intent.setAction(INTENT_ACTION_NEXT);
        sendBroadcast(intent);
    }
    public void doPlayOrpause(View view){
        Intent intent =new Intent();
        intent.setAction(INTENT_ACTION_PLAY_OR_PAUSE);
        sendBroadcast(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(new Intent(MainActivity.this, MusicPlayService.class));
        if (receiver!=null){
            unregisterReceiver(receiver);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值