diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Epg.java b/app/src/main/java/com/fongmi/android/tv/bean/Epg.java index 5152d2926..52a58204a 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Epg.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Epg.java @@ -97,7 +97,7 @@ public class Epg { private String format() { if (getTitle().isEmpty()) return ""; - if (getStart().isEmpty() || getEnd().isEmpty()) return ResUtil.getString(R.string.live_epg_now, getTitle()); + if (getStart().isEmpty() || getEnd().isEmpty()) return ResUtil.getString(R.string.play_now, getTitle()); return getStart() + " ~ " + getEnd() + " " + getTitle(); } 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 775fb1dca..32a9888f3 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 @@ -3,11 +3,12 @@ package com.fongmi.android.tv.player; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; +import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.text.TextUtils; import androidx.annotation.NonNull; -import androidx.media3.common.MediaMetadata; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; import androidx.media3.common.util.Util; @@ -22,6 +23,7 @@ import com.fongmi.android.tv.Setting; import com.fongmi.android.tv.bean.Channel; import com.fongmi.android.tv.bean.Result; import com.fongmi.android.tv.bean.Track; +import com.fongmi.android.tv.event.ActionEvent; import com.fongmi.android.tv.event.ErrorEvent; import com.fongmi.android.tv.event.PlayerEvent; import com.fongmi.android.tv.impl.ParseCallback; @@ -47,9 +49,9 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic public static final int SOFT = 0; public static final int HARD = 1; + private MediaMetadataCompat metadata; private MediaSessionCompat session; private IjkVideoView ijkPlayer; - private MediaMetadata metadata; private StringBuilder builder; private Formatter formatter; private ExoPlayer exoPlayer; @@ -90,7 +92,6 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic private void createSession(Activity activity) { session = new MediaSessionCompat(activity, "TV"); session.setSessionActivity(PendingIntent.getActivity(activity, 0, new Intent(activity, activity.getClass()), Utils.getPendingFlag())); - session.setActive(true); } public void set(PlayerView exo, IjkVideoView ijk) { @@ -127,12 +128,10 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic return session; } - public MediaMetadata getMetadata() { - return metadata; - } - - public void setMetadata(MediaMetadata metadata) { + public void setMetadata(MediaMetadataCompat metadata) { this.metadata = metadata; + session.setMetadata(metadata); + ActionEvent.update(); } public int getPlayer() { @@ -279,21 +278,25 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic public void play() { if (isExo()) exoPlayer.play(); else if (isIjk()) ijkPlayer.start(); + session.setActive(true); } public void pause() { if (isExo()) pauseExo(); else if (isIjk()) pauseIjk(); + session.setActive(false); } public void stop() { reset(); if (isExo()) stopExo(); else if (isIjk()) stopIjk(); + session.setActive(false); } public void release() { stopParse(); + session.release(); if (isExo()) releaseExo(); else if (isIjk()) releaseIjk(); } @@ -450,6 +453,16 @@ public class Players implements Player.Listener, IMediaPlayer.Listener, Analytic ErrorEvent.parse(); } + @Override + public void onEvents(@NonNull Player player, @NonNull Player.Events events) { + session.setPlaybackState(new PlaybackStateCompat.Builder().setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED, getPosition(), getSpeed()).build()); + } + + @Override + public void onBufferingUpdate(IMediaPlayer mp, int percent) { + session.setPlaybackState(new PlaybackStateCompat.Builder().setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED, getPosition(), getSpeed()).build()); + } + @Override public void onPlayerError(@NonNull PlaybackException error) { this.errorCode = error.errorCode; diff --git a/app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java b/app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java index 71d7de741..8aae02c2c 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java @@ -5,7 +5,6 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; @@ -43,11 +42,6 @@ public class ImgUtil { else Glide.with(App.get()).load(getUrl(url)).error(error).dontAnimate().into(target); } - public static void load(Uri uri, int error, CustomTarget target) { - if (uri == null || uri.toString().isEmpty()) target.onLoadFailed(ResUtil.getDrawable(error)); - else Glide.with(App.get()).asBitmap().load(getUrl(uri.toString())).error(error).dontAnimate().into(target); - } - public static void load(String url, ImageView view, ImageView.ScaleType scaleType) { view.setScaleType(scaleType); if (TextUtils.isEmpty(url)) view.setImageResource(R.drawable.ic_img_error); diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index a07418a7d..bd76e1768 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -10,7 +10,6 @@ 密码 未分类 - 正在播放:%s 线路 %s @@ -47,6 +46,7 @@ 视轨 已切换正序播放 已切换倒序播放 + 正在播放:%s 准备播放:%s 正在切换解析至「%s 正在切换线路至「%s diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 7c73df02f..c494f3d2c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -10,7 +10,6 @@ 密碼 未分類 - 正在播放:%s 來源 %s @@ -47,6 +46,7 @@ 視軌 已切換正序播放 已切換倒序播放 + 正在播放:%s 準備播放:%s 正在切换解析至「%s 正在切換線路至「%s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f5bf52626..1fd8d9412 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,7 +10,6 @@ Pass Group - Playing: %s Line %s @@ -47,6 +46,7 @@ Video Normal play switched Reverse play switched + Playing: %s Ready to play: %s Switching parse to %s Switching flag to %s diff --git a/app/src/mobile/AndroidManifest.xml b/app/src/mobile/AndroidManifest.xml index f98cb6d53..1d736d4ec 100644 --- a/app/src/mobile/AndroidManifest.xml +++ b/app/src/mobile/AndroidManifest.xml @@ -132,7 +132,7 @@ 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 c0cc73aff..44ed45614 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 @@ -5,21 +5,23 @@ import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; -import android.net.Uri; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.support.v4.media.MediaMetadataCompat; import android.view.View; import androidx.annotation.Dimension; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.app.ShareCompat; import androidx.lifecycle.ViewModelProvider; import androidx.media3.common.C; -import androidx.media3.common.MediaMetadata; import androidx.media3.common.Player; import androidx.media3.ui.PlayerView; import androidx.viewbinding.ViewBinding; +import com.bumptech.glide.request.transition.Transition; import com.fongmi.android.tv.App; import com.fongmi.android.tv.Constant; import com.fongmi.android.tv.R; @@ -37,6 +39,7 @@ import com.fongmi.android.tv.event.ActionEvent; import com.fongmi.android.tv.event.ErrorEvent; import com.fongmi.android.tv.event.PlayerEvent; import com.fongmi.android.tv.impl.Callback; +import com.fongmi.android.tv.impl.CustomTarget; import com.fongmi.android.tv.impl.LiveCallback; import com.fongmi.android.tv.impl.PassCallback; import com.fongmi.android.tv.impl.SubtitleCallback; @@ -56,6 +59,7 @@ import com.fongmi.android.tv.ui.custom.dialog.SubtitleDialog; import com.fongmi.android.tv.ui.custom.dialog.TrackDialog; import com.fongmi.android.tv.utils.Biometric; import com.fongmi.android.tv.utils.Clock; +import com.fongmi.android.tv.utils.ImgUtil; import com.fongmi.android.tv.utils.Notify; import com.fongmi.android.tv.utils.PiP; import com.fongmi.android.tv.utils.ResUtil; @@ -447,7 +451,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List private void showEpg() { mBinding.widget.play.setText(mChannel.getData().getEpg()); - mPlayers.setMetadata(new MediaMetadata.Builder().setTitle(mChannel.getName()).setArtist(mChannel.getData().getEpg()).setArtworkUri(Uri.parse(mChannel.getLogo())).build()); + setMetadata(); } private void setTraffic() { @@ -474,6 +478,23 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List this.passCount = 0; } + private void setArtwork(String url) { + ImgUtil.load(url, R.drawable.radio, new CustomTarget<>() { + @Override + public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { + getExo().setDefaultArtwork(resource); + getIjk().setDefaultArtwork(resource); + setMetadata(); + } + + @Override + public void onLoadFailed(@Nullable Drawable error) { + getExo().setDefaultArtwork(error); + getIjk().setDefaultArtwork(error); + } + }); + } + @Override public void onItemClick(Group item) { mGroupAdapter.setSelected(mGroup = item); @@ -490,6 +511,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List public void onItemClick(Channel item) { mGroup.setPosition(mChannelAdapter.setSelected(item.group(mGroup))); mPlayers.setPlayer(getPlayerType(item.getPlayerType())); + setArtwork(item.getLogo()); mChannel = item; setPlayerView(); showInfo(); @@ -642,6 +664,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List break; case Player.STATE_READY: checkRotate(); + setMetadata(); resetToggle(); hideProgress(); mPlayers.reset(); @@ -674,6 +697,15 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List mBinding.control.action.video.setVisibility(visible && mPlayers.haveTrack(C.TRACK_TYPE_VIDEO) ? View.VISIBLE : View.GONE); } + private void setMetadata() { + MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mChannel.getName()); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mChannel.getData().getEpg()); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork()); + builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration()); + mPlayers.setMetadata(builder.build()); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { if (mPlayers.addRetry() > event.getRetry()) checkError(event); 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 4147d2442..7f843f10f 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 @@ -10,6 +10,7 @@ import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.support.v4.media.MediaMetadataCompat; import android.text.Html; import android.text.TextUtils; import android.view.MotionEvent; @@ -27,7 +28,6 @@ import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.media3.common.C; -import androidx.media3.common.MediaMetadata; import androidx.media3.common.Player; import androidx.media3.ui.PlayerView; import androidx.recyclerview.widget.RecyclerView; @@ -484,11 +484,10 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo private void getPlayer(Flag flag, Episode episode, boolean replay) { mBinding.control.title.setText(getString(R.string.detail_title, mBinding.name.getText(), episode.getName())); - mPlayers.setMetadata(new MediaMetadata.Builder().setTitle(mHistory.getVodName()).setArtist(episode.getName()).setArtworkUri(Uri.parse(mHistory.getVodPic())).build()); mViewModel.playerContent(getKey(), flag.getFlag(), episode.getUrl()); updateHistory(episode, replay); - ActionEvent.update(); showProgress(); + setMetadata(); hidePreview(); setUrl(null); } @@ -926,6 +925,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo getExo().setDefaultArtwork(resource); getIjk().setDefaultArtwork(resource); showPreview(resource); + setMetadata(); } @Override @@ -1056,6 +1056,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo case Player.STATE_READY: stopSearch(); checkRotate(); + setMetadata(); resetToggle(); hideProgress(); mPlayers.reset(); @@ -1105,6 +1106,15 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo } } + private void setMetadata() { + MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, mHistory == null ? getName() : mHistory.getVodName()); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, mEpisodeAdapter.getItemCount() == 0 ? "" : getString(R.string.play_now, getEpisode().getName())); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork()); + builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration()); + mPlayers.setMetadata(builder.build()); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onErrorEvent(ErrorEvent event) { if (mPlayers.addRetry() > event.getRetry()) checkError(event); diff --git a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/IjkVideoView.java b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/IjkVideoView.java index 107cc0221..75b3cd30e 100644 --- a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/IjkVideoView.java +++ b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/IjkVideoView.java @@ -2,6 +2,8 @@ package tv.danmaku.ijk.media.player.ui; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.MediaPlayer; @@ -415,6 +417,10 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl } } + public Bitmap getDefaultArtwork() { + return ((BitmapDrawable) mDefaultArtwork).getBitmap(); + } + private void updateForCurrentTrackSelections() { if (mPlayer == null || mPlayer.getTrackInfo().isEmpty()) return; int select = getSelectedTrack(ITrackInfo.MEDIA_TRACK_TYPE_VIDEO); @@ -524,11 +530,13 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl @Override public void onBufferingUpdate(IMediaPlayer mp, int percent) { + mListener.onBufferingUpdate(mp, percent); mCurrentBufferPercentage = percent; } @Override public void onBufferingUpdate(IMediaPlayer mp, long position) { + mListener.onBufferingUpdate(mp, position); mCurrentBufferPosition = position; }