功能说明:在Fragment布局的tab页面中添加了基本的音乐播放器,包括下一曲、上一曲、播放、停止等功能。
分析:BroadcastReceiver是Android的四大组件之一,用来编写广播接收者程序,对广播做出响应;
BroadcastReceiver程序必须在清单文件里注册(配置);
广播划分为系统广播和用户自定义广播两种;
在Android系统里,存在大量的系统广播,如短信到来时会产生一个系统广播,系统程序和用户程序都可以处理广播;
接收系统的广播,有静态注册和动态注册两种使用方式;
可以发送自定义广播并动态注册广播接收者;
短信到来时,系统的短信处理程序会在手机通知栏产生一条通知,单击通知标题可以查看通知内容,这是使用了PendingIntent。当然,从手机联系人也可以查看短信内容。
代码:
Fragment.java :
package com.example.zy;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.ImageButton;
import
android.widget.TextView;
import
androidx.fragment.app.Fragment;
/**
* A simple {@link Fragment}subclass.
* Use the {@link FrdFragment#newInstance}factory method to
* create an instance of this fragment.
*/
public class FrdFragment extends Fragment implements View.OnClickListener {
// TODO:Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g.ARG_ITEM_NUMBER
private static final String ARG_PARAM1= "param1";
private static final
String ARG_PARAM2 = "param2";
// TODO:Rename and change types of parameters
private StringmParam1;
private
String mParam2;
TextView title, author;
ImageButton play, stop,last,next;
ActivityReceiver activityReceiver;
public static final
String CTL_ACTION=
"org.jay.action.CTL_ACTION";
public static final
String UPDATE_ACTION=
"org.jay.action.UPDATE_ACTION";
int
status = 0x11;
String[] titleStrs= new String[]
{"Not Afraid ","你要相信这不是最后一天","失眠飞行","男孩","你不是真正的快乐"};
String[] authorStrs= new String[]
{"Eminem~","华晨宇","沈以诚","梁博","五月天"};
public
FrdFragment() {
// Required empty public constructor
}
/**
* Use this factory method to createa new instance of
* this fragment using the providedparameters.
*
*@param param1 Parameter 1.
*@param param2 Parameter 2.
*@return A new instance offragment BlankFragment.
*/
// TODO:Rename and change types and number of parameters
public static FrdFragment newInstance(String param1, Stringparam2) {
FrdFragment fragment =
new FrdFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return
fragment;
}
@Override
public void onClick(View view) {
Intent intent =
new Intent(CTL_ACTION);
//在主界面按下对应按钮,传递给service对应参数
switch (view.getId())
{
case R.id.play:
intent.putExtra(
"control",1);
break;
case
R.id.stop:
intent.putExtra(
"control",2);
break;
case
R.id.next:
intent.putExtra(
"control",3);
break;
case
R.id.last:
intent.putExtra(
"control",4);
break;
}
getActivity().sendBroadcast(intent)
;
}
@Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
if
(getArguments() != null) {
mParam1 =
getArguments().getString(ARG_PARAM1);
mParam2 =
getArguments().getString(ARG_PARAM2);
}
activityReceiver = new ActivityReceiver();
IntentFilter filter = new IntentFilter(UPDATE_ACTION);
getActivity().getApplicationContext().registerReceiver(activityReceiver,filter);
Intent intent = new Intent(getActivity(),MusicService.class);
getActivity().startService(intent);
}
class ActivityReceiverextends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取来自receive中intent的update消息,代表播放状态
int update = intent.getIntExtra("update",-1);
//获取来自receive中intent的curruent消息,代表正在播放的歌曲
int current = intent.getIntExtra("current",-1);
//如果状态为正在播放歌曲或暂停
if(current>=0 && (update == 0x12 || update == 0x13))
{
title.setText(titleStrs[current]);
author.setText(authorStrs[current]);
}
//如果状态为未播放歌曲
else if (update == 0x11)
{
title.setText("未播放歌曲");
author.setText("未播放歌曲");
}
switch (update)
{
//如果未播放歌曲,则播放图标为播放
case 0x11:
play.setImageResource(R.drawable.play);
status=0x11;
break;
//如果正在播放歌曲,则播放图标为暂停
case 0x12:
play.setImageResource(R.drawable.pause);
status=0x12;
break;
case
0x13:
play.setImageResource(R.drawable.play);
status=0x13;
break;
}
}
}
@Override
public ViewonCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.tab02,container,false);
//找到对应控件
play = view.findViewById(R.id.play);
stop =
view.findViewById(R.id.stop);
next =
view.findViewById(R.id.next);
last =
view.findViewById(R.id.last);
title =
view.findViewById(R.id.name);
author =
view.findViewById(R.id.singer);
//添加监听
play.setOnClickListener(this);
stop.setOnClickListener(this);
next.setOnClickListener(this);
last.setOnClickListener(this);
return
view;
}
}
我们加入资源文件后就是要进行页面布局了,我们在/res/layout文件夹下新建.xml文件,然后将布局布置为自己所喜欢的样子即可,需要四个imagebutton和两个TextView,其他的可以自行添加,位置可以改变,这个也比较容易去配置
创建MusicService.java文件。新建一个MusicService.java文件,由它来继承Service,实现音乐的播放功能。
代码:
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaPlayer;
import android.os.IBinder;
import androidx.annotation.Nullable;
import java.io.IOException;
public class MusicService extends Service {
@Nullable
MyReceiver serviceReceiver;
AssetManager
am;
String[]
musics=new String[]{"Fairy_town.mp3","Mojito.mp3","Re0.mp3","SayGood_NoCrying.mp3","Write_US.mp3"};
MediaPlayer
mPlayer;
//0x11表示没有播放,0x12代表正在播放,0x13代表暂停
int status=0x11;
int current=0;
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
am=getAssets();
//创建BroadcastReceiver
serviceReceiver=new MyReceiver();
//创建IntentFilter
IntentFilter filter=new IntentFilter();
filter.addAction(FrdFragment.
CTL_ACTION);
registerReceiver(
serviceReceiver,filter);
mPlayer=new MediaPlayer();
//为MediaPlayer播放完成事件绑定监听器
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
current++;
Intent sendIntent2 =
new Intent(FrdFragment.UPDATE_ACTION);
sendIntent2.putExtra(
"current",current);
//发送广播,将被Activity组件中的BroadcastReceiver接收
sendBroadcast(sendIntent2);
if (current>4)
{
current=0;
}
Intent sendIntent3 =
new Intent(FrdFragment.UPDATE_ACTION);
sendIntent3.putExtra(
"current",current);
//发送广播,将被Activity组件中的BroadcastReceiver接收
sendBroadcast(sendIntent3);
//准备播放音乐
prepareAndPlay(musics[current]);
}
});
}
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int control =intent.getIntExtra("control",-1);
switch (control)
{
//播放或暂停
case 1:
//原来处于没有播放状态
if (status==0x11)
{
//准备并播放音乐
prepareAndPlay(musics[current]);
status=0x12;
}
//原来处于播放状态
else if (status==0x12)
{
//暂停
mPlayer.pause();
//改变为暂停状态
status=0x13;
}
//原来处于暂停状态
else if (status==0x13)
{
//播放
mPlayer.start();
//改变状态
status=0x12;
}
break;
//停止声音
case 2:
//如果原来正在播放或暂停
if (status==0x12||status==0x13) {
//停止播放
mPlayer.stop();
status = 0x11;
}
break;
case 3:
//原来处于没有播放或暂停状态
if (status==0x11||status==0x13)
{
if(current==0) {
current=4;
}
//准备并播放音乐
else {
current=current-1;
}
prepareAndPlay(
musics[current]);
status=0x12;
}
//原来处于播放状态
else if (status==0x12)
{
//上一首//准备并播放音乐
if(current==0) {
current=4;
}
else {
current=current-1;
}
prepareAndPlay(
musics[current]);
}
break;
case 4:
//原来处于没有播放或暂停状态
if (status==0x11||status==0x13)
{
if(current==4) {
current=0;
}
//准备并播放音乐
else {
current=current+1;
}
prepareAndPlay(
musics[current]);
status=0x12;
}
else if (status==0x12)
{
if(current==4) {
current=0;
}
else {
current=current+1;
}
prepareAndPlay(
musics[current]);
}
break;
}
//广播通知Activity更改图标、文本框
Intent sendIntent=new Intent(FrdFragment.UPDATE_ACTION);
sendIntent.putExtra(
"update",status);
sendIntent.putExtra(
"current",current);
//发送广播,将被Activity组件中的BroadcastReceiver接收
sendBroadcast(sendIntent);
}
}
private void prepareAndPlay(String music)
{
try
{
//打开指定音乐文件
AssetFileDescriptor afd=am.openFd(music);
mPlayer.reset();
//使用MediaPlayer加载指定的音乐文件
mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
//准备声音
mPlayer.prepare();
//播放
mPlayer.start();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
结果截图: