装了MediaPlayer10后又删除了!

博主升级安装MediaPlayer10后,遇到媒体库列表和播放列表无法同步显示当前播放项目的问题,即不能同时聚焦在同一项目,只能通过反删除操作处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

升级安装了一个mediaplayer10,发现媒体库里面的列表和播放列表无法同步显示当前播放项目(无法同时聚焦在同一项目),只能反删除!

package com.example.demoapplication; import android.Manifest; // 导入录音权限类 import android.content.pm.PackageManager; // 导入包管理器权限类 import android.media.AudioFormat; // 导入音频格式类 import android.media.AudioManager; // 导入音频管理类 import android.media.AudioRecord; // 导入音频录制类 import android.media.MediaPlayer; // 导入媒体播放器类 import android.media.MediaRecorder; // 导入媒体录制器类 import android.os.Bundle; // 导入Android数据包类 import android.os.Handler; // 导入消息处理类 import android.os.Looper; // 导入线程循环类 import android.os.Message; // 导入消息传递类 import android.speech.tts.TextToSpeech; // 导入文本转语音接口 import android.util.Log; // 导入日志工具类 import android.widget.Button; // 导入按钮组件 import android.widget.Toast; // 导入提示框类 import androidx.annotation.NonNull; // 导入非空注解 import androidx.appcompat.app.AppCompatActivity; // 导入AppCompatActivity基类 import androidx.core.app.ActivityCompat; // 导入兼容库活动权限工具类 import androidx.core.content.ContextCompat; // 导入兼容库内容上下文工具类 import org.json.JSONObject; // 导入JSON对象类 import java.io.BufferedReader; // 导入缓冲字符读取流 import java.io.BufferedWriter; // 导入缓冲字符写入流 import java.io.File; // 导入文件操作类 import java.io.FileOutputStream; // 导入文件输出流 import java.io.IOException; // 导入输入输出异常类 import java.io.InputStreamReader; // 导入字符输入流包器 import java.io.OutputStreamWriter; // 导入字符输出流包器 import java.net.ServerSocket; // 导入服务器套接字 import java.net.Socket; // 导入网络连接套接字 import java.util.LinkedList; // 导入链表队列结构 import java.util.Locale; // 导入语言环境类 import java.util.Queue; // 导入队列接口 import java.util.concurrent.ExecutorService; // 导入执行服务线程池 import java.util.concurrent.Executors; // 导入线程池工厂类 import java.util.concurrent.ScheduledExecutorService; // 导入定时任务执行服务 import java.util.concurrent.TimeUnit; // 导入时间单位枚举 import java.util.concurrent.atomic.AtomicBoolean; // 导入原子布尔值 public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener { private static final String TAG = "AudioRecorder"; // 日志标签 private static final int PERMISSION_REQUEST_CODE = 1; // 权限请求代码 private static final int SAMPLE_RATE = 16000; // 音频采样率 private static final int BUFFER_SIZE; // 缓冲区大小 static { // 计算最小缓冲区大小 int minBufferSize = AudioRecord.getMinBufferSize( SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, // 单声道采集 AudioFormat.ENCODING_PCM_16BIT // 16位PCM编码 ); BUFFER_SIZE = Math.max(minBufferSize, 4096); // 取最大值作为最终缓冲区大小 } // UI组件声明 private Button startRecordButton, stopRecordButton; // 录音控制按钮 private Button playSoundButton, pauseSoundButton, stopSoundButton, resumeSoundButton, clearSoundsButton; // 播放控制按钮 // 音频录制相关变量 private AudioRecord audioRecord; // 音频录制对象 private ScheduledExecutorService scheduler; // 定时任务调度器 private AtomicBoolean isRecording = new AtomicBoolean(false); // 是否正在录音标志 private final Queue<byte[]> recordingQueue = new LinkedList<>(); // 录制数据队列 // 网络通信相关变量 private final ExecutorService executorService = Executors.newCachedThreadPool(); // 弹性线程池 private ServerSocket serverSocket; // 服务器端监听套接字 private volatile boolean isServerRunning = true; // 服务器运行状态标志 private volatile Socket clientSocket; // 客户端连接套接字 private volatile BufferedWriter socketWriter; // 套接字写入器 // 文本转语音相关变量 private TextToSpeech ttsEngine; // TTS引擎实例 private boolean isTtsInitialized = false; // TTS初始化状态标志 // MP3播放相关变量 private MediaPlayer mediaPlayer; // 媒体播放器实例 private final Queue<byte[]> mp3PlaybackQueue = new LinkedList<>(); // 播放队列 private final AtomicBoolean isPlaying = new AtomicBoolean(false); // 是否正在播放 private final AtomicBoolean isPaused = new AtomicBoolean(false); // 是否暂停 private volatile boolean isPlaybackThreadActive = false; // 播放线程活跃状态 // 同步锁对象 private final Object playbackQueueLock = new Object(); // 播放队列锁 private final Object recordingQueueLock = new Object(); // 录制队列锁 private final Object mediaPlayerLock = new Object(); // 媒体播放器锁 // 主线程消息处理器 private final Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(@NonNull Message msg) { switch (msg.what) { case 0x11: // 客户端连接事件 Toast.makeText(MainActivity.this, "客户端已连接", Toast.LENGTH_SHORT).show(); break; case 0x12: // 开始录音事件 Toast.makeText(MainActivity.this, "开始录音", Toast.LENGTH_SHORT).show(); sendJsonPacket("startRecorder", null); playTts("开始录音"); break; case 0x14: // 停止录音事件 Toast.makeText(MainActivity.this, "停止录音", Toast.LENGTH_SHORT).show(); sendJsonPacket("stopRecorder", null); playTts("停止录音"); break; case 0x16: // 错误消息事件 Toast.makeText(MainActivity.this, "错误: " + msg.obj, Toast.LENGTH_LONG).show(); break; case 0x17: // 播放完成事件 Toast.makeText(MainActivity.this, "播放完成", Toast.LENGTH_SHORT).show(); isPlaying.set(false); isPlaybackThreadActive = false; updatePlayButtonsState(); break; case 0x18: // 添加到播放队列 Toast.makeText(MainActivity.this, "已添加到播放队列", Toast.LENGTH_SHORT).show(); break; case 0x19: // 更新播放按钮状态 updatePlayButtonsState(); break; case 0x20: // 开始播放MP3 Toast.makeText(MainActivity.this, "开始播放MP3", Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 设置界面布局 // 初始化文本转语音功能 ttsEngine = new TextToSpeech(this, this); // 初始化视图组件 initViews(); setupClickListeners(); // 绑定点击事件 // 检查必要权限 checkPermissions(); // 启动服务器并开始监听 startServer(30000); startSocketListener(); } private void initViews() { // 绑定UI控件 startRecordButton = findViewById(R.id.startRecordButton); stopRecordButton = findViewById(R.id.stopRecordButton); playSoundButton = findViewById(R.id.playSoundButton); pauseSoundButton = findViewById(R.id.pauseSoundButton); stopSoundButton = findViewById(R.id.stopSoundButton); resumeSoundButton = findViewById(R.id.resumeSoundButton); clearSoundsButton = findViewById(R.id.clearSoundsButton); // 设置初始按钮状态 stopRecordButton.setEnabled(false); pauseSoundButton.setEnabled(false); stopSoundButton.setEnabled(false); resumeSoundButton.setEnabled(false); } private void setupClickListeners() { // 设置录音按钮点击事件 startRecordButton.setOnClickListener(v -> startRecording()); stopRecordButton.setOnClickListener(v -> stopRecording()); // 设置播放控制按钮点击事件 playSoundButton.setOnClickListener(v -> playNextInQueue()); pauseSoundButton.setOnClickListener(v -> pausePlayback()); stopSoundButton.setOnClickListener(v -> stopPlayback()); resumeSoundButton.setOnClickListener(v -> resumePlayback()); clearSoundsButton.setOnClickListener(v -> { clearPlaybackQueue(); // 清空播放队列 handler.sendEmptyMessage(0x19); // 发送更新消息 }); } // ==================== 录音功能模块 ==================== private void startRecording() { // 检查录音权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { sendErrorMessage("没有录音权限"); return; } // 如果已经在录音则先释放资源 if (isRecording.get()) { releaseAudioResources(); } try { // 创建音频录制对象 audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, // 使用麦克风输入 SAMPLE_RATE, // 采样率 AudioFormat.CHANNEL_IN_MONO, // 单声道 AudioFormat.ENCODING_PCM_16BIT, // 16位PCM编码 BUFFER_SIZE // 缓冲区大小 ); // 检查初始化状态 if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) { throw new IllegalStateException("AudioRecord 初始化失败"); } // 开始录音 audioRecord.startRecording(); isRecording.set(true); startRecordButton.setEnabled(false); stopRecordButton.setEnabled(true); updatePlayButtonsState(); // 更新播放按钮状态 // 关闭旧的调度器 if (scheduler != null && !scheduler.isShutdown()) { scheduler.shutdownNow(); } // 创建新的单线程调度器 scheduler = Executors.newSingleThreadScheduledExecutor(); // 定期采集音频数据(每100ms) scheduler.scheduleAtFixedRate(this::captureAudioData, 0, 100, TimeUnit.MILLISECONDS); handler.sendEmptyMessage(0x12); // 发送开始录音通知 } catch (Exception e) { Log.e(TAG, "录音启动失败", e); sendErrorMessage("录音启动失败: " + e.getMessage()); releaseAudioResources(); } } private void stopRecording() { if (!isRecording.get()) return; isRecording.set(false); releaseAudioResources(); // 释放音频资源 stopRecordButton.setEnabled(false); startRecordButton.setEnabled(true); updatePlayButtonsState(); // 更新播放按钮状态 handler.sendEmptyMessage(0x14); // 发送停止录音通知 } private void captureAudioData() { if (!isRecording.get() || audioRecord == null) return; byte[] buffer = new byte[BUFFER_SIZE]; // 创建缓冲区 try { // 从音频设备读取数据 int bytesRead = audioRecord.read(buffer, 0, BUFFER_SIZE); if (bytesRead > 0) { synchronized (recordingQueueLock) { recordingQueue.offer(buffer.clone()); // 存储音频数据 } sendJsonPacket("recording", buffer); // 发送数据包 } } catch (Exception e) { Log.e(TAG, "音频采集失败", e); } } // ==================== MP3播放功能模块 ==================== private void addMp3ToQueue(byte[] mp3Data) { synchronized (playbackQueueLock) { mp3PlaybackQueue.offer(mp3Data); // 将MP3数据加入播放队列 } handler.sendEmptyMessage(0x18); // 发送加入队列通知 // 如果没有播放且线程不活跃,开始播放 if (!isPlaying.get() && !isPlaybackThreadActive) { playNextInQueue(); } } private void playNextInQueue() { if (isPlaybackThreadActive || mp3PlaybackQueue.isEmpty()) return; isPlaybackThreadActive = true; executorService.execute(() -> { // 在线程池中执行 try { while (!mp3PlaybackQueue.isEmpty() && !isPaused.get()) { byte[] mp3Data; synchronized (playbackQueueLock) { mp3Data = mp3PlaybackQueue.poll(); // 取出队列中的MP3数据 } if (mp3Data != null) { playMp3Data(mp3Data); // 播放MP3数据 } } if (!isPaused.get()) { isPlaying.set(false); isPlaybackThreadActive = false; handler.sendEmptyMessage(0x17); // 发送播放完成通知 } } catch (Exception e) { Log.e(TAG, "MP3播放失败", e); sendErrorMessage("MP3播放失败: " + e.getMessage()); } }); } private void playMp3Data(final byte[] mp3Data) { try { // 创建临时文件 File tempFile = File.createTempFile("audio_", ".mp3", getCacheDir()); try (FileOutputStream fos = new FileOutputStream(tempFile)) { fos.write(mp3Data); // 写入文件 } runOnUiThread(() -> { synchronized (mediaPlayerLock) { try { releaseMediaPlayer(); // 释放之前的播放器资源 mediaPlayer = new MediaPlayer(); // 创建新播放器 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // 设置音频流类型 mediaPlayer.setDataSource(tempFile.getAbsolutePath()); // 设置数据源 // 设置准备监听器 mediaPlayer.setOnPreparedListener(mp -> { mediaPlayer.start(); // 开始播放 isPlaying.set(true); // 标记为正在播放 isPaused.set(false); // 标记为未暂停 handler.sendEmptyMessage(0x20); // 发送开始播放通知 updatePlayButtonsState(); // 更新按钮状态 }); // 设置完成监听器 mediaPlayer.setOnCompletionListener(mp -> { // 删除临时文件 tempFile.delete(); // 播放下一个文件 if (!playNextInQueueImmediately()) { isPlaying.set(false); isPlaybackThreadActive = false; handler.sendEmptyMessage(0x17); } }); // 设置错误监听器 mediaPlayer.setOnErrorListener((mp, what, extra) -> { Log.e(TAG, "MediaPlayer error: " + what + ", " + extra); sendErrorMessage("播放错误: " + what); tempFile.delete(); // 删除临时文件 return false; }); mediaPlayer.prepareAsync(); // 准备播放 } catch (IOException e) { Log.e(TAG, "MediaPlayer初始化失败", e); tempFile.delete(); // 删除临时文件 } } }); } catch (IOException e) { Log.e(TAG, "创建临时文件失败", e); } } private boolean playNextInQueueImmediately() { if (!mp3PlaybackQueue.isEmpty()) { byte[] nextData; synchronized (playbackQueueLock) { nextData = mp3PlaybackQueue.poll(); // 取出下一个播放项 } if (nextData != null) { playMp3Data(nextData); // 直接播放 return true; } } return false; } // ==================== 播放控制 ==================== private void pausePlayback() { synchronized (mediaPlayerLock) { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); // 暂停播放 isPaused.set(true); // 设置暂停标志 updatePlayButtonsState(); // 更新按钮状态 } } } private void resumePlayback() { synchronized (mediaPlayerLock) { if (mediaPlayer != null && isPaused.get()) { mediaPlayer.start(); // 恢复播放 isPaused.set(false); // 取消暂停标志 updatePlayButtonsState(); // 更新按钮状态 } } } private void stopPlayback() { synchronized (mediaPlayerLock) { if (mediaPlayer != null) { try { mediaPlayer.stop(); // 停止播放 } catch (IllegalStateException e) { Log.e(TAG, "停止播放失败", e); } } } clearPlaybackQueue(); // 清空播放队列 isPlaying.set(false); // 设置未播放状态 isPaused.set(false); // 取消暂停状态 updatePlayButtonsState(); // 更新按钮状态 } private void clearPlaybackQueue() { synchronized (playbackQueueLock) { mp3PlaybackQueue.clear(); // 清空播放队列 } } private void releaseMediaPlayer() { synchronized (mediaPlayerLock) { if (mediaPlayer != null) { try { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); // 停止播放 } mediaPlayer.release(); // 释放资源 } catch (Exception e) { Log.e(TAG, "释放MediaPlayer失败", e); } finally { mediaPlayer = null; // 清空引用 } } } } // ==================== 辅助方法 ==================== private void updatePlayButtonsState() { runOnUiThread(() -> { boolean hasRecordings = !mp3PlaybackQueue.isEmpty(); // 是否有录音 boolean isPlayingState = isPlaying.get() && !isPaused.get(); // 是否正在播放 boolean isPausedState = isPaused.get(); // 是否暂停 // 设置按钮启用状态 playSoundButton.setEnabled(hasRecordings && !isPlayingState); pauseSoundButton.setEnabled(isPlayingState); stopSoundButton.setEnabled(isPlaying.get() || isPausedState); resumeSoundButton.setEnabled(isPausedState); clearSoundsButton.setEnabled(hasRecordings); }); } private void playTts(String text) { if (isTtsInitialized) { ttsEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null); // 播放TTS } } private void releaseAudioResources() { if (audioRecord != null) { try { // 如果正在录音则停止 if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { audioRecord.stop(); } audioRecord.release(); // 释放资源 } catch (IllegalStateException e) { Log.e(TAG, "停止录音失败", e); } finally { audioRecord = null; // 清除引用 } } if (scheduler != null) { try { scheduler.shutdownNow(); // 关闭调度器 // 等待关闭完成 if (!scheduler.awaitTermination(500, TimeUnit.MILLISECONDS)) { Log.w(TAG, "录音线程池未正常关闭"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 重新设置中断标志 } finally { scheduler = null; // 清除引用 } } } private void sendJsonPacket(String type, Object data) { if (clientSocket == null || clientSocket.isClosed() || socketWriter == null) { return; // 如果连接无效则返回 } try { JSONObject packet = new JSONObject(); // 创建JSON包 packet.put("type", type); // 设置类型 if (data != null) { packet.put("data", data); // 添加数据 } synchronized (this) { if (socketWriter != null) { socketWriter.write(packet.toString()); // 写入JSON字符串 socketWriter.write("\n\n"); // 添加分隔符 socketWriter.flush(); // 刷新缓冲区 } } } catch (Exception e) { Log.e(TAG, "发送数据包失败: " + type, e); } } private void sendErrorMessage(String message) { handler.obtainMessage(0x16, message).sendToTarget(); // 发送错误消息 } private void checkPermissions() { // 检查录音权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSION_REQUEST_CODE ); } // 检查存储权限(用于临时文件) if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE + 1 ); } } // ==================== 网络通信 ==================== private void startServer(int port) { executorService.execute(() -> { // 在线程池中执行 try { serverSocket = new ServerSocket(port); // 创建服务器套接字 Log.i(TAG, "服务器启动: " + port); // 打印日志 while (isServerRunning) { // 服务器运行循环 try { Socket socket = serverSocket.accept(); // 接受连接 clientSocket = socket; // 保存客户端套接字 synchronized (this) { // 创建套接字写入器 socketWriter = new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(), "UTF-8") ); } handler.sendEmptyMessage(0x11); // 发送连接成功通知 } catch (IOException e) { if (isServerRunning) Log.e(TAG, "接受连接失败", e); } } } catch (IOException e) { Log.e(TAG, "服务器启动失败", e); runOnUiThread(() -> Toast.makeText( this, "服务器启动失败: " + e.getMessage(), Toast.LENGTH_LONG ).show()); } finally { closeServerSocket(); // 关闭服务器套接字 } }); } private void startSocketListener() { executorService.execute(() -> { // 在线程池中执行 while (isServerRunning) { if (clientSocket != null && !clientSocket.isClosed()) { try { BufferedReader reader = new BufferedReader( new InputStreamReader(clientSocket.getInputStream(), "UTF-8") ); // 创建输入流读取器 // 先读取数据长度 String lengthLine = reader.readLine(); if (lengthLine == null) break; int dataLength = Integer.parseInt(lengthLine.trim()); // 解析数据长度 byte[] mp3Data = new byte[dataLength]; // 创建数据缓冲区 // 读取二进制数据 int bytesRead = 0; while (bytesRead < dataLength) { int count = clientSocket.getInputStream().read( mp3Data, bytesRead, dataLength - bytesRead); if (count == -1) break; bytesRead += count; } if (bytesRead == dataLength) { addMp3ToQueue(mp3Data); // 添加到播放队列 } else { Log.w(TAG, "数据不完整: " + bytesRead + "/" + dataLength); } } catch (IOException | NumberFormatException e) { Log.e(TAG, "Socket读取失败", e); closeSocket(clientSocket); // 关闭套接字 } } else { try { Thread.sleep(500); // 等待500毫秒 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 重新设置中断标志 break; } } } }); } private void closeServerSocket() { try { if (serverSocket != null && !serverSocket.isClosed()) { serverSocket.close(); // 关闭服务器套接字 } } catch (IOException e) { Log.w(TAG, "关闭ServerSocket失败", e); } } private void closeSocket(Socket socket) { try { if (socket != null && !socket.isClosed()) { socket.close(); // 关闭套接字 } } catch (IOException e) { Log.w(TAG, "关闭Socket失败", e); } if (socket == clientSocket) { clientSocket = null; // 清除客户端套接字引用 synchronized (this) { socketWriter = null; // 清除写入器引用 } } } // ==================== 文本转语音 ==================== @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { int result = ttsEngine.setLanguage(Locale.CHINESE); // 设置中文语言 if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { Log.e(TAG, "TTS语言不支持中文"); } else { isTtsInitialized = true; // 设置初始化完成标志 } } } // ==================== 生命周期 ==================== @Override protected void onDestroy() { super.onDestroy(); isServerRunning = false; // 停止服务器 // 释放TTS资源 if (ttsEngine != null) { ttsEngine.stop(); ttsEngine.shutdown(); } // 释放网络资源 closeServerSocket(); closeSocket(clientSocket); // 释放音频资源 stopRecording(); releaseMediaPlayer(); // 关闭线程池 executorService.shutdown(); try { // 等待关闭完成 if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) { executorService.shutdownNow(); // 强制关闭 } } catch (InterruptedException e) { executorService.shutdownNow(); // 强制关闭 Thread.currentThread().interrupt(); // 重新设置中断标志 } } } 我这个安卓端口是多少
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值