android MediaPlayer 的SeekTo 方法

android使用 mediaPlayer 播放video视频过程中, 当用户退出当前播放,再从后台恢复播放时,需要跳转到之前退出的时间点继续播放。

使用的方法基本都是 SeekTo 之前的时间点,但是经常遇到恢复播放时位置不准的问题,而且甚至有重头开始播放的现象。这个是因为SeekTo是回到上一时间点附近的关键帧导致的。

针对这个问题,在最新的android 8.0平台上,已经有了新的解决方案:

SeekTo() 方法在android O 平台新增了一个多参数的方法:

void seekTo(long msec, @SeekMode int mode)

这里的Mode 传入

int SEEK_CLOSEST = 0x03 

就不会出现播放视频位置不准确的现象了。


/**
     * Seek modes used in method seekTo(long, int) to move media position
     * to a specified location.
     *
     * Do not change these mode values without updating their counterparts
     * in include/media/IMediaSource.h!
     */
    /**
     * This mode is used with {@link #seekTo(long, int)} to move media position to
     * a sync (or key) frame associated with a data source that is located
     * right before or at the given time.
     *
     * @see #seekTo(long, int)
     */
    public static final int SEEK_PREVIOUS_SYNC    = 0x00;
    /**
     * This mode is used with {@link #seekTo(long, int)} to move media position to
     * a sync (or key) frame associated with a data source that is located
     * right after or at the given time.
     *
     * @see #seekTo(long, int)
     */
    public static final int SEEK_NEXT_SYNC        = 0x01;
    /**
     * This mode is used with {@link #seekTo(long, int)} to move media position to
     * a sync (or key) frame associated with a data source that is located
     * closest to (in time) or at the given time.
     *
     * @see #seekTo(long, int)
     */
    public static final int SEEK_CLOSEST_SYNC     = 0x02;
    /**
     * This mode is used with {@link #seekTo(long, int)} to move media position to
     * a frame (not necessarily a key frame) associated with a data source that
     * is located closest to or at the given time.
     *
     * @see #seekTo(long, int)
     */
    public static final int SEEK_CLOSEST          = 0x03;

    /** @hide */
    @IntDef(
        value = {
            SEEK_PREVIOUS_SYNC,
            SEEK_NEXT_SYNC,
            SEEK_CLOSEST_SYNC,
            SEEK_CLOSEST,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SeekMode {}

    private native final void _seekTo(long msec, int mode);

    /**
     * Moves the media to specified time position by considering the given mode.
     * 

     * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.      * There is at most one active seekTo processed at any time. If there is a to-be-completed      * seekTo, new seekTo requests will be queued in such a way that only the last request      * is kept. When current seekTo is completed, the queued request will be processed if      * that request is different from just-finished seekTo operation, i.e., the requested      * position or mode is different.      *      * @param msec the offset in milliseconds from the start to seek to.      * When seeking to the given time position, there is no guarantee that the data source      * has a frame located at the position. When this happens, a frame nearby will be rendered.      * If msec is negative, time position zero will be used.      * If msec is larger than duration, duration will be used.      * @param mode the mode indicating where exactly to seek to.      * Use {@link #SEEK_PREVIOUS_SYNC} if one wants to seek to a sync frame      * that has a timestamp earlier than or the same as msec. Use      * {@link #SEEK_NEXT_SYNC} if one wants to seek to a sync frame      * that has a timestamp later than or the same as msec. Use      * {@link #SEEK_CLOSEST_SYNC} if one wants to seek to a sync frame      * that has a timestamp closest to or the same as msec. Use      * {@link #SEEK_CLOSEST} if one wants to seek to a frame that may      * or may not be a sync frame but is closest to or the same as msec.      * {@link #SEEK_CLOSEST} often has larger performance overhead compared      * to the other options if there is no sync frame located at msec.      * @throws IllegalStateException if the internal player engine has not been      * initialized      * @throws IllegalArgumentException if the mode is invalid.      */     public void seekTo(long msec, @SeekMode int mode) {         if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) {             final String msg = "Illegal seek mode: " + mode;             throw new IllegalArgumentException(msg);         }         // TODO: pass long to native, instead of truncating here.         if (msec > Integer.MAX_VALUE) {             Log.w(TAG, "seekTo offset " + msec + " is too large, cap to " + Integer.MAX_VALUE);             msec = Integer.MAX_VALUE;         } else if (msec < Integer.MIN_VALUE) {             Log.w(TAG, "seekTo offset " + msec + " is too small, cap to " + Integer.MIN_VALUE);             msec = Integer.MIN_VALUE;         }         _seekTo(msec, mode);     }


你可能感兴趣的:(android MediaPlayer 的SeekTo 方法)