【达内课程】音乐播放器3.0(中)

创建Service开发步骤

上一篇文章中我们完成了步骤【1】,下面我们来完善剩下的步骤。

【2】开发 Service
  1)创建并注册 Service
    a)创建 PlayMusicService
    b)注册
  2)在 Service 内部完成播放控制相关方法,例如 play() 等
    a)声明 MediaPlayer
    b)声明数据源 List<Music>
    c)声明必要变量,例如 currentMusicIndex、pausePosition
    d)在 onCreate()中初始化 MediaPlayer、List<Music>
    e)添加歌曲的播放控制相关方法,包括:void play()void play(int position)void pause()void previous()void next()

按照步骤2开发Service

创建 PlayMusicService

public class PlayMusicService extends Service {
    public PlayMusicService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

AndroidManifest 注册

<service
            android:name=".service.PlayMusicService"
            android:enabled="true"
            android:exported="true"></service>

在 MainActivity 中启动 service

public class MainActivity extends AppCompatActivity {
    ......
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        //激活Service
        Intent intent = new Intent(this, PlayMusicService.class);
        startService(intent);
    }
    ......
}

PlayMusicService 中获取数据的时候虽然可以用

musics = MusicDaoFactory.newInstance(this).getData();

得到数据,但是我们的 MainActivity 中执行了一次getData(),PlayMusicService 中又执行了一次,不合理。我们这时就要用到 Application

新建 MusicPlayerApplication

public class MusicPlayerApplication extends Application {
    private List<Music> musics;

    @Override
    public void onCreate() {
        super.onCreate();
        musics = MusicDaoFactory.newInstance(this).getData();
    }

    public List<Music> getMusics() {
        return musics;
    }
}

AndroidManifest 中注册

<application
	android:name=".MusicPlayerApplication"
	......>
</application>

我们在 MainActivity 和 PlayMusicService 中获取数据的代码需要修改

MainActivity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        //获取数据
        MusicPlayerApplication application = (MusicPlayerApplication)getApplication();
        musics = application.getMusics();
        adapter = new MusicAdapter(this, musics);
        listView.setAdapter(adapter);
        ......
    }

PlayMusicService 增加其他播放方法,完整的PlayMusicService代码如下

public class PlayMusicService extends Service {
    private MediaPlayer player;
    private List<Music> musics;
    private int currentMusicIndex;
    private int pausePosition;

    @Override
    public void onCreate() {
        player = new MediaPlayer();
        player.setOnCompletionListener(mediaPlayer -> next());

        //获取数据
        MusicPlayerApplication application = (MusicPlayerApplication) getApplication();
        musics = application.getMusics();
    }

    //播放
    private void play() {
        try {
            player.reset();
            player.setDataSource(musics.get(currentMusicIndex).getPath());
            player.prepare();
            player.seekTo(pausePosition);
            player.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //播放指定位置歌曲
    private void play(int position) {
        currentMusicIndex = position;
        pausePosition = 0;
        play();
    }

    //暂停
    private void pause() {
        player.pause();
        pausePosition = player.getCurrentPosition();
    }

    //上一首
    private void priviout() {
        currentMusicIndex--;
        if (currentMusicIndex < 0) {
            currentMusicIndex = musics.size() - 1;
        }
        pausePosition = 0;
        play();
    }

    //播放下一首
    private void next() {
        currentMusicIndex++;
        if (currentMusicIndex >= musics.size()) {
            currentMusicIndex = 0;
        }
        pausePosition = 0;
        play();
    }

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

实现基本控制开发步骤

【3】实现基本控制
  1)实现播放和暂停功能
    a)在 Activity 声明并初始化相关控件,并配置监听器
    b)点击监听方式中,发送广播,使用“频道号”标识要求执行的操作是“播放或暂停”
    c)在 Service 中使用内部类创建广播接受者,并动态注册接收 Activity 发送的广播,并根据当前的播放状态决定调用播放或暂停方法
    d)在 Service 的播放和暂停方法中,分别发送广播,要求 Activity 把界面显示设置为播放或暂停状态
    e)在 Activity 中使用内部创建广播接受者,并动态注册接收 Service 发送的 2 种广播,根据广播的“频道号”设置界面显示
    f)在 Activity 和 Service 的 onDestroy() 中注销各自广播接收者
  2)使用类似的模式实现上一首、下一首
  3)使用类似的模式实现播放指定歌曲

