androidflac

Playing .flac media with Android


I'm trying out different formats that Android devices can play. This page at the docs specifies all the media codecs that is supported by the Android platform. Notice that it also includes flac codec(.flac container). I am only using a very prototypical class to see if the media can be played.

Below is my 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>

And my very simple MainActivity.java file:

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();

    }

}    

But, when I try to play the flac file, I get the following error:

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) 

Now, I do see an error that the file cannot be opened as a file descriptor since it may be compressed. And I do know that flac is a lossless compression, so that could work, but I'm not satisfied with the logic here. Since mp3 are also compressed formats how come that played?


Solution

  • Disable compression for the flac file extension.

    android {
        aaptOptions {
            noCompress 'flac'
        }
    }
    

    For multiple extensions

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

    As part of preparing your APK, aapt selectively compresses various assets to save space on the device. The way aapt determines which assets need compression is by their file extension. From aapt source code Package.cpp these file extensions by default are exempted from compression.

    {
        ".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"
    }