源码在最后哦!

一、Service组件介绍

1、Service

        Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。

        虽然服务是在后台运行的,但是Service和Activity都是运行在当前APP所在的main thread(UI主线程)中的,而耗时操作(如网络请求、拷贝数据、大文件)会阻塞主线程,给用户带来不好的体验。如果需要在服务中进行耗时操作,可以选择 IntentService,IntentService是Service的子类,用来处理异步请求。

2、Service启动的两种方式

(1)在Acitivity界面通过显式意图(或隐式意图)的方式来启动服务和关闭服务。

Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);
 startService(intentService);

(2)bindService()绑定服务

        当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

二、实现简单音乐播放器

1、首先创建一个Service

        创建Service直接在Android Studio中右键选择Service创建即可。默认我们所创建的Service是继承Service的。同时我们为了实现后台音乐播放的功能,所以我们还要实MediaPlayer.OnCompletionListener的接口。

        同时还要在AndroidManifest.xml文件中对已经创建的Service进行注册,这一点Android Studio已经帮我们自动创建好了。

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

        创建 AudioServiceOnBind服务,在应用时通过绑定的方式进行服务调用。

public class AudioServiceOnBind extends Service implements MediaPlayer.OnCompletionListener{

    private final IBinder binder = new AudioBinder();
   
    public AudioServiceOnBind() {
        super();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onStartCommand()");
     return 0;
    }
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
    @Override
    public void onCreate(){
        super.onCreate();
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onCreate()");
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        stopSelf();
    }

    @Override
    public void onDestroy(){
       super.onDestroy();
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onDestroy()");
    }

    //为了和Activity交互,我们需要定义一个Binder对象
    class AudioBinder extends Binder {

        //返回Service对象
        AudioServiceOnBind getService(){
            return AudioServiceOnBind.this;
        }
    }
}

2、实现媒体播放功能

(1)首先准备好需要播放的音乐资源,放在res目录下的raw文件下。

        

Android 代码播放提示音 安卓service代码播放音乐_ide

(2)在Service中 重写onCreate()方法实现对媒体资源的加载以及播放。

//用于播放音乐等媒体资源
    private MediaPlayer mediaPlayer;

 @Override
    public void onCreate(){
        super.onCreate();
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onCreate()");
        if (mediaPlayer==null){
            mediaPlayer=MediaPlayer.create(this,R.raw.gumeng);
            mediaPlayer.setOnCompletionListener(this);
        }
        mediaPlayer.start();
    }

 (3)实现播放暂停功能

public void pause() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }

 (4)实现继续播放功能

public void play() {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    }

(5)实现服务销毁时释放资源

@Override
    public void onDestroy(){
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        stopForeground(true);

        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onDestroy()");
    }

(6)Service完整代码

public class AudioServiceOnBind extends Service implements MediaPlayer.OnCompletionListener{

    private final IBinder binder = new AudioBinder();
    //用于播放音乐等媒体资源
    private MediaPlayer mediaPlayer;

    public AudioServiceOnBind() {
        super();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onStartCommand()");
       
        return 0;
    }

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

    @Override
    public void onCreate(){
        super.onCreate();
        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onCreate()");
        if (mediaPlayer==null){
            mediaPlayer=MediaPlayer.create(this,R.raw.gumeng);
            mediaPlayer.setOnCompletionListener(this);
        }
        mediaPlayer.start();
    }


    @Override
    public void onCompletion(MediaPlayer mp) {
        stopSelf();
    }

    @Override
    public void onDestroy(){
        if(mediaPlayer.isPlaying()){
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        stopForeground(true);

        Log.d(AudioServiceOnBind.this.getClass().getName(),"执行onDestroy()");
    }

    public void pause() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }

    public void play() {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    }

    //为了和Activity交互,我们需要定义一个Binder对象
    class AudioBinder extends Binder {

        //返回Service对象
        AudioServiceOnBind getService(){
            return AudioServiceOnBind.this;
        }
    }
}

3、实现对音乐播放服务的调用

(1)创建一个Activity

public class MainActivity extends AppCompatActivity {

    private AudioServiceOnBind audioServiceOnBind;

    //使用ServiceConnection来监听Service状态的变化
    private ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            audioServiceOnBind = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            //这里我们实例化audioService,通过binder来实现
            audioServiceOnBind = ((AudioServiceOnBind.AudioBinder) binder).getService();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Objects.requireNonNull(getSupportActionBar()).hide();

        setContentView(R.layout.activity_main);
        requestWindowFeature(Window.FEATURE_NO_TITLE); 

        setStatusBarFullTransparent();
        System.out.println("MainActivity:onCreate()方法执行了,主界面被创建了");
    }

    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("MainActivity:onStart()方法执行了,界面可以看到了");
    }

    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("MainActivity:onResume()方法执行了,我获得焦点了");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("MainActivity:onRestart()方法执行了,用户重启界面了");
    }

    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("MainActivity:onPause()方法执行了,我失去焦点了");
    }

    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("MainActivity:onStop()方法执行了,界面看不见了");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("MainActivity:onDestroy()方法执行了,界面被销毁了");
    }

  
    //点击播放音乐按钮进行服务绑定
    public void click_music_open(View view) {
        Intent intentService = new Intent(MainActivity.this, AudioServiceOnBind.class);
        bindService(intentService, conn, Context.BIND_AUTO_CREATE);

    }
    //暂停播放音乐
    public void click_music_pause(View view) {
        audioServiceOnBind.pause();
    }
    //继续播放
    public void music_button_play(View view) {
        audioServiceOnBind.play();
    }
    //停止播放
    public void click_music_stop(View view) {
        unbindService(conn);
    }
}

(2)定义界面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/fullwhite"
    android:orientation="vertical"
    tools:context=".MainActivity"
    tools:visibility="visible">

        <TextView
            android:id="@+id/text_viwe"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="40dp"
            android:gravity="center_horizontal"
            android:text="@string/activity"
            android:textSize="20sp"
            tools:ignore="MissingConstraints" />

        <Button
            android:id="@+id/music_button_open"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="30dp"
            android:layout_marginRight="50dp"
            android:onClick="click_music_open"
            android:text="播放音乐"
            tools:ignore="MissingConstraints" />

        <Button
            android:id="@+id/music_button_pause"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="30dp"
            android:layout_marginRight="50dp"
            android:onClick="click_music_pause"
            android:text="暂停播放"
            tools:ignore="MissingConstraints" />

        <Button
            android:id="@+id/music_button_play"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="30dp"
            android:layout_marginRight="50dp"
            android:onClick="music_button_play"
            android:text="继续播放"
            tools:ignore="MissingConstraints" />

        <Button
            android:id="@+id/music_button_stop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="20dp"
            android:layout_marginRight="50dp"
            android:onClick="click_music_stop"
            android:text="停止播放"
            tools:ignore="MissingConstraints" />

</LinearLayout>