实战中了解四大组件(至善影音二)
Android
上一篇文章给大家介绍了一些关于VideoPlayer.同样为多媒体知识,今天就为大家讲解一下我们需要实现的音乐播放器.
首先为了完成AudioFragment页面,我们应该采用跟昨天一样的方式,利用ListView+Adapter的方式,这里我就不过多讲解了.
大家平时使用音乐软件的时候,有没有发现其实很多的音乐软件,就算退出了Activity,他们仍可以在后台播放.,那么引出了今天重点Service服务的,作为四大组件,昨天我们应该已经讲解了三个,今天我就来讲解一下Service的作用.
服务是不需要跟用户进行交互,不依赖于任何用户界面,即使程序被切到了后台,仍可以保持正常运行.当然服务是依靠应用程序进程的,当我们杀死了进程,还是会停掉这个服务的.
Service
创建Service类继承Service—实现方法onBind,实现Activity与Service之间的绑定.
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return audioServiceBinder;
}
Activity绑定Service
Intent intent = new Intent(this,AudioPlayService.class);
audioServiceConnection=new AudioServiceConnection();
startService(intent);//这个方法是传递数据-->对应Service--Start();
bindService(intent, audioServiceConnection, Service.BIND_AUTO_CREATE);
这里我们需要注意的是Acivity绑定Service是通过发送一个Intent,所以我们一直强调Intent意图的作用.
bindService(Intent service, ServiceConnection conn, int flags) ;//是实现绑定Service的方法.
参数分析:
参数1:连接的Intent
参数2:服务连接类
参数3:标记,服务创建的类型
这里我们对于服务连接类需要解析:
首先服务连接类ServiceConnection,包含两个回调方法
onServiceConnected()
其中参数Ibinder就是Service,onBind()返回的Binder类对象,作为一个信鸽,作为Service和Activity交互的代理类,其实一般来说我们可以认为假如OnBind()返回Null,就是不交互.
系统调用这个来传送在service的onBind()中返回的IBinder.
OnServiceDisconnected()
当上面的我们处理过后,我们就能完成Service和Activity的交互.
而对于交互的两者,我们可以将处理方法逻辑,包括歌曲的播放,暂停等可以放到Binder下,然后再调用他们的对象的方法去处理.
到了这里,我仍要说一个注意点,就是Service是后台运行的,他获取的数据是当时Activity运行时候,通过Intent传递对象进来的,然而他一直能够使用这些数据,但是Activity一旦销毁,Activity自身的数据就会被销毁,那么对于这些数据,我们应该使用Service进行保存,然后Service就能把这个数据更新赋值给Activity.
//利用通知-->然后发送广播
private void notifyPrepare(){
//利用广播来传递数据
Intent intent=new Intent(ACION_MEDIA_PREPARED);
Bundle bundle=new Bundle();
bundle.putSerializable("audioItem", audioList.get(currentPosition));
intent.putExtras(bundle);
sendBroadcast(intent);
}
那么这个时候,我们应该要使用发一个通知显示准备,儿广播中我们要携带数据,那么我们就要在Activity中注册广播接收器.Activity这边接到通知就设定数据给相关的控件.
Notification
正如我们刚刚说的,我们按照日常的APP运行,日常的app运行都会利用后台运行一个自定义notification.那么今天我们就来写一下这个notification.
先完成布局
获取NotificationManager(管理)
notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Notification
private void sendNotification(){
AudioItem audioItem = audioList.get(currentPosition);
Notification.Builder builder = new Notification.Builder(this);
//这种写法是推荐的,所以我认为以后我们还是这么写吧
builder.setOngoing(true) //一直都在
.setSmallIcon(R.drawable.notification_music_playing) //設置圖片
.setTicker("正在播放:"+StringUtil.formatAudioName(audioItem.getTitle()))//設定通知時候 橫欄上顯示的一句話
.setWhen(System.currentTimeMillis()) //時間
.setContent(getRemoteViews()); //佈局
//notificationManager.notify(1, builder.build());
startForeground(1, builder.build());
}
同学会看到上面存在一个setContent()的方法,这就是我们要填充布局的.
设定自定义布局–利用RemoteViews
顾名思义,它是一个远程视图。App Widget中的视图,都是通过RemoteViews表现的。
在RemoteViews的构造函数中,通过传入layout文件的id来获取 “layout文件对应的视图(RemoteViews)”;然后,调用RemoteViews中的方法能对layout中的组件进行设置(例如,可以调用setTextViewText()来设置TextView组件的文本,可以调用setOnClickPendingIntent() 来设置Button的点击响应事件)。
说明:
(01) RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
获取布局对应的 RemoteViews ;进而通过RemoteViews对 布局中的各个元素进行管理。
(02) rv.setOnClickPendingIntent(R.id.bt_refresh, btPendingIntent);
设置 点击“按钮”时会触发的Intent 。从而对按钮点击事件进行处理。
private RemoteViews getRemoteViews(){
AudioItem audioItem = audioList.get(currentPosition);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification);
remoteViews.setTextViewText(R.id.tv_song_name, StringUtil.formatAudioName(audioItem.getTitle())); //设置歌曲名
remoteViews.setTextViewText(R.id.tv_artist_name, audioItem.getArtist());
//传进来的是点击的常量--构建通知
//去上一个
Intent preIntent = createNotificationIntent(VIEW_PRE);//
PendingIntent preContentIntent = PendingIntent.getService(this, 0, preIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.iv_notification_pre, preContentIntent);
//去下一个
Intent nextIntent = createNotificationIntent(VIEW_NEXT);
PendingIntent nextContentIntent = PendingIntent.getService(this, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.iv_notification_next, nextContentIntent);
Intent containerIntent = createNotificationIntent(VIEW_CONTAINER);;
PendingIntent containerContentIntent = PendingIntent.getActivity(this, 2, containerIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.notification_container, containerContentIntent);
return remoteViews;
}