Support backup db

pull/171/head
FongMi 2 years ago
parent fe32e6ffdd
commit 60a9186602
  1. 4
      app/build.gradle
  2. 1
      app/src/leanback/java/com/fongmi/android/tv/receiver/BootReceiver.java
  3. 4
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
  4. 18
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  5. 12
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingActivity.java
  6. 3
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  7. 36
      app/src/leanback/res/layout/activity_setting.xml
  8. 40
      app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
  9. 8
      app/src/main/java/com/fongmi/android/tv/utils/Util.java
  10. 1
      app/src/main/res/values-zh-rCN/strings.xml
  11. 1
      app/src/main/res/values-zh-rTW/strings.xml
  12. 1
      app/src/main/res/values/strings.xml
  13. 18
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/MainActivity.java
  14. 3
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  15. 12
      app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java
  16. 27
      app/src/mobile/res/layout/fragment_setting.xml
  17. 4
      catvod/src/main/java/com/github/catvod/utils/Path.java

@ -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"

@ -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));
}
}

@ -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

@ -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();
}
}

@ -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());
}
}));
}
}

@ -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) {

@ -512,7 +512,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/version"
android:id="@+id/backup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -525,19 +525,47 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/setting_version"
android:text="@string/setting_backup"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/versionText"
android:id="@+id/backupText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="1.2.1" />
tools:text="20231103" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/selector_item"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/setting_version"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/versionText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="1.2.1" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

@ -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)

@ -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);

@ -81,6 +81,7 @@
<string name="setting_doh">DoH</string>
<string name="setting_proxy">Proxy</string>
<string name="setting_cache">缓存</string>
<string name="setting_backup">备份</string>
<string name="setting_version">版本</string>
<string name="setting_storage">权限</string>
<string name="setting_off">关闭</string>

@ -81,6 +81,7 @@
<string name="setting_doh">DoH</string>
<string name="setting_proxy">Proxy</string>
<string name="setting_cache">暫存</string>
<string name="setting_backup">備份</string>
<string name="setting_version">版本</string>
<string name="setting_storage">權限</string>
<string name="setting_off">關閉</string>

@ -81,6 +81,7 @@
<string name="setting_doh">DoH</string>
<string name="setting_proxy">Proxy</string>
<string name="setting_cache">Cache</string>
<string name="setting_backup">Backup</string>
<string name="setting_version">Version</string>
<string name="setting_storage">Permission</string>
<string name="setting_off">Off</string>

@ -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();
}
}

@ -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) {

@ -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;

@ -426,6 +426,33 @@
</LinearLayout>
<LinearLayout
android:id="@+id/backup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/shape_item"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/setting_backup"
android:textColor="@color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/backupText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="20231103" />
</LinearLayout>
<LinearLayout
android:id="@+id/version"
android:layout_width="match_parent"

@ -50,6 +50,10 @@ public class Path {
return root().getAbsolutePath();
}
public static File tv() {
return check(new File(root() + File.separator + "TV"));
}
public static File so() {
return check(new File(files() + File.separator + "so"));
}

Loading…
Cancel
Save