之前的一段时间在学习服务和广播这两个知识点,然后在网上看到一些对于后台操作需要通过服务与广播的一些例子,便索性做一个小demo对这些知识点进行巩固;通过服务+广播+通知对后台音乐进行播放、暂停、停止这三样简单的控制。
创建demo后的第一步便是创建服务,创建一个名为MusicService的类,继承Service类;然后在MusicService里实现音乐文件的初始化,同时创建各种方法对音乐播放的控制,其中音乐控制相关方法与通知控制都设为静态,其他类可直接通过类进行调用,以下为代码,材料自找
public class MusicService extends Service {
private static MediaPlayer mediaPlayer; //声明操作媒体的对象
static int pos = 0; //记录播放的位置
private static NotificationManager notificationManager;
private String TAG = "media";
private static Notification notification;
class MyBinder extends Binder{
public MusicService getService(){
//绑定服务同时进行播放
play();
return MusicService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
showMusicNotification();
//初始化播放对象
if (mediaPlayer == null){
mediaPlayer = mediaPlayer.create(MusicService.this,R.raw.lit);
mediaPlayer.setLooping(false);
}
//监听播放结束,释放资源
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
}
});
}
//用于开始播放的方法
public static void play(){
if (mediaPlayer != null && !mediaPlayer.isPlaying()){
try {
if (pos != 0){
//根据指定位置进行播放
mediaPlayer.seekTo(pos);
mediaPlayer.start();
}else {
//首次或从头播放,并显示通知
notificationManager.notify(200,notification);
mediaPlayer.stop();
mediaPlayer.prepare();
mediaPlayer.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//暂停播放
public static void pause(){
if (mediaPlayer != null && mediaPlayer.isPlaying()){
//获取播放位置
pos = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
}
}
//停止播放
public static void stop(){
if (mediaPlayer != null){
mediaPlayer.stop();
pos = 0; //停止后播放位置置为0
}
}
服务类需要在AndroidManifest.xml里进行注册
<service
android:name=".MusicService"
android:enabled="true"
android:exported="true"/>
接着是创建通知,通过使用RemoteViews类创建自定义通知样式的对象,样式自己可通过创建布局进行自定义,而其中对布局控件的点击操作是通过发送广播进行操作
public void showMusicNotification(){
Notification.Builder builder = new Notification.Builder(this);
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification);
remoteViews.setImageViewResource(R.id.image,R.drawable.timg);
builder.setContent(remoteViews)
.setWhen(System.currentTimeMillis())
.setTicker("正在播放")
.setPriority(Notification.PRIORITY_DEFAULT)
.setAutoCancel(false)
.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher);
//通知栏控制器播放按钮广播操作
Intent intentPlay = new Intent("play");//新建意图,设置action标记为“play”,用于接收广播时过滤意图信息
PendingIntent playPendingIntent = PendingIntent.getBroadcast(this,0,intentPlay,0);
remoteViews.setOnClickPendingIntent(R.id.play,playPendingIntent);//为play控件注册事件
//通知栏控制器暂停按钮广播操作
Intent intentPause = new Intent("pause");
PendingIntent pausePendingIntent = PendingIntent.getBroadcast(this,0,intentPause,0);
remoteViews.setOnClickPendingIntent(R.id.pause,pausePendingIntent);
//通知栏控制器停止按钮广播操作
Intent intentStop = new Intent("stop");
PendingIntent stopPendingIntent = PendingIntent.getBroadcast(this,0,intentStop,0);
remoteViews.setOnClickPendingIntent(R.id.stop,stopPendingIntent);
通知栏控制器关闭通知按钮广播操作
Intent intentDead = new Intent("clear");
PendingIntent deadPendingIntent = PendingIntent.getBroadcast(this,0,intentDead,0);
remoteViews.setOnClickPendingIntent(R.id.dead,deadPendingIntent);
notification = builder.build();
notification.flags = notification.FLAG_ONGOING_EVENT;
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
以下是我的通知栏的布局文件,图片可网上找
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="80dp">
<ImageView
android:id="@+id/image"
android:src="@mipmap/ic_launcher"
android:layout_width="80dp"
android:layout_height="80dp" />
<LinearLayout
android:layout_centerInParent="true"
android:layout_toRightOf="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:src="@mipmap/pause"
android:id="@+id/pause"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:layout_marginTop="10dp"
android:layout_marginLeft="40dp"
android:src="@mipmap/play"
android:id="@+id/play"
android:layout_width="40dp"
android:layout_height="40dp" />
<ImageView
android:layout_marginTop="10dp"
android:layout_marginLeft="40dp"
android:src="@mipmap/stop"
android:id="@+id/stop"
android:layout_width="40dp"
android:layout_height="40dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp">
<ImageView
android:id="@+id/dead"
android:src="@mipmap/clear"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
接下来是广播接收器,创建名为MusicReciver的类,继承BroadcastReceiver类,以下为代码文件
public class MusicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String ctrl_code = intent.getAction();
if ("play".equals(ctrl_code)){
//通知栏音乐播放操作
MusicService.play();
}else if ("pause".equals(ctrl_code)){
//通知栏音乐暂停操作
MusicService.pause();
}else if ("stop".equals(ctrl_code)){
//通知栏音乐停止操作
MusicService.stop();
}else if ("clear".equals(ctrl_code)){
//通知栏关闭通知操作
MusicService.clearNotification();
MusicService.stop();
}
}
}
接收器需要在AndroidManifest.xml里进行注册,并且自定义的广播消息需要在注册的接收器内进行定义,否则程序会报错
<receiver android:name=".MusicReceiver"
android:exported="true">
<intent-filter>
<action android:name="play"/>
<action android:name="pause"/>
<action android:name="stop"/>
<action android:name="clear"/>
</intent-filter>
</receiver>
最后的是主activity的布局与类文件,主布局如下
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.li.musictest.MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/timg"
android:layout_marginTop="100dp"
android:layout_centerHorizontal="true"
android:layout_width="200dp"
android:layout_height="200dp" />
<LinearLayout
android:layout_marginBottom="100dp"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_toRightOf="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="@mipmap/pause"
android:id="@+id/pause"
android:layout_width="50dp"
android:layout_height="50dp" />
<ImageView
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:src="@mipmap/play"
android:id="@+id/play"
android:layout_width="50dp"
android:layout_height="50dp" />
<ImageView
android:src="@mipmap/stop"
android:id="@+id/stop"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
</RelativeLayout>
主类主要实现主布局的点击操作,其中有一内部类继承了ServiceConnection类,为与服务通讯的主要实现类,其余是我们平常的点击操作
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Intent intent;
private MusicService musicService;
private MusicConnection myConnection = new MusicConnection();
private String TAG = "media";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.play).setOnClickListener(this);
findViewById(R.id.pause).setOnClickListener(this);
findViewById(R.id.stop).setOnClickListener(this);
}
@Override
public void onClick(View v) {
//activity页面的相关点击操作
switch (v.getId()){
//播放
case R.id.play:
if (musicService == null) {
//首次播放绑定服务
intent = new Intent(MainActivity.this,MusicService.class);
bindService(intent,myConnection, Context.BIND_AUTO_CREATE);
startService(intent);
}else {
musicService.play();
}
break;
//暂停
case R.id.pause:
if (musicService != null){
musicService.pause();
}
break;
//停止
case R.id.stop:
if (musicService != null){
musicService.stop();
}
break;
}
}
private class MusicConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MyBinder myBinder = (MusicService.MyBinder) service;
musicService = myBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
myConnection = null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(myConnection);
MusicService.clearNotification();
Log.i(TAG, "onDestroy: ");
}
}
第一次写博客,可能有很多不足的地方,代码也可能有错误的地方,希望多加指正
以下为运行图