Android media player ------ Simple music player (detailed) [reprint]

1. The effect of the case

2. Design and function of welcome interface

  2.1 **,** case effect

 Design a page that counts down and automatically jumps

  2.2**,** Layout interface activity_welcome.xml reference code:

<?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:orientation="vertical" 
     android:background="@drawable/welcome_picture" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".MainActivity"> 
     <TextView 
         android:text="欢 迎" 
         android:textSize="90dp" 
         android:textStyle="bold" 
         android:textColor="#ad0000" 
         android:layout_marginTop="150dp" 
         android:layout_gravity="center" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"/> 
     <TextView 
         android:id="@+id/text1" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:text="H" 
         android:layout_gravity="center" 
         android:layout_marginTop="50dp" 
         android:textSize="100sp" 
         android:textColor="#000000" 
     /> 
</LinearLayout> 
复制代码

  2.3, class file WelcomeActivity.java reference code:

package com.example.musicplayer; 
import androidx.annotation.NonNull; 
import androidx.appcompat.app.AppCompatActivity; 
import android.app.Activity; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.widget.TextView; 
import java.util.Timer; 
import java.util.TimerTask; 
public class WelcomeActivity extends AppCompatActivity { 
private static final String TAG="MainActicity"; 
private TextView textView1; 
private Timer timer; //创建定时器 
private TimerTask timerTask; //创建定时器任务 
private int count=5; 
private Handler handler; //消息处理器,专门发送和接收消息 
     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_welcome); 
         initView(); //控件初始化 
         initDate(); //数据初始化 
         initStatus(); //页面状态初始化 
     } 
     private void initView() { 
         textView1=findViewById(R.id.text1); 
     } 
     private void initDate() { 
         timer=new Timer(); 
         timerTask=new TimerTask() { 
             @Override 
//run()中的代码是定时器要完成的任务,都是耗时的操作,在 android中,耗时的操作都放在子线程中进行 
             public void run() { 
             // count++; 
             Log.d(TAG, "run: "+count); 
         //让子线程给主线程发送消息信号,主线程接收到消息信号后就可以更新主界面的数字显示信息 
             if(count!=0){ 
                 //给主线程发送消息信息 1 
                 Message msg=new Message(); 
                 msg.what=1; //1 表示消息信号 
                 handler.sendMessage(msg); 
             }else { 
                 //给主线程发送消息信息 0 
                 Message msg=new Message(); 
                 msg.what=0; //0 表示消息信号 
                 handler.sendMessage(msg); 
             } 
         } 
     }; 
     //开启定时器 参数 1:定时器任务 参数 2:延迟 参数 3:变化的周期 
     timer.schedule(timerTask,0,1000); 
     //主线程接受到消息信号对主界面数字显示进行更新 
     handler=new Handler(){ 
         @Override 
         public void handleMessage(@NonNull Message msg) { 
         super.handleMessage(msg); 
         //主线程根据接收到的消息进行判断 
             switch (msg.what){ 
                 case 1: 
                     //让数字递减 
                     count--; 
                     textView1.setText(count+""); //让变化的数字显示在主界面上 
                     break; 
                 case 0: 
                     //倒计时结束,跳转到主界面 
                     Intent intent=new Intent(WelcomeActivity.this,MainActivity.class); 
                     startActivity(intent); 
                     finish(); 
                     timer.cancel(); //关闭定时器 
                     timerTask.cancel(); //关闭定时器任务 
                     break; 
                 default: 
                     break; 
                 } 
             } 
         }; 
     } 
//第一次登录 APP 时显示欢迎界面的倒计时,第二次登录 APP 时直接进入到主界面 
     private void initStatus() { 
         //读取保存的登录状态值 
         Boolean status = getSharedPreferences("mystatus",MODE_PRIVATE).getBoolean("status",false); 
         //将第一次登录的状态 True 保存起来,下次登录后判断状态,如果为 True 直接跳转到主页面,否则从欢迎界面倒计时登录 
         SharedPreferences.Editor editor =getSharedPreferences("mystatus",MODE_PRIVATE).edit(); 
         editor.putBoolean("firstlogin_status",true); 
         editor.commit(); 
         if(status){ 
             //如果 status 为 True 
             Intent intent2=new Intent(WelcomeActivity.this,MainActivity.class); 
             startActivity(intent2); 
             finish(); 
             timer.cancel(); 
             timerTask.cancel(); 
         } 
     } 
} 
复制代码

  2.4. Explanation of knowledge points

    1. The use of Timer and TemerTask (timer tool class)

