Search code examples
androidsqliteaudioandroid-sqliteandroid-mediaplayer

Play list<byte[]> audio files from SQLite database


I have a table with audio data saved in BLOB format. I want to play the audio files but I have problem in calling the method from database.

This is my DatabaseAccess.java

    public List<byte[]> getAudio(long i) {
    List<byte[]> list = new ArrayList<>();
    File file;
    FileOutputStream fos;

    byte[] byteaudio = null;
    String selectAudio = "SELECT VocabAudio FROM Vocab WHERE VocabTopic =" + i;
    Cursor c = database.rawQuery(selectAudio, null);
    if(c.moveToFirst())
        do{
            byteaudio = c.getBlob(c.getColumnIndex("VocabAudio"));

            try{
                file = File.createTempFile("audio", "audio");
                fos = new FileOutputStream(file);
                fos.write(byteaudio);
                fos.close();

            }catch (IOException e){
                e.printStackTrace();
            }

        }while(c.moveToNext());

    return list;
}

This is my activity class where I want to call my getAudio() method. It says that it cannot find symbol variable file (from the Uri.fromFile(file)).

    public void startSlides() {

    timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {

        public void run() {
            runOnUiThread(new Runnable() {
                public void run() {

                    Intent intent = getIntent();
                    long topicId = intent.getLongExtra("SelectedTopicId", 0);

                    databaseAccess.open();

                    List<byte[]> audio = databaseAccess.getAudio(topicId);

                    mp= MediaPlayer.create(Choice.this,Uri.fromFile(file));
                    i++;
                    mp.start();


                    databaseAccess.close();

                    if (j == vocab.size()+1) {
                        timer.cancel();
                    }
                }
            });
        }

    }, 0, 1000;
}

Anyone knows how should I call the getAudio() method? Thanks.


Solution

  • you are not adding anything to list, you only write bytes into a file, the other thing, is file is in another method, you will not be able to see that reference from your activity.

    instead of writing the file (in getAutdio) add the bytes to the list and return it.

    now from the list you can play the audio or write the files and then play the audio.

    your code may look like this:

    public List<byte[]> getAudio(long i) {
        List<byte[]> list = new ArrayList<>();
    
        byte[] byteaudio = null;
        String selectAudio = "SELECT VocabAudio FROM Vocab WHERE VocabTopic =" + i;
        Cursor c = database.rawQuery(selectAudio, null);
        if(c.moveToFirst())
        do{
            byteaudio = c.getBlob(c.getColumnIndex("VocabAudio"));
            list.add(byteaudio);
        }while(c.moveToNext());
    
        return list;
    }
    

    And for playing, you can write the byte[] in a file create the MediaPlayer refere to this answer it's just a concept, you may need to change it a little bit, or use latest code to use MediaPlayer

    public void run() {
    
        Intent intent = getIntent();
        long topicId = intent.getLongExtra("SelectedTopicId", 0);
    
        databaseAccess.open();
        List<byte[]> audio = databaseAccess.getAudio(topicId);
        databaseAccess.close();
    
        for(byte[] track : audio){
            playMp3(track);
        }//for loop
    
        if (j == vocab.size()+1) {
            timer.cancel();
        }
    }
    

    NOW: since you are mainly using Files (to play the media) and as suggested by comments above, you may instead of storing bytes of the audio file, store the file name and path (as string) you can then immediatly retrive file names from DB and start the media player

    EDIT: to play files one by one, you may want to make List<byte[]> audio class scope, and call playMp3(audio.get(index)); where index is an integer that you increase every time you play a file (but be careful not to check

    Class Scope:

    private List<byte[]> audio;
    private int index =0;
    

    Then onClick of the play button:

    @Override
    public void onClick(View view){
        if(index >= audio.size()){
            index = 0; // back to first track ?
        }
        playMp3(audio.get(index));
        ++index;
    }