实现一个简单的播放器——Service,Handle和MediaPlayer的使用

实现一个简单的播放器,要求功能有:

1. 播放、暂停,停止,退出功能;

2. 后台播放功能;

3. 进度条显示播放进度、拖动进度条改变进度功能;

4. 播放时图片旋转,显示当前播放时间功能;

效果图:

图片旋转:

  图片布局:主要是要实现图片居中,还有就是id

 

       定义rotate旋转效果:在res/anim文件夹下新建tip.xml文件。

下面的代码表示从0到359度开始循环旋转,0-359(若设置成360在停止时会出现停顿现象)度旋转所用时间为10000ms,旋转中心距离view的左顶点为50%距离,距离view的上边缘为50%距离,即正中心.

 

android:fromDegrees 起始的角度度数

android:toDegrees 结束的角度度数,负数表示逆时针,正数表示顺时针。如10圈则比android:fromDegrees大3600即可

android:pivotX 旋转中心的X坐标

android:pivotY 旋转中心的Y坐标

浮点数或是百分比。浮点数表示相对于Object的左边缘,如5; 百分比表示相对于Object的左边缘,如5%; 另一种百分比表示相对于父容器的左边缘,如5%p; 一般设置为50%表示在Object中心

android:duration 表示从android:fromDegrees转动到android:toDegrees所花费的时间,单位为毫秒。可以用来计算速度。

android:interpolator表示变化率,但不是运行速度。一个插补属性,可以将动画效果设置为加速,减速,反复,反弹等。默认为开始和结束慢中间快,

android:startOffset 在调用start函数之后等待开始运行的时间,单位为毫秒,若为10,表示10ms后开始运行

android:repeatCount 重复的次数,默认为0,必须是int,可以为-1表示不停止

android:repeatMode 重复的模式,默认为restart,即重头开始重新运行,可以为reverse即从结束开始向前重新运行。在android:repeatCount大于0或为infinite时生效

android:detachWallpaper 表示是否在壁纸上运行

android:zAdjustment 表示被animated的内容在运行时在z轴上的位置,默认为normal。

normal保持内容当前的z轴顺序

top运行时在最顶层显示

bottom运行时在最底层显示

运行速度为运行时间(android:duration)除以运行角度差(android:toDegrees-android:fromDegrees)

 

setInterpolator表示设置旋转速率。LinearInterpolator为匀速效果,Accelerateinterpolator为加速效果、DecelerateInterpolator为减速效果

AnimationUtils.loadAnimation(this,R.anim.tip)就是加载一个动态效果,tip就是前面定义的xml。

开始旋转:imageview.startAnimation(operatingAnim)

停止旋转:imageview.clearAnimation();

代码:

package com.example.hp.lab6;

import android.app.Activity;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.media.Image;
import android.os.Handler;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

import java.text.SimpleDateFormat;


public class MainActivity extends Activity implements OnClickListener {

