release
FongMi 3 weeks ago
parent f7de743da1
commit 580c270095
  1. 4
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  2. 4
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  3. 84
      app/src/main/java/com/fongmi/android/tv/api/config/BaseConfig.java
  4. 100
      app/src/main/java/com/fongmi/android/tv/api/config/LiveConfig.java
  5. 61
      app/src/main/java/com/fongmi/android/tv/api/config/VodConfig.java
  6. 72
      app/src/main/java/com/fongmi/android/tv/api/config/WallConfig.java
  7. 8
      app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java
  8. 2
      app/src/main/java/com/fongmi/android/tv/model/LiveViewModel.java
  9. 7
      app/src/main/java/com/fongmi/android/tv/utils/UrlUtil.java
  10. 1
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java
  11. 2
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java

@ -23,6 +23,7 @@ import androidx.viewbinding.ViewBinding;
import com.fongmi.android.tv.App; import com.fongmi.android.tv.App;
import com.fongmi.android.tv.Product; import com.fongmi.android.tv.Product;
import com.fongmi.android.tv.R; import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.Updater; import com.fongmi.android.tv.Updater;
import com.fongmi.android.tv.api.config.LiveConfig; import com.fongmi.android.tv.api.config.LiveConfig;
import com.fongmi.android.tv.api.config.VodConfig; import com.fongmi.android.tv.api.config.VodConfig;
@ -333,6 +334,9 @@ public class HomeActivity extends BaseActivity implements CustomTitleView.Listen
getVideo(); getVideo();
getHistory(true); getHistory(true);
break; break;
case BOOT:
LiveActivity.start(this);
break;
} }
} }