• In development, we sometimes have the need to execute a certain task at regular intervals. For example, the controls on the UI need to change with time. We can use the timer tool classes provided by Java, namely Timer and TimerTask.

• Timer is a common class with several important methods; TimerTask is an abstract class with an abstract method run(), similar to the run() method in threads, we use Timer to create an object of it , and then use the schedule method of this object to complete this interval operation.

Timer is a thread, using the schedule method to complete the scheduling of TimerTask, multiple TimerTasks can share a Timer, that is to say, a Timer object calls the schedule method once to create a thread, and after calling the schedule once, the TimerTask loops indefinitely , use Timer's cancel() to stop the operation.

    2. schedule method

The schedule method has three parameters:

The first parameter is an object of type TimerTask. We implement the run() method of TimerTask, which is a task to be executed periodically;

The second parameter has two types, the first is the long type, which means how long to start the execution, and the other is the Date type, which means that the execution starts after that time;

The third parameter is the execution cycle, which is of type long.

    3. Use of Handler

• 耗时的操作放在一个子线程中,因为子线程涉及到UI更新,**更新UI只能在主线程 中更新,子线程中操作是危险的。**这个时候,Handler就可以解决这个复杂的问题 , Handler 是主要接受子线程发送的数据, 并用此数据配合主线程更新UI。

• 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来 传递数据, 这个时候,Handler就承担着接受子线程传递过来的Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

•Handler :子线程向主线程发送消息、主线程处理接收到的消息;

•Message:消息载体,如果传输数据简单可以直接使用arg1、arg2这两个整型数 据,如果需要传复杂的消息,使用obj传输对象数据;

三、主界面的设计与功能

  3.1 **、**案例效果

  3.2 **、**布局界面 activity_welcome.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:orientation="vertical" 
     android:background="@drawable/main_picture" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".MainActivity"> 
     <TextView 
         android:text="音乐播放器" 
         android:textSize="60dp" 
         android:textStyle="bold" 
         android:textColor="#0000ff" 
         android:layout_marginTop="150dp" 
         android:layout_gravity="center" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"/> 
     <Button 
         android:id="@+id/button1" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:text="进入音乐列表" 
         android:background="@drawable/button_style" 
         android:layout_gravity="center" 
         android:layout_marginTop="150dp" 
         android:textSize="30sp" 
         android:textStyle="bold" 
         android:textColor="#000000" 
         /> 
</LinearLayout>
复制代码

   3.3、类文件 MainActivity.java 参考代码:

package com.example.musicplayer; 
import androidx.appcompat.app.AppCompatActivity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
 
public class MainActivity extends AppCompatActivity { 
//定义对象 
     Button button1; 
     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_main); 
         initView(); 
         btnclick(); 
     } 
 
     private void initView() { 
         button1=findViewById(R.id.button1); 
     } 
     private void btnclick() { 
         button1.setOnClickListener(new View.OnClickListener() { 
             @Override 
             public void onClick(View view) { 
                 Intent intent=new Intent(MainActivity.this,MusicActivity.class); 
                 startActivity(intent); 
                 finish(); 
             } 
         }); 
     } 
} 
复制代码

四、音乐列表界面的设计与功能

  4.1 **、**案例效果

提醒:(1)添加依赖,由于 RecyclerView 是 android 5.0 新增的控件,所以需 要在 build.gradle 里面添加依赖:如下

implementation 'androidx.recyclerview:recyclerview:1.1.0'
复制代码

(2)因为要读写 sd 卡上的歌曲,所以需要在配置文件中添加权限,如下

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" 
 tools:ignore="ProtectedPermissions" /> 
复制代码

  4.2、布局界面 activity_music.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:orientation="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".MusicActivity"> 
     <TextView 
         android:text="音乐列表" 
         android:textSize="50sp" 
         android:layout_gravity="center" 
         android:textStyle="bold" 
         android:textColor="#000078" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"/> 
     <androidx.recyclerview.widget.RecyclerView 
         android:id="@+id/recyclerview" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent"/> 
</LinearLayout> 