    private Button play_pauseBtn,stopBtn,quitBtn;
    private MusicService musicService;
    private ImageView imageview;
    private TextView state, playing_time,max_time;
    private SeekBar seekbar;
    private SimpleDateFormat time = new SimpleDateFormat("mm:ss");
    //Bitmap bmp = BitmapFactory.decodeResource(this.getResources(),R.mipmap.image);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);//绑定布局
        findView();//findIdByView,找到个个控件
        bindButton();//按钮绑定监听器。
        musicService=new MusicService();//新建一个MusicService后台服务
        connection();//绑定后台服务
        max_time.setText(time.format(musicService.mediaPlayer.getDuration()));//设置max_time这个textview的内容是歌曲的时间长度
        Animation operatingAnim = AnimationUtils.loadAnimation(this, R.anim.tip);
        LinearInterpolator lin = new LinearInterpolator();//LinearInterpolator为匀速效果
        operatingAnim.setInterpolator(lin);//setInterpolator表示设置旋转速率。
        imageview.startAnimation(operatingAnim);//开始旋转

    }

    private void findView(){
        /** 通过id获得各种组件 */
        play_pauseBtn=(Button) findViewById(R.id.play_pause);//开始/暂停按钮
        stopBtn=(Button) findViewById(R.id.stop);//停止按钮
        quitBtn=(Button) findViewById(R.id.quit);//退出按钮
        state=(TextView) findViewById(R.id.state);//seekbar上面表示状态的文字textview
        playing_time=(TextView) findViewById(R.id.playing_time);//seekbar左边现在播放的时间
        max_time=(TextView) findViewById(R.id.song_time);//播放的这首歌曲的时长
        seekbar=(SeekBar) findViewById(R.id.seekbar);//seekbar
        imageview=(ImageView ) findViewById(R.id.imageview);//旋转的图片
    }

    private void bindButton(){
        /** 为按钮添加监听 ,三个按钮的监听器都是MainActivity*/
        play_pauseBtn.setOnClickListener(this);
        stopBtn.setOnClickListener(this);
        quitBtn.setOnClickListener(this);
    }
    private ServiceConnection sc=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            musicService=((MusicService.MyBinder)service).getService();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            musicService=null;
        }
    };

    Handler mHandler=new Handler(); //创建Handler对象
    //要用handler来处理多线程可以使用runnable接口,这里先定义该接口,线程中运行该接口的run函数
    Runnable mRunnable=new Runnable() { //新建一个Runnable接口
        @Override
        public void run() {//将要执行的操作写在线程对象的run方法当中

            //Matrix mtx = new Matrix();
            //mtx.postRotate(1);
            // Rotating Bitmap
            //Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mtx, true);
            //BitmapDrawable bmd = new BitmapDrawable(rotatedBMP);
            //imageview.setImageDrawable(bmd);

            //设置seekbar左边的playing_time textview为当前歌曲播放到的时间
            playing_time.setText(time.format(musicService.mediaPlayer.getCurrentPosition()));
            //设置seekbar为当前歌曲播放到的时间
            seekbar.setProgress(musicService.mediaPlayer.getCurrentPosition());
            //seekbar条拖动监听事件
            seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override//seekbar发生改变时
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    if(fromUser){
                        musicService.mediaPlayer.seekTo(seekBar.getProgress());
                    }//根据seekbar拖动到的位置改变设置歌曲播放到的进度
                }
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                }
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                }
            });
            mHandler.postDelayed(mRunnable,100);//100ms执行一次tun()函数
        }
    };
    @Override
    public void onClick(View v){
        switch (v.getId()){
            case R.id.play_pause://点击play_pause按钮事件
                musicService.playORpuase();//调用musicService中的playORpause函数,暂停或开始音乐播放
                if(musicService.mediaPlayer.isPlaying()){
                    state.setText("Playing");//当音乐在播放时,我们设置state的内容为Playing
                    play_pauseBtn.setText("PAUSE");//设置button的内容为Puase
                    //Animation operatingAnim = AnimationUtils.loadAnimation(this, R.anim.tip);
                    //LinearInterpolator lin = new LinearInterpolator();//LinearInterpolator为匀速效果
                    //operatingAnim.setInterpolator(lin);//setInterpolator表示设置旋转速率。
                   // imageview.startAnimation(operatingAnim);//开始旋转
                }
                else{
                    state.setText("Paused");//当音乐停止时,设置state内容为Paused
                    play_pauseBtn.setText("PLAY");//button内容为Play
                }
                break;
            case R.id.stop://点击暂停
                musicService.stop();//关闭音乐
                play_pauseBtn.setText("PLAY");//设置开始和暂停按钮的内容为Play
                state.setText("Stop");//设置state为Stop
                //imageview.clearAnimation();
                break;
            case R.id.quit://点击退出
                mHandler.removeCallbacks(mRunnable);//回调mRunnable接口
                unbindService(sc);//解除后台服务的绑定
                try{
                    MainActivity.this.finish();//结束当前的时间
                    System.exit(0);
                }
                catch (Exception e){
                    e.printStackTrace();
                }
                break;
        }

    }

    private void connection(){
        //启动指定的Service
        Intent intent=new Intent(this ,MusicService.class);
        bindService(intent,sc,BIND_AUTO_CREATE);//绑定服务
    }

    @Override
    protected void onResume() {
        seekbar.setProgress(musicService.mediaPlayer.getCurrentPosition());
        seekbar.setMax(musicService.mediaPlayer.getDuration());
        mHandler.post(mRunnable);//通过Handler启动Runnable
        super.onResume();
    }

}
package com.example.hp.lab6;

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

public class MusicService extends Service {
    public MediaPlayer mediaPlayer=new MediaPlayer();
    private final IBinder binder=new MyBinder();
    public class MyBinder extends Binder {
        MusicService getService(){
            return MusicService.this;//找到后台服务的指针,返回后台服务实例
        }
    }
    public MusicService() {
        try{
            mediaPlayer.setDataSource("/data/K.Will-Melt.mp3");//绑定播放的歌曲
            mediaPlayer.prepare();//进入就绪状态
            mediaPlayer.setLooping(true);//设置循环播放
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        //throw new UnsupportedOperationException("Not yet implemented");
        return binder;
    }
    @Override
    public void onCreate(){
        super.onCreate();
    }
    @Override
    public void onDestroy(){
        super.onDestroy();
        if(mediaPlayer!=null){
            mediaPlayer.stop();//停止歌曲播放
            mediaPlayer.release();//释放mediaPlayer资源
        }
    }
    public void playORpuase(){
        if(mediaPlayer.isPlaying()){
            mediaPlayer.pause();//暂停
        }
        else{
            mediaPlayer.start();//开始
        }
    }
    public void stop(){
        if(mediaPlayer!=null){
            mediaPlayer.stop();//停止
            try{
                mediaPlayer.prepare();//就绪
                mediaPlayer.seekTo(0);//设置歌曲回到最开始
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.hp.lab6.MainActivity"
    >

    <ImageView
        android:id="@+id/imageview"
        android:layout_gravity="center"
        android:layout_width="300sp"
        android:layout_height="300sp"
        android:src="@drawable/image"
        />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical">
        <TextView
            android:id="@+id/state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/margin_top"
            android:textSize="@dimen/textsize1"
            android:text="" />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="@dimen/margin_top"
            android:gravity="center_horizontal">
            <TextView
                android:id="@+id/playing_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"/>
            <SeekBar
                android:id="@+id/seekbar"
                android:layout_width="280sp"
                android:layout_height="wrap_content" />

            <TextView
                android:id="@+id/song_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="04:00"/>
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_top"
        android:layout_gravity="center_horizontal"
        android:orientation="horizontal">
        <Button
            android:id="@+id/play_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="PLAY"

            />
        <Button
            android:id="@+id/stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/textsize1"
            android:text="STOP"
            />
        <Button
            android:id="@+id/quit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/textsize1"
            android:text="QUIT"
            />

    </LinearLayout>
</LinearLayout>

项目仓库:https://github.com/luqx3/mediaPlayer

原文地址:https://www.cnblogs.com/slothccc/p/6014044.html