@ -261,7 +261,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
List<Group> items = new ArrayList<>(); List<Group> items = new ArrayList<>();
for (Group group : live.getGroups()) (group.isHidden() ? mHides : items).add(group); for (Group group : live.getGroups()) (group.isHidden() ? mHides : items).add(group);
mGroupAdapter.setItems(items, null); mGroupAdapter.setItems(items, null);
setPosition(LiveConfig.get().find(items)); setPosition(LiveConfig.get().findKeepPosition(items));
} }
private void setWidth(Live live) { private void setWidth(Live live) {
@ -957,7 +957,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick
@Override @Override
public void onFind(String number) { public void onFind(String number) {
mBinding.widget.digital.setVisibility(View.GONE); mBinding.widget.digital.setVisibility(View.GONE);
setPosition(LiveConfig.get().find(number, mGroupAdapter.unmodifiableList())); setPosition(LiveConfig.get().findByChannelNumber(number, mGroupAdapter.unmodifiableList()));
} }
@Override @Override

@ -0,0 +1,84 @@
package com.fongmi.android.tv.api.config;
import android.text.TextUtils;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.bean.Config;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.server.Server;
import com.fongmi.android.tv.utils.Notify;
import com.github.catvod.net.OkHttp;
import java.io.InterruptedIOException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
abstract class BaseConfig {
public static final int VOD = 0;
public static final int LIVE = 1;
public static final int WALL = 2;
private final AtomicInteger taskId = new AtomicInteger(0);
private Future<?> future;
protected Config config;
protected boolean sync;
protected abstract String getTag();
protected abstract Config defaultConfig();
protected abstract void doLoad(int id, Config config, Callback callback) throws Throwable;
public boolean needSync(String url) {
return sync || TextUtils.isEmpty(config.getUrl()) || url.equals(config.getUrl());
}
public Config getConfig() {
return config == null ? defaultConfig() : config;
}
public static String getUrl(BaseConfig instance) {
return instance.getConfig().getUrl();
}
public static String getDesc(BaseConfig instance) {
return instance.getConfig().getDesc();
}
public void load(Callback callback) {
int id = taskId.incrementAndGet();
if (future != null && !future.isDone()) future.cancel(true);
future = App.submit(() -> loadConfig(id, config, callback));
callback.start();
}
protected void loadConfig(int id, Config config, Callback callback) {
try {
Server.get().start();
OkHttp.cancel(getTag());
doLoad(id, config, callback);
if (taskId.get() == id && config.equals(this.config)) config.update();
} catch (Throwable e) {
e.printStackTrace();
if (isCanceled(e)) return;
if (taskId.get() != id) return;
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
}
}
protected boolean isCanceled(Throwable e) {
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e instanceof InterruptedIOException || e.getCause() instanceof InterruptedIOException;
}
protected int getTaskId() {
return taskId.get();
}
protected int nextTaskId() {
return taskId.incrementAndGet();
}
}

@ -1,8 +1,5 @@
package com.fongmi.android.tv.api.config; package com.fongmi.android.tv.api.config;
import android.net.Uri;
import android.text.TextUtils;
import com.fongmi.android.tv.App; import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R; import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting; import com.fongmi.android.tv.Setting;
@ -17,9 +14,8 @@ import com.fongmi.android.tv.bean.Keep;
import com.fongmi.android.tv.bean.Live; import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Rule; import com.fongmi.android.tv.bean.Rule;
import com.fongmi.android.tv.db.AppDatabase; 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.Callback;
import com.fongmi.android.tv.server.Server;
import com.fongmi.android.tv.ui.activity.LiveActivity;
import com.fongmi.android.tv.utils.Notify; import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.UrlUtil; import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.bean.Header; import com.github.catvod.bean.Header;
@ -28,29 +24,22 @@ import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Json; import com.github.catvod.utils.Json;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import java.io.InterruptedIOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class LiveConfig { public class LiveConfig extends BaseConfig {
private static final String TAG = LiveConfig.class.getSimpleName(); private static final String TAG = LiveConfig.class.getSimpleName();
private final AtomicInteger taskId = new AtomicInteger(0);
private Live home; private Live home;
private Config config;
private List<Live> lives; private List<Live> lives;
private List<Rule> rules; private List<Rule> rules;
private List<String> ads; private List<String> ads;
private Future<?> future;
private boolean sync;
private static class Loader { private static class Loader {
static volatile LiveConfig INSTANCE = new LiveConfig(); static volatile LiveConfig INSTANCE = new LiveConfig();
@ -85,7 +74,8 @@ public class LiveConfig {
} }
public static boolean hasUrl() { public static boolean hasUrl() {
return getUrl() != null && !getUrl().isEmpty(); String url = getUrl();
return url != null && !url.isEmpty();
} }
public static void load(Config config, Callback callback) { public static void load(Config config, Callback callback) {
@ -106,55 +96,39 @@ public class LiveConfig {
public LiveConfig clear() { public LiveConfig clear() {
home = null; home = null;
lives = null; lives = null;
rules = null;
ads = null;
return this; return this;
} }
private boolean isCanceled(Throwable e) { @Override
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e instanceof InterruptedIOException; protected String getTag() {
return TAG;
} }
public void load() { @Override
if (sync) return; protected Config defaultConfig() {
load(new Callback()); return Config.live();
} }
public void load(Callback callback) { @Override
int id = taskId.incrementAndGet(); protected void doLoad(int id, Config config, Callback callback) throws Throwable {
if (future != null && !future.isDone()) future.cancel(true); String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG);
future = App.submit(() -> loadConfig(id, config, callback)); if (Json.isObj(json)) checkJson(id, config, callback, Json.parse(json).getAsJsonObject());
callback.start(); else parseText(id, config, callback, json);
} }
private void loadConfig(int id, Config config, Callback callback) { public void load() {
try { if (sync) return;
OkHttp.cancel(TAG); load(new Callback());
Server.get().start();
String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG);
if (Json.isObj(json)) checkJson(id, config, callback, Json.parse(json).getAsJsonObject());
else parseText(id, config, callback, json);
if (taskId.get() == id && config.equals(this.config)) config.update();
} catch (Throwable e) {
e.printStackTrace();
if (isCanceled(e)) return;
if (taskId.get() != id) return;
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
}
} }
private void parseText(int id, Config config, Callback callback, String text) { private void parseText(int id, Config config, Callback callback, String text) {
Live live = new Live(parseName(config.getUrl()), config.getUrl()).sync(); Live live = new Live(UrlUtil.getName(config.getUrl()), config.getUrl()).sync();
lives = new ArrayList<>(List.of(live)); lives = new ArrayList<>(List.of(live));
LiveParser.text(live, text); LiveParser.text(live, text);
setHome(config, live, false); setHome(config, live, false);
if (taskId.get() == id) App.post(callback::success); if (getTaskId() == id) App.post(callback::success);
}
private String parseName(String url) {
Uri uri = Uri.parse(url);
String path = UrlUtil.path(uri);
String host = UrlUtil.host(uri);
return !path.isEmpty() ? path : !host.isEmpty() ? host : url;
} }
private void checkJson(int id, Config config, Callback callback, JsonObject object) { private void checkJson(int id, Config config, Callback callback, JsonObject object) {
@ -170,7 +144,7 @@ public class LiveConfig {
private void parseDepot(int id, Config config, Callback callback, JsonObject object) { private void parseDepot(int id, Config config, Callback callback, JsonObject object) {
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString()); List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString());
List<Config> configs = new ArrayList<>(); List<Config> configs = new ArrayList<>();
for (Depot item : items) configs.add(Config.find(item, 1)); for (Depot item : items) configs.add(Config.find(item, LIVE));
loadConfig(id, this.config = configs.get(0), callback); loadConfig(id, this.config = configs.get(0), callback);
Config.delete(config.getUrl()); Config.delete(config.getUrl());
} }
@ -179,11 +153,11 @@ public class LiveConfig {
try { try {
initList(object); initList(object);
initLive(config, object); initLive(config, object);
if (taskId.get() != id) return; if (getTaskId() != id) return;
if (callback != null) App.post(callback::success); if (callback != null) App.post(callback::success);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
if (taskId.get() != id) return; if (getTaskId() != id) return;
if (callback != null) App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e))); if (callback != null) App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e)));
} }
} }
@ -205,13 +179,8 @@ public class LiveConfig {
setHome(config, getLives().isEmpty() ? new Live() : getLives().stream().filter(item -> item.getName().equals(config.getHome())).findFirst().orElse(getLives().get(0)), false); setHome(config, getLives().isEmpty() ? new Live() : getLives().stream().filter(item -> item.getName().equals(config.getHome())).findFirst().orElse(getLives().get(0)), false);
} }
private void bootLive() {
Setting.putBootLive(false);
LiveActivity.start(App.get());
}
public void parse(JsonObject object) { public void parse(JsonObject object) {
int id = taskId.incrementAndGet(); int id = nextTaskId();
parseConfig(id, getConfig(), null, object); parseConfig(id, getConfig(), null, object);
} }
@ -219,7 +188,7 @@ public class LiveConfig {
if (home != null && !channel.getGroup().isHidden()) home.keep(channel).save(); if (home != null && !channel.getGroup().isHidden()) home.keep(channel).save();
} }
public void setKeep(List<Group> items) { public void applyKeepsToGroups(List<Group> items) {
Set<String> key = Keep.getLive().stream().map(Keep::getKey).collect(Collectors.toSet()); Set<String> key = Keep.getLive().stream().map(Keep::getKey).collect(Collectors.toSet());
items.stream().filter(group -> !group.isKeep()) items.stream().filter(group -> !group.isKeep())
.flatMap(group -> group.getChannel().stream()) .flatMap(group -> group.getChannel().stream())
@ -227,7 +196,7 @@ public class LiveConfig {
.forEach(channel -> items.get(0).add(channel)); .forEach(channel -> items.get(0).add(channel));
} }
public int[] find(List<Group> items) { public int[] findKeepPosition(List<Group> items) {
String[] splits = getHome().getKeep().split(AppDatabase.SYMBOL); String[] splits = getHome().getKeep().split(AppDatabase.SYMBOL);
if (splits.length < 3) return new int[]{1, 0}; if (splits.length < 3) return new int[]{1, 0};
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
@ -243,7 +212,7 @@ public class LiveConfig {
return new int[]{1, 0}; return new int[]{1, 0};
} }
public int[] find(String number, List<Group> items) { public int[] findByChannelNumber(String number, List<Group> items) {
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
int j = items.get(i).find(Integer.parseInt(number)); int j = items.get(i).find(Integer.parseInt(number));
if (j != -1) return new int[]{i, j}; if (j != -1) return new int[]{i, j};
@ -251,10 +220,6 @@ public class LiveConfig {
return new int[]{-1, -1}; return new int[]{-1, -1};
} }
public boolean needSync(String url) {
return sync || TextUtils.isEmpty(config.getUrl()) || url.equals(config.getUrl());
}
public List<Live> getLives() { public List<Live> getLives() {
return lives == null ? lives = new ArrayList<>() : lives; return lives == null ? lives = new ArrayList<>() : lives;
} }
@ -292,10 +257,6 @@ public class LiveConfig {
this.ads = ads; this.ads = ads;
} }
public Config getConfig() {
return config == null ? Config.live() : config;
}
public Live getHome() { public Live getHome() {
return home == null ? new Live() : home; return home == null ? new Live() : home;
} }
@ -314,7 +275,6 @@ public class LiveConfig {
config.home(home.getName()); config.home(home.getName());
if (save) config.save(); if (save) config.save();
getLives().forEach(item -> item.setActivated(home)); getLives().forEach(item -> item.setActivated(home));
if (App.activity() != null && App.activity() instanceof LiveActivity) return; if (!save && (home.isBoot() || Setting.isBootLive())) RefreshEvent.boot();
if (!save && (home.isBoot() || Setting.isBootLive())) App.post(this::bootLive);
} }
} }

