From 9acb3a85b5ed53d04a0a82c26d8ecaa74b4c9063 Mon Sep 17 00:00:00 2001 From: jhengazuki Date: Sat, 27 Sep 2025 15:09:22 +0800 Subject: [PATCH] Add error msg provider --- .../fongmi/android/tv/event/ErrorEvent.java | 2 +- .../com/fongmi/android/tv/player/Players.java | 5 +- .../tv/player/exo/ErrorMsgProvider.java | 74 +++++++++++++++++++ .../tv/player/exo/TrackNameProvider.java | 20 ++--- .../android/tv/player/extractor/TVBus.java | 2 +- app/src/main/res/values-zh-rCN/error.xml | 44 +++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 3 +- app/src/main/res/values-zh-rTW/error.xml | 44 +++++++++++ app/src/main/res/values-zh-rTW/strings.xml | 3 +- app/src/main/res/values/error.xml | 44 +++++++++++ app/src/main/res/values/strings.xml | 3 +- 11 files changed, 222 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java create mode 100644 app/src/main/res/values-zh-rCN/error.xml create mode 100644 app/src/main/res/values-zh-rTW/error.xml create mode 100644 app/src/main/res/values/error.xml diff --git a/app/src/main/java/com/fongmi/android/tv/event/ErrorEvent.java b/app/src/main/java/com/fongmi/android/tv/event/ErrorEvent.java index 944ae4726..6df01a3eb 100644 --- a/app/src/main/java/com/fongmi/android/tv/event/ErrorEvent.java +++ b/app/src/main/java/com/fongmi/android/tv/event/ErrorEvent.java @@ -56,7 +56,7 @@ public class ErrorEvent { public String getMsg() { if (type == Type.URL) return ResUtil.getString(R.string.error_play_url); - if (type == Type.DRM) return ResUtil.getString(R.string.error_play_drm_scheme); + if (type == Type.DRM) return ResUtil.getString(R.string.error_play_drm); if (type == Type.FLAG) return ResUtil.getString(R.string.error_play_flag); if (type == Type.PARSE) return ResUtil.getString(R.string.error_play_parse); if (type == Type.TIMEOUT) return ResUtil.getString(R.string.error_play_timeout); 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 00432915d..7b5026030 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 @@ -48,6 +48,7 @@ import com.fongmi.android.tv.impl.ParseCallback; import com.fongmi.android.tv.impl.SessionCallback; import com.fongmi.android.tv.player.danmaku.DanPlayer; import com.fongmi.android.tv.player.exo.CacheManager; +import com.fongmi.android.tv.player.exo.ErrorMsgProvider; import com.fongmi.android.tv.player.exo.ExoUtil; import com.fongmi.android.tv.server.Server; import com.fongmi.android.tv.utils.FileUtil; @@ -77,6 +78,7 @@ public class Players implements Player.Listener, ParseCallback { public static final int SOFT = 0; public static final int HARD = 1; + private final ErrorMsgProvider provider; private final AudioManager audioManager; private final StringBuilder builder; private final Formatter formatter; @@ -110,6 +112,7 @@ public class Players implements Player.Listener, ParseCallback { private Players(Activity activity) { decode = Setting.getDecode(); builder = new StringBuilder(); + provider = new ErrorMsgProvider(); runnable = () -> ErrorEvent.timeout(tag); formatter = new Formatter(builder, Locale.getDefault()); audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE); @@ -673,7 +676,7 @@ public class Players implements Player.Listener, ParseCallback { @Override public void onPlayerError(@NonNull PlaybackException error) { Logger.t(TAG).e(error.errorCode + "," + url); - if (retried()) ErrorEvent.extract(tag, error.getErrorCodeName()); + if (retried()) ErrorEvent.extract(tag, provider.get(error)); else switch (error.errorCode) { case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: seekToDefaultPosition(); diff --git a/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java b/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java new file mode 100644 index 000000000..5d19c72d6 --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/player/exo/ErrorMsgProvider.java @@ -0,0 +1,74 @@ +package com.fongmi.android.tv.player.exo; + +import android.content.res.Resources; + +import androidx.media3.common.PlaybackException; +import androidx.media3.exoplayer.mediacodec.MediaCodecRenderer; +import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; + +import com.fongmi.android.tv.App; +import com.fongmi.android.tv.R; + +public class ErrorMsgProvider { + + private final Resources resources; + + public ErrorMsgProvider() { + this.resources = App.get().getResources(); + } + + public String get(PlaybackException e) { + if (e.getCause() instanceof MediaCodecRenderer.DecoderInitializationException e2) return custom(e2); + return resources.getString(getId(e.errorCode)); + } + + private String custom(MediaCodecRenderer.DecoderInitializationException e) { + if (e.codecInfo != null) return resources.getString(R.string.error_instantiating_decoder, e.codecInfo.name); + if (e.getCause() instanceof MediaCodecUtil.DecoderQueryException) return resources.getString(R.string.error_querying_decoders); + else if (e.secureDecoderRequired) return resources.getString(R.string.error_no_secure_decoder, e.mimeType); + else return resources.getString(R.string.error_no_decoder, e.mimeType); + } + + private int getId(int errorCode) { + return switch (errorCode) { + case PlaybackException.ERROR_CODE_REMOTE_ERROR -> R.string.error_remote_error; + case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> R.string.error_behind_live_window; + case PlaybackException.ERROR_CODE_TIMEOUT -> R.string.error_timeout; + case PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK -> R.string.error_failed_runtime_check; + case PlaybackException.ERROR_CODE_IO_UNSPECIFIED -> R.string.error_io_unspecified; + case PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED -> R.string.error_io_network_connection_failed; + case PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT -> R.string.error_io_network_connection_timeout; + case PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE -> R.string.error_io_invalid_http_content_type; + case PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS -> R.string.error_io_bad_http_status; + case PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND -> R.string.error_io_file_not_found; + case PlaybackException.ERROR_CODE_IO_NO_PERMISSION -> R.string.error_io_no_permission; + case PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED -> R.string.error_io_cleartext_not_permitted; + case PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE -> R.string.error_io_read_position_out_of_range; + case PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED -> R.string.error_parsing_container_malformed; + case PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED -> R.string.error_parsing_manifest_malformed; + case PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED -> R.string.error_parsing_container_unsupported; + case PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED -> R.string.error_parsing_manifest_unsupported; + case PlaybackException.ERROR_CODE_DECODER_INIT_FAILED -> R.string.error_decoder_init_failed; + case PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED -> R.string.error_decoder_query_failed; + case PlaybackException.ERROR_CODE_DECODING_FAILED -> R.string.error_decoding_failed; + case PlaybackException.ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES -> R.string.error_decoding_format_exceeds_capabilities; + case PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED -> R.string.error_decoding_format_unsupported; + case PlaybackException.ERROR_CODE_DECODING_RESOURCES_RECLAIMED -> R.string.error_decoding_resources_reclaimed; + case PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED -> R.string.error_audio_track_init_failed; + case PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED -> R.string.error_audio_track_write_failed; + case PlaybackException.ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED -> R.string.error_audio_track_offload_write_failed; + case PlaybackException.ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED -> R.string.error_audio_track_offload_init_failed; + case PlaybackException.ERROR_CODE_DRM_UNSPECIFIED -> R.string.error_drm_unspecified; + case PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED -> R.string.error_drm_provisioning_failed; + case PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR -> R.string.error_drm_content_error; + case PlaybackException.ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED -> R.string.error_drm_license_acquisition_failed; + case PlaybackException.ERROR_CODE_DRM_DISALLOWED_OPERATION -> R.string.error_drm_disallowed_operation; + case PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR -> R.string.error_drm_system_error; + case PlaybackException.ERROR_CODE_DRM_DEVICE_REVOKED -> R.string.error_drm_device_revoked; + case PlaybackException.ERROR_CODE_DRM_LICENSE_EXPIRED -> R.string.error_drm_license_expired; + case PlaybackException.ERROR_CODE_VIDEO_FRAME_PROCESSOR_INIT_FAILED -> R.string.error_video_frame_processor_init_failed; + case PlaybackException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED -> R.string.error_video_frame_processing_failed; + default -> R.string.error_unspecified; + }; + } +} diff --git a/app/src/main/java/com/fongmi/android/tv/player/exo/TrackNameProvider.java b/app/src/main/java/com/fongmi/android/tv/player/exo/TrackNameProvider.java index f4ca5f6b4..92e62585c 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/exo/TrackNameProvider.java +++ b/app/src/main/java/com/fongmi/android/tv/player/exo/TrackNameProvider.java @@ -54,19 +54,13 @@ public class TrackNameProvider { private String buildAudioChannelString(Format format) { int channelCount = format.channelCount; if (channelCount < 1) return ""; - switch (channelCount) { - case 1: - return resources.getString(R.string.exo_track_mono); - case 2: - return resources.getString(R.string.exo_track_stereo); - case 6: - case 7: - return resources.getString(R.string.exo_track_surround_5_point_1); - case 8: - return resources.getString(R.string.exo_track_surround_7_point_1); - default: - return resources.getString(R.string.exo_track_surround); - } + return switch (channelCount) { + case 1 -> resources.getString(R.string.exo_track_mono); + case 2 -> resources.getString(R.string.exo_track_stereo); + case 6, 7 -> resources.getString(R.string.exo_track_surround_5_point_1); + case 8 -> resources.getString(R.string.exo_track_surround_7_point_1); + default -> resources.getString(R.string.exo_track_surround); + }; } private String buildLanguageOrLabelString(Format format) { diff --git a/app/src/main/java/com/fongmi/android/tv/player/extractor/TVBus.java b/app/src/main/java/com/fongmi/android/tv/player/extractor/TVBus.java index 27ec76608..18ad40874 100644 --- a/app/src/main/java/com/fongmi/android/tv/player/extractor/TVBus.java +++ b/app/src/main/java/com/fongmi/android/tv/player/extractor/TVBus.java @@ -72,7 +72,7 @@ public class TVBus implements Source.Extractor, Listener { private String check() throws Exception { if (hls == null) return ""; if (!hls.startsWith("-")) return hls; - throw new ExtractException(ResUtil.getString(R.string.error_play_code, hls)); + throw new ExtractException(ResUtil.getString(R.string.error_play_url)); } @Override diff --git a/app/src/main/res/values-zh-rCN/error.xml b/app/src/main/res/values-zh-rCN/error.xml new file mode 100644 index 000000000..39d439be1 --- /dev/null +++ b/app/src/main/res/values-zh-rCN/error.xml @@ -0,0 +1,44 @@ + + 发生未预期的错误 + 发生远程错误 + 已落后直播流过多 + 操作超时 + 发生内部播放器错误 + 发生未知的 I/O 错误 + 网络连接失败 + 网络连接超时 + 无效的服务器响应 + 无法连接至服务器 + 找不到文件 + I/O 权限不足 + 此内容需要安全的网络连接 + 读取源数据失败 + 媒体文件已损坏或格式不受支持 + 流清单无效 + 不支持此媒体容器格式 + 不支持此流清单格式 + 初始化媒体解码器失败 + 找不到适合此格式的媒体解码器 + 解码媒体时发生错误 + 媒体画质超过设备能力上限 + 此设备不支持该媒体格式 + 解码资源已被系统回收 + 初始化音轨失败 + 写入音频数据失败 + 写入 Offload 音频数据失败 + 初始化 Offload 音轨失败 + 发生未知的 DRM 错误 + 设置设备 DRM 失败 + 受保护的内容发生错误 + 获取内容授权失败 + 不允许此 DRM 操作 + 发生 DRM 系统错误 + 此设备的内容访问权已被撤销 + 内容授权已过期 + 初始化视频帧处理器失败 + 处理视频帧时发生错误 + 此设备未提供 %1$s 格式的解码器 + 此设备未提供 %1$s 格式的安全解码器 + 无法查询设备的解码器 + 无法将解码器 %1$s 实例化 + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 23d1a5ab7..8b0d72bf9 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -124,8 +124,7 @@ 已经是最后一集了! 已经是第一集了! 播放地址解析失败 - 此设备不支持所需的 DRM scheme - 错误代码:%s + 此设备不支持所需的 DRM scheme 播放地址加载失败 暂无线路数据 连接超时 diff --git a/app/src/main/res/values-zh-rTW/error.xml b/app/src/main/res/values-zh-rTW/error.xml new file mode 100644 index 000000000..c2fec29d0 --- /dev/null +++ b/app/src/main/res/values-zh-rTW/error.xml @@ -0,0 +1,44 @@ + + 發生未預期的錯誤 + 發生遠端錯誤 + 已落後直播串流過多 + 操作逾時 + 發生內部播放器錯誤 + 發生未知的 I/O 錯誤 + 網路連線失敗 + 網路連線逾時 + 無效的伺服器回應 + 無法連接至伺服器 + 找不到檔案 + I/O 權限不足 + 此內容需要安全的網路連線 + 讀取來源資料失敗 + 媒體檔案已損毀或格式不受支援 + 串流清單無效 + 不支援此媒體容器格式 + 不支援此串流清單格式 + 初始化媒體解碼器失敗 + 找不到適合此格式的媒體解碼器 + 解碼媒體時發生錯誤 + 媒體品質超過裝置能力上限 + 此裝置不支援該媒體格式 + 解碼資源已被系統收回 + 初始化音軌失敗 + 寫入音訊資料失敗 + 寫入 Offload 音訊資料失敗 + 初始化 Offload 音軌失敗 + 發生未知的 DRM 錯誤 + 設定裝置 DRM 失敗 + 受保護的內容發生錯誤 + 取得內容授權失敗 + 不允許此 DRM 操作 + 發生 DRM 系統錯誤 + 此裝置的內容存取權已被撤銷 + 內容授權已過期 + 初始化影片影格處理器失敗 + 處理影片影格時發生錯誤 + 此裝置未提供 %1$s 格式的解碼器 + 此裝置未提供 %1$s 格式的安全解碼器 + 無法查詢裝置的解碼器 + 無法將解碼器 %1$s 實例化 + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 337d3b45a..79ae88de8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -124,8 +124,7 @@ 已經是最後一集了! 已經是第一集了! 播放網址解析失敗 - 本設備不支援所需的 DRM scheme - 錯誤代碼:%s + 本設備不支援所需的 DRM scheme 播放網址載入失敗 暫無線路資料 連線逾時 diff --git a/app/src/main/res/values/error.xml b/app/src/main/res/values/error.xml new file mode 100644 index 000000000..3ef1e7626 --- /dev/null +++ b/app/src/main/res/values/error.xml @@ -0,0 +1,44 @@ + + An unexpected error occurred + A remote error occurred + Fell too far behind the live stream + The operation timed out + An internal player error occurred + An unknown I/O error occurred + Network connection failed + Network connection timed out + Invalid server response + Unable to connect to the server + File not found + I/O permission denied + A secure connection is required for this content + Failed to read data from the source + The media file is corrupted or in an unsupported format + The stream manifest is invalid + The media container format is not supported + The stream manifest format is not supported + Failed to initialize the media decoder + Failed to find a suitable media decoder for the format + An error occurred while decoding the media + The media quality exceeds the device\'s capabilities + The media format is not supported by this device + Decoding resources were reclaimed by the system + Failed to initialize the audio track + Failed to write audio data + Failed to write offloaded audio data + Failed to initialize the offloaded audio track + An unknown DRM error occurred + Failed to configure DRM on this device + An error occurred with the protected content + Failed to acquire the content license + The requested DRM operation is not allowed + A DRM system error occurred + Access to this content has been revoked for this device + The content license has expired + Failed to initialize the video frame processor + An error occurred while processing a video frame + This device does not provide a decoder for %1$s + This device does not provide a secure decoder for %1$s + Unable to query device decoders + Unable to instantiate decoder %1$s + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37462de20..e5de31e7e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,8 +125,7 @@ It\'s the last episode! It\'s the first episode! Unable to parse url - This device does not support the required DRM scheme - Error code: %s + This device does not support the required DRM scheme Unable to load url No flag data Timed out