Clean time code

release
FongMi 1 month ago
parent ae4a369fa0
commit d51d1c1748
  1. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  2. 1
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VodActivity.java
  3. 5
      app/src/main/java/com/fongmi/android/tv/App.java
  4. 2
      app/src/main/java/com/fongmi/android/tv/api/config/BaseConfig.java
  5. 8
      app/src/main/java/com/fongmi/android/tv/api/config/LiveConfig.java
  6. 6
      app/src/main/java/com/fongmi/android/tv/bean/Catchup.java
  7. 28
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  8. 26
      app/src/main/java/com/fongmi/android/tv/bean/Epg.java
  9. 20
      app/src/main/java/com/fongmi/android/tv/bean/EpgData.java
  10. 7
      app/src/main/java/com/fongmi/android/tv/db/AppDatabase.java
  11. 4
      app/src/main/java/com/fongmi/android/tv/server/Server.java
  12. 14
      app/src/main/java/com/fongmi/android/tv/server/process/Local.java
  13. 15
      app/src/main/java/com/fongmi/android/tv/utils/Clock.java
  14. 21
      app/src/main/java/com/fongmi/android/tv/utils/Formatters.java
  15. 3
      app/src/main/java/com/fongmi/android/tv/utils/ImgUtil.java
  16. 14
      app/src/main/java/com/fongmi/android/tv/utils/Util.java
  17. 2
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  18. 8
      app/src/mobile/java/com/fongmi/android/tv/ui/adapter/RestoreAdapter.java

