zoukankan      html  css  js  c++  java
  • 实现一个简单的播放器——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

  • 相关阅读:
    Thinkphp M方法出错,D方法却可以
    Composer项目安装依赖包
    wamp httpd-vhosts.conf
    博客园报错 Mixed Content: The page at 'https://i.cnblogs.com/EditPosts.aspx?opt=1' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://upload.cnblogs.com/imageuploa
    Thinkphp js、css压缩类minify
    Thinkphp 不足之处
    Thinkphp 调试方法
    Lavavel 程序报错 MassAssignmentException in Model.php line 452: _token
    Laravel 安装mysql、表增加模拟数据、生成控制器
    Laravel 安装登录模块
  • 原文地址:https://www.cnblogs.com/slothccc/p/6014044.html
Copyright © 2011-2022 走看看