diff --git a/app/build.gradle b/app/build.gradle
index a86896f30..fa958b730 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -21,12 +21,12 @@ android {
leanback {
dimension "mode"
versionCode 207
- versionName "20231103#2"
+ versionName "20231104"
}
mobile {
dimension "mode"
versionCode 207
- versionName "20231103#2"
+ versionName "20231104"
}
java {
dimension "api"
diff --git a/app/src/leanback/java/com/fongmi/android/tv/receiver/BootReceiver.java b/app/src/leanback/java/com/fongmi/android/tv/receiver/BootReceiver.java
index 236378bac..75e9d8df0 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/receiver/BootReceiver.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/receiver/BootReceiver.java
@@ -13,6 +13,5 @@ public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
DLNARendererService.Companion.start(App.get(), R.drawable.ic_logo);
- context.startActivity(context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
index a416df584..51bb4049b 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
@@ -401,8 +401,8 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List
@Override
public void onTimeChanged() {
- position = mPlayers.getPosition();
- duration = mPlayers.getDuration();
+ App.post(() -> position = mPlayers.getPosition());
+ App.post(() -> duration = mPlayers.getDuration());
}
@Override
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
index 5d7a4f71b..ed50a7992 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
@@ -1,7 +1,9 @@
package com.fongmi.android.tv.ui.activity;
+import android.Manifest;
import android.content.Intent;
import android.net.Uri;
+import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
@@ -31,6 +33,7 @@ import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.bean.Style;
import com.fongmi.android.tv.bean.Vod;
import com.fongmi.android.tv.databinding.ActivityHomeBinding;
+import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.CastEvent;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.event.ServerEvent;
@@ -55,6 +58,7 @@ import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.ResUtil;
import com.fongmi.android.tv.utils.UrlUtil;
import com.google.common.collect.Lists;
+import com.permissionx.guolindev.PermissionX;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -169,7 +173,8 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen
@Override
public void error(String msg) {
- mBinding.progressLayout.showContent();
+ if (TextUtils.isEmpty(msg) && AppDatabase.getDate().length() > 0) onRestore();
+ else mBinding.progressLayout.showContent();
mResult = Result.empty();
Notify.show(msg);
setFocus();
@@ -177,6 +182,15 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen
};
}
+ private void onRestore() {
+ PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> AppDatabase.restore(new Callback() {
+ @Override
+ public void success() {
+ initConfig();
+ }
+ }));
+ }
+
private void loadLive(String url) {
LiveConfig.load(Config.find(url, 1), new Callback() {
@Override
@@ -422,7 +436,7 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen
} else if (!confirm) {
setConfirm();
} else {
- finish();
+ super.onBackPressed();
}
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
index 8b1123f9e..9b58b5448 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
@@ -18,6 +18,7 @@ import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.databinding.ActivitySettingBinding;
+import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.impl.ConfigCallback;
@@ -79,6 +80,7 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
mBinding.vodUrl.setText(ApiConfig.getDesc());
mBinding.liveUrl.setText(LiveConfig.getDesc());
mBinding.wallUrl.setText(WallConfig.getDesc());
+ mBinding.backupText.setText(AppDatabase.getDate());
mBinding.dohText.setText(getDohList()[getDohIndex()]);
mBinding.versionText.setText(BuildConfig.VERSION_NAME);
mBinding.proxyText.setText(UrlUtil.scheme(Setting.getProxy()));
@@ -107,6 +109,7 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
mBinding.wall.setOnClickListener(this::onWall);
mBinding.proxy.setOnClickListener(this::onProxy);
mBinding.cache.setOnClickListener(this::onCache);
+ mBinding.backup.setOnClickListener(this::onBackup);
mBinding.version.setOnClickListener(this::onVersion);
mBinding.vod.setOnLongClickListener(this::onVodEdit);
mBinding.vodHome.setOnClickListener(this::onVodHome);
@@ -350,4 +353,13 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
}
});
}
+
+ private void onBackup(View view) {
+ PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> AppDatabase.backup(new Callback() {
+ @Override
+ public void success() {
+ mBinding.backupText.setText(AppDatabase.getDate());
+ }
+ }));
+ }
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
index be54fe84b..63dbd0e7b 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
@@ -154,8 +154,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
public static void file(FragmentActivity activity, String path) {
if (TextUtils.isEmpty(path)) return;
String name = new File(path).getName();
- if (PermissionX.isGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) start(activity, "push_agent", "file://" + path, name, true);
- else PermissionX.init(activity).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> start(activity, "push_agent", "file://" + path, name, true));
+ PermissionX.init(activity).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> start(activity, "push_agent", "file://" + path, name, true));
}
public static void cast(Activity activity, History history) {
diff --git a/app/src/leanback/res/layout/activity_setting.xml b/app/src/leanback/res/layout/activity_setting.xml
index 4d941f724..2e59537d5 100644
--- a/app/src/leanback/res/layout/activity_setting.xml
+++ b/app/src/leanback/res/layout/activity_setting.xml
@@ -512,7 +512,7 @@
+ tools:text="20231103" />
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java b/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
index a66ad3c2e..3154e1961 100644
--- a/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
+++ b/app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
@@ -23,11 +23,18 @@ import com.fongmi.android.tv.db.dao.HistoryDao;
import com.fongmi.android.tv.db.dao.KeepDao;
import com.fongmi.android.tv.db.dao.SiteDao;
import com.fongmi.android.tv.db.dao.TrackDao;
+import com.fongmi.android.tv.utils.Util;
+import com.github.catvod.utils.Path;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
@Database(entities = {Keep.class, Site.class, Track.class, Config.class, Device.class, History.class}, version = AppDatabase.VERSION)
public abstract class AppDatabase extends RoomDatabase {
public static final int VERSION = 25;
+ public static final String NAME = "tv";
public static final String SYMBOL = "@@@";
private static volatile AppDatabase instance;
@@ -37,8 +44,39 @@ public abstract class AppDatabase extends RoomDatabase {
return instance;
}
+ public static String getDate() {
+ File file = new File(Path.tv(), NAME);
+ return file.exists() ? Util.format(new SimpleDateFormat("yyyyMMdd", Locale.getDefault()), file.lastModified()) : "";
+ }
+
+ public static void backup(com.fongmi.android.tv.impl.Callback callback) {
+ App.execute(() -> {
+ File db = App.get().getDatabasePath(NAME).getAbsoluteFile();
+ File wal = App.get().getDatabasePath(NAME + "-wal").getAbsoluteFile();
+ File shm = App.get().getDatabasePath(NAME + "-shm").getAbsoluteFile();
+ boolean exists = db.exists() && wal.exists() && shm.exists();
+ if (exists) Path.copy(db, new File(Path.tv(), db.getName()));
+ if (exists) Path.copy(wal, new File(Path.tv(), wal.getName()));
+ if (exists) Path.copy(shm, new File(Path.tv(), shm.getName()));
+ if (exists) App.post(callback::success);
+ });
+ }
+
+ public static void restore(com.fongmi.android.tv.impl.Callback callback) {
+ App.execute(() -> {
+ File db = new File(Path.tv(), NAME);
+ File wal = new File(Path.tv(), NAME + "-wal");
+ File shm = new File(Path.tv(), NAME + "-shm");
+ boolean exists = db.exists() && wal.exists() && shm.exists();
+ if (exists) Path.copy(db, App.get().getDatabasePath(db.getName()).getAbsoluteFile());
+ if (exists) Path.copy(wal, App.get().getDatabasePath(wal.getName()).getAbsoluteFile());
+ if (exists) Path.copy(shm, App.get().getDatabasePath(shm.getName()).getAbsoluteFile());
+ if (exists) App.post(callback::success);
+ });
+ }
+
private static AppDatabase create(Context context) {
- return Room.databaseBuilder(context, AppDatabase.class, "tv")
+ return Room.databaseBuilder(context, AppDatabase.class, NAME)
.addMigrations(MIGRATION_11_12)
.addMigrations(MIGRATION_12_13)
.addMigrations(MIGRATION_13_14)
diff --git a/app/src/main/java/com/fongmi/android/tv/utils/Util.java b/app/src/main/java/com/fongmi/android/tv/utils/Util.java
index eff4d8220..b7a543fc4 100644
--- a/app/src/main/java/com/fongmi/android/tv/utils/Util.java
+++ b/app/src/main/java/com/fongmi/android/tv/utils/Util.java
@@ -100,6 +100,14 @@ public class Util {
}
}
+ public static String format(SimpleDateFormat format, long time) {
+ try {
+ return format.format(time);
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
public static String format(StringBuilder builder, Formatter formatter, long timeMs) {
try {
return androidx.media3.common.util.Util.getStringForTime(builder, formatter, timeMs);
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index d61857907..834acb720 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -81,6 +81,7 @@
DoH
Proxy
缓存
+ 备份
版本
权限
关闭
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 70abd642b..605693d18 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -81,6 +81,7 @@
DoH
Proxy
暫存
+ 備份
版本
權限
關閉
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e20a6039f..0dbbee37b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -81,6 +81,7 @@
DoH
Proxy
Cache
+ Backup
Version
Permission
Off
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/MainActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/MainActivity.java
index bd86fa761..6eb2892dd 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/MainActivity.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/MainActivity.java
@@ -1,9 +1,11 @@
package com.fongmi.android.tv.ui.activity;
+import android.Manifest;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
+import android.text.TextUtils;
import android.view.MenuItem;
import androidx.annotation.NonNull;
@@ -18,6 +20,7 @@ import com.fongmi.android.tv.api.LiveConfig;
import com.fongmi.android.tv.api.WallConfig;
import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.databinding.ActivityMainBinding;
+import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.event.ServerEvent;
import com.fongmi.android.tv.impl.Callback;
@@ -32,6 +35,7 @@ import com.fongmi.android.tv.utils.FileChooser;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.UrlUtil;
import com.google.android.material.navigation.NavigationBarView;
+import com.permissionx.guolindev.PermissionX;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -108,13 +112,23 @@ public class MainActivity extends BaseActivity implements NavigationBarView.OnIt
@Override
public void error(String msg) {
+ if (TextUtils.isEmpty(msg) && AppDatabase.getDate().length() > 0) onRestore();
+ else RefreshEvent.empty();
RefreshEvent.config();
- RefreshEvent.empty();
Notify.show(msg);
}
};
}
+ private void onRestore() {
+ PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> AppDatabase.restore(new Callback() {
+ @Override
+ public void success() {
+ initConfig();
+ }
+ }));
+ }
+
private void loadLive(String url) {
LiveConfig.load(Config.find(url, 1), new Callback() {
@Override
@@ -182,7 +196,7 @@ public class MainActivity extends BaseActivity implements NavigationBarView.OnIt
mBinding.navigation.setSelectedItemId(R.id.vod);
} else if (mManager.canBack(0)) {
if (!confirm) setConfirm();
- else finish();
+ else super.onBackPressed();
}
}
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
index 955615239..886548d91 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
@@ -164,8 +164,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
public static void file(FragmentActivity activity, String path) {
if (TextUtils.isEmpty(path)) return;
String name = new File(path).getName();
- if (PermissionX.isGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) start(activity, "push_agent", "file://" + path, name);
- else PermissionX.init(activity).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> start(activity, "push_agent", "file://" + path, name));
+ PermissionX.init(activity).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> start(activity, "push_agent", "file://" + path, name));
}
public static void cast(Activity activity, History history) {
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
index 8cb9c013a..c52a14bed 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
@@ -22,6 +22,7 @@ import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.databinding.FragmentSettingBinding;
+import com.fongmi.android.tv.db.AppDatabase;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.impl.ConfigCallback;
@@ -88,6 +89,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.vodUrl.setText(ApiConfig.getDesc());
mBinding.liveUrl.setText(LiveConfig.getDesc());
mBinding.wallUrl.setText(WallConfig.getDesc());
+ mBinding.backupText.setText(AppDatabase.getDate());
mBinding.dohText.setText(getDohList()[getDohIndex()]);
mBinding.versionText.setText(BuildConfig.VERSION_NAME);
mBinding.proxyText.setText(UrlUtil.scheme(Setting.getProxy()));
@@ -115,6 +117,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.wall.setOnClickListener(this::onWall);
mBinding.proxy.setOnClickListener(this::onProxy);
mBinding.cache.setOnClickListener(this::onCache);
+ mBinding.backup.setOnClickListener(this::onBackup);
mBinding.version.setOnClickListener(this::onVersion);
mBinding.vod.setOnLongClickListener(this::onVodEdit);
mBinding.vodHome.setOnClickListener(this::onVodHome);
@@ -358,6 +361,15 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
});
}
+ private void onBackup(View view) {
+ PermissionX.init(this).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE).request((allGranted, grantedList, deniedList) -> AppDatabase.backup(new Callback() {
+ @Override
+ public void success() {
+ mBinding.backupText.setText(AppDatabase.getDate());
+ }
+ }));
+ }
+
@Override
public void onHiddenChanged(boolean hidden) {
if (hidden || player == null || decode == null) return;
diff --git a/app/src/mobile/res/layout/fragment_setting.xml b/app/src/mobile/res/layout/fragment_setting.xml
index b4515cb8f..efef97772 100644
--- a/app/src/mobile/res/layout/fragment_setting.xml
+++ b/app/src/mobile/res/layout/fragment_setting.xml
@@ -426,6 +426,33 @@
+
+
+
+
+
+
+
+