@ -12,7 +12,6 @@ import com.fongmi.android.tv.bean.Parse;
import com.fongmi.android.tv.bean.Rule; import com.fongmi.android.tv.bean.Rule;
import com.fongmi.android.tv.bean.Site; import com.fongmi.android.tv.bean.Site;
import com.fongmi.android.tv.impl.Callback; import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.server.Server;
import com.fongmi.android.tv.utils.Notify; import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.UrlUtil; import com.fongmi.android.tv.utils.UrlUtil;
import com.github.catvod.bean.Doh; import com.github.catvod.bean.Doh;
@ -22,32 +21,26 @@ import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Json; import com.github.catvod.utils.Json;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import java.io.InterruptedIOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class VodConfig { public class VodConfig extends BaseConfig {
private static final String TAG = VodConfig.class.getSimpleName(); private static final String TAG = VodConfig.class.getSimpleName();
private final AtomicInteger taskId = new AtomicInteger(0);
private Site home; private Site home;
private String wall; private String wall;
private Parse parse; private Parse parse;
private Config config;
private List<Doh> doh; private List<Doh> doh;
private List<Rule> rules; private List<Rule> rules;
private List<Site> sites; private List<Site> sites;
private List<String> ads; private List<String> ads;
private List<String> flags; private List<String> flags;
private List<Parse> parses; private List<Parse> parses;
private Future<?> future;
private static class Loader { private static class Loader {
static volatile VodConfig INSTANCE = new VodConfig(); static volatile VodConfig INSTANCE = new VodConfig();
@ -95,35 +88,29 @@ public class VodConfig {
wall = null; wall = null;
parse = null; parse = null;
sites = null; sites = null;
parses = null;
rules = null;
ads = null;
doh = null;
flags = null;
BaseLoader.get().clear(); BaseLoader.get().clear();
return this; return this;
} }
private boolean isCanceled(Throwable e) { @Override
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e instanceof InterruptedIOException; protected String getTag() {
return TAG;
} }
public void load(Callback callback) { @Override
int id = taskId.incrementAndGet(); protected Config defaultConfig() {
if (future != null && !future.isDone()) future.cancel(true); return Config.vod();
future = App.submit(() -> loadConfig(id, config, callback));
callback.start();
} }
private void loadConfig(int id, Config config, Callback callback) { @Override
try { protected void doLoad(int id, Config config, Callback callback) throws Throwable {
OkHttp.cancel(TAG); String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG);
Server.get().start(); checkJson(id, config, callback, Json.parse(json).getAsJsonObject());
String json = Decoder.getJson(UrlUtil.convert(config.getUrl()), TAG);
checkJson(id, config, callback, Json.parse(json).getAsJsonObject());
if (taskId.get() == id && config.equals(this.config)) config.update();
} catch (Throwable e) {
e.printStackTrace();
if (isCanceled(e)) return;
if (taskId.get() != id) return;
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
}
} }
private void checkJson(int id, Config config, Callback callback, JsonObject object) { private void checkJson(int id, Config config, Callback callback, JsonObject object) {
@ -139,7 +126,7 @@ public class VodConfig {
private void parseDepot(int id, Config config, Callback callback, JsonObject object) { private void parseDepot(int id, Config config, Callback callback, JsonObject object) {
List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString()); List<Depot> items = Depot.arrayFrom(object.getAsJsonArray("urls").toString());
List<Config> configs = new ArrayList<>(); List<Config> configs = new ArrayList<>();
for (Depot item : items) configs.add(Config.find(item, 0)); for (Depot item : items) configs.add(Config.find(item, VOD));
loadConfig(id, this.config = configs.get(0), callback); loadConfig(id, this.config = configs.get(0), callback);
Config.delete(config.getUrl()); Config.delete(config.getUrl());
} }
@ -152,13 +139,11 @@ public class VodConfig {
initSite(config, object); initSite(config, object);
initParse(config, object); initParse(config, object);
config.logo(Json.safeString(object, "logo")); config.logo(Json.safeString(object, "logo"));
String notice = Json.safeString(object, "notice"); if (getTaskId() != id) return;
if (taskId.get() != id) return;
App.post(() -> callback.success(notice));
App.post(callback::success); App.post(callback::success);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
if (taskId.get() != id) return; if (getTaskId() != id) return;
App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e))); App.post(() -> callback.error(Notify.getError(R.string.error_config_parse, e)));
} }
} }
@ -175,7 +160,7 @@ public class VodConfig {
private void initLive(Config config, JsonObject object) { private void initLive(Config config, JsonObject object) {
if (Json.isEmpty(object, "lives")) return; if (Json.isEmpty(object, "lives")) return;
Config temp = Config.find(config, 1).save(); Config temp = Config.find(config, LIVE).save();
boolean sync = LiveConfig.get().needSync(config.getUrl()); boolean sync = LiveConfig.get().needSync(config.getUrl());
if (sync) LiveConfig.get().config(temp.update()).parse(object); if (sync) LiveConfig.get().config(temp.update()).parse(object);
} }
@ -183,7 +168,7 @@ public class VodConfig {
private void initWall(Config config, JsonObject object) { private void initWall(Config config, JsonObject object) {
if (Json.isEmpty(object, "wallpaper")) return; if (Json.isEmpty(object, "wallpaper")) return;
this.wall = Json.safeString(object, "wallpaper"); this.wall = Json.safeString(object, "wallpaper");
Config temp = Config.find(wall, config.getName(), 2).save(); Config temp = Config.find(wall, config.getName(), WALL).save();
boolean sync = WallConfig.get().needSync(wall); boolean sync = WallConfig.get().needSync(wall);
if (sync) WallConfig.get().config(temp.update()); if (sync) WallConfig.get().config(temp.update());
} }
@ -278,10 +263,6 @@ public class VodConfig {
this.ads = ads; this.ads = ads;
} }
public Config getConfig() {
return config == null ? Config.vod() : config;
}
public Parse getParse() { public Parse getParse() {
return parse == null ? new Parse() : parse; return parse == null ? new Parse() : parse;
} }

@ -24,18 +24,10 @@ import com.github.catvod.utils.Path;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.InterruptedIOException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
public class WallConfig { public class WallConfig extends BaseConfig {
private static final String TAG = WallConfig.class.getSimpleName(); private static final String TAG = WallConfig.class.getSimpleName();
private final AtomicInteger taskId = new AtomicInteger(0);
private Config config;
private Future<?> future;
private boolean sync;
private static class Loader { private static class Loader {
static volatile WallConfig INSTANCE = new WallConfig(); static volatile WallConfig INSTANCE = new WallConfig();
@ -68,34 +60,40 @@ public class WallConfig {
return this; return this;
} }
private boolean isCanceled(Throwable e) {
return "Canceled".equals(e.getMessage()) || e instanceof InterruptedException || e.getCause() instanceof InterruptedIOException;
}
public void load() { public void load() {
if (sync) return;
load(new Callback()); load(new Callback());
} }
public void load(Callback callback) { @Override
int id = taskId.incrementAndGet(); protected String getTag() {
if (future != null && !future.isDone()) future.cancel(true); return TAG;
future = App.submit(() -> loadConfig(id, config, callback));
callback.start();
} }
private void loadConfig(int id, Config config, Callback callback) { @Override
protected Config defaultConfig() {
return Config.wall();
}
@Override
protected void doLoad(int id, Config config, Callback callback) throws Throwable {
download(id, config.getUrl(), callback);
}
@Override
protected void loadConfig(int id, Config config, Callback callback) {
try { try {
OkHttp.cancel(TAG); OkHttp.cancel(TAG);
download(id, config.getUrl(), callback); doLoad(id, config, callback);
if (taskId.get() == id && config.equals(this.config)) config.update(); if (getTaskId() == id && config.equals(this.config)) config.update();
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
if (isCanceled(e)) return; if (isCanceled(e)) return;
if (taskId.get() != id) return; if (getTaskId() != id) return;
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
Setting.putWall(1); Setting.putWall(1);
RefreshEvent.wall(); RefreshEvent.wall();
if (TextUtils.isEmpty(config.getUrl())) App.post(() -> callback.error(""));
else App.post(() -> callback.error(Notify.getError(R.string.error_config_get, e)));
} }
} }
@ -104,27 +102,31 @@ public class WallConfig {
if (url.startsWith("file")) Path.copy(Path.local(url), file); if (url.startsWith("file")) Path.copy(Path.local(url), file);
else Download.create(UrlUtil.convert(url), file).tag(TAG).get(); else Download.create(UrlUtil.convert(url), file).tag(TAG).get();
if (!Path.exists(file)) throw new FileNotFoundException(); if (!Path.exists(file)) throw new FileNotFoundException();
if (taskId.get() != id) return; if (getTaskId() != id) return;
setWallType(file); process(file);
setSnapshot(file);
RefreshEvent.wall(); RefreshEvent.wall();
App.post(callback::success); App.post(callback::success);
} }
private void setWallType(File file) { private static void process(File file) throws Throwable {
setWallType(file);
setSnapshot(file);
}
private static void setWallType(File file) {
Setting.putWallType(0); Setting.putWallType(0);
if (isGif(file)) Setting.putWallType(1); if (isGif(file)) Setting.putWallType(1);
else if (isVideo(file)) Setting.putWallType(2); else if (isVideo(file)) Setting.putWallType(2);
} }
private void setSnapshot(File file) throws Throwable { private static void setSnapshot(File file) throws Throwable {
Bitmap bitmap = Glide.with(App.get()).asBitmap().frame(0).load(file).override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).submit().get(); Bitmap bitmap = Glide.with(App.get()).asBitmap().frame(0).load(file).override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).submit().get();
try (FileOutputStream fos = new FileOutputStream(FileUtil.getWallCache())) { try (FileOutputStream fos = new FileOutputStream(FileUtil.getWallCache())) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} }
} }
private boolean isVideo(File file) { private static boolean isVideo(File file) {
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
retriever.setDataSource(file.getAbsolutePath()); retriever.setDataSource(file.getAbsolutePath());
return "yes".equalsIgnoreCase(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO)); return "yes".equalsIgnoreCase(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO));
@ -133,7 +135,7 @@ public class WallConfig {
} }
} }
private boolean isGif(File file) { private static boolean isGif(File file) {
try { try {
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; options.inJustDecodeBounds = true;
@ -143,12 +145,4 @@ public class WallConfig {
return false; return false;
} }
} }
public boolean needSync(String url) {
return sync || TextUtils.isEmpty(config.getUrl()) || url.equals(config.getUrl());
}
public Config getConfig() {
return config == null ? Config.wall() : config;
}
} }