按照步骤3实现基本控制

我们按照开发步骤,写下重点代码

MainActivity 中增加播放按钮的点击事件

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  	......
    private void setListeners() {
        ibPlay.setOnClickListener(this);
    }
	......
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ib_play:
                //发送广播
                sendBroadcast(new Intent("play or pause"));
                break;
            default:
                break;
        }
    }
}

PlayMusicService 中自定义广播接收者

public class PlayMusicService extends Service {
	......
    //内部广播接收者对象
    private InnerReceiver receiver;

    @Override
    public void onCreate() {
        ......
        //注册广播接收者
        receiver = new InnerReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("play or pause");
        registerReceiver(receiver, filter);
    }
	......
    /**
     * 内部广播接收者
     */
    private class InnerReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //获取广播中的Action
            String action = intent.getAction();
            //判断Action
            if ("play or pause".equals(action)) {
                //判断应该播放或暂停
                if (player.isPlaying()) {
                    pause();
                } else {
                    play();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        //注销广播接收者
        unregisterReceiver(receiver);
        super.onDestroy();
    }
}

这样播放或暂停功能就做好了,但播放按钮的状态没有改变,下面我们在 PlayMusicService 中发送广播来通知 MainActivity 改变按钮样式

//播放
    private void play() {
        try {
            ......
            //发送广播要求界面显示为播放状态
            //发送广播要求界面显示为播放状态
            Intent intent = new Intent("set play state");
            sendBroadcast(intent);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	//暂停
    private void pause() {
       	......
        //发送广播要求界面显示为暂停状态
        Intent intent = new Intent("set pause state");
        sendBroadcast(intent);
    }

MainActivity 按照同样的方式接收广播

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
   	......
    private InnerReceiver receiver;
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        //注册广播接收者
        receiver = new InnerReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("set play state");
        filter.addAction("set pause state");
        registerReceiver(receiver,filter);
    }
    ......
    private class InnerReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("set play state".equals(action)) {
                ibPlay.setImageResource(android.R.drawable.ic_media_pause);
            } else if ("set pause state".equals(action)) {
                ibPlay.setImageResource(android.R.drawable.ic_media_play);
            }
        }
    }

    @Override
    protected void onDestroy() {
        //注销广播接收者
        unregisterReceiver(receiver);
        super.onDestroy();
    }
}

同样的方法增加上一首和下一首按钮的功能。

下面说一下点击 Listview 播放相应歌曲的实现

MainActivity

package com.example.musicapplication.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.musicapplication.R;
import com.example.musicapplication.adapter.MusicAdapter;
import com.example.musicapplication.app.MusicPlayerApplication;
import com.example.musicapplication.entity.Music;
import com.example.musicapplication.service.PlayMusicService;

import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
    ......
    private void setListeners() {
        ......
        listView.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent intent = new Intent();
        intent.setAction("play appoint");
        intent.putExtra("position", position);
        sendBroadcast(intent);
    }
    ......
}

PlayMusicService

public class PlayMusicService extends Service {
    ......
    @Override
    public void onCreate() {
        ......
        //注册广播接收者
        receiver = new InnerReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("play or pause");
        filter.addAction("play appoint");
        registerReceiver(receiver, filter);
    }
	......
    /**
     * 内部广播接收者
     */
    private class InnerReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //获取广播中的Action
            String action = intent.getAction();
            //判断Action
            if ("play or pause".equals(action)) {
                ......
            } else if ("play appoint".equals(action)) {
                int position = intent.getIntExtra("position", 0);
                play(position);
            }
        }
    }
	......
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值