【Android】Service+Seek Bar实现后台音乐播放器小呆萌

1. Android四大组件之Service

相信大家对于身为四大组件之一的Service一定很熟悉。Service可以运行在后台来处理一些耗时操作,也可以用来维持一些需要长期运行的任务,甚至可以在用户退出程序是仍然运行在后台中。作为一个初学者,我可以联想到很多关于Service的应用场景。比如:闹钟、音乐播放器等等。
今天我就来给大家展示一个关于音乐播放器退出时后台播放的小Demo。

2.Android控件SeekBar

SeekBar相当与ProgressBar的一个扩展,SeekBar的主要应用场景是在多媒体播放器当中,用来控制播放的进度;也用作一些范围型参数的选择器,比如我们常见的音量调节和屏幕亮度调节。
【Android】Service+Seek Bar实现后台音乐播放器小呆萌_第1张图片

3.Demo的具体实现

1.创建一个Service

首先进入到我们的工程,创建一个新的package为Service,再到其中创建一个MusicBindService类。
为了实现音乐播放的一些功能我们需要在这个类中新建一个MusicController方法,继承Binder类实现对内部组件的绑定。
下面就是MusicBindService的具体实现。

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;

import com.jinni.servicedemo.R;

public class MusicBindService extends Service {

    private MediaPlayer mPlayer;

    public MusicBindService() {
    }

    /*
    * 绑定服务的实现流程:
    * 1.服务 onCreate, onBind, onDestroy 方法
    * 2.onBind 方法需要返回一个 IBinder 对象
    * 3.如果 Activity 绑定,Activity 就可以取到 IBinder 对象,可以直接调用对象的方法
    */

    // 相同应用内部不同组件绑定,可以使用内部类以及Binder对象来返回。
    public class MusicController extends Binder {
        public void play() {
            mPlayer.start();//开启音乐
        }

        public void pause() {
            mPlayer.pause();//暂停音乐
        }

        public long getMusicDuration() {
            return mPlayer.getDuration();//获取文件的总长度
        }

        public long getPosition() {
            return mPlayer.getCurrentPosition();//获取当前播放进度
        }

        public void setPosition (int position) {
            mPlayer.seekTo(position);//重新设定播放进度
        }
    }

    /**
     * 当绑定服务的时候,自动回调这个方法
     * 返回的对象可以直接操作Service内部的内容
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        return new MusicController();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mPlayer = MediaPlayer.create(this, R.raw.nobody);
    }

    /**
     * 任意一次unbindService()方法,都会触发这个方法
     * 用于释放一些绑定时使用的资源
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        if (mPlayer.isPlaying()) {
            mPlayer.stop();
        }
        mPlayer.release();
        mPlayer = null;
        super.onDestroy();
    }
}

2. MusicActivity的实现

首先进入我们的布局文件当中,编辑一个简单的音乐播放器界面。当中不仅加入了SeekBar同时还加入了一个ProgressBar作为对比。STOP按钮是用来停止服务的,点击之后退出程序将不会继续在后台播放音乐。在编写代码之前,还需要在res文件夹中新建一个raw文件夹,并且将我们的音乐文件拷贝到里面。
【Android】Service+Seek Bar实现后台音乐播放器小呆萌_第2张图片【Android】Service+Seek Bar实现后台音乐播放器小呆萌_第3张图片

1.activity_music.xml


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.jinni.servicedemo.MusicActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="btnMusicPlay"
        android:text="Play"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="btnMusicPause"
        android:text="Pause"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="btnStopService"
        android:text="Stop"/>

    <TextSwitcher
        android:id="@+id/text_switcher"
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    TextSwitcher>

    <ProgressBar
        android:id="@+id/music_progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <SeekBar
        android:id="@+id/music_seek_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
LinearLayout>

2.MusicActivity.java

package com.jinni.servicedemo;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextSwitcher;
import com.jinni.servicedemo.services.MusicBindService;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MusicActivity extends AppCompatActivity implements Runnable, ServiceConnection, SeekBar.OnSeekBarChangeListener {

    private static final String TAG = MusicActivity.class.getSimpleName();
    private MusicBindService.MusicController mMusicController;
    private ProgressBar mProgressBar;
    private boolean running;
    private TextSwitcher mSwitcher;
    private SeekBar mSeekBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music);
        mSeekBar = (SeekBar) findViewById(R.id.music_seek_bar);
        mSeekBar.setOnSeekBarChangeListener(this);
        mProgressBar = ((ProgressBar) findViewById(R.id.music_progress));
        mSwitcher = (TextSwitcher) findViewById(R.id.text_switcher);
        mSwitcher.setInAnimation(this, android.R.anim.fade_in);
        mSwitcher.setOutAnimation(this, android.R.anim.fade_out);
        Intent intent = new Intent(this, MusicBindService.class);
        //增加StartService,来增加后台播放功能
        startService(intent);
        // 绑定服务,使用context来绑定
        // 那个界面需要绑定 就用哪个 Activity
        // 参数1:Intent               代表需要绑定哪一个Service
        // 参数2:ServiceConnection    回调接口,可以接收到Service连接成功和断开的回调,成功就可以取到对象。
        // 绑定服务 参数2就是服务和指定的对象绑定在一起
        bindService(intent, this, BIND_AUTO_CREATE);

    }

    @Override
    protected void onStart() {
        super.onStart();
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    protected void onStop() {
        running = false;
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        // 解除绑定
        unbindService(this);
        super.onDestroy();
    }

    //------------------------

    @Override
    public void run() {
        running = true;
        try {
            while (running) {
                if (mMusicController != null) {
                    long musicDuration = mMusicController.getMusicDuration();
                    final long position = mMusicController.getPosition();
                    final Date dateTotal = new Date(musicDuration);
                    final SimpleDateFormat sb = new SimpleDateFormat("mm:ss");
                    mProgressBar.setMax(((int) musicDuration));
                    mProgressBar.setProgress(((int) position));
                    mSeekBar.setMax((int) musicDuration);
                    mSeekBar.setProgress((int) position);
                    mSwitcher.post(
                            new Runnable() {
                                @Override
                                public void run() {
                                    Date date = new Date(position);
                                    String time = sb.format(date) + "/" + sb.format(dateTotal);
                                    mSwitcher.setCurrentText(time);
                                }
                            }
                    );
                }

                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //------------------------
    public void btnMusicPlay(View view) {
        if (mMusicController != null) {
            mMusicController.play();
        }
    }

    public void btnMusicPause(View view) {
        if (mMusicController != null) {
            mMusicController.pause();
        }
    }

    //-----------------------------
    //服务绑定与解除绑定的回调

    /**
     * 当服务与当前绑定对象,绑定成功,服务onBind方法调用并且返回之后
     * 回调给这个方法
     *
     * @param name
     * @param service IBinder 就是服务 onBind 返回的对象
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mMusicController = ((MusicBindService.MusicController) service);
    }

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

    public void btnStopService(View view) {
        Intent intent = new Intent(this, MusicBindService.class);
        stopService(intent);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        mMusicController.setPosition(seekBar.getProgress());
    }
}

第一次写博客,写得好希望大家可以点个赞,如果不好也希望大家多多指点,谢谢大家!

你可能感兴趣的:(Android)