模仿网易音乐播放器

要求:

1.实验报告要完整,即要有实验要求与目的、实验内容与步骤(必要流程图或活动图、代码)、运行结果与分析、实验体会与收获;

2.代码要有必要的注释;

3.标题为四号黑体,其他为宋体小四号,行间距为单倍行间距,纸张大小为A4;

4.考核项目

考核项目

格式与完成性

实验内容

实验结果与分析

实验体会与收获

总成绩

权重

20%

60%

10%

10%

100%

得分

  • 实验目的

1.了解服务的概述,能够说出什么是服务;

2.掌握服务的创建方式,能够独立创建一个服务;

3. 熟悉服务的生命周期,能够阐述服务生命周期中的方法;

4.掌握服务的两种启动方式,能够实现服务的启动与关闭功能;

5.掌握服务的通信,能够完成仿网易音乐播放器案例。

  • 实验工具

Android studio。

  • 实验内容

运行效果图如下:

  1. 完成上图的布局;

  2. 点击“播放”按钮、“暂停”按钮、“继续”按钮完成相应功能。

  • 实验过程(含代码)

   activity_main.xml: <?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:orientation="vertical"

    android:gravity="center"

    android:background="@drawable/music_bg"

    tools:context=".MainActivity">



    <RelativeLayout

        android:layout_width="match_parent"

        android:layout_height="160dp">

        <RelativeLayout

            android:layout_width="300dp"

            android:layout_height="70dp"

            android:id="@+id/rl_title"

            android:layout_centerHorizontal="true"

            android:background="@drawable/title_bg"

            android:gravity="center_horizontal"

            android:paddingLeft="80dp">



            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:id="@+id/tv_music_title"

                android:layout_marginTop="8dp"

                android:text="体面"

                android:textSize="12sp"

                android:textStyle="bold"

                android:textColor="@color/black"/>

            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:id="@+id/tv_type"

                android:layout_marginTop="4dp"

                android:layout_below="@id/tv_music_title"

                android:layout_alignLeft="@id/tv_music_title"

                android:text="流行音乐"

                android:textSize="10dp"/>

            <SeekBar

                android:layout_width="150dp"

                android:layout_height="wrap_content"

                android:id="@+id/sb"

                android:layout_below="@+id/rl_time"

                android:layout_alignParentBottom="true"

                android:thumb="@null"/>

            <RelativeLayout

                android:layout_width="150dp"

                android:layout_height="wrap_content"

                android:layout_marginTop="4dp"

                android:id="@+id/rl_time"

                android:layout_below="@id/tv_type">

                <TextView

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:id="@+id/tv_progress"

                    android:text="00:00"

                    android:textSize="10dp"/>

                <TextView

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:id="@+id/tv_total"

                    android:layout_alignParentRight="true"

                    android:text="00:00"/>



            </RelativeLayout>

        </RelativeLayout>

        <LinearLayout

            android:layout_width="340dp"

            android:layout_height="90dp"

            android:layout_below="@id/rl_title"

            android:layout_centerHorizontal="true"

            android:background="@drawable/btn_bg"

            android:gravity="center_vertical"

            android:paddingLeft="120dp"

            android:paddingRight="10dp">

            <Button

                android:layout_width="0dp"

                android:layout_height="55dp"

                android:layout_margin="4dp"

                android:id="@+id/btn_play"

                android:layout_weight="1"

                android:background="@drawable/btn_bg_selector"

                android:text="播放"

                android:textSize="10sp"/>

            <Button

                android:layout_width="0dp"

                android:layout_height="55dp"

                android:id="@+id/btn_pause"

                android:layout_margin="4dp"

                android:layout_weight="1"

                android:background="@drawable/btn_bg_selector"

                android:text="暂停"

                android:textSize="10sp"/>

            <Button

                android:layout_width="0dp"

                android:layout_height="55dp"

                android:id="@+id/btn_continue_play"

                android:layout_margin="4dp"

                android:layout_weight="1"

                android:background="@drawable/btn_bg_selector"

                android:text="继续"

                android:textSize="10sp"/>

            <Button

                android:layout_width="0dp"

                android:layout_height="55dp"

                android:id="@+id/btn_exit"

                android:layout_margin="4dp"

                android:layout_weight="1"

                android:background="@drawable/btn_bg_selector"

                android:text="退出"

                android:textSize="10sp"/>

        </LinearLayout>

        <ImageView

            android:layout_width="100dp"

            android:layout_height="100dp"

            android:id="@+id/iv_music"

            android:layout_centerVertical="true"

            android:layout_marginLeft="35dp"

            android:layout_marginBottom="50dp"

            android:src="@drawable/img_music"/>

    </RelativeLayout>