@ -577,7 +577,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
public void onItemClick(EpgData item) {
if (item.isSelected()) {
fetch(item);
} else if (mChannel.hasCatchup()) {
} else if (mChannel.hasCatchup() || mChannel.isRtsp()) {
mBinding.widget.title.setText(getString(R.string.detail_title, mChannel.getShow(), item.getTitle()));
Notify.show(getString(R.string.play_ready, item.getTitle()));
setActivated(item);

@ -87,6 +87,7 @@ public class VodActivity extends BaseActivity implements TypePresenter.OnClickLi
@Override
public void onPageSelected(int position) {
mBinding.recycler.setSelectedPosition(position);
mBinding.recycler.requestFocus();
}
});
mBinding.recycler.addOnChildViewHolderSelectedListener(new OnChildViewHolderSelectedListener() {

@ -27,10 +27,11 @@ public class App extends Application implements Application.ActivityLifecycleCal
private final ExecutorService searchExecutor;
private final ExecutorService executor;
private final Handler handler;
private static App instance;
private Activity activity;
private final Gson gson;
private final long time;
private static volatile App instance;
private Activity activity;
private Hook hook;
public App() {

@ -32,7 +32,7 @@ abstract class BaseConfig {
private final AtomicInteger taskId = new AtomicInteger(0);
protected boolean sync;
protected Config config;
protected volatile Config config;
private volatile Future<?> future;
protected abstract String getTag();

@ -30,6 +30,8 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.time.ZoneId;
public class LiveConfig extends BaseConfig {
private static final String TAG = LiveConfig.class.getSimpleName();
@ -235,6 +237,12 @@ public class LiveConfig extends BaseConfig {
this.ads = ads;
}
public ZoneId getZoneId() {
String tz = getHome().getTimeZone();
if (tz.isEmpty()) return ZoneId.systemDefault();
try { return ZoneId.of(tz); } catch (Exception ignored) { return ZoneId.systemDefault(); }
}
public Live getHome() {
return home == null ? new Live() : home;
}

@ -5,7 +5,9 @@ import android.text.TextUtils;
import com.google.gson.annotations.SerializedName;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -114,7 +116,7 @@ public class Catchup {
private String formatTime(long millis, String fmt) {
if (fmt.equals("timestamp")) return String.valueOf(millis / 1000);
return new SimpleDateFormat(fmt, Locale.getDefault()).format(millis);
return DateTimeFormatter.ofPattern(fmt, Locale.getDefault()).format(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()));
}
private String format(String group, long start, long end) {

@ -17,7 +17,11 @@ import com.google.gson.JsonElement;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.fongmi.android.tv.utils.Formatters;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -64,7 +68,7 @@ public class Channel {
private Group group;
private String show;
private int index;
private Epg data;
private List<Epg> dataList;
public static Channel objectFrom(JsonElement element) {
return App.gson().fromJson(element, Channel.class);
@ -234,11 +238,23 @@ public class Channel {
}
public Epg getData() {
return data == null ? new Epg() : data;
String today = LocalDate.now().format(Formatters.DATE);
if (dataList == null) return new Epg();
return dataList.stream().filter(e -> e.equal(today)).findFirst().orElse(new Epg());
}
public List<Epg> getDataList() {
return dataList == null ? Collections.emptyList() : dataList;
}
public void setData(Epg data) {
this.data = data;
if (dataList == null) dataList = new ArrayList<>();
dataList.removeIf(e -> e.equal(data.getDate()));
dataList.add(data);
}
public void setDataList(List<Epg> list) {
this.dataList = new ArrayList<>(list);
}
public int getIndex() {
@ -291,6 +307,10 @@ public class Channel {
return getUrls().isEmpty() || getIndex() == getUrls().size() - 1;
}
public boolean isRtsp() {
return getCurrent().startsWith("rtsp");
}
public boolean hasCatchup() {
if (getCatchup().isEmpty() && getCurrent().contains("/PLTV/")) setCatchup(Catchup.PLTV());
if (!getCatchup().getRegex().isEmpty()) return getCatchup().match(getCurrent());
@ -358,7 +378,7 @@ public class Channel {
setName(item.getName());
setShow(item.getShow());
setUrls(item.getUrls());
setData(item.getData());
setDataList(item.getDataList());
setDrm(item.getDrm());
setEpg(item.getEpg());
setUa(item.getUa());

@ -4,11 +4,12 @@ import android.text.TextUtils;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.api.EpgParser;
import com.fongmi.android.tv.utils.Util;
import com.fongmi.android.tv.utils.Formatters;
import com.github.catvod.utils.Json;
import com.google.gson.annotations.SerializedName;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
@ -25,10 +26,10 @@ public class Epg {
private int width;
public static Epg objectFrom(String str, String key, List<SimpleDateFormat> formats) throws Exception {
if (!Json.isObj(str)) return EpgParser.getEpg(str, key);
public static Epg objectFrom(String str, String key, ZoneId zoneId) throws Exception {
if (!Json.isObj(str)) return EpgParser.getEpg(str, key, zoneId);
Epg item = App.gson().fromJson(str, Epg.class);
item.setTime(formats);
item.setTime(zoneId);
item.setKey(key);
return item;
}
@ -77,11 +78,11 @@ public class Epg {
return getDate().equals(date);
}
private void setTime(List<SimpleDateFormat> formats) {
private void setTime(ZoneId zoneId) {
setList(new ArrayList<>(new LinkedHashSet<>(getList())));
for (EpgData item : getList()) {
item.setStartTime(Util.parse(formats, getDate().concat(item.getStart())));
item.setEndTime(Util.parse(formats, getDate().concat(item.getEnd())));
item.setStartTime(parseEpgTime(getDate().concat(item.getStart()), zoneId));
item.setEndTime(parseEpgTime(getDate().concat(item.getEnd()), zoneId));
if (item.getEndTime() < item.getStartTime()) item.checkDay();
item.trans();
}
@ -106,4 +107,13 @@ public class Epg {
for (int i = 0; i < getList().size(); i++) if (getList().get(i).isInRange()) return i;
return -1;
}
private long parseEpgTime(String source, ZoneId zoneId) {
try {
var fmt = source.length() > 16 ? Formatters.EPG_DT_LONG : Formatters.EPG_DT_SHORT;
return LocalDateTime.parse(source, fmt).atZone(zoneId).toInstant().toEpochMilli();
} catch (Exception ignored) {
return 0L;
}
}
}

@ -5,15 +5,14 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.utils.Formatters;
import com.fongmi.android.tv.utils.ResUtil;
import com.github.catvod.utils.Trans;
import com.google.gson.annotations.SerializedName;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Objects;
import java.util.TimeZone;
public class EpgData {
@ -99,17 +98,12 @@ public class EpgData {
return getStart() + " ~ " + getEnd();
}
public void checkDay() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(getEndTime());
cal.add(Calendar.DAY_OF_MONTH, 1);
setEndTime(cal.getTimeInMillis());
public String getRange() {
return "clock=" + Formatters.EPG_RANGE.format(Instant.ofEpochMilli(getStartTime())) + "-" + Formatters.EPG_RANGE.format(Instant.ofEpochMilli(getEndTime()));
}
public String getRange() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return "clock=" + sdf.format(getStartTime()) + "-" + sdf.format(getEndTime());
public void checkDay() {
setEndTime(Instant.ofEpochMilli(getEndTime()).atZone(ZoneId.systemDefault()).plusDays(1).toInstant().toEpochMilli());
}
public void trans() {

@ -23,14 +23,13 @@ import com.fongmi.android.tv.db.dao.LiveDao;
import com.fongmi.android.tv.db.dao.SiteDao;
import com.fongmi.android.tv.db.dao.TrackDao;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.Formatters;
import com.github.catvod.utils.Path;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@Database(entities = {Keep.class, Site.class, Live.class, Track.class, Config.class, Device.class, History.class}, version = AppDatabase.VERSION)
public abstract class AppDatabase extends RoomDatabase {
@ -52,7 +51,7 @@ public abstract class AppDatabase extends RoomDatabase {
public static void backup(com.fongmi.android.tv.impl.Callback callback) {
App.execute(() -> {
File file = new File(Path.tv(), "tv-" + new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date()) + ".bk");
File file = new File(Path.tv(), "tv-" + LocalDate.now().format(Formatters.DATE) + ".bk");
Backup backup = Backup.create();
if (backup.getConfig().isEmpty()) {
App.post(callback::error);

@ -7,8 +7,8 @@ import com.github.catvod.utils.Util;
public class Server {
private Players player;
private Nano nano;
private volatile Players player;
private volatile Nano nano;
private static class Loader {
static volatile Server INSTANCE = new Server();

@ -7,6 +7,7 @@ import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
import com.fongmi.android.tv.server.Nano;
import com.fongmi.android.tv.server.impl.Process;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.Formatters;
import com.github.catvod.utils.Path;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@ -16,9 +17,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Map;
import java.util.zip.CRC32;
@ -28,12 +28,6 @@ import fi.iki.elonen.NanoHTTPD.Response.Status;
public class Local implements Process {
private final SimpleDateFormat format;
public Local() {
this.format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
}
@Override
public boolean isRequest(IHTTPSession session, String url) {
return url.startsWith("/file") || url.startsWith("/upload") || url.startsWith("/newFolder") || url.startsWith("/delFolder") || url.startsWith("/delFile");
@ -91,7 +85,7 @@ public class Local implements Process {
JsonObject obj = new JsonObject();
obj.addProperty("name", file.getName());
obj.addProperty("path", relativeTo(file, rootPath));
obj.addProperty("time", format.format(new Date(file.lastModified())));
obj.addProperty("time", Formatters.LOCAL_DATETIME.format(Instant.ofEpochMilli(file.lastModified()).atZone(ZoneId.systemDefault())));
obj.addProperty("dir", file.isDirectory() ? 1 : 0);
files.add(obj);
}

@ -4,17 +4,16 @@ import android.widget.TextView;
import com.fongmi.android.tv.App;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
public class Clock {
private SimpleDateFormat format;
private DateTimeFormatter format;
private Callback callback;
private final Date date;
private TextView view;
private Timer timer;
@ -27,7 +26,6 @@ public class Clock {
}
public Clock() {
this.date = new Date();
}
public Clock view(TextView view) {
@ -36,7 +34,7 @@ public class Clock {
}
public Clock format(String format) {
this.format = new SimpleDateFormat(format, Locale.getDefault());
this.format = DateTimeFormatter.ofPattern(format, Locale.getDefault());
return this;
}
@ -56,10 +54,9 @@ public class Clock {
private void doJob() {
try {
long time;
date.setTime(time = System.currentTimeMillis());
long time = System.currentTimeMillis();
if (callback != null) callback.onTimeChanged(time);
if (view != null) view.setText(format.format(date));
if (view != null) view.setText(format.format(LocalDateTime.now()));
} catch (Exception ignored) {
}
}

@ -0,0 +1,21 @@
package com.fongmi.android.tv.utils;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public final class Formatters {
public static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ROOT);
public static final DateTimeFormatter TIME = DateTimeFormatter.ofPattern("HH:mm", Locale.ROOT);
public static final DateTimeFormatter TIME_SEC = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ROOT).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter LOCAL_DATETIME = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss", Locale.ROOT);
public static final DateTimeFormatter EPG_DT_SHORT = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm", Locale.ROOT);
public static final DateTimeFormatter EPG_DT_LONG = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss", Locale.ROOT);
public static final DateTimeFormatter EPG_RANGE = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'", Locale.ROOT).withZone(ZoneOffset.UTC);
public static final DateTimeFormatter EPG_FULL = DateTimeFormatter.ofPattern("yyyyMMddHHmmss Z", Locale.ROOT);
public static final DateTimeFormatter EPG_FULL_NO_TZ = DateTimeFormatter.ofPattern("yyyyMMddHHmmss", Locale.ROOT);
public static final DateTimeFormatter EPG_FULL_COLON = DateTimeFormatter.ofPattern("yyyyMMddHHmmss ZZZ", Locale.ROOT);
}

@ -28,6 +28,7 @@ import com.fongmi.android.tv.impl.CustomTarget;
import com.github.catvod.utils.Json;
import com.google.common.net.HttpHeaders;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@ -36,7 +37,7 @@ import jahirfiquitiva.libs.textdrawable.TextDrawable;
public class ImgUtil {
private static final Set<String> failed = new HashSet<>();
private static final Set<String> failed = Collections.synchronizedSet(new HashSet<>());
public static void logo(ImageView view) {
try {

@ -28,9 +28,7 @@ import com.fongmi.android.tv.R;
import com.github.catvod.utils.Shell;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Formatter;
import java.util.List;
import java.util.regex.Matcher;
@ -168,18 +166,6 @@ public class Util {
return text;
}
public static Date parse(SimpleDateFormat format, String source) {
try {
return format.parse(source);
} catch (Exception e) {
return new Date(0);
}
}
public static long parse(List<SimpleDateFormat> formats, String source) {
return formats.stream().map(format -> parse(format, source)).map(Date::getTime).filter(time -> time > 0).findFirst().orElse(0L);
}
public static boolean isLeanback() {
return "leanback".equals(BuildConfig.FLAVOR_mode);
}

@ -609,7 +609,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDown.Listener
public void onItemClick(EpgData item) {
if (item.isSelected()) {
fetch(item);
} else if (mChannel.hasCatchup()) {
} else if (mChannel.hasCatchup() || mChannel.isRtsp()) {
mBinding.control.title.setText(getString(R.string.detail_title, mChannel.getShow(), item.getTitle()));
Notify.show(getString(R.string.play_ready, item.getTitle()));
mEpgDataAdapter.setSelected(item);

@ -7,22 +7,20 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fongmi.android.tv.databinding.AdapterRestoreBinding;
import com.fongmi.android.tv.utils.Formatters;
import com.github.catvod.utils.Path;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class RestoreAdapter extends RecyclerView.Adapter<RestoreAdapter.ViewHolder> {
private final OnClickListener listener;
private final SimpleDateFormat format;
private final List<File> mItems;
public RestoreAdapter(OnClickListener listener) {
this.format = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
this.mItems = new ArrayList<>();
this.listener = listener;
this.addAll();
@ -67,7 +65,7 @@ public class RestoreAdapter extends RecyclerView.Adapter<RestoreAdapter.ViewHold
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
File item = mItems.get(position);
holder.binding.name.setText(item.getName());
holder.binding.time.setText(format.format(item.lastModified()));
holder.binding.time.setText(Formatters.TIME_SEC.format(Instant.ofEpochMilli(item.lastModified())));
holder.binding.delete.setOnClickListener(v -> listener.onDeleteClick(item));
holder.binding.getRoot().setOnClickListener(v -> listener.onItemClick(item));
}

Loading…
Cancel
Save