diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java index 4f5988d1e..588491b2e 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java @@ -216,7 +216,11 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List } private void onDecode() { - mPlayers.toggleDecode(); + onDecode(true); + } + + private void onDecode(boolean save) { + mPlayers.toggleDecode(save); mPlayers.set(getExo(), getIjk()); setDecodeView(); onReset(); @@ -361,7 +365,7 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { - if (event.getCode() / 1000 == 4 && mPlayers.isExo() && Players.isHard(Players.EXO)) onDecode(); + if (event.getCode() / 1000 == 4 && mPlayers.isExo() && mPlayers.isHard()) onDecode(false); else if (mPlayers.addRetry() > event.getRetry()) onError(event); else onReset(); } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index 15cab687b..8fc610e15 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -426,7 +426,11 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP } private void onDecode() { - mPlayers.toggleDecode(); + onDecode(true); + } + + private void onDecode(boolean save) { + mPlayers.toggleDecode(save); mPlayers.set(getExo(), getIjk()); setDecodeView(); fetch(); @@ -792,7 +796,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { - if (event.getCode() / 1000 == 4 && mPlayers.isExo() && Players.isHard(Players.EXO)) onDecode(); + if (event.getCode() / 1000 == 4 && mPlayers.isExo() && mPlayers.isHard()) onDecode(false); else if (mPlayers.addRetry() > event.getRetry()) checkError(event); else fetch(); } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 9798169ff..31e3fbd56 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -1062,7 +1062,11 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List } private void onDecode() { - mPlayers.toggleDecode(); + onDecode(true); + } + + private void onDecode(boolean save) { + mPlayers.toggleDecode(save); mPlayers.set(getExo(), getIjk()); setDecodeView(); onRefresh(); @@ -1419,7 +1423,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { if (isBackground()) return; - if (event.getCode() / 1000 == 4 && mPlayers.isExo() && Players.isHard(Players.EXO)) onDecode(); + if (event.getCode() / 1000 == 4 && mPlayers.isExo() && mPlayers.isHard()) onDecode(false); else if (mPlayers.addRetry() > event.getRetry()) checkError(event); else onRefresh(); } diff --git a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java index c1d650dd0..53e968f64 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/player/ExoUtil.java @@ -45,14 +45,13 @@ import com.fongmi.android.tv.bean.Drm; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.bean.Sub; import com.fongmi.android.tv.player.custom.NextRenderersFactory; +import com.fongmi.android.tv.utils.Sniffer; import com.fongmi.android.tv.utils.UrlUtil; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Path; -import com.github.catvod.utils.Util; -import com.google.common.net.HttpHeaders; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -77,8 +76,8 @@ public class ExoUtil { return trackSelector; } - public static RenderersFactory buildRenderersFactory() { - return new NextRenderersFactory(App.get()).setEnableDecoderFallback(true).setExtensionRendererMode(Players.isSoft(Players.EXO) ? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER : DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON); + public static RenderersFactory buildRenderersFactory(int decode) { + return new NextRenderersFactory(App.get()).setEnableDecoderFallback(true).setExtensionRendererMode(decode == Players.SOFT ? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER : DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON); } public static CaptionStyleCompat getCaptionStyle() { @@ -122,45 +121,45 @@ public class ExoUtil { return null; } - public static MediaSource getSource(Result result, Sub sub, int errorCode) { - return getSource(result.getHeaders(), result.getRealUrl(), result.getFormat(), result.getSubs(), sub, null, errorCode); + public static MediaSource getSource(Result result, Sub sub, int decode, int errorCode) { + return getSource(result.getHeaders(), result.getRealUrl(), result.getFormat(), result.getSubs(), sub, null, decode, errorCode); } - public static MediaSource getSource(Channel channel, int errorCode) { - return getSource(channel.getHeaders(), channel.getUrl(), null, Collections.emptyList(), null, channel.getDrm(), errorCode); + public static MediaSource getSource(Channel channel, Sub sub, int decode, int errorCode) { + return getSource(channel.getHeaders(), channel.getUrl(), channel.getFormat(), new ArrayList<>(), sub, channel.getDrm(), decode, errorCode); } - public static MediaSource getSource(Map headers, String url, Sub sub, int errorCode) { - return getSource(headers, url, null, new ArrayList<>(), sub, null, errorCode); + public static MediaSource getSource(Map headers, String url, Sub sub, int decode, int errorCode) { + return getSource(headers, url, null, new ArrayList<>(), sub, null, decode, errorCode); } - private static MediaSource getSource(Map headers, String url, String format, List subs, Sub sub, Drm drm, int errorCode) { + private static MediaSource getSource(Map headers, String url, String format, List subs, Sub sub, Drm drm, int decode, int errorCode) { Uri uri = UrlUtil.uri(url); if (sub != null) subs.add(sub); String mimeType = getMimeType(format, errorCode); - if (uri.getUserInfo() != null) headers.put(HttpHeaders.AUTHORIZATION, Util.basic(uri.getUserInfo())); - if (url.contains("***") && url.contains("|||")) return getConcat(headers, url, format, subs, sub, drm, errorCode); - return new DefaultMediaSourceFactory(getDataSourceFactory(headers), getExtractorsFactory()).createMediaSource(getMediaItem(uri, mimeType, subs, drm)); + if (url.contains("***") && url.contains("|||")) return getConcat(headers, url, format, subs, drm, decode, errorCode); + return new DefaultMediaSourceFactory(getDataSourceFactory(headers), getExtractorsFactory()).createMediaSource(getMediaItem(uri, mimeType, subs, drm, decode)); } - private static MediaSource getConcat(Map headers, String url, String format, List subs, Sub sub, Drm drm, int errorCode) { + private static MediaSource getConcat(Map headers, String url, String format, List subs, Drm drm, int decode, int errorCode) { ConcatenatingMediaSource2.Builder builder = new ConcatenatingMediaSource2.Builder(); for (String split : url.split("\\*\\*\\*")) { String[] info = split.split("\\|\\|\\|"); if (info.length < 2) continue; long duration = Long.parseLong(info[1]); - builder.add(getSource(headers, info[0], format, subs, sub, drm, errorCode), duration); + builder.add(getSource(headers, info[0], format, subs, null, drm, decode, errorCode), duration); } return builder.build(); } - private static MediaItem getMediaItem(Uri uri, String mimeType, List subs, Drm drm) { + private static MediaItem getMediaItem(Uri uri, String mimeType, List subs, Drm drm, int decode) { MediaItem.Builder builder = new MediaItem.Builder().setUri(uri); if (!subs.isEmpty()) builder.setSubtitleConfigurations(getSubtitles(subs)); if (drm != null) builder.setDrmConfiguration(drm.get()); - builder.setAllowChunklessPreparation(Players.isHard(Players.EXO)); if (mimeType != null) builder.setMimeType(mimeType); + builder.setAllowChunklessPreparation(decode == Players.HARD); builder.setForceUseRtpTcp(Setting.getRtsp() == 1); + builder.setAds(Setting.isRemoveAd() ? Arrays.asList("9999") : Sniffer.getRegex(uri)); return builder.build(); } diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java index 4a708abda..45d0bca2f 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/Players.java +++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java @@ -84,6 +84,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic private Sub sub; private long position; + private int decode; private int player; private int error; private int retry; @@ -92,12 +93,12 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic return type == EXO; } - public static boolean isHard(int player) { - return Setting.getDecode(player) == HARD; + public boolean isHard() { + return decode == HARD; } - public static boolean isSoft(int player) { - return Setting.getDecode(player) == SOFT; + public boolean isSoft() { + return decode == SOFT; } public boolean isExo() { @@ -110,6 +111,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic public Players init(Activity activity) { player = Setting.getPlayer(); + decode = Setting.getDecode(player); builder = new StringBuilder(); runnable = ErrorEvent::timeout; formatter = new Formatter(builder, Locale.getDefault()); @@ -119,10 +121,8 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic private void createSession(Activity activity) { session = new MediaSessionCompat(activity, "TV"); - session.setMediaButtonReceiver(null); session.setCallback(SessionCallback.create(this)); - session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); - session.setSessionActivity(PendingIntent.getActivity(App.get(), 99, new Intent(App.get(), activity.getClass()), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); + session.setSessionActivity(PendingIntent.getActivity(App.get(), 0, new Intent(App.get(), activity.getClass()), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); MediaControllerCompat.setMediaController(activity, session.getController()); } @@ -134,7 +134,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic } private void setupExo(PlayerView view) { - exoPlayer = new ExoPlayer.Builder(App.get()).setLoadControl(ExoUtil.buildLoadControl()).setRenderersFactory(ExoUtil.buildRenderersFactory()).setTrackSelector(ExoUtil.buildTrackSelector()).build(); + exoPlayer = new ExoPlayer.Builder(App.get()).setLoadControl(ExoUtil.buildLoadControl()).setRenderersFactory(ExoUtil.buildRenderersFactory(decode)).setTrackSelector(ExoUtil.buildTrackSelector()).build(); exoPlayer.setAudioAttributes(AudioAttributes.DEFAULT, true); exoPlayer.addAnalyticsListener(new EventLogger()); exoPlayer.setHandleAudioBecomingNoisy(true); @@ -146,7 +146,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic } private void setupIjk(IjkVideoView view) { - ijkPlayer = view.render(Setting.getRender()).decode(Setting.getDecode(IJK)); + ijkPlayer = view.render(Setting.getRender()).decode(decode); ijkPlayer.addListener(this); ijkPlayer.setPlayer(player); } @@ -198,6 +198,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic public void setPlayer(int player) { if (this.player != player) stop(); this.player = player; + this.decode = getDecode(player); } public int getDecode(int player) { @@ -314,7 +315,7 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic } public String getDecodeText() { - return ResUtil.getStringArray(R.array.select_decode)[Setting.getDecode(player)]; + return ResUtil.getStringArray(R.array.select_decode)[decode]; } public String setSpeed(float speed) { @@ -356,8 +357,9 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic setPlayer(isExo() ? IJK : EXO); } - public void toggleDecode() { - setDecode(player, getDecode(player) == HARD ? SOFT : HARD); + public void toggleDecode(boolean save) { + decode = isHard() ? SOFT : HARD; + if (save) setDecode(player, decode); } public String getPositionTime(long time) { @@ -510,21 +512,21 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic private void setMediaSource(Result result, int timeout) { if (isIjk() && ijkPlayer != null) ijkPlayer.setMediaSource(IjkUtil.getSource(result), position); - if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(result, sub, error), position); + if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(result, sub, decode, error), position); if (isExo() && exoPlayer != null) exoPlayer.prepare(); setTimeoutCheck(result.getHeaders(), result.getRealUrl(), timeout); } private void setMediaSource(Channel channel, int timeout) { if (isIjk() && ijkPlayer != null) ijkPlayer.setMediaSource(IjkUtil.getSource(channel)); - if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(channel, error)); + if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(channel, sub, decode, error)); if (isExo() && exoPlayer != null) exoPlayer.prepare(); setTimeoutCheck(channel.getHeaders(), channel.getUrl(), timeout); } private void setMediaSource(Map headers, String url) { if (isIjk() && ijkPlayer != null) ijkPlayer.setMediaSource(IjkUtil.getSource(headers, url), position); - if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(headers, url, sub, error), position); + if (isExo() && exoPlayer != null) exoPlayer.setMediaSource(ExoUtil.getSource(headers, url, sub, decode, error), position); if (isExo() && exoPlayer != null) exoPlayer.prepare(); setTimeoutCheck(headers, url, Constant.TIMEOUT_PLAY); } diff --git a/app/src/main/java/com/fongmi/android/tv/receiver/ActionReceiver.java b/app/src/main/java/com/fongmi/android/tv/receiver/ActionReceiver.java index dd2bc178a..8c42063ef 100644 --- a/app/src/main/java/com/fongmi/android/tv/receiver/ActionReceiver.java +++ b/app/src/main/java/com/fongmi/android/tv/receiver/ActionReceiver.java @@ -10,7 +10,7 @@ import com.fongmi.android.tv.event.ActionEvent; public class ActionReceiver extends BroadcastReceiver { public static PendingIntent getPendingIntent(Context context, String action) { - return PendingIntent.getBroadcast(context, 100, new Intent(action).setPackage(context.getPackageName()), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + return PendingIntent.getBroadcast(context, 0, new Intent(action).setPackage(context.getPackageName()), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } @Override diff --git a/app/src/mobile/AndroidManifest.xml b/app/src/mobile/AndroidManifest.xml index 8287b25e6..2393f7b51 100644 --- a/app/src/mobile/AndroidManifest.xml +++ b/app/src/mobile/AndroidManifest.xml @@ -134,7 +134,11 @@ + android:foregroundServiceType="mediaPlayback"> + + + + \ No newline at end of file diff --git a/app/src/mobile/java/com/fongmi/android/tv/service/PlaybackService.java b/app/src/mobile/java/com/fongmi/android/tv/service/PlaybackService.java index e44ee9fe8..d8b9461ca 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/service/PlaybackService.java +++ b/app/src/mobile/java/com/fongmi/android/tv/service/PlaybackService.java @@ -17,6 +17,7 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; import androidx.media.app.NotificationCompat.MediaStyle; +import androidx.media.session.MediaButtonReceiver; import com.fongmi.android.tv.App; import com.fongmi.android.tv.R; @@ -137,6 +138,7 @@ public class PlaybackService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { + if (nonNull()) MediaButtonReceiver.handleIntent(players.getSession(), intent); startForeground(ID, buildNotification()); return START_NOT_STICKY; } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index 77e5ec0a2..f029a7e54 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -461,7 +461,11 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom } private void onDecode() { - mPlayers.toggleDecode(); + onDecode(true); + } + + private void onDecode(boolean save) { + mPlayers.toggleDecode(save); mPlayers.set(getExo(), getIjk()); setDecodeView(); setR1Callback(); @@ -857,7 +861,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { - if (event.getCode() / 1000 == 4 && mPlayers.isExo() && Players.isHard(Players.EXO)) onDecode(); + if (event.getCode() / 1000 == 4 && mPlayers.isExo() && mPlayers.isHard()) onDecode(false); else if (mPlayers.addRetry() > event.getRetry()) checkError(event); else fetch(); } diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java index 1c48ed9ce..f1dc61a51 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java @@ -872,7 +872,11 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } private void onDecode() { - mPlayers.toggleDecode(); + onDecode(true); + } + + private void onDecode(boolean save) { + mPlayers.toggleDecode(save); mPlayers.set(getExo(), getIjk()); setDecodeView(); setR1Callback(); @@ -1326,7 +1330,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { if (isRedirect()) return; - if (event.getCode() / 1000 == 4 && mPlayers.isExo() && Players.isHard(Players.EXO)) onDecode(); + if (event.getCode() / 1000 == 4 && mPlayers.isExo() && mPlayers.isHard()) onDecode(false); else if (mPlayers.addRetry() > event.getRetry()) checkError(event); else onRefresh(); }