音频界面显示缓冲进度

pull/1816/head
ag2s20150909 2 years ago
parent e59746eae0
commit 1bb3437ae5
  1. 1
      app/src/main/java/io/legado/app/constant/EventBus.kt
  2. 8
      app/src/main/java/io/legado/app/help/exoplayer/ExoPlayerHelper.kt
  3. 40
      app/src/main/java/io/legado/app/help/exoplayer/OkhttpCacheDataSource.java
  4. 12
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  5. 4
      app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt

@ -16,6 +16,7 @@ object EventBus {
const val AUDIO_SUB_TITLE = "audioSubTitle"
const val AUDIO_STATE = "audioState"
const val AUDIO_PROGRESS = "audioProgress"
const val AUDIO_BUFFER_PROGRESS = "audioBufferProgress"
const val AUDIO_SIZE = "audioSize"
const val AUDIO_SPEED = "audioSpeed"
const val NOTIFY_MAIN = "notifyMain"

@ -6,7 +6,9 @@ import com.google.android.exoplayer2.database.StandaloneDatabaseProvider
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.FileDataSource
import com.google.android.exoplayer2.upstream.cache.Cache
import com.google.android.exoplayer2.upstream.cache.CacheDataSink
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
import com.google.android.exoplayer2.upstream.cache.SimpleCache
import io.legado.app.help.http.okHttpClient
@ -36,6 +38,12 @@ object ExoPlayerHelper {
return@lazy OkhttpCacheDataSource.Factory()
.setCache(cache)
.setUpstreamDataSourceFactory(okhttpDataFactory)
.setCacheReadDataSourceFactory(FileDataSource.Factory())
.setCacheWriteDataSinkFactory(
CacheDataSink.Factory()
.setCache(cache)
.setFragmentSize(CacheDataSink.DEFAULT_FRAGMENT_SIZE)
)
}
/**

@ -1,8 +1,29 @@
package io.legado.app.help.exoplayer;
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.min;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri;
@ -37,10 +58,12 @@ import java.io.InterruptedIOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* A {@link DataSource} that reads and writes a {@link Cache}. Requests are fulfilled from the cache
* when possible. When data is not cached it is requested from an upstream {@link DataSource} and
@ -66,8 +89,7 @@ public final class OkhttpCacheDataSource implements DataSource {
@Nullable
private PriorityTaskManager upstreamPriorityTaskManager;
private int upstreamPriority;
@OkhttpCacheDataSource.Flags
private int flags;
private @OkhttpCacheDataSource.Flags int flags;
@Nullable
private OkhttpCacheDataSource.EventListener eventListener;
@ -351,6 +373,7 @@ public final class OkhttpCacheDataSource implements DataSource {
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef(
flag = true,
value = {
@ -384,8 +407,11 @@ public final class OkhttpCacheDataSource implements DataSource {
* Reasons the cache may be ignored. One of {@link #CACHE_IGNORED_REASON_ERROR} or {@link
* #CACHE_IGNORED_REASON_UNSET_LENGTH}.
*/
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({CACHE_IGNORED_REASON_ERROR, CACHE_IGNORED_REASON_UNSET_LENGTH})
public @interface CacheIgnoredReason {
}
@ -641,15 +667,15 @@ public final class OkhttpCacheDataSource implements DataSource {
}
@Override
public int read(@NonNull byte[] buffer, int offset, int length) throws IOException {
DataSpec requestDataSpec = checkNotNull(this.requestDataSpec);
DataSpec currentDataSpec = checkNotNull(this.currentDataSpec);
public int read(byte[] buffer, int offset, int length) throws IOException {
if (length == 0) {
return 0;
}
if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
DataSpec requestDataSpec = checkNotNull(this.requestDataSpec);
DataSpec currentDataSpec = checkNotNull(this.currentDataSpec);
try {
if (readPosition >= checkCachePosition) {
openNextSource(requestDataSpec, true);
@ -683,9 +709,8 @@ public final class OkhttpCacheDataSource implements DataSource {
}
}
@Nullable
@Override
@Nullable
public Uri getUri() {
return actualUri;
}
@ -693,6 +718,7 @@ public final class OkhttpCacheDataSource implements DataSource {
@NonNull
@Override
public Map<String, List<String>> getResponseHeaders() {
// TODO: Implement.
return isReadingFromUpstream()
? upstreamDataSource.getResponseHeaders()
: Collections.emptyMap();

@ -13,6 +13,7 @@ import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import androidx.core.app.NotificationCompat
import androidx.media.AudioFocusRequestCompat
import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
@ -57,7 +58,14 @@ class AudioPlayService : BaseService(),
MediaHelp.getFocusRequest(this)
}
private val exoPlayer: ExoPlayer by lazy {
ExoPlayer.Builder(this).build()
ExoPlayer.Builder(this).setLoadControl(
DefaultLoadControl.Builder().setBufferDurationsMs(
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS / 10,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS / 10
).build()
).build()
}
private var mediaSessionCompat: MediaSessionCompat? = null
private var broadcastReceiver: BroadcastReceiver? = null
@ -302,6 +310,8 @@ class AudioPlayService : BaseService(),
upPlayProgressJob = launch {
while (isActive) {
AudioPlay.book?.let {
//更新buffer位置
postEvent(EventBus.AUDIO_BUFFER_PROGRESS, exoPlayer.bufferedPosition.toInt())
it.durChapterPos = exoPlayer.currentPosition.toInt()
postEvent(EventBus.AUDIO_PROGRESS, it.durChapterPos)
saveProgress(it)

@ -273,6 +273,10 @@ class AudioPlayActivity :
if (!adjustProgress) binding.playerProgress.progress = it
binding.tvDurTime.text = progressTimeFormat.format(it.toLong())
}
observeEventSticky<Int>(EventBus.AUDIO_BUFFER_PROGRESS) {
binding.playerProgress.secondaryProgress = it
}
observeEventSticky<Float>(EventBus.AUDIO_SPEED) {
binding.tvSpeed.text = String.format("%.1fX", it)
binding.tvSpeed.visible()

Loading…
Cancel
Save