从音乐播放器谈Service
2017-01-06 16:01
323 查看
Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色。它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。
![](https://img-blog.csdn.net/20170106155833176?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzU3MDMyMzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这种service可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它。
当service被停止时,系统会销毁它。
客户可以通过一个IBinder接口和service进行通信。
客户可以通过 unbindService()方法来关闭这种连接。
1.Service与Activity之间可以相互调用(bindService,拿到一个binder实例任意调用)
2.如果采用bindService Service实例生命周期与Activity绑定到一起了,如果Activity销毁,Service也会销毁,那么不能做到后台播放
startService(Service实例与启动者的生命周期无关,除非调用stopService方法而消亡)
bindService(Service实例与启动者的生命周期关联,用户手动调用unbindService或者Activity消亡会跟着消亡)
两种方式各有千秋,结合起来可以实现灵活控制
比如,一个音乐播放service可以在onCreate()中创建播放音乐的线程,在onDestory()中停止这个线程。
onCreate() 和 onDestroy()会被所有的service调用,不论service是通过startService()还是bindService()建立。
因此,如果你的service是一个纯粹的绑定service,那么你不需要管理它的生命周期。然而,如果你选择实现onStartCommand()回调方法,那么你必须显式地停止service,因为service此时被看做是开启的。这种情况下,service会一直运行到它自己调用stopSelf()或另一个组件调用stopService(),不论它是否和客户端绑定。 另外,如果你的service被开启并且接受绑定,那么当系统调用你的onUnbind()方法时,如果你想要在下次客户端绑定的时候接受一个onRebind()的调用(而不是调用onBind()),你可以选择在onUnbind()中返回true。onRebind()的返回值为void,但是客户端仍然在它的 onServiceConnected()回调方法中得到 IBinder 对象。
![](https://img-blog.csdn.net/20170106155908883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzU3MDMyMzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
简单的音乐播放器代码:
public class MainActivity extends Activity {
private Button mPlayBtn;
private Button mStopBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayBtn = (Button) findViewById(R.id.play_pause);
mPlayBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Started
Intent intent = new Intent();
intent.putExtra(“command”, “play”);
intent.setClass(MainActivity.this, MusicService.class);
startService(intent);
}
});
mStopBtn = (Button) findViewById(R.id.stop_play);
mStopBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Stop
stopService(new Intent(MainActivity.this, MusicService.class));
}
});
findViewById(R.id.next).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//切换下一首歌曲
Intent intent = new Intent();
intent.putExtra(“command”, “next”);
intent.setClass(MainActivity.this, MusicService.class);
startService(intent);
}
});
}
}
import java.util.ArrayList;
import java.util.List;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
public class MusicService extends Service {
}
注意。由于Service是四大组建:一定要在清单文件中声明:
android:name=”.MusicService”
![](https://img-blog.csdn.net/20170106155939192?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzU3MDMyMzQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1. startedService
被开启的service通过其他组件调用 startService()被创建。这种service可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它。
当service被停止时,系统会销毁它。
2.boundService
被绑定的service是当其他组件(一个客户)调用bindService()来创建的。客户可以通过一个IBinder接口和service进行通信。
客户可以通过 unbindService()方法来关闭这种连接。
注意:
一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。1.Service与Activity之间可以相互调用(bindService,拿到一个binder实例任意调用)
2.如果采用bindService Service实例生命周期与Activity绑定到一起了,如果Activity销毁,Service也会销毁,那么不能做到后台播放
startService(Service实例与启动者的生命周期无关,除非调用stopService方法而消亡)
bindService(Service实例与启动者的生命周期关联,用户手动调用unbindService或者Activity消亡会跟着消亡)
两种方式各有千秋,结合起来可以实现灵活控制
生命周期
service整体的生命时间是从onCreate()被调用开始,到onDestroy()方法返回为止。和activity一样,service在onCreate()中进行它的初始化工作,在onDestroy()中释放残留的资源。比如,一个音乐播放service可以在onCreate()中创建播放音乐的线程,在onDestory()中停止这个线程。
onCreate() 和 onDestroy()会被所有的service调用,不论service是通过startService()还是bindService()建立。
BindService:
当绑定service和所有客户端解除绑定之后,Android系统将会销毁它,(除非它同时被onStartCommand()方法开启)。因此,如果你的service是一个纯粹的绑定service,那么你不需要管理它的生命周期。然而,如果你选择实现onStartCommand()回调方法,那么你必须显式地停止service,因为service此时被看做是开启的。这种情况下,service会一直运行到它自己调用stopSelf()或另一个组件调用stopService(),不论它是否和客户端绑定。 另外,如果你的service被开启并且接受绑定,那么当系统调用你的onUnbind()方法时,如果你想要在下次客户端绑定的时候接受一个onRebind()的调用(而不是调用onBind()),你可以选择在onUnbind()中返回true。onRebind()的返回值为void,但是客户端仍然在它的 onServiceConnected()回调方法中得到 IBinder 对象。
简单的音乐播放器代码:
public class MainActivity extends Activity {
private Button mPlayBtn;
private Button mStopBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayBtn = (Button) findViewById(R.id.play_pause);
mPlayBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Started
Intent intent = new Intent();
intent.putExtra(“command”, “play”);
intent.setClass(MainActivity.this, MusicService.class);
startService(intent);
}
});
mStopBtn = (Button) findViewById(R.id.stop_play);
mStopBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Stop
stopService(new Intent(MainActivity.this, MusicService.class));
}
});
findViewById(R.id.next).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//切换下一首歌曲
Intent intent = new Intent();
intent.putExtra(“command”, “next”);
intent.setClass(MainActivity.this, MusicService.class);
startService(intent);
}
});
}
}
Service代码:
package com.example.lesson18_service_start;import java.util.ArrayList;
import java.util.List;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
public class MusicService extends Service {
MediaPlayer mediaPlayer; List<Integer> songList = new ArrayList<>(); List<String> songNameList = new ArrayList<>(); int playIndex;// 当前播放歌曲的下标 @Override public void onCreate() {// Service实例被创建 super.onCreate(); Log.i("at22", "onCreate"); // 歌曲的资源集合 songList.add(R.raw.abc); songList.add(R.raw.areyouok); songList.add(R.raw.zxmzf); // 歌曲的名字 songNameList.add("abc"); songNameList.add("areyouok"); songNameList.add("zxmzf"); mediaPlayer = MediaPlayer.create(this, songList.get(playIndex)); // 第一次播放的时候更新通知栏的歌曲名字 updateNotification(); } /** * 更新通知栏 */ private void updateNotification() { //创建能兼容v7以上的通知栏构建者对象 NotificationCompat.Builder builder = new NotificationCompat.Builder( this); // 通知栏三个必须的属性需要设置 builder.setSmallIcon(R.drawable.ic_launcher); // builder.setContentText("abc");//自定义通知视图可以不写 // builder.setContentTitle("abc title");//自定义通知视图可以不写 //创建通知栏中自定义视图的类 RemoteViews views = new RemoteViews(getPackageName(), R.layout.notification_layout); //获取当前的歌曲名字 String songName = songNameList.get(playIndex); // 更新RemoteView中的文本内容 views.setTextViewText(R.id.song, songName); Intent intent = new Intent();//下一首的歌曲 intent.putExtra("command", "next"); intent.setClass(this, MusicService.class); Pendin 4000 gIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 给RemoteView中的某个视图这是点击处理 views.setOnClickPendingIntent(R.id.next, pendingIntent);//第一个参数是下一首button视图的id // 将自定义视图设置到通知栏中去 builder.setContent(views); //启动一个通知与当前的服务“命运”关联 startForeground(111, builder.build()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { String command = intent.getStringExtra("command"); if ("play".equals(command)) { playOrPause(); } else if ("next".equals(command)) { playNext(); } Log.i("at22", "onStartCommand" + command); return super.onStartCommand(intent, flags, startId); } private void playNext() { if (mediaPlayer != null) {// 释放播放器 mediaPlayer.stop(); mediaPlayer.release(); } playIndex++; if (playIndex >= songList.size()) {// 切换下一首歌曲 playIndex = 0; } int songRawId = songList.get(playIndex);// 歌曲的资源id mediaPlayer = MediaPlayer.create(this, songRawId); mediaPlayer.start(); // 有歌曲名变化时通知栏更新 updateNotification(); } private void playOrPause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) {//如果正在播放就暂停 mediaPlayer.pause();//暂停 } else { mediaPlayer.start();//播放 } } @Override public void onDestroy() {// Service实例被销毁 super.onDestroy(); Log.i("at22", "onDestroy"); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; }
}
注意。由于Service是四大组建:一定要在清单文件中声明:
android:name=”.MusicService”
音乐播放器源代码:代码链接
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题