</LinearLayout>
btn_bg_selector.xml: <?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true" >

        <shape android:shape="rectangle">

            <corners android:radius="3dp"/>

            <solid android:color="#d4d4d4"/>

        </shape>

    </item>

    <item android:state_pressed="false" >

        <shape android:shape="rectangle">

            <corners android:radius="3dp"/>

            <solid android:color="#ffffff" />

        </shape>

    </item>

</selector>
MainActivity.java:     package com.example.musicdemo;



import androidx.annotation.NonNull;

import androidx.appcompat.app.AppCompatActivity;



import android.animation.ObjectAnimator;

import android.animation.ValueAnimator;

import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.Handler;

import android.os.IBinder;

import android.os.Message;

import android.view.View;

import android.view.animation.LinearInterpolator;

import android.widget.ImageView;

import android.widget.SeekBar;

import android.widget.TextView;



public class MainActivity extends AppCompatActivity implements View.OnClickListener {



    private static SeekBar sb;

    private static TextView tv_progress,tv_total;

    private ObjectAnimator animator;

    private MusicService.MusicControl musicControl;

    MyServiceConn conn;

    Intent intent;

    private boolean isUnbind=false;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        init();

    }

    private void  init(){

        tv_progress=findViewById(R.id.tv_progress);

        tv_total=findViewById(R.id.tv_total);

        sb=findViewById(R.id.sb);

        findViewById(R.id.btn_play).setOnClickListener(this);

        findViewById(R.id.btn_pause).setOnClickListener(this);

        findViewById(R.id.btn_continue_play).setOnClickListener(this);

        findViewById(R.id.btn_exit).setOnClickListener(this);

        intent=new Intent(this,MusicService.class);

        conn=new MyServiceConn();

        bindService(intent,conn,BIND_AUTO_CREATE);

        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override

            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {                                //滑动条进度改变调用此方法,滑动条到末端结束动画

                if (progress==seekBar.getMax()){

                    animator.pause();  //停止播放动画

                }

            }





            @Override

            public void onStartTrackingTouch(SeekBar seekBar) {



            }



            @Override

            public void onStopTrackingTouch(SeekBar seekBar) {

                int progress=seekBar.getProgress();

                musicControl.seekTo(progress);

            }

        });

        ImageView iv_music = (ImageView) findViewById(R.id.iv_music);

        animator = ObjectAnimator.ofFloat(iv_music, "rotation", 0f, 360.0f);

        animator.setDuration(10000);  //动画旋转一周的时间为10秒

        animator.setInterpolator(new LinearInterpolator());

        animator.setRepeatCount(-1);  //-1表示设置动画无限循环

    }

    public  static Handler handler=new Handler(){

        @Override

        public void handleMessage(@NonNull Message msg) {

            Bundle bundle=msg.getData();

            int duration=bundle.getInt("duration");

            int currentPosition=bundle.getInt("currentPosition");

            sb.setMax(duration);

            sb.setProgress(currentPosition);

            int minute=duration/1000/60;

            int second=duration/1000%60;

            String strMinute=null;

            String strSecond=null;

            if (minute<10){

                strMinute="0"+minute;// //如果歌曲时间中的分钟数小于10在分钟前+0



            }else {

                strMinute=minute+"";

            }

            if (second<10){

                strSecond="0"+second;// //如果歌曲时间中的秒数小于10在秒钟前+0

            }else {

                strSecond=second+"";

            }

            tv_total.setText(strMinute+":"+strSecond);

            minute=currentPosition/1000/60;

            second=currentPosition/1000%60;

            if (minute<10){

                strMinute="0"+minute;

            }else {

                strMinute=minute+"";

            }

            if (second<10){

                strSecond="0"+second;

            }else {

                strSecond=second+"";

            }

            tv_progress.setText(strMinute+":"+strSecond);

            super.handleMessage(msg);

        }

    };

    class MyServiceConn implements ServiceConnection{



        @Override

        public void onServiceConnected(ComponentName name, IBinder service) {

            musicControl= (MusicService.MusicControl) service;

        }



        @Override

        public void onServiceDisconnected(ComponentName name) {



        }

    }

    private void unbind(boolean isUnbind){

        if (!isUnbind){

            musicControl.pausePlay();

            unbindService(conn);

            stopService(intent);

        }

    }

    @Override

    public void onClick(View v) {

        switch (v.getId()){

            case R.id.btn_play:

                musicControl.play();

                animator.start();

                break;

            case R.id.btn_pause:

                musicControl.pausePlay();

                animator.pause();

                break;

            case R.id.btn_continue_play:

                musicControl.continuePlay();

                animator.start();

                break;

            case R.id.btn_exit:

                unbind(isUnbind);

                isUnbind=true;

                finish();

                break;

        }

    }



    @Override

    protected void onDestroy() {

        super.onDestroy();

        unbind(isUnbind);

    }

}
 
