使用 Android 播放 .flac 媒体

Playing .flac media with Android

我正在尝试 Android 设备可以播放的不同格式。 This page at the docs 指定 Android 平台支持的所有媒体编解码器。请注意,它还包括 flac 编解码器(.flac 容器)。我只是用一个非常原型的 class 来查看媒体是否可以播放。

下面是我的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"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="timre-CCBYNC.flac"
        android:onClick="playMusic"
        />


</LinearLayout>

还有我非常简单的 MainActivity.java 文件:

package com.hbad.www.testmusic_playaudio;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void playMusic(View view)throws IOException {
        Button passed_btn = (Button)view;
        AssetFileDescriptor afd = getAssets().openFd(passed_btn.getText().toString());
        MediaPlayer player = new MediaPlayer();
        player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        player.prepare();
        player.start();

    }

}    

但是,当我尝试播放 flac 文件时,出现以下错误:

11-13 13:04:19.087 16332-16332/com.hbad.www.testmusic_playaudio E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.hbad.www.testmusic_playaudio, PID: 16332
    java.lang.IllegalStateException: Could not execute method for android:onClick
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
        at android.view.View.performClick(View.java:4496)
        at android.view.View$PerformClick.run(View.java:18603)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5433)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
        at android.view.View.performClick(View.java:4496) 
        at android.view.View$PerformClick.run(View.java:18603) 
        at android.os.Handler.handleCallback(Handler.java:733) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:136) 
        at android.app.ActivityThread.main(ActivityThread.java:5433) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
        at dalvik.system.NativeStart.main(Native Method) 
     Caused by: java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
        at android.content.res.AssetManager.openAssetFd(Native Method)
        at android.content.res.AssetManager.openFd(AssetManager.java:343)
        at com.hbad.www.testmusic_playaudio.MainActivity.playMusic(MainActivity.java:24)
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
        at android.view.View.performClick(View.java:4496) 
        at android.view.View$PerformClick.run(View.java:18603) 
        at android.os.Handler.handleCallback(Handler.java:733) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:136) 
        at android.app.ActivityThread.main(ActivityThread.java:5433) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
        at dalvik.system.NativeStart.main(Native Method) 

现在,我确实看到一个错误,该文件无法作为文件描述符打开,因为它可能被压缩了。我知道 flac 是一种无损压缩,所以它可以工作,但我对这里的逻辑不满意。既然mp3也是压缩格式怎么播放呢?

您可以为某些扩展禁用资产压缩,您可以将其添加到您的 build.gradle

android {
    aaptOptions {
        noCompress "your_extension"
    }
}

禁用 flac 文件扩展名的压缩。

android {
    aaptOptions {
        noCompress 'flac'
    }
}

对于多个扩展

android {
    aaptOptions {
        noCompress 'flac', 'other extensions'
    }
}

作为准备 APK 的一部分,aapt 有选择地压缩各种资产以在设备上保存 space。 aapt 确定哪些资产需要压缩的方式是通过它们的文件扩展名。从 aapt 源代码 Package.cpp 默认情况下,这些文件扩展名免于压缩。

{
    ".jpg", ".jpeg", ".png", ".gif",
    ".wav", ".mp2", ".mp3", ".ogg", ".aac",
    ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
    ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
    ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
    ".amr", ".awb", ".wma", ".wmv"
}