复制代码

  4.3、类文件 MusicAdapter.java 参考代码:

package com.example.musicplayer; 
import android.content.Context; 
import android.content.Intent; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 
import java.util.List; 
import androidx.annotation.NonNull; 
import androidx.appcompat.view.menu.ActionMenuItemView; 
import androidx.recyclerview.widget.RecyclerView; 
public class MusicAdapter extends 
RecyclerView.Adapter<MusicAdapter.ViewHolder> { 
     Context mcontext; 
     List<Music> myMusicList; 
     public MusicAdapter(List<Music> musicList) { 
         myMusicList=musicList; 
     } 
//方法 1:用于创建 ViewHolder 实例 
     @NonNull 
     @Override 
     public MusicAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 
         View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.music_item,parent,false); 
         final ViewHolder holder=new ViewHolder(view); 
         //单击任意歌曲跳转到播放界面 
         holder.musicview.setOnClickListener(new View.OnClickListener() { 
             @Override 
             public void onClick(View view) { 
                 int position= holder.getAdapterPosition(); //返回数据在适配器中的位置 
                 Intent intent=new Intent(view.getContext(),PlayerActivity.class); 
                 intent.putExtra("my",position); 
                 view.getContext().startActivity(intent); 
             } 
         }); 
         return holder; 
     } 
//方法 2:用于对 Recyclerview 中子项的数据进行赋值的 
     @Override 
     public void onBindViewHolder(@NonNull MusicAdapter.ViewHolder holder, int position) { 
         Music musicinfo=myMusicList.get(position); 
         holder.music_title.setText(musicinfo.getMusicTitle()); 
         holder.singer_name.setText(musicinfo.getSingerName()); 
 } 
//方法 3:数据源长度 
     @Override 
     public int getItemCount() { 
         return myMusicList.size(); 
     } 
     public class ViewHolder extends RecyclerView.ViewHolder{ 
         View musicview; 
         TextView music_title; 
         TextView singer_name; 
         public ViewHolder(@NonNull View view) { 
             super(view); 
             musicview=view; 
             music_title=view.findViewById(R.id.music_title); 
             singer_name=view.findViewById(R.id.singer_name); 
         } 
     } 
} 
复制代码

  4.4、布局界面 music_item.xml 参考代码:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:orientation="horizontal" 
     android:layout_height="wrap_content"> 
     <ImageView 
         android:src="@drawable/music_icon" 
         android:layout_width="70dp" 
         android:layout_height="70dp"/> 
     <LinearLayout 
         android:orientation="vertical" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"> 
         <TextView 
             android:id="@+id/music_title" 
             android:textStyle="bold" 
             android:text="音乐的名字" 
             android:textSize="30sp" 
             android:textColor="#000000" 
             android:layout_width="wrap_content" 
             android:layout_height="wrap_content"/> 
         <TextView 
             android:id="@+id/singer_name" 
             android:textStyle="bold" 
             android:text="歌手的名字" 
             android:textSize="20sp" 
             android:textColor="#0000ff" 
             android:layout_width="wrap_content" 
             android:layout_height="wrap_content"/> 
     </LinearLayout> 
</LinearLayout> 
复制代码

  4.5、类文件 Music.java 参考代码:

package com.example.musicplayer; 
public class Music { 
     private String musicTitle; 
     private String singerName; 
     public String getMusicTitle() { 
         return musicTitle; 
     } 
     public String getSingerName() { 
         return singerName; 
     } 
     public Music(String musicTitle, String singerName) { 
         this.musicTitle = musicTitle; 
         this.singerName = singerName; 
     } 
} 
复制代码

  4.6、类文件 MusicActivity.java 参考代码