AndroidMainfest.xml: <?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.musicdemo">



    <application

        android:allowBackup="true"

        android:icon="@mipmap/ic_launcher"

        android:label="@string/app_name"

        android:roundIcon="@mipmap/ic_launcher_round"

        android:supportsRtl="true"

        android:theme="@style/Theme.Musicdemo">

        <activity android:name=".MainActivity">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />



                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <service android:name=".MusicService"

            android:enabled="true"

            android:exported="true"/>

    </application>



</manifest>


           
自定义MediaServer.java类,继承Server,然后在AndroidManifest里添加
MusicService.java: package com.example.musicdemo;



import android.app.Service;

import android.content.Intent;

import android.media.MediaPlayer;

import android.os.Binder;

import android.os.Bundle;

import android.os.IBinder;

import android.os.Message;



import androidx.annotation.Nullable;



import java.util.Timer;

import java.util.TimerTask;



public class MusicService extends Service {

    private MediaPlayer player;

    private Timer timer;

    public MusicService(){

    }

    @Nullable

    @Override

    public IBinder onBind(Intent intent) {

        return new MusicControl();

    }



    @Override

    public void onCreate() {

        super.onCreate();

        player=new MediaPlayer(); //创建音乐播放对象

    }

    public  void addTimer(){  //添加计时器用于设置音乐播放器中的播放进度条

        if (timer==null){

            timer=new Timer();  //创建计时对象

            TimerTask task=new TimerTask() {

                @Override

                public void run() {

                    if (player==null)return;

                    int duration=player.getDuration();//获取歌曲总时长

                    int currentPosition=player.getCurrentPosition();//获取播放进度

                    Message msg=MainActivity.handler.obtainMessage();//创建消息对象

                    Bundle bundle=new Bundle();

                    bundle.putInt("duration",duration);

                    bundle.putInt("currentPosition",currentPosition);

                    msg.setData(bundle);

                    MainActivity.handler.sendMessage(msg);

                }

            };

            timer.schedule(task,5,500);  
//开始计时任务5毫秒后,第一次执行task任务,以后每500毫秒执行一次

        }

    }

    class MusicControl extends Binder{

        public void play(){

            try{

                player.reset();  //重置音乐播放器

                player=MediaPlayer.create(getApplicationContext(),R.raw.music);

                addTimer();

            }catch (Exception e){

                e.printStackTrace();

            }

        }

        public  void pausePlay(){

            player.pause(); //暂停播放

        }

        public  void continuePlay(){

            player.start();  //继续播放

        }

        public void seekTo(int progress){

            player.seekTo(progress);

        }



    }



    @Override

    public void onDestroy() {

        super.onDestroy();

        if (player==null)return;

        if (player.isPlaying())player.stop();  //停止播放

        player.release();  //释放占用资源

        player=null;  //player置为空

    }

}
  • 运行结果与分析

播放中:

暂停:

继续:

退出:

  • 实验体会与收获

本实验学习了什么是服务,服务种类有哪些,怎么实现服务,了解服务的两种启动方式并采用第二种服务启动方式

Service:

是android四大组件之一,主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。而Service是运行在主线程里的,如果直接在Service中处理一些耗时的逻辑,就会导致程序ANR,所以需要另外开启子线程来处理。

两种模式: startService()/bindService()

.Service的第一种启动方式

采用start的方式开启服务

使用Service的步骤:

1.定义一个类继承Service

2.在Manifest.xml文件中配置该Service

3.使用Context的startService(Intent)方法启动该Service

4.不再使用时,调用stopService(Intent)方法停止该服务

使用这种start方式启动的Service的生命周期如下:

onCreate() --> onStartCommand() (onStart()方法已过时) --> onDestory()

Service的第二种启动方式

采用bind的方式开启服务

使用Service的步骤:

1.定义一个类继承Service

2.在Manifest.xml文件中配置该Service

3.使用Context的bindService(Intent,ServiceConnection,int)方法启动该Service

4.不再使用时,调用unbindService(ServiceConnection)方法停止该服务

使用这种start方式启动的Service的生命周期如下:

onCreate() -->> onBind() --> onUnbind() -->> onDestory()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值