@ -1,5 +1,6 @@
package com.fongmi.android.tv.event; package com.fongmi.android.tv.event;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.bean.Vod; import com.fongmi.android.tv.bean.Vod;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
@ -38,6 +39,11 @@ public class RefreshEvent {
EventBus.getDefault().post(new RefreshEvent(Type.LIVE)); EventBus.getDefault().post(new RefreshEvent(Type.LIVE));
} }
public static void boot() {
EventBus.getDefault().post(new RefreshEvent(Type.BOOT));
Setting.putBootLive(false);
}
public static void detail() { public static void detail() {
EventBus.getDefault().post(new RefreshEvent(Type.DETAIL)); EventBus.getDefault().post(new RefreshEvent(Type.DETAIL));
} }
@ -85,6 +91,6 @@ public class RefreshEvent {
} }
public enum Type { public enum Type {
CONFIG, VIDEO, HISTORY, KEEP, SIZE, WALL, LIVE, DETAIL, PLAYER, SUBTITLE, DANMAKU, VOD CONFIG, VIDEO, HISTORY, KEEP, SIZE, WALL, LIVE, BOOT, DETAIL, PLAYER, SUBTITLE, DANMAKU, VOD
} }
} }

@ -139,7 +139,7 @@ public class LiveViewModel extends ViewModel {
item.getGroups().removeIf(Group::isEmpty); item.getGroups().removeIf(Group::isEmpty);
if (item.getGroups().isEmpty() || item.getGroups().get(0).isKeep()) return; if (item.getGroups().isEmpty() || item.getGroups().get(0).isKeep()) return;
item.getGroups().add(0, Group.create(R.string.keep)); item.getGroups().add(0, Group.create(R.string.keep));
LiveConfig.get().setKeep(item.getGroups()); LiveConfig.get().applyKeepsToGroups(item.getGroups());
} }
private <T> void execute(TaskType type, Callable<T> callable) { private <T> void execute(TaskType type, Callable<T> callable) {

@ -52,6 +52,13 @@ public class UrlUtil {
return path != null ? url.replace(scheme + "://", Server.get().getAddress(path)) : url; return path != null ? url.replace(scheme + "://", Server.get().getAddress(path)) : url;
} }
public static String getName(String url) {
Uri uri = Uri.parse(url);
String path = path(uri);
String host = host(uri);
return !path.isEmpty() ? path : !host.isEmpty() ? host : url;
}
public static String fixHeader(String key) { public static String fixHeader(String key) {
if (HttpHeaders.USER_AGENT.equalsIgnoreCase(key)) return HttpHeaders.USER_AGENT; if (HttpHeaders.USER_AGENT.equalsIgnoreCase(key)) return HttpHeaders.USER_AGENT;
if (HttpHeaders.REFERER.equalsIgnoreCase(key)) return HttpHeaders.REFERER; if (HttpHeaders.REFERER.equalsIgnoreCase(key)) return HttpHeaders.REFERER;

@ -178,6 +178,7 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) { public void onRefreshEvent(RefreshEvent event) {
if (event.getType().equals(RefreshEvent.Type.CONFIG)) setNavigation(); if (event.getType().equals(RefreshEvent.Type.CONFIG)) setNavigation();
if (event.getType().equals(RefreshEvent.Type.BOOT)) LiveActivity.start(this);
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)

@ -268,7 +268,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDown.Listener
List<Group> items = new ArrayList<>(); List<Group> items = new ArrayList<>();
for (Group group : live.getGroups()) (group.isHidden() ? mHides : items).add(group); for (Group group : live.getGroups()) (group.isHidden() ? mHides : items).add(group);
mGroupAdapter.addAll(items); mGroupAdapter.addAll(items);
setPosition(LiveConfig.get().find(items)); setPosition(LiveConfig.get().findKeepPosition(items));
} }
private void setWidth(Live live) { private void setWidth(Live live) {

Loading…
Cancel
Save