package com.example.musicplayer; 
import androidx.appcompat.app.AppCompatActivity; 
import androidx.recyclerview.widget.RecyclerView; 
import androidx.recyclerview.widget.StaggeredGridLayoutManager; 
import android.database.Cursor; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.util.Log; 
import java.util.ArrayList; 
import java.util.List; 
public class MusicActivity extends AppCompatActivity { 
     //定义对象 
     RecyclerView recyclerView; 
     private static final String TAG = "MusicActivity"; 
     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_music); 
         initView(); 
         initData(); 
     } 
     private void initView() { 
         recyclerView = findViewById(R.id.recyclerview); 
     } 
     private void initData() { 
         List<Music> musicList = new ArrayList<>(); 
         Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); 
         Log.d(TAG, "initData:我查询获取到的歌曲共:" + cursor.getCount() + "首"); 
         while (cursor.moveToNext()){ 
             String mymusictitle=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); 
             String mysingername =cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); 
             Music music=new Music(mymusictitle,mysingername); 
             musicList.add(music); 
         } 
         cursor.close(); 
         MusicAdapter adapter=new MusicAdapter(musicList); 
         StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL); 
         recyclerView.setLayoutManager(layoutManager); 
         recyclerView.setAdapter(adapter); 
     } 
 }

复制代码

  4.7**、**代码讲解

         在android中,每个应用程序是可以实现数据共享的,就是我们可以为每个应用程序创建一个ContentProvider,也就是说你可以通过ContentProvider把应用程序中的数据共享给其他程序访问调用。其他应用程序可以通过ContentProvider对你应用程序中的数据进行访问,修改,删除等操作。

getContentResolver是管理所有程序的contentProvider的实例(ContentResolver负责获取ContentProvider提供的数据)即:APP--->ContentReSolver--->ContentProvider。

getContentResolver.query参数说明:

   第1个参数: table,是根据Uri确定的数据库表;

   第2个参数: projection,是要查询的列;

   第3个参数: selection, 查询条件;

   第4个参数: selectionArgs ,填充where查找条件中的占位符”?“

   第5个参数: order,是我们想要的排序方式。

   对应于SQL的结构是:select projection from table where ( selection ) order by order;

五、音乐播放界面的设计与功能

  5.1 **、**案例效果

   5.2、布局界面 activity_player.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" 
     tools:context=".PlayerActivity"> 
     <TextView 
         android:id="@+id/title" 
         android:text="获取到的音乐标题" 
         android:textColor="#000000" 
         android:textSize="35sp" 
         android:gravity="center" 
         android:layout_margin="5dp" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"/> 
     <TextView 
         android:id="@+id/name" 
         android:text="获取到的歌手名字" 
         android:textColor="#000000" 
         android:textSize="35sp" 
         android:gravity="center" 
         android:layout_margin="5dp" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"/> 
     <ImageView 
         android:src="@drawable/music_icon" 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content"/> 
     <LinearLayout 
         android:orientation="horizontal" 
         android:layout_marginLeft="5dp" 
         android:layout_marginRight="5dp" 
         android:weightSum="1" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"> 
         <TextView 
             android:id="@+id/current_time" 
             android:text="0:00" 
             android:textSize="25sp" 
             android:layout_width="wrap_content" 
             android:layout_height="wrap_content"/> 
         <SeekBar 
             android:id="@+id/seek_bar" 
             android:layout_weight="1" 
             android:layout_gravity="center_vertical" 
             android:layout_width="wrap_content" 
             android:layout_height="wrap_content"/> 
         <TextView 
             android:id="@+id/total_time" 
             android:text="8:23" 
             android:textSize="25sp" 
             android:layout_width="wrap_content" 
             android:layout_height="wrap_content"/> 
 </LinearLayout> 
复制代码

  5.3、类文件 PlayerActivity.java 参考代码:

package com.example.musicplayer; 
import androidx.annotation.NonNull; 
import androidx.appcompat.app.AppCompatActivity; 
import android.database.Cursor; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.provider.MediaStore; 
import android.util.Log; 
import android.widget.Button; 
import android.widget.SeekBar; 
import android.widget.TextView; 
import java.io.IOException; 
import java.util.Timer; 
import java.util.TimerTask; 
public class PlayerActivity extends AppCompatActivity { 
//定义对象 
     private static final String TAG = "PlayerActivity"; 
     private TextView title; 
     private TextView name; 
     private Cursor cursor; 
     private MediaPlayer mediaPlayer; 
     private SeekBar seekBar; 
     private TextView current_time; 
     private TextView total_time; 
     private Handler mhandler; 
     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_player); 
         initView(); //绑定控件 
         initData(); //获取并显示歌曲标题和歌手名字 
         initPlay(); //播放歌曲 
         initSeek(); //初始化进度条 
         moveSeek(); //拖动滑动条 
         initUpdate(); //实时更新滑动条的当前时间 
     } 
     private void initView() { 
         title=findViewById(R.id.title); 
         name=findViewById(R.id.name); 
         seekBar=findViewById(R.id.seek_bar); 
         current_time=findViewById(R.id.current_time); 
         total_time=findViewById(R.id.total_time); 
 
 
     } 
     private void initData() { 
         int position=getIntent().getIntExtra("my",0); 
         Log.d(TAG, "initData: "+position); 
        cursor=getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Audio.Media.DEFAULT_SORT_ORDER); 
         cursor.moveToPosition(position); 
         String mytitle=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); 
         String myname=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); 
         title.setText(mytitle); 
         name.setText(myname); 
     } 
     private void initPlay() { 
         mediaPlayer=new MediaPlayer(); 
         String path=cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); 
         mediaPlayer.reset(); //清空里面的其他歌曲 
         try { 
             mediaPlayer.setDataSource(path); 
             mediaPlayer.prepare(); //准备就绪 
             mediaPlayer.start(); //开始唱歌 
         } catch (IOException e) { 
             e.printStackTrace(); 
         } 
     } 
     private void initSeek() { 
     seekBar.setMax(mediaPlayer.getDuration()); //获取音频文件总时长 
     seekBar.setProgress(mediaPlayer.getCurrentPosition()); //获取当前播放的进度值 
     total_time.setText(toTime(mediaPlayer.getDuration())); 
     current_time.setText(toTime(mediaPlayer.getCurrentPosition())); 
 
     } 
 
     private String toTime(int getDutation) { 
         int time=getDutation/1000; //毫秒转化为秒 
         int minute=time/60; //取整:求出分钟 
         int second=time%60; //取余:求出秒 90 秒/60=1(分钟)....30(秒) 
         String mm=String.format("%01d:%02d",minute,second); //指定显示的格式 
         return mm; 
     } 
     private void moveSeek() { 
         seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 
             @Override 
             public void onProgressChanged(SeekBar seekBar, int position, boolean b) { 
                 if(b){ 
                     mediaPlayer.seekTo(position); //音频从你拖到的位置处开始播放 
                     initSeek(); 
                 } 
             } 
 
             @Override 
             public void onStartTrackingTouch(SeekBar seekBar) { 
 
             } 
 
             @Override 
             public void onStopTrackingTouch(SeekBar seekBar) { 
 
             } 
         }); 
     } 
     private void initUpdate() { 
         Timer timer=new Timer(); 
         TimerTask timerTask=new TimerTask() { 
             @Override 
             public void run() { 
                 Message msg=new Message(); 
                 msg.what=11; 
                 mhandler.sendMessage(msg); 
             } 
         }; 
         timer.schedule(timerTask,0,1000); 
         mhandler=new Handler(){ 
             @Override 
             public void handleMessage(@NonNull Message msg) { 
                 super.handleMessage(msg); 
                 switch (msg.what){ 
                     case 11: 
                         initSeek(); //重新执行进度条的初始化代码 
                         break; 
                         default: 
                             break; 
                 } 
             } 
         }; 
 
     } 
     //按返回键停止播放 
     @Override 
     protected void onDestroy() { 
         super.onDestroy(); 
         mediaPlayer.stop(); 
     } 
} 
复制代码

  5.4**、代码讲解;**

MediaPlayer详解

    Android的MediaPlayer包含了Audio和Video的播放功能,在Android的界 面上,Music和Video两个应用程序都是调用MediaPlayer来实现的。 MediaPlayer的工作流程:

        1、首先创建MediaPlayer对象;

        2、然后调用setDataSource()方法来设置音频文件的路径;

        3、再调用prepare()方法使MediaPlayer进入到准备状态;

        4、调用start方法就可以播放音频。

SeekBar.OnSeekBarChangeListener解析

    当进度改变后用于通知客户端的回调函数。这包括用户通过手势、方向键戒 轨迹球触发的改变, 以及编程触发的改变。

    public abstract void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)

参数

seekBar 当前被修改进度的SeekBar;

progress 当前的进度值,此值的取值范围为0到max之间;

fromUser 如果是用户触发的改变则返回True。

六、资源文件

免费资源

本文转自 blog.csdn.net/indeedes/ar…,如有侵权,请联系删除。

Guess you like

Origin juejin.im/post/7120214897857658888