Not able to achieve Gapless audio looping so far on Android

后端 未结 9 1893
走了就别回头了
走了就别回头了 2020-11-28 06:05

I have tried almost every method but I\'ve failed to achieve gapless audio playback between looping a single track with a duration of 10-15 seconds.

Steps I\'ve trie

9条回答
  •  庸人自扰
    2020-11-28 06:58

    For some reason, I found that my "OnCompletion" Event was always firing a fraction of second late when attempting to loop an 8-second OGG file. For anyone experiencing this type of delay, try the following.

    It is possible to forcibly queue a "nextMediaPlayer" as recommend in previous solutions, by simply posting a delayed Runnable to a Handler for your MediaPlayers and avoiding looping in onCompletion Event altogether.

    This performs flawlessly for me with my 160kbps 8-second OGG, min API 16.

    Somewhere in your Activity/Service, create a HandlerThread & Handler...

    private HandlerThread SongLooperThread = new HandlerThread("SongLooperThread");
    private Handler SongLooperHandler;
    
    public void startSongLooperThread(){
        SongLooperThread.start();
        Looper looper = SongLooperThread.getLooper();
        SongLooperHandler = new Handler(looper){
            @Override
            public void handleMessage(Message msg){
                //do whatever...
            }
        }
    }
    
    public void stopSongLooperThread(){
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){
            SongLooperThread.quit();
        } else {
            SongLooperThread.quitSafely();
        }
    }`
    

    ...start the Thread, declare and set up your MediaPlayers...

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    
        startSongLooperThread();
    
        activeSongResID = R.raw.some_loop;
        activeMP = MediaPlayer.create(getApplicationContext(), activeSongResID);
        activeSongMilliseconds = activeMP.getDuration();
    
        queuedMP = MediaPlayer.create(getApplicationContext(),activeSongResID);
    }
    
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        stopSongLooperThread();
    
        activeMP.release();
        queuedMP.release();
        activeMP = null;
        queuedMP = null;
    }
    

    ...create a Method for swapping your MediaPlayers...

    private void swapActivePlayers(){
        Log.v("SongLooperService","MediaPlayer swap started....");
        queuedMP.start();
    
        //Immediately get the Duration of the current track, then queue the next swap.
        activeSongMilliseconds = queuedMP.getDuration();
        SongLooperHandler.postDelayed(timedQueue,activeSongMilliseconds);
        Log.v("SongLooperService","Next call queued...");
    
        activeMP.release();
    
        //Swap your active and queued MPs...
        Log.v("SongLooperService","MediaPlayers swapping....");
        MediaPlayer temp = activeMP;
        activeMP = queuedMP;
        queuedMP = temp;
    
        //Prepare your now invalid queuedMP...
        queuedMP = MediaPlayer.create(getApplicationContext(),activeSongResID);
        Log.v("SongLooperService","MediaPlayer swapped.");
    }
    

    ...create Runnables to post to your thread...

    private Runnable startMP = new Runnable(){
        public void run(){
            activeMP.start();
            SongLooperHandler.postDelayed(timedQueue,activeSongMilliseconds);
        }
    };
    
    private Runnable timedQueue = new Runnable(){
        public void run(){
            swapActivePlayers();
        }
    };
    

    In your Service's onStartCommand() or somewhere in your Activity, start the MediaPlayer...

    ...
    SongLooperHandler.post(startMP);
    ...
    

提交回复
热议问题