You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android通知栏播放字节数组转换音频文件的实现方法

将音频Byte数组转为可播放的音频文件(Android平台)

嘿,你这个思路完全没问题——把音频byte数组写入临时文件再用MediaPlayer播放,我来帮你补全代码,还会加上通知栏播放的实现细节,适配Android的最新要求~

1. 基础版:Byte数组转临时文件+MediaPlayer播放

先给你补全完整的基础播放代码,包含异常处理和资源释放:

// 假设这是你的音频byte数组
byte[] mp3SoundByteArray = ...;

try {
    // 创建应用私有缓存目录下的临时MP3文件,应用退出时自动删除
    File tempMp3 = File.createTempFile("temp_audio", ".mp3", getCacheDir());
    tempMp3.deleteOnExit();

    // 将byte数组写入临时文件
    FileOutputStream fos = new FileOutputStream(tempMp3);
    fos.write(mp3SoundByteArray);
    fos.close();

    // 初始化MediaPlayer并设置播放逻辑
    MediaPlayer mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(tempMp3.getAbsolutePath());
    mediaPlayer.prepareAsync(); // 异步准备,避免阻塞主线程引发ANR

    // 准备完成后开始播放
    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.start();
            // 这里可以触发通知栏显示逻辑
            showPlaybackNotification(mp);
        }
    });

    // 监听播放错误,及时释放资源
    mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            Toast.makeText(getApplicationContext(), "音频播放失败", Toast.LENGTH_SHORT).show();
            mp.release();
            return true;
        }
    });

    // 播放结束后自动释放资源并移除通知
    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            mp.release();
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel(1);
        }
    });

} catch (IOException e) {
    e.printStackTrace();
    Toast.makeText(getApplicationContext(), "临时文件创建失败", Toast.LENGTH_SHORT).show();
}

几个关键细节要注意:

  • 用getCacheDir()创建的文件属于应用私有缓存目录,不需要申请外部存储权限,Android 10+也不会有存储权限限制,非常省心。
  • 一定要用prepareAsync()而非同步的prepare(),否则在主线程执行会导致应用无响应(ANR)。
  • 务必在播放完成、出错时调用mediaPlayer.release(),避免内存泄漏。

2. 进阶版:通知栏播放控制(适配Android 8.0+)

如果要在通知栏显示播放/暂停、停止按钮,建议用前台服务实现(Android 8.0以后后台服务会被系统限制,播放音频必须用前台服务才能稳定运行)。

第一步:创建音频播放服务

public class AudioPlaybackService extends Service {
    private MediaPlayer mediaPlayer;
    private static final int NOTIFICATION_ID = 1;
    private static final String CHANNEL_ID = "AUDIO_PLAYBACK_CHANNEL";

    @Override
    public void onCreate() {
        super.onCreate();
        // Android 8.0+必须创建通知渠道
        createNotificationChannel();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 接收从Activity传入的音频byte数组
        byte[] mp3ByteArray = intent.getByteArrayExtra("AUDIO_BYTE_ARRAY");
        if (mp3ByteArray != null) {
            try {
                File tempMp3 = File.createTempFile("service_audio", ".mp3", getCacheDir());
                tempMp3.deleteOnExit();
                FileOutputStream fos = new FileOutputStream(tempMp3);
                fos.write(mp3ByteArray);
                fos.close();

                mediaPlayer = new MediaPlayer();
                mediaPlayer.setDataSource(tempMp3.getAbsolutePath());
                mediaPlayer.prepareAsync();
                mediaPlayer.setOnPreparedListener(mp -> {
                    mp.start();
                    // 启动前台服务并显示通知
                    startForeground(NOTIFICATION_ID, createPlaybackNotification());
                });
                mediaPlayer.setOnCompletionListener(mp -> {
                    mp.release();
                    stopForeground(true);
                    stopSelf();
                });
                mediaPlayer.setOnErrorListener((mp, what, extra) -> {
                    mp.release();
                    stopForeground(true);
                    stopSelf();
                    return true;
                });
            } catch (IOException e) {
                e.printStackTrace();
                stopSelf();
            }
        }
        return START_STICKY;
    }

    // 创建带播放控制按钮的通知
    private Notification createPlaybackNotification() {
        // 暂停按钮的Intent
        Intent pauseIntent = new Intent(this, AudioPlaybackService.class);
        pauseIntent.setAction("ACTION_PAUSE");
        PendingIntent pausePendingIntent = PendingIntent.getService(this, 0, pauseIntent, PendingIntent.FLAG_IMMUTABLE);

        // 停止按钮的Intent
        Intent stopIntent = new Intent(this, AudioPlaybackService.class);
        stopIntent.setAction("ACTION_STOP");
        PendingIntent stopPendingIntent = PendingIntent.getService(this, 1, stopIntent, PendingIntent.FLAG_IMMUTABLE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_audio) // 替换成你的图标
                .setContentTitle("正在播放音频")
                .setContentText("临时音频文件")
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .addAction(R.drawable.ic_pause, "暂停", pausePendingIntent) // 替换成你的暂停图标
                .addAction(R.drawable.ic_stop, "停止", stopPendingIntent) // 替换成你的停止图标
                .setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
                        .setShowActionsInCompactView(0, 1)); // 在紧凑视图显示控制按钮

        return builder.build();
    }

    // 创建通知渠道(Android 8.0+必填)
    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "音频播放", NotificationManager.IMPORTANCE_LOW);
            channel.setDescription("用于显示音频播放控制通知");
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
        }
    }
}

第二步:在Activity中启动服务

Intent serviceIntent = new Intent(this, AudioPlaybackService.class);
serviceIntent.putExtra("AUDIO_BYTE_ARRAY", mp3SoundByteArray);
// Android 8.0+用startForegroundService,旧版本用startService
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(serviceIntent);
} else {
    startService(serviceIntent);
}

第三步:在Manifest中注册服务

别忘了在AndroidManifest.xml里添加服务声明:

<service android:name=".AudioPlaybackService" />

3. 额外提醒

  • 临时文件清理:deleteOnExit()会在应用退出时自动删除临时文件,你也可以在播放完成后主动调用tempMp3.delete()提前清理。
  • 播放控制逻辑扩展:上面的服务只实现了基础播放,你可以在onStartCommand中判断Intent的Action,添加暂停、继续播放的逻辑。
  • 兼容性:PendingIntent.FLAG_IMMUTABLE是Android 12+推荐的,如果你要兼容更低版本,可以根据SDK版本切换为FLAG_UPDATE_CURRENT。

内容的提问来源于stack exchange,提问作者Proxy Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:03:15