您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
67_音乐播放器
发布时间:2021-03-09 17:53:04编辑:雪饮阅读()
这次要实现一个音乐播放器,需要提供一个可以输入文件路径(音乐文件)的输入框,然后根据该音乐文件进行播放、暂停、重置(重新播放)、停止
并且当有电话来了,电话铃响的时候音乐就暂停,电话挂断后音乐再次恢复。
则布局文件一个输入框,四个按钮activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="/sdcard/bslr.mp3"
android:hint="请输入音乐的路径"
android:id="@+id/et_path"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放" />
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停" />
<Button
android:id="@+id/replay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重播" />
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="/sdcard/bslr.mp3"
android:hint="请输入音乐的路径"
android:id="@+id/et_path"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal">
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放" />
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停" />
<Button
android:id="@+id/replay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重播" />
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
因为需要读取音乐文件,且需要监听电话状态,所以读取扩展存储、读取电话状态的权限还是需要在清单文件中声明好AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mp3player">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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.Mp3player">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
然后是主程序MainActivity.java:
package com.example.mp3player;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_path;
private Button bt_play, bt_pause, bt_replay, bt_stop;
private MediaPlayer mediaPlayer;
private TelephonyManager manager ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
manager.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
et_path = (EditText) this.findViewById(R.id.et_path);
bt_play = (Button) this.findViewById(R.id.play);
bt_pause = (Button) this.findViewById(R.id.pause);
bt_replay = (Button) this.findViewById(R.id.replay);
bt_stop = (Button) this.findViewById(R.id.stop);
bt_play.setOnClickListener(this);
bt_pause.setOnClickListener(this);
bt_replay.setOnClickListener(this);
bt_stop.setOnClickListener(this);
}
public void onClick(View v) {
String path;
try {
switch (v.getId()) {
case R.id.play:
path = et_path.getText().toString().trim();
play(path);
break;
case R.id.pause:
pause();
break;
case R.id.replay:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
//重播的核心
mediaPlayer.seekTo(0);
} else {
path = et_path.getText().toString().trim();
play(path);
}
break;
case R.id.stop:
//停止播放后,释放播放器,播放按钮重新设置为可点击
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer = null;
bt_play.setEnabled(true);
bt_play.setClickable(true);
}
break;
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "文件播放出现异常", 0).show();
}
}
private void pause() {
// 判断音乐是否在播放
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
// 暂停音乐播放器
mediaPlayer.pause();
bt_pause.setText("续播");
return;
}
if (mediaPlayer != null
&& "续播".equals(bt_pause.getText().toString())) {
mediaPlayer.start();
bt_pause.setText("暂停");
}
}
/**
* 播放指定地址的音乐文件.mp3 .wav .amr
*
* @param path
*/
private void play(String path) throws Exception {
if ("".equals(path)) {
Toast.makeText(getApplicationContext(), "路径不能为空", 0).show();
return;
}
File file = new File(path);
if (file.exists()) {
// 如果文件存在才进行播放操作
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
mediaPlayer.start();
bt_play.setEnabled(false);
bt_play.setClickable(false);
//注册播放完毕后的监听事件播放完毕后释放播放器,并且开始播放按钮重新设置为可点击
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
mediaPlayer = null;
bt_play.setEnabled(true);
bt_play.setClickable(true);
}
});
} else {
Toast.makeText(getApplicationContext(), "文件不存在", 0).show();
return;
}
}
private class MyListener extends PhoneStateListener{
//当有电话来的时候音乐暂停,电话进程结束后音乐恢复播放
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
System.out.println("音乐播放器:state:"+state);
System.out.println("音乐播放器:TelephonyManager.CALL_STATE_RINGING:"+TelephonyManager.CALL_STATE_RINGING);
System.out.println("音乐播放器:TelephonyManager.CALL_STATE_IDLE:"+TelephonyManager.CALL_STATE_IDLE);
switch (state) {
//电话铃响(1)
case TelephonyManager.CALL_STATE_RINGING:
// 音乐播放器暂停
pause();
break;
//电话进程恢复到正常状态(IDLE状态,结束)(0)
case TelephonyManager.CALL_STATE_IDLE:
// 重新播放音乐
pause();
break;
//挂起(已接听,正在通话)(2)
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
}
}
}
最后将项目部署到设备中将清单文件中的两个权限勾选了就可以进行测试效果了。
需要注意的是TelephonyManager.CALL_STATE_IDLE“电话挂断”状态的监听
经过测试时候发现电话挂断后音乐不恢复播放了,原来电话挂断时候根本没有触发onCallStateChanged回调方法。
最后发现问题出现在了sdk版本上面,我的项目所运行的目标设备都是api 28的设备,但是我的项目编译及构造工具却都是是api 30,在这里将构造版本都修改为28即可
也就是说项目编译及构造工具的api版本最好是和运行的目标设备的api 版本要一致。
然后重新运行项目就不会出现上面挂断电话不触发onCallStateChanged回调的问题了。
关键字词:android,播放器,编译,构造
上一篇:66_采用aidl挂断电话
下一篇:68_知识点如何显示歌词