改进UI: 更新设置页面图标,添加关于弹窗,优化镜像更新功能
This commit is contained in:
+36
-7
@@ -1,8 +1,37 @@
|
|||||||
.idea
|
# Gradle files
|
||||||
.gradle
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Log/OS Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio generated files and folders
|
||||||
|
captures/
|
||||||
|
.externalNativeBuild/
|
||||||
|
.cxx/
|
||||||
|
*.apk
|
||||||
|
*.aab
|
||||||
|
output.json
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
misc.xml
|
||||||
|
deploymentTargetDropDown.xml
|
||||||
|
render.experimental.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
*.jks
|
*.jks
|
||||||
lib-*.aar
|
*.keystore
|
||||||
*build
|
|
||||||
/media*
|
# Google Services (e.g. APIs or Firebase)
|
||||||
/Release
|
google-services.json
|
||||||
/local.properties
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# APK files
|
||||||
|
apk/release/*.apk
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"java.configuration.updateBuildConfiguration": "automatic"
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import androidx.core.os.HandlerCompat;
|
|||||||
|
|
||||||
import com.fongmi.android.tv.event.EventIndex;
|
import com.fongmi.android.tv.event.EventIndex;
|
||||||
import com.fongmi.android.tv.ui.activity.CrashActivity;
|
import com.fongmi.android.tv.ui.activity.CrashActivity;
|
||||||
|
import com.fongmi.android.tv.utils.CacheCleaner;
|
||||||
import com.fongmi.android.tv.utils.Notify;
|
import com.fongmi.android.tv.utils.Notify;
|
||||||
import com.fongmi.hook.Hook;
|
import com.fongmi.hook.Hook;
|
||||||
import com.github.catvod.Init;
|
import com.github.catvod.Init;
|
||||||
@@ -41,6 +42,7 @@ public class App extends Application {
|
|||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private final long time;
|
private final long time;
|
||||||
private Hook hook;
|
private Hook hook;
|
||||||
|
private final Runnable cleanTask;
|
||||||
|
|
||||||
public App() {
|
public App() {
|
||||||
instance = this;
|
instance = this;
|
||||||
@@ -48,6 +50,7 @@ public class App extends Application {
|
|||||||
handler = HandlerCompat.createAsync(Looper.getMainLooper());
|
handler = HandlerCompat.createAsync(Looper.getMainLooper());
|
||||||
time = System.currentTimeMillis();
|
time = System.currentTimeMillis();
|
||||||
gson = new Gson();
|
gson = new Gson();
|
||||||
|
cleanTask = this::checkCacheClean;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static App get() {
|
public static App get() {
|
||||||
@@ -119,6 +122,10 @@ public class App extends Application {
|
|||||||
OkHttp.get().setDoh(Doh.objectFrom(Setting.getDoh()));
|
OkHttp.get().setDoh(Doh.objectFrom(Setting.getDoh()));
|
||||||
EventBus.builder().addIndex(new EventIndex()).installDefaultEventBus();
|
EventBus.builder().addIndex(new EventIndex()).installDefaultEventBus();
|
||||||
CaocConfig.Builder.create().backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT).errorActivity(CrashActivity.class).apply();
|
CaocConfig.Builder.create().backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT).errorActivity(CrashActivity.class).apply();
|
||||||
|
|
||||||
|
// 初始化自动缓存清理
|
||||||
|
initCacheCleaner();
|
||||||
|
|
||||||
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
|
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
|
||||||
@@ -133,6 +140,8 @@ public class App extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityResumed(@NonNull Activity activity) {
|
public void onActivityResumed(@NonNull Activity activity) {
|
||||||
if (activity != activity()) setActivity(activity);
|
if (activity != activity()) setActivity(activity);
|
||||||
|
// 应用回到前台时检查缓存
|
||||||
|
checkCacheClean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -156,6 +165,20 @@ public class App extends Application {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initCacheCleaner() {
|
||||||
|
CacheCleaner cleaner = CacheCleaner.get();
|
||||||
|
cleaner.setCacheThreshold(200 * 1024 * 1024); // 固定使用200MB阈值
|
||||||
|
|
||||||
|
// 定期检查缓存 (每30分钟)
|
||||||
|
post(cleanTask, 30 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCacheClean() {
|
||||||
|
CacheCleaner.get().checkAndClean();
|
||||||
|
// 每30分钟定期检查缓存
|
||||||
|
post(cleanTask, 30 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PackageManager getPackageManager() {
|
public PackageManager getPackageManager() {
|
||||||
return hook != null ? hook : getBaseContext().getPackageManager();
|
return hook != null ? hook : getBaseContext().getPackageManager();
|
||||||
|
|||||||
@@ -201,6 +201,14 @@ public class Setting {
|
|||||||
Prefers.put("update", update);
|
Prefers.put("update", update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getUseCnMirror() {
|
||||||
|
return Prefers.getBoolean("use_cn_mirror", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putUseCnMirror(boolean useCnMirror) {
|
||||||
|
Prefers.put("use_cn_mirror", useCnMirror);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isCaption() {
|
public static boolean isCaption() {
|
||||||
return Prefers.getBoolean("caption");
|
return Prefers.getBoolean("caption");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,6 +267,19 @@ public class Config {
|
|||||||
Keep.delete(getId());
|
Keep.delete(getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Config copy() {
|
||||||
|
Config copy = new Config();
|
||||||
|
copy.setType(type);
|
||||||
|
copy.setUrl(url);
|
||||||
|
copy.setJson(json);
|
||||||
|
copy.setName(TextUtils.isEmpty(name) ? url + " 副本" : name + " 副本");
|
||||||
|
copy.setLogo(logo);
|
||||||
|
copy.setHome(home);
|
||||||
|
copy.setParse(parse);
|
||||||
|
copy.setTime(System.currentTimeMillis());
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.fongmi.android.tv.utils;
|
||||||
|
|
||||||
|
import android.os.StatFs;
|
||||||
|
|
||||||
|
import com.fongmi.android.tv.App;
|
||||||
|
import com.fongmi.android.tv.impl.Callback;
|
||||||
|
import com.github.catvod.utils.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存自动清理管理器
|
||||||
|
*/
|
||||||
|
public class CacheCleaner {
|
||||||
|
|
||||||
|
// 默认缓存清理阈值 200MB
|
||||||
|
private static final long DEFAULT_CACHE_THRESHOLD = 200 * 1024 * 1024;
|
||||||
|
// 最小保留空间 500MB
|
||||||
|
private static final long MIN_FREE_SPACE = 500 * 1024 * 1024;
|
||||||
|
// 单例实例
|
||||||
|
private static CacheCleaner instance;
|
||||||
|
// 缓存清理阈值
|
||||||
|
private long cacheThreshold;
|
||||||
|
|
||||||
|
private CacheCleaner() {
|
||||||
|
this.cacheThreshold = DEFAULT_CACHE_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CacheCleaner get() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (CacheCleaner.class) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new CacheCleaner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置缓存阈值
|
||||||
|
* @param threshold 阈值大小(字节)
|
||||||
|
*/
|
||||||
|
public void setCacheThreshold(long threshold) {
|
||||||
|
this.cacheThreshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查缓存,如果超过阈值则清理
|
||||||
|
*/
|
||||||
|
public void checkAndClean() {
|
||||||
|
App.execute(() -> {
|
||||||
|
try {
|
||||||
|
// 获取当前缓存大小
|
||||||
|
long cacheSize = FileUtil.getDirectorySize(Path.cache());
|
||||||
|
// 获取剩余存储空间
|
||||||
|
long freeSpace = getAvailableStorageSpace();
|
||||||
|
|
||||||
|
// 如果缓存超过阈值或可用空间低于最小要求,清理缓存
|
||||||
|
if (cacheSize > cacheThreshold || freeSpace < MIN_FREE_SPACE) {
|
||||||
|
cleanCache();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理缓存
|
||||||
|
*/
|
||||||
|
private void cleanCache() {
|
||||||
|
FileUtil.clearCache(new Callback() {
|
||||||
|
@Override
|
||||||
|
public void success() {
|
||||||
|
// 缓存清理成功
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备可用存储空间
|
||||||
|
* @return 可用空间(字节)
|
||||||
|
*/
|
||||||
|
private long getAvailableStorageSpace() {
|
||||||
|
try {
|
||||||
|
StatFs stat = new StatFs(Path.cache().getPath());
|
||||||
|
return stat.getAvailableBlocksLong() * stat.getBlockSizeLong();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -78,6 +78,8 @@
|
|||||||
<string name="setting_doh">DoH</string>
|
<string name="setting_doh">DoH</string>
|
||||||
<string name="setting_proxy">Proxy</string>
|
<string name="setting_proxy">Proxy</string>
|
||||||
<string name="setting_cache">缓存</string>
|
<string name="setting_cache">缓存</string>
|
||||||
|
<string name="setting_auto_clean">自动清理缓存</string>
|
||||||
|
<string name="setting_cache_threshold">清理阈值</string>
|
||||||
<string name="setting_backup">备份</string>
|
<string name="setting_backup">备份</string>
|
||||||
<string name="setting_restore">恢复</string>
|
<string name="setting_restore">恢复</string>
|
||||||
<string name="setting_version">版本</string>
|
<string name="setting_version">版本</string>
|
||||||
@@ -88,6 +90,8 @@
|
|||||||
<string name="setting_app">应用设置</string>
|
<string name="setting_app">应用设置</string>
|
||||||
<string name="setting_network">网络设置</string>
|
<string name="setting_network">网络设置</string>
|
||||||
<string name="setting_data">数据管理</string>
|
<string name="setting_data">数据管理</string>
|
||||||
|
<string name="app_version">v3.0.3</string>
|
||||||
|
<string name="about_github">在GitHub上查看</string>
|
||||||
|
|
||||||
<!-- Backup & Restore -->
|
<!-- Backup & Restore -->
|
||||||
<string name="restore_select">选择备份</string>
|
<string name="restore_select">选择备份</string>
|
||||||
@@ -143,6 +147,7 @@
|
|||||||
<string name="error_cast_file">不支持的文件格式</string>
|
<string name="error_cast_file">不支持的文件格式</string>
|
||||||
<string name="error_device_limit">设备授权数已达上限</string>
|
<string name="error_device_limit">设备授权数已达上限</string>
|
||||||
<string name="error_live_empty">该订阅无直播内容</string>
|
<string name="error_live_empty">该订阅无直播内容</string>
|
||||||
|
<string name="error_no_live">当前源没有直播内容</string>
|
||||||
|
|
||||||
<!-- Update -->
|
<!-- Update -->
|
||||||
<string name="update_version">发现新版本 <xliff:g name="name">%s</xliff:g></string>
|
<string name="update_version">发现新版本 <xliff:g name="name">%s</xliff:g></string>
|
||||||
|
|||||||
@@ -76,7 +76,9 @@
|
|||||||
<string name="setting_size">圖片尺寸</string>
|
<string name="setting_size">圖片尺寸</string>
|
||||||
<string name="setting_doh">DoH</string>
|
<string name="setting_doh">DoH</string>
|
||||||
<string name="setting_proxy">Proxy</string>
|
<string name="setting_proxy">Proxy</string>
|
||||||
<string name="setting_cache">暫存</string>
|
<string name="setting_cache">緩存</string>
|
||||||
|
<string name="setting_auto_clean">自動清理緩存</string>
|
||||||
|
<string name="setting_cache_threshold">清理閾值</string>
|
||||||
<string name="setting_backup">備份</string>
|
<string name="setting_backup">備份</string>
|
||||||
<string name="setting_restore">還原</string>
|
<string name="setting_restore">還原</string>
|
||||||
<string name="setting_version">版本</string>
|
<string name="setting_version">版本</string>
|
||||||
@@ -87,6 +89,8 @@
|
|||||||
<string name="setting_app">應用設置</string>
|
<string name="setting_app">應用設置</string>
|
||||||
<string name="setting_network">網絡設置</string>
|
<string name="setting_network">網絡設置</string>
|
||||||
<string name="setting_data">數據管理</string>
|
<string name="setting_data">數據管理</string>
|
||||||
|
<string name="app_version">v3.0.3</string>
|
||||||
|
<string name="about_github">在GitHub上查看</string>
|
||||||
|
|
||||||
<!-- Backup & Restore -->
|
<!-- Backup & Restore -->
|
||||||
<string name="restore_select">選擇備份</string>
|
<string name="restore_select">選擇備份</string>
|
||||||
@@ -138,6 +142,10 @@
|
|||||||
<string name="error_play_timeout">連線逾時</string>
|
<string name="error_play_timeout">連線逾時</string>
|
||||||
<string name="error_detail">暫無播放資料</string>
|
<string name="error_detail">暫無播放資料</string>
|
||||||
<string name="error_empty">找不到資料</string>
|
<string name="error_empty">找不到資料</string>
|
||||||
|
<string name="error_cast_file">不支持的檔案格式</string>
|
||||||
|
<string name="error_device_limit">設備授權數已達上限</string>
|
||||||
|
<string name="error_live_empty">該訂閱無直播內容</string>
|
||||||
|
<string name="error_no_live">當前源沒有直播內容</string>
|
||||||
|
|
||||||
<!-- Update -->
|
<!-- Update -->
|
||||||
<string name="update_version">發現新版本 <xliff:g name="name">%s</xliff:g></string>
|
<string name="update_version">發現新版本 <xliff:g name="name">%s</xliff:g></string>
|
||||||
@@ -204,4 +212,8 @@
|
|||||||
<item>選擇字幕</item>
|
<item>選擇字幕</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="config_set_current">已設為當前點播源</string>
|
||||||
|
|
||||||
|
<string name="source_hint">點我添加源</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -82,13 +82,17 @@
|
|||||||
<string name="setting_size">Image size</string>
|
<string name="setting_size">Image size</string>
|
||||||
<string name="setting_doh">DoH</string>
|
<string name="setting_doh">DoH</string>
|
||||||
<string name="setting_proxy">Proxy</string>
|
<string name="setting_proxy">Proxy</string>
|
||||||
<string name="setting_cache">Cache</string>
|
<string name="setting_cache">缓存</string>
|
||||||
<string name="setting_backup">Backup</string>
|
<string name="setting_auto_clean">Auto Clean Cache</string>
|
||||||
<string name="setting_restore">Restore</string>
|
<string name="setting_cache_threshold">Cache Threshold</string>
|
||||||
<string name="setting_version">Version</string>
|
<string name="setting_backup">备份</string>
|
||||||
|
<string name="setting_restore">恢复</string>
|
||||||
|
<string name="setting_version">版本</string>
|
||||||
<string name="setting_choose">Choose</string>
|
<string name="setting_choose">Choose</string>
|
||||||
<string name="setting_off">Off</string>
|
<string name="setting_off">Off</string>
|
||||||
<string name="setting_on">On</string>
|
<string name="setting_on">On</string>
|
||||||
|
<string name="app_version">v3.0.3</string>
|
||||||
|
<string name="about_github">View on GitHub</string>
|
||||||
|
|
||||||
<!-- Backup & Restore -->
|
<!-- Backup & Restore -->
|
||||||
<string name="restore_select">Select backup</string>
|
<string name="restore_select">Select backup</string>
|
||||||
@@ -146,6 +150,7 @@
|
|||||||
<string name="error_cast_file">Unsupported file format</string>
|
<string name="error_cast_file">Unsupported file format</string>
|
||||||
<string name="error_device_limit">Device authorization limit reached</string>
|
<string name="error_device_limit">Device authorization limit reached</string>
|
||||||
<string name="error_live_empty">This subscription has no live content</string>
|
<string name="error_live_empty">This subscription has no live content</string>
|
||||||
|
<string name="error_no_live">Current source has no live content</string>
|
||||||
<string name="error_empty">Not found</string>
|
<string name="error_empty">Not found</string>
|
||||||
<string name="error_detail">No play data</string>
|
<string name="error_detail">No play data</string>
|
||||||
<string name="error_play_flag">No flag data</string>
|
<string name="error_play_flag">No flag data</string>
|
||||||
@@ -224,4 +229,10 @@
|
|||||||
|
|
||||||
<string name="config_set_current">已设为当前点播源</string>
|
<string name="config_set_current">已设为当前点播源</string>
|
||||||
|
|
||||||
|
<string name="remember_setting">Remember settings</string>
|
||||||
|
<string name="target_size">Target size</string>
|
||||||
|
<string name="scan_result">Scan result</string>
|
||||||
|
|
||||||
|
<string name="source_hint">点我添加源</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -16,7 +16,9 @@ import com.github.catvod.net.OkHttp;
|
|||||||
import com.github.catvod.utils.Github;
|
import com.github.catvod.utils.Github;
|
||||||
import com.github.catvod.utils.Path;
|
import com.github.catvod.utils.Path;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import com.orhanobut.logger.Logger;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -25,20 +27,25 @@ import java.util.Locale;
|
|||||||
public class Updater implements Download.Callback {
|
public class Updater implements Download.Callback {
|
||||||
|
|
||||||
private DialogUpdateBinding binding;
|
private DialogUpdateBinding binding;
|
||||||
private final Download download;
|
private Download download;
|
||||||
private AlertDialog dialog;
|
private AlertDialog dialog;
|
||||||
private boolean dev;
|
private boolean dev;
|
||||||
|
private String downloadUrl;
|
||||||
|
|
||||||
private File getFile() {
|
private File getFile() {
|
||||||
return Path.cache("update.apk");
|
return Path.cache("update.apk");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getJson() {
|
private String getApkName() {
|
||||||
return Github.getJson(dev, BuildConfig.FLAVOR_mode);
|
return "mobile-" + BuildConfig.FLAVOR_abi + ".apk";
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getApk() {
|
private String getJson() {
|
||||||
return Github.getApk(dev, BuildConfig.FLAVOR_mode + "-" + BuildConfig.FLAVOR_abi);
|
String url = Github.getReleaseApi();
|
||||||
|
boolean usingCnMirror = Github.useCnMirror();
|
||||||
|
Logger.d("Using CN Mirror: " + usingCnMirror);
|
||||||
|
Logger.d("Update check URL: " + url);
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Updater create() {
|
public static Updater create() {
|
||||||
@@ -46,7 +53,7 @@ public class Updater implements Download.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Updater() {
|
public Updater() {
|
||||||
this.download = Download.create(getApk(), getFile(), this);
|
this.download = Download.create("", getFile(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Updater force() {
|
public Updater force() {
|
||||||
@@ -74,18 +81,43 @@ public class Updater implements Download.Callback {
|
|||||||
App.execute(() -> doInBackground(activity));
|
App.execute(() -> doInBackground(activity));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean need(int code, String name) {
|
private boolean need(String tagName) {
|
||||||
return Setting.getUpdate() && (dev ? !name.equals(BuildConfig.VERSION_NAME) && code >= BuildConfig.VERSION_CODE : code > BuildConfig.VERSION_CODE);
|
Logger.d("Current version: " + BuildConfig.VERSION_NAME);
|
||||||
|
Logger.d("Latest version: " + tagName);
|
||||||
|
if (tagName.startsWith("v")) tagName = tagName.substring(1);
|
||||||
|
return Setting.getUpdate() && !tagName.equals(BuildConfig.VERSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doInBackground(Activity activity) {
|
private void doInBackground(Activity activity) {
|
||||||
try {
|
try {
|
||||||
JSONObject object = new JSONObject(OkHttp.string(getJson()));
|
String jsonUrl = getJson();
|
||||||
String name = object.optString("name");
|
Logger.d("Fetching update info from: " + jsonUrl);
|
||||||
String desc = object.optString("desc");
|
String response = OkHttp.string(jsonUrl);
|
||||||
int code = object.optInt("code");
|
Logger.d("Update check response: " + response);
|
||||||
if (need(code, name)) App.post(() -> show(activity, name, desc));
|
|
||||||
|
JSONObject release = new JSONObject(response);
|
||||||
|
String tagName = release.getString("tag_name");
|
||||||
|
String body = release.getString("body");
|
||||||
|
JSONArray assets = release.getJSONArray("assets");
|
||||||
|
|
||||||
|
// Find the correct APK asset
|
||||||
|
String apkName = getApkName();
|
||||||
|
for (int i = 0; i < assets.length(); i++) {
|
||||||
|
JSONObject asset = assets.getJSONObject(i);
|
||||||
|
if (asset.getString("name").equals(apkName)) {
|
||||||
|
downloadUrl = asset.getString("browser_download_url");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadUrl != null && need(tagName)) {
|
||||||
|
download = Download.create(downloadUrl, getFile(), this);
|
||||||
|
App.post(() -> show(activity, tagName, body));
|
||||||
|
} else {
|
||||||
|
Logger.d("No update needed or APK not found");
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Logger.e("Update check failed", e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,6 +159,7 @@ public class Updater implements Download.Callback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String msg) {
|
public void error(String msg) {
|
||||||
|
Logger.e("Download error: " + msg);
|
||||||
Notify.show(msg);
|
Notify.show(msg);
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,13 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt
|
|||||||
if (mBinding.navigation.getSelectedItemId() == item.getItemId()) return false;
|
if (mBinding.navigation.getSelectedItemId() == item.getItemId()) return false;
|
||||||
if (item.getItemId() == R.id.setting) return mManager.change(1);
|
if (item.getItemId() == R.id.setting) return mManager.change(1);
|
||||||
if (item.getItemId() == R.id.vod) return mManager.change(0);
|
if (item.getItemId() == R.id.vod) return mManager.change(0);
|
||||||
if (item.getItemId() == R.id.live) return openLive();
|
if (item.getItemId() == R.id.live) {
|
||||||
|
if (LiveConfig.isEmpty()) {
|
||||||
|
Notify.showCenter(R.string.error_no_live);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return openLive();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,24 @@ import android.Manifest;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.BatteryManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -22,6 +29,7 @@ import android.view.ViewGroup;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -63,6 +71,7 @@ import com.fongmi.android.tv.event.RefreshEvent;
|
|||||||
import com.fongmi.android.tv.model.SiteViewModel;
|
import com.fongmi.android.tv.model.SiteViewModel;
|
||||||
import com.fongmi.android.tv.player.Players;
|
import com.fongmi.android.tv.player.Players;
|
||||||
import com.fongmi.android.tv.player.exo.ExoUtil;
|
import com.fongmi.android.tv.player.exo.ExoUtil;
|
||||||
|
import com.fongmi.android.tv.player.Source;
|
||||||
import com.fongmi.android.tv.service.PlaybackService;
|
import com.fongmi.android.tv.service.PlaybackService;
|
||||||
import com.fongmi.android.tv.ui.adapter.EpisodeAdapter;
|
import com.fongmi.android.tv.ui.adapter.EpisodeAdapter;
|
||||||
import com.fongmi.android.tv.ui.adapter.FlagAdapter;
|
import com.fongmi.android.tv.ui.adapter.FlagAdapter;
|
||||||
@@ -98,6 +107,7 @@ import com.github.catvod.utils.Trans;
|
|||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
import com.permissionx.guolindev.PermissionX;
|
import com.permissionx.guolindev.PermissionX;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.greenrobot.eventbus.Subscribe;
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
@@ -148,6 +158,10 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
private Clock mClock;
|
private Clock mClock;
|
||||||
private String tag;
|
private String tag;
|
||||||
private PiP mPiP;
|
private PiP mPiP;
|
||||||
|
private Handler mHandler;
|
||||||
|
private Runnable mTimeUpdateRunnable;
|
||||||
|
private BroadcastReceiver mBatteryReceiver;
|
||||||
|
private int mBatteryLevel = -1;
|
||||||
|
|
||||||
public static void push(FragmentActivity activity, String text) {
|
public static void push(FragmentActivity activity, String text) {
|
||||||
if (FileChooser.isValid(activity, Uri.parse(text))) file(activity, FileChooser.getPathFromUri(activity, Uri.parse(text)));
|
if (FileChooser.isValid(activity, Uri.parse(text))) file(activity, FileChooser.getPathFromUri(activity, Uri.parse(text)));
|
||||||
@@ -302,6 +316,64 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
showProgress();
|
showProgress();
|
||||||
showDanmaku();
|
showDanmaku();
|
||||||
checkId();
|
checkId();
|
||||||
|
mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
initTimeBatteryUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTimeBatteryUpdate() {
|
||||||
|
mBatteryReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
|
||||||
|
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||||
|
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
|
||||||
|
if (level != -1 && scale != -1) {
|
||||||
|
mBatteryLevel = (int) ((level / (float) scale) * 100);
|
||||||
|
updateTimeBattery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mTimeUpdateRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateTimeBattery();
|
||||||
|
mHandler.postDelayed(this, 30000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTimeBattery() {
|
||||||
|
TextView timeBattery = mBinding.getRoot().findViewById(R.id.time_battery);
|
||||||
|
if (timeBattery == null) return;
|
||||||
|
|
||||||
|
// 只在横屏模式下显示
|
||||||
|
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
String time = DateFormat.getTimeFormat(this).format(System.currentTimeMillis());
|
||||||
|
String battery = mBatteryLevel >= 0 ? mBatteryLevel + "%" : "";
|
||||||
|
String text = time + (battery.isEmpty() ? "" : " | " + battery);
|
||||||
|
timeBattery.setText(text);
|
||||||
|
timeBattery.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
timeBattery.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTimeBatteryUpdates() {
|
||||||
|
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||||
|
updateTimeBattery();
|
||||||
|
mHandler.post(mTimeUpdateRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopTimeBatteryUpdates() {
|
||||||
|
try {
|
||||||
|
if (mBatteryReceiver != null) {
|
||||||
|
unregisterReceiver(mBatteryReceiver);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
mHandler.removeCallbacks(mTimeUpdateRunnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -960,6 +1032,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
mBinding.control.bottom.setVisibility(isLock() ? View.GONE : View.VISIBLE);
|
mBinding.control.bottom.setVisibility(isLock() ? View.GONE : View.VISIBLE);
|
||||||
mBinding.control.top.setVisibility(isLock() ? View.GONE : View.VISIBLE);
|
mBinding.control.top.setVisibility(isLock() ? View.GONE : View.VISIBLE);
|
||||||
mBinding.control.getRoot().setVisibility(View.VISIBLE);
|
mBinding.control.getRoot().setVisibility(View.VISIBLE);
|
||||||
|
updateTimeBattery();
|
||||||
setR1Callback();
|
setR1Callback();
|
||||||
checkPlayImg();
|
checkPlayImg();
|
||||||
}
|
}
|
||||||
@@ -1555,6 +1628,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
if (isAutoRotate() && isPort() && newConfig.orientation == Configuration.ORIENTATION_PORTRAIT && !isRotate()) exitFullscreen();
|
if (isAutoRotate() && isPort() && newConfig.orientation == Configuration.ORIENTATION_PORTRAIT && !isRotate()) exitFullscreen();
|
||||||
if (isAutoRotate() && isPort() && newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) enterFullscreen();
|
if (isAutoRotate() && isPort() && newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) enterFullscreen();
|
||||||
if (isFullscreen()) Util.hideSystemUI(this);
|
if (isFullscreen()) Util.hideSystemUI(this);
|
||||||
|
updateTimeBattery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1574,6 +1648,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
startTimeBatteryUpdates();
|
||||||
if (isRedirect()) onPlay();
|
if (isRedirect()) onPlay();
|
||||||
setRedirect(false);
|
setRedirect(false);
|
||||||
}
|
}
|
||||||
@@ -1581,6 +1656,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
stopTimeBatteryUpdates();
|
||||||
if (isRedirect()) onPaused();
|
if (isRedirect()) onPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1608,14 +1684,17 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
|
|||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
stopSearch();
|
stopSearch();
|
||||||
mClock.release();
|
|
||||||
mPlayers.release();
|
mPlayers.release();
|
||||||
|
mClock.release();
|
||||||
Timer.get().reset();
|
Timer.get().reset();
|
||||||
RefreshEvent.history();
|
RefreshEvent.history();
|
||||||
PlaybackService.stop();
|
PlaybackService.stop();
|
||||||
|
mHandler.removeCallbacksAndMessages(null);
|
||||||
App.removeCallbacks(mR1, mR2, mR3, mR4);
|
App.removeCallbacks(mR1, mR2, mR3, mR4);
|
||||||
|
EventBus.getDefault().unregister(this);
|
||||||
mViewModel.result.removeObserver(mObserveDetail);
|
mViewModel.result.removeObserver(mObserveDetail);
|
||||||
mViewModel.player.removeObserver(mObservePlayer);
|
mViewModel.player.removeObserver(mObservePlayer);
|
||||||
mViewModel.search.removeObserver(mObserveSearch);
|
mViewModel.search.removeObserver(mObserveSearch);
|
||||||
|
stopTimeBatteryUpdates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.fongmi.android.tv.api.config.VodConfig;
|
|||||||
import com.fongmi.android.tv.bean.Config;
|
import com.fongmi.android.tv.bean.Config;
|
||||||
import com.fongmi.android.tv.databinding.AdapterConfigBinding;
|
import com.fongmi.android.tv.databinding.AdapterConfigBinding;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ConfigAdapter extends RecyclerView.Adapter<ConfigAdapter.ViewHolder> {
|
public class ConfigAdapter extends RecyclerView.Adapter<ConfigAdapter.ViewHolder> {
|
||||||
@@ -26,19 +27,36 @@ public class ConfigAdapter extends RecyclerView.Adapter<ConfigAdapter.ViewHolder
|
|||||||
|
|
||||||
void onTextClick(Config item);
|
void onTextClick(Config item);
|
||||||
|
|
||||||
|
void onCopyClick(Config item);
|
||||||
|
|
||||||
void onDeleteClick(Config item);
|
void onDeleteClick(Config item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigAdapter addAll(int type) {
|
public ConfigAdapter addAll(int type) {
|
||||||
mItems = Config.getAll(type);
|
mItems = new ArrayList<>();
|
||||||
mItems.remove(type == 0 ? VodConfig.get().getConfig() : LiveConfig.get().getConfig());
|
List<Config> configs = Config.getAll(type);
|
||||||
|
Config currentConfig = type == 0 ? VodConfig.get().getConfig() : LiveConfig.get().getConfig();
|
||||||
|
|
||||||
|
for (Config config : configs) {
|
||||||
|
if (config.equals(currentConfig) || config.isEmpty()) continue;
|
||||||
|
mItems.add(config);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addItem(Config item) {
|
||||||
|
if (item.isEmpty()) return;
|
||||||
|
|
||||||
|
mItems.add(0, item);
|
||||||
|
notifyItemInserted(0);
|
||||||
|
}
|
||||||
|
|
||||||
public int remove(Config item) {
|
public int remove(Config item) {
|
||||||
|
int position = mItems.indexOf(item);
|
||||||
item.delete();
|
item.delete();
|
||||||
mItems.remove(item);
|
mItems.remove(item);
|
||||||
notifyDataSetChanged();
|
notifyItemRemoved(position);
|
||||||
return getItemCount();
|
return getItemCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +76,7 @@ public class ConfigAdapter extends RecyclerView.Adapter<ConfigAdapter.ViewHolder
|
|||||||
Config item = mItems.get(position);
|
Config item = mItems.get(position);
|
||||||
holder.binding.text.setText(item.getDesc());
|
holder.binding.text.setText(item.getDesc());
|
||||||
holder.binding.text.setOnClickListener(v -> mListener.onTextClick(item));
|
holder.binding.text.setOnClickListener(v -> mListener.onTextClick(item));
|
||||||
|
holder.binding.copy.setOnClickListener(v -> mListener.onCopyClick(item));
|
||||||
holder.binding.delete.setOnClickListener(v -> mListener.onDeleteClick(item));
|
holder.binding.delete.setOnClickListener(v -> mListener.onDeleteClick(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ public class TypeAdapter extends RecyclerView.Adapter<TypeAdapter.ViewHolder> {
|
|||||||
|
|
||||||
public void addAll(Result result) {
|
public void addAll(Result result) {
|
||||||
mItems.addAll(result.getTypes());
|
mItems.addAll(result.getTypes());
|
||||||
if (!result.getList().isEmpty()) mItems.add(0, home());
|
|
||||||
if (!mItems.isEmpty()) mItems.get(0).setActivated(true);
|
if (!mItems.isEmpty()) mItems.get(0).setActivated(true);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,8 +144,18 @@ public class ConfigDialog {
|
|||||||
private void onPositive(DialogInterface dialog, int which) {
|
private void onPositive(DialogInterface dialog, int which) {
|
||||||
String url = binding.url.getText().toString().trim();
|
String url = binding.url.getText().toString().trim();
|
||||||
String name = binding.name.getText().toString().trim();
|
String name = binding.name.getText().toString().trim();
|
||||||
|
|
||||||
|
// 如果是编辑模式,更新现有配置
|
||||||
if (edit) Config.find(ori, type).url(url).name(name).update();
|
if (edit) Config.find(ori, type).url(url).name(name).update();
|
||||||
if (url.isEmpty()) Config.delete(ori, type);
|
|
||||||
|
// 如果URL为空,删除配置
|
||||||
|
if (url.isEmpty()) {
|
||||||
|
Config.delete(ori, type);
|
||||||
|
dialog.dismiss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有URL不为空时,才设置配置
|
||||||
callback.setConfig(Config.find(url, type));
|
callback.setConfig(Config.find(url, type));
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ public class HistoryDialog implements ConfigAdapter.OnClickListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeleteClick(Config item) {
|
public void onDeleteClick(Config item) {
|
||||||
if (adapter.remove(item) == 0) dialog.dismiss();
|
int count = adapter.remove(item);
|
||||||
|
if (count == 0) {
|
||||||
|
dialog.dismiss();
|
||||||
|
} else {
|
||||||
|
// 强制重新测量布局高度
|
||||||
|
binding.recycler.requestLayout();
|
||||||
|
dialog.getWindow().setLayout(dialog.getWindow().getAttributes().width, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,15 @@ package com.fongmi.android.tv.ui.fragment;
|
|||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
import android.text.style.RelativeSizeSpan;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -32,6 +38,7 @@ import com.fongmi.android.tv.impl.SiteCallback;
|
|||||||
import com.fongmi.android.tv.player.Source;
|
import com.fongmi.android.tv.player.Source;
|
||||||
import com.fongmi.android.tv.ui.activity.HomeActivity;
|
import com.fongmi.android.tv.ui.activity.HomeActivity;
|
||||||
import com.fongmi.android.tv.ui.base.BaseFragment;
|
import com.fongmi.android.tv.ui.base.BaseFragment;
|
||||||
|
import com.fongmi.android.tv.ui.dialog.AboutDialog;
|
||||||
import com.fongmi.android.tv.ui.dialog.ConfigDialog;
|
import com.fongmi.android.tv.ui.dialog.ConfigDialog;
|
||||||
import com.fongmi.android.tv.ui.dialog.HistoryDialog;
|
import com.fongmi.android.tv.ui.dialog.HistoryDialog;
|
||||||
import com.fongmi.android.tv.ui.dialog.LiveDialog;
|
import com.fongmi.android.tv.ui.dialog.LiveDialog;
|
||||||
@@ -91,9 +98,9 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initView() {
|
protected void initView() {
|
||||||
mBinding.vodUrl.setText(VodConfig.getDesc());
|
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc());
|
||||||
mBinding.liveUrl.setText(LiveConfig.getDesc());
|
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc());
|
||||||
mBinding.wallUrl.setText(WallConfig.getDesc());
|
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc());
|
||||||
mBinding.versionText.setText(BuildConfig.VERSION_NAME);
|
mBinding.versionText.setText(BuildConfig.VERSION_NAME);
|
||||||
|
|
||||||
// 设置开关的颜色为黄色
|
// 设置开关的颜色为黄色
|
||||||
@@ -145,6 +152,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
mBinding.player.setOnClickListener(this::onPlayer);
|
mBinding.player.setOnClickListener(this::onPlayer);
|
||||||
mBinding.restore.setOnClickListener(this::onRestore);
|
mBinding.restore.setOnClickListener(this::onRestore);
|
||||||
mBinding.version.setOnClickListener(this::onVersion);
|
mBinding.version.setOnClickListener(this::onVersion);
|
||||||
|
mBinding.about.setOnClickListener(this::onAbout);
|
||||||
mBinding.vod.setOnLongClickListener(this::onVodEdit);
|
mBinding.vod.setOnLongClickListener(this::onVodEdit);
|
||||||
mBinding.vodHome.setOnClickListener(this::onVodHome);
|
mBinding.vodHome.setOnClickListener(this::onVodHome);
|
||||||
mBinding.live.setOnLongClickListener(this::onLiveEdit);
|
mBinding.live.setOnLongClickListener(this::onLiveEdit);
|
||||||
@@ -162,6 +170,9 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setConfig(Config config) {
|
public void setConfig(Config config) {
|
||||||
|
// 如果URL为空,不进行任何操作
|
||||||
|
if (config.isEmpty()) return;
|
||||||
|
|
||||||
if (config.getUrl().startsWith("file") && !PermissionX.isGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
if (config.getUrl().startsWith("file") && !PermissionX.isGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||||
PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> load(config));
|
PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> load(config));
|
||||||
} else {
|
} else {
|
||||||
@@ -204,7 +215,18 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
@Override
|
@Override
|
||||||
public void error(String msg) {
|
public void error(String msg) {
|
||||||
Notify.show(msg);
|
Notify.show(msg);
|
||||||
setConfig(type);
|
Notify.dismiss();
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -216,24 +238,37 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
Notify.dismiss();
|
Notify.dismiss();
|
||||||
RefreshEvent.video();
|
RefreshEvent.video();
|
||||||
RefreshEvent.config();
|
RefreshEvent.config();
|
||||||
mBinding.vodUrl.setText(VodConfig.getDesc());
|
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc());
|
||||||
mBinding.liveUrl.setText(LiveConfig.getDesc());
|
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc());
|
||||||
mBinding.wallUrl.setText(WallConfig.getDesc());
|
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
setCacheText();
|
setCacheText();
|
||||||
Notify.dismiss();
|
Notify.dismiss();
|
||||||
RefreshEvent.config();
|
RefreshEvent.config();
|
||||||
mBinding.liveUrl.setText(LiveConfig.getDesc());
|
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc());
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
setCacheText();
|
setCacheText();
|
||||||
Notify.dismiss();
|
Notify.dismiss();
|
||||||
mBinding.wallUrl.setText(WallConfig.getDesc());
|
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSourceHintText(TextView textView, String desc) {
|
||||||
|
if (TextUtils.isEmpty(desc)) {
|
||||||
|
SpannableString spannable = new SpannableString(getString(R.string.source_hint));
|
||||||
|
spannable.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.white)), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
spannable.setSpan(new RelativeSizeSpan(0.8f), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
int alpha = (int)(255 * 0.5f);
|
||||||
|
spannable.setSpan(new ForegroundColorSpan(android.graphics.Color.argb(alpha, 255, 255, 255)), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
textView.setText(spannable);
|
||||||
|
} else {
|
||||||
|
textView.setText(desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSite(Site item) {
|
public void setSite(Site item) {
|
||||||
VodConfig.get().setHome(item);
|
VodConfig.get().setHome(item);
|
||||||
@@ -300,6 +335,10 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
Updater.create().force().release().start(getActivity());
|
Updater.create().force().release().start(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onAbout(View view) {
|
||||||
|
AboutDialog.show(this);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean onVersionDev(View view) {
|
private boolean onVersionDev(View view) {
|
||||||
Updater.create().force().dev().start(getActivity());
|
Updater.create().force().dev().start(getActivity());
|
||||||
return true;
|
return true;
|
||||||
@@ -415,9 +454,9 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
|
|||||||
@Override
|
@Override
|
||||||
public void onHiddenChanged(boolean hidden) {
|
public void onHiddenChanged(boolean hidden) {
|
||||||
if (hidden) return;
|
if (hidden) return;
|
||||||
mBinding.vodUrl.setText(VodConfig.getDesc());
|
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc());
|
||||||
mBinding.liveUrl.setText(LiveConfig.getDesc());
|
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc());
|
||||||
mBinding.wallUrl.setText(WallConfig.getDesc());
|
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc());
|
||||||
setCacheText();
|
setCacheText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:color="@color/white" android:state_checked="true" />
|
<item android:color="@color/black" android:state_checked="true" />
|
||||||
<item android:color="@color/white" android:state_checked="false" />
|
<item android:color="@color/white" android:state_checked="false" />
|
||||||
</selector>
|
</selector>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:color="@color/white" android:state_checked="true" />
|
<item android:color="@color/black" android:state_checked="true" />
|
||||||
<item android:color="@color/white" android:state_checked="false" />
|
<item android:color="@color/white" android:state_checked="false" />
|
||||||
</selector>
|
</selector>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="#1AFFFFFF" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<size android:height="48dp" />
|
||||||
|
</shape>
|
||||||
@@ -1,10 +1,18 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="?attr/colorControlNormal"
|
android:viewportWidth="24"
|
||||||
android:viewportWidth="960"
|
android:viewportHeight="24">
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="#FF000000"
|
||||||
android:pathData="M438,617L613,503Q627,494 627,478Q627,462 613,453L438,339Q423,329 407.5,337.37Q392,345.74 392,364L392,592Q392,610.26 407.5,618.63Q423,627 438,617ZM140,800Q116,800 98,782Q80,764 80,740L80,220Q80,196 98,178Q116,160 140,160L820,160Q844.75,160 862.38,178Q880,196 880,220L880,740Q880,764 862.38,782Q844.75,800 820,800L140,800ZM140,740L140,740Q140,740 140,740Q140,740 140,740L140,220Q140,220 140,220Q140,220 140,220L140,220Q140,220 140,220Q140,220 140,220L140,740Q140,740 140,740Q140,740 140,740ZM140,740L820,740Q820,740 820,740Q820,740 820,740L820,220Q820,220 820,220Q820,220 820,220L140,220Q140,220 140,220Q140,220 140,220L140,740Q140,740 140,740Q140,740 140,740Z" />
|
android:fillAlpha="0"
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:strokeColor="#FF000000"
|
||||||
|
android:pathData="M3,6C3,4.89543 3.89543,4 5,4H19C20.1046,4 21,4.89543 21,6V18C21,19.1046 20.1046,20 19,20H5C3.89543,20 3,19.1046 3,18V6Z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:fillAlpha="0"
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:strokeColor="#FF000000"
|
||||||
|
android:pathData="M10,9l5,3l-5,3l0,-6z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:strokeColor="#FF000000"
|
||||||
|
android:pathData="M3,6C3,4.89543 3.89543,4 5,4H19C20.1046,4 21,4.89543 21,6V18C21,19.1046 20.1046,20 19,20H5C3.89543,20 3,19.1046 3,18V6Z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:strokeColor="#FF000000"
|
||||||
|
android:pathData="M10,9l5,3l-5,3l0,-6z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="?attr/colorControlNormal"
|
|
||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="#000000"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M140,160L214,312L344,312L270,160L359,160L433,312L563,312L489,160L578,160L652,312L782,312L708,160L820,160Q844,160 862,178Q880,196 880,220L880,740Q880,764 862,782Q844,800 820,800L140,800Q116,800 98,782Q80,764 80,740L80,220Q80,196 98,178Q116,160 140,160L140,160ZM140,372L140,740Q140,740 140,740Q140,740 140,740L820,740Q820,740 820,740Q820,740 820,740L820,372L140,372ZM140,372L140,372L140,740Q140,740 140,740Q140,740 140,740L140,740Q140,740 140,740Q140,740 140,740L140,372Z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M20,3H4C2.9,3 2,3.9 2,5v14c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V5C22,3.9 21.1,3 20,3zM9,17H7v-5h2V17zM13,17h-2V7h2V17zM17,17h-2v-9h2V17z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12V5l-9,-4zM12,11.99h7c-0.53,4.12 -3.28,7.79 -7,8.94V12H5V6.3l7,-3.11v8.8z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@drawable/ic_nav_live_selected" android:state_checked="true" />
|
||||||
|
<item android:drawable="@drawable/ic_nav_live" android:state_checked="false" />
|
||||||
|
</selector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@drawable/ic_nav_setting_selected" android:state_checked="true" />
|
||||||
|
<item android:drawable="@drawable/ic_nav_setting" android:state_checked="false" />
|
||||||
|
</selector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@drawable/ic_nav_vod_selected" android:state_checked="true" />
|
||||||
|
<item android:drawable="@drawable/ic_nav_vod" android:state_checked="false" />
|
||||||
|
</selector>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="?attr/colorControlHighlight">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@color/yellow_500" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<padding
|
||||||
|
android:bottom="14dp"
|
||||||
|
android:left="12dp"
|
||||||
|
android:right="12dp"
|
||||||
|
android:top="14dp" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="14dp" />
|
||||||
|
<solid android:color="#212121" />
|
||||||
|
</shape>
|
||||||
@@ -4,9 +4,6 @@
|
|||||||
<item android:id="@android:id/background">
|
<item android:id="@android:id/background">
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="@color/black_20" />
|
<solid android:color="@color/black_20" />
|
||||||
<stroke
|
|
||||||
android:width="1dp"
|
|
||||||
android:color="#BDBDBD" />
|
|
||||||
<corners android:radius="8dp" />
|
<corners android:radius="8dp" />
|
||||||
<padding
|
<padding
|
||||||
android:bottom="14dp"
|
android:bottom="14dp"
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="14dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/white_10" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/black_20">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/top"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
tools:text="慶餘年第一季:第一集" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/size"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
tools:text="1920 x 1080" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time_battery"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:text="21:30 | 85%" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cast"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_control_cast" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/info"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_control_info" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/keep"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_control_keep_off" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/setting"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_control_setting" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/center"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/prevRoot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/shape_control"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/prev"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/exo_icon_previous" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="48dp"
|
||||||
|
android:layout_marginEnd="48dp"
|
||||||
|
android:background="@drawable/shape_control">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/play"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/exo_icon_play" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/nextRoot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/shape_control"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/next"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/exo_icon_next" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/danmaku"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_control_danmaku_on" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/right"
|
||||||
|
layout="@layout/view_control_right"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bottom"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/parse"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:itemCount="5"
|
||||||
|
tools:listitem="@layout/adapter_parse_dark" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
|
<com.fongmi.android.tv.ui.custom.CustomSeekView
|
||||||
|
android:id="@+id/seek"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/full"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/ic_control_full" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/action"
|
||||||
|
layout="@layout/view_control_vod_action"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
@@ -14,14 +14,14 @@
|
|||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/navigation"
|
android:id="@+id/navigation"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="68dp"
|
android:layout_height="70dp"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
app:elevation="0dp"
|
app:elevation="0dp"
|
||||||
app:itemIconSize="24dp"
|
app:itemIconSize="24dp"
|
||||||
app:itemIconTint="@color/nav"
|
app:itemIconTint="@color/nav"
|
||||||
app:itemTextColor="@color/nav"
|
app:itemTextColor="@color/nav"
|
||||||
app:labelVisibilityMode="labeled"
|
app:labelVisibilityMode="unlabeled"
|
||||||
app:itemActiveIndicatorStyle="@style/Indicator"
|
app:itemActiveIndicatorStyle="@style/Indicator"
|
||||||
app:menu="@menu/menu_nav" />
|
app:menu="@menu/menu_nav" />
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,38 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<FrameLayout
|
||||||
android:id="@+id/text"
|
|
||||||
style="@style/Widget.App.Button.OutlinedButton.SiteDialog"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/shape_site_dialog"
|
||||||
|
android:gravity="center"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="14dp"
|
||||||
|
android:paddingBottom="14dp"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
tools:text="https://fongmi.github.io/cat.json" />
|
tools:text="https://fongmi.github.io/cat.json" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/copy"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/ic_setting_copy" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="关于"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="开发说明"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="本项目仅用于学习Android开发,代码改自FongMi/TV (https://github.com/FongMi/TV)。"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="免责声明"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="1.本项目仅供学习交流使用,不得用于商业用途\n2.项目中的内容均来自网络,如有侵权请联系删除\n3.使用本项目产生的一切后果由使用者自行承担"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/github"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:background="@drawable/shape_about_button"
|
||||||
|
android:text="我的GitHub"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:padding="12dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -58,16 +58,32 @@
|
|||||||
android:paddingBottom="24dp">
|
android:paddingBottom="24dp">
|
||||||
|
|
||||||
<!-- 源管理分组 -->
|
<!-- 源管理分组 -->
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/setting_source"
|
android:text="@string/setting_source"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:alpha="0.7" />
|
android:alpha="0.7" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="(长按输入框可改源名)"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:alpha="0.5" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -260,6 +276,13 @@
|
|||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_control_setting"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -280,6 +303,13 @@
|
|||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="16dp">
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_setting_incognito"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -304,6 +334,13 @@
|
|||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_setting_size"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -342,6 +379,13 @@
|
|||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_setting_doh"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -369,6 +413,13 @@
|
|||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_fab_link"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -396,6 +447,13 @@
|
|||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_folder"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -434,45 +492,78 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="0dp">
|
android:padding="0dp">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/backup"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_file"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/backup"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:text="@string/setting_backup"
|
android:text="@string/setting_backup"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/restore"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/restore"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:text="@string/setting_restore"
|
android:text="@string/setting_restore"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/version"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/version"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
android:background="@drawable/shape_item"
|
android:background="@drawable/shape_item"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_setting_github"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -491,6 +582,32 @@
|
|||||||
tools:text="1.2.1" />
|
tools:text="1.2.1" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/about"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_item"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_control_info"
|
||||||
|
android:tint="@color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="关于"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -55,7 +55,10 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp">
|
android:paddingStart="24dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingEnd="24dp"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/render"
|
android:id="@+id/render"
|
||||||
|
|||||||
@@ -47,6 +47,18 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time_battery"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="21:30 | 85%" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/cast"
|
android:id="@+id/cast"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:src="@drawable/ic_empty" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/error_no_live" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -60,7 +60,8 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Indicator" parent="Widget.Material3.BottomNavigationView.ActiveIndicator">
|
<style name="Indicator" parent="Widget.Material3.BottomNavigationView.ActiveIndicator">
|
||||||
<item name="android:color">#1F1F1F</item>
|
<item name="android:color">@color/primary</item>
|
||||||
|
<item name="android:height">42dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="BottomNavigationView.TextAppearance" parent="TextAppearance.AppCompat">
|
<style name="BottomNavigationView.TextAppearance" parent="TextAppearance.AppCompat">
|
||||||
@@ -69,10 +70,12 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="BottomNavigation" parent="Widget.Material3.BottomNavigationView">
|
<style name="BottomNavigation" parent="Widget.Material3.BottomNavigationView">
|
||||||
<item name="itemPaddingTop">8dp</item>
|
<item name="itemPaddingTop">4dp</item>
|
||||||
<item name="itemPaddingBottom">8dp</item>
|
<item name="itemPaddingBottom">4dp</item>
|
||||||
<item name="itemTextAppearanceActive">@style/BottomNavigationView.TextAppearance</item>
|
<item name="itemTextAppearanceActive">@style/BottomNavigationView.TextAppearance</item>
|
||||||
<item name="itemTextAppearanceInactive">@style/BottomNavigationView.TextAppearance</item>
|
<item name="itemTextAppearanceInactive">@style/BottomNavigationView.TextAppearance</item>
|
||||||
|
<item name="itemRippleColor">@android:color/transparent</item>
|
||||||
|
<item name="android:background">@null</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- M3 Switch Style -->
|
<!-- M3 Switch Style -->
|
||||||
|
|||||||
@@ -1,18 +1,118 @@
|
|||||||
package com.github.catvod.utils;
|
package com.github.catvod.utils;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
|
||||||
|
import com.github.catvod.net.OkHttp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
public class Github {
|
public class Github {
|
||||||
|
|
||||||
public static final String URL = "https://github.com/Tosencen/XMBOX";
|
public static final String URL = "https://raw.githubusercontent.com/Tosencen/XMBOX/main";
|
||||||
|
public static final String API_URL = "https://api.github.com/repos/Tosencen/XMBOX/releases/latest";
|
||||||
|
|
||||||
|
// 国内镜像地址 - 使用Gitee作为示例,实际应替换为您的镜像地址
|
||||||
|
public static final String CN_URL = "https://gitee.com/tosencen/XMBOX/raw/main";
|
||||||
|
public static final String CN_API_URL = "https://gitee.com/api/v5/repos/tosencen/XMBOX/releases/latest";
|
||||||
|
|
||||||
|
// 存储测速结果
|
||||||
|
private static Boolean useCnMirror = null;
|
||||||
|
private static long lastCheckTime = 0;
|
||||||
|
private static final long CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24小时
|
||||||
|
|
||||||
private static String getUrl(String path, String name) {
|
private static String getUrl(String path, String name) {
|
||||||
return URL + "/" + path + "/" + name;
|
return URL + "/" + path + "/" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getCnUrl(String path, String name) {
|
||||||
|
return CN_URL + "/" + path + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getReleaseApi() {
|
||||||
|
return useCnMirror() ? CN_API_URL : API_URL;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getJson(boolean dev, String name) {
|
public static String getJson(boolean dev, String name) {
|
||||||
|
if (useCnMirror()) {
|
||||||
|
return getCnUrl("apk/" + (dev ? "dev" : "release"), name + ".json");
|
||||||
|
} else {
|
||||||
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".json");
|
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".json");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String getApk(boolean dev, String name) {
|
public static String getApk(boolean dev, String name) {
|
||||||
|
if (useCnMirror()) {
|
||||||
|
return getCnUrl("apk/" + (dev ? "dev" : "release"), name + ".apk");
|
||||||
|
} else {
|
||||||
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".apk");
|
return getUrl("apk/" + (dev ? "dev" : "release"), name + ".apk");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 智能检测是否使用国内镜像
|
||||||
|
public static boolean useCnMirror() {
|
||||||
|
// 如果已经测试过并且在24小时内,直接返回上次的结果
|
||||||
|
long currentTime = SystemClock.elapsedRealtime();
|
||||||
|
if (useCnMirror != null && (currentTime - lastCheckTime < CHECK_INTERVAL)) {
|
||||||
|
return useCnMirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行网络测速
|
||||||
|
useCnMirror = testMirrorSpeed();
|
||||||
|
lastCheckTime = currentTime;
|
||||||
|
return useCnMirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试镜像速度
|
||||||
|
private static boolean testMirrorSpeed() {
|
||||||
|
try {
|
||||||
|
OkHttpClient client = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(3, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(3, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 测试国际源
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
boolean intlSuccess = testUrl(client, URL + "/README.md");
|
||||||
|
long intlTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
||||||
|
// 测试国内源
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
boolean cnSuccess = testUrl(client, CN_URL + "/README.md");
|
||||||
|
long cnTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
||||||
|
// 如果两个都成功,选择更快的
|
||||||
|
if (intlSuccess && cnSuccess) {
|
||||||
|
return cnTime < intlTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果只有一个成功,选择成功的那个
|
||||||
|
if (intlSuccess) return false;
|
||||||
|
if (cnSuccess) return true;
|
||||||
|
|
||||||
|
// 如果都失败,默认国际源
|
||||||
|
return false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false; // 出错时默认使用国际源
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean testUrl(OkHttpClient client, String url) {
|
||||||
|
Request request = new Request.Builder().url(url).build();
|
||||||
|
Call call = client.newCall(request);
|
||||||
|
try {
|
||||||
|
Response response = call.execute();
|
||||||
|
boolean success = response.isSuccessful();
|
||||||
|
response.close();
|
||||||
|
return success;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user