Merge pull request #491 from okcaptain/dev

Dev
pull/492/head
okcaptain 2 years ago committed by GitHub
commit 41cbebf69c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      app/proguard-rules.pro
  2. 6
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
  3. 18
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  4. 6
      app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  5. 36
      app/src/leanback/java/com/fongmi/android/tv/ui/base/BaseActivity.java
  6. 2
      app/src/leanback/java/com/fongmi/android/tv/ui/presenter/ChannelPresenter.java
  7. 10
      app/src/leanback/res/drawable/ic_action_arrow.xml
  8. 8
      app/src/leanback/res/layout/adapter_channel.xml
  9. 89
      app/src/main/java/com/fongmi/android/tv/api/EpgParser.java
  10. 3
      app/src/main/java/com/fongmi/android/tv/api/LiveParser.java
  11. 34
      app/src/main/java/com/fongmi/android/tv/api/config/WallConfig.java
  12. 4
      app/src/main/java/com/fongmi/android/tv/bean/Channel.java
  13. 14
      app/src/main/java/com/fongmi/android/tv/bean/Epg.java
  14. 8
      app/src/main/java/com/fongmi/android/tv/bean/EpgData.java
  15. 4
      app/src/main/java/com/fongmi/android/tv/bean/Live.java
  16. 90
      app/src/main/java/com/fongmi/android/tv/bean/Tv.java
  17. 4
      app/src/main/java/com/fongmi/android/tv/model/LiveViewModel.java
  18. 6
      app/src/main/java/com/fongmi/android/tv/player/ParseJob.java
  19. 22
      app/src/main/java/com/fongmi/android/tv/player/danmu/Parser.java
  20. 4
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/CollectActivity.java
  21. 31
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
  22. 6
      app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
  23. 3
      app/src/mobile/java/com/fongmi/android/tv/ui/adapter/ChannelAdapter.java
  24. 41
      app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java
  25. 106
      app/src/mobile/res/layout/activity_collect.xml

@ -1,3 +1,6 @@
# TV
-keep class com.fongmi.android.tv.bean.** { *; }
# Gson
-keepattributes Signature
-keepattributes *Annotation*
@ -92,9 +95,6 @@
public static ** valueOf(java.lang.String);
}
# bean
-keep class com.fongmi.android.tv.bean.** { *; }
# x5
-dontwarn dalvik.**
-dontwarn com.tencent.smtt.**

@ -353,7 +353,11 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List
String title = mBinding.widget.title.getText().toString();
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title);
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
try {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
} catch (Exception e) {
e.printStackTrace();
}
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration());
mPlayers.setMetadata(builder.build());
}

@ -590,9 +590,13 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
@Override
public void onItemClick(Channel item) {
mGroup.setPosition(mBinding.channel.getSelectedPosition());
setChannel(item.group(mGroup));
hideUI();
if (item.getData().getList().size() > 0 && item.isSelected() && mChannel != null) {
showEpg(item);
} else {
mGroup.setPosition(mBinding.channel.getSelectedPosition());
setChannel(item.group(mGroup));
hideUI();
}
}
@Override
@ -664,7 +668,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
}
private void setEpg(Epg epg) {
if (mChannel != null && mChannel.getName().equals(epg.getKey())) setEpg();
if (mChannel != null && mChannel.getTvgName().equals(epg.getKey())) setEpg();
}
private void fetch() {
@ -778,7 +782,11 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, GroupP
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title);
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist);
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
try {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
} catch (Exception e) {
e.printStackTrace();
}
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration());
mPlayers.setMetadata(builder.build());
}

@ -1377,7 +1377,11 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title);
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist);
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
try {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
} catch (Exception e) {
e.printStackTrace();
}
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration());
mPlayers.setMetadata(builder.build());
}

@ -3,25 +3,19 @@ package com.fongmi.android.tv.ui.base;
import android.app.Activity;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.api.config.WallConfig;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.ResUtil;
@ -89,10 +83,6 @@ public abstract class BaseActivity extends AppCompatActivity {
if (!view.isComputingLayout()) adapter.notifyArrayItemRangeChanged(0, adapter.size());
}
protected void notifyItemChanged(RecyclerView view, RecyclerView.Adapter<?> adapter) {
if (!view.isComputingLayout()) adapter.notifyItemRangeChanged(0, adapter.getItemCount());
}
private void setBackCallback() {
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(handleBack()) {
@Override
@ -106,31 +96,13 @@ public abstract class BaseActivity extends AppCompatActivity {
try {
if (!customWall()) return;
File file = FileUtil.getWall(Setting.getWall());
if (file.exists() && file.length() > 0) loadWall(file);
if (file.exists() && file.length() > 0) getWindow().setBackgroundDrawable(WallConfig.drawable(file));
else getWindow().setBackgroundDrawableResource(ResUtil.getDrawable(file.getName()));
} catch (Exception e) {
getWindow().setBackgroundDrawableResource(R.drawable.wallpaper_1);
}
}
private void loadWall(File file) {
Glide.with(App.get()).load(file).centerCrop().override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight()).signature(new ObjectKey(com.github.catvod.utils.Util.md5(file))).into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable drawable, @Nullable Transition<? super Drawable> transition) {
getWindow().setBackgroundDrawable(drawable);
}
@Override
public void onLoadFailed(@Nullable Drawable error) {
getWindow().setBackgroundDrawableResource(R.drawable.wallpaper_1);
}
@Override
public void onLoadCleared(@Nullable Drawable drawable) {
}
});
}
private Resources hackResources(Resources resources) {
try {
AutoSizeCompat.autoConvertDensityOfGlobal(resources);
@ -142,7 +114,9 @@ public abstract class BaseActivity extends AppCompatActivity {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.WALL) refreshWall();
if (event.getType() != RefreshEvent.Type.WALL) return;
WallConfig.get().setDrawable(null);
refreshWall();
}
@Override

@ -1,6 +1,7 @@
package com.fongmi.android.tv.ui.presenter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
@ -42,6 +43,7 @@ public class ChannelPresenter extends Presenter {
setOnClickListener(holder, view -> mListener.onItemClick(item));
holder.view.setOnLongClickListener(view -> mListener.onLongClick(item));
holder.binding.getRoot().setRightListener(() -> mListener.showEpg(item));
holder.binding.epg.setVisibility(item.getData().getList().isEmpty() || !item.isSelected() ? View.GONE : View.VISIBLE);
}
@Override

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M496.35,480L312.35,296L376,232.35L623.65,480L376,727.65L312.35,664L496.35,480Z" />
</vector>

@ -42,4 +42,12 @@
android:textStyle="bold"
tools:text="CNN" />
<ImageView
android:id="@+id/epg"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="4dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_action_arrow" />
</com.fongmi.android.tv.ui.custom.CustomLeftRightLayout>

@ -0,0 +1,89 @@
package com.fongmi.android.tv.api;
import android.net.Uri;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Epg;
import com.fongmi.android.tv.bean.EpgData;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Tv;
import com.fongmi.android.tv.utils.Download;
import com.github.catvod.utils.Path;
import com.github.catvod.utils.Trans;
import org.simpleframework.xml.core.Persister;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class EpgParser {
private static final SimpleDateFormat formatFull = new SimpleDateFormat("yyyyMMddHHmmss");
private static final SimpleDateFormat formatDate = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat formatTime = new SimpleDateFormat("HH:mm");
public static void start(Live live) {
try {
if (!live.getEpg().contains(".xml") || live.getEpg().contains("{")) return;
File file = Path.cache(Uri.parse(live.getEpg()).getLastPathSegment());
if (shouldDownload(file)) Download.create(live.getEpg(), file).start();
readXml(live, Path.read(file));
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean shouldDownload(File file) {
return !file.exists() || !equalToday(file);
}
private static boolean equalToday(File file) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(file.lastModified());
return calendar.get(Calendar.DAY_OF_MONTH) == Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
}
private static Date parseDateTime(String text) throws Exception {
return formatFull.parse(text.substring(0, 14));
}
private static void readXml(Live live, String xml) throws Exception {
Set<String> exist = new HashSet<>();
Map<String, Epg> epgMap = new HashMap<>();
Map<String, String> mapping = new HashMap<>();
String today = formatDate.format(new Date());
Tv tv = new Persister().read(Tv.class, xml);
for (Group group : live.getGroups()) for (Channel channel : group.getChannel()) exist.add(channel.getTvgName());
for (Tv.Channel channel : tv.getChannel()) mapping.put(channel.getId(), channel.getDisplayName());
for (Tv.Programme programme : tv.getProgramme()) {
String key = mapping.get(programme.getChannel());
if (!exist.contains(key)) continue;
if (!programme.equals(today)) continue;
if (!epgMap.containsKey(key)) epgMap.put(key, Epg.create(key, today));
String title = programme.getTitle();
String start = programme.getStart();
String stop = programme.getStop();
Date startDate = parseDateTime(start);
Date endDate = parseDateTime(stop);
EpgData epgData = new EpgData();
epgData.setStart(formatTime.format(startDate));
epgData.setEnd(formatTime.format(endDate));
epgData.setStartTime(startDate.getTime());
epgData.setEndTime(endDate.getTime());
epgData.setTitle(Trans.s2t(title));
epgMap.get(key).getList().add(epgData);
}
for (Group group : live.getGroups()) {
for (Channel channel : group.getChannel()) {
channel.setData(epgMap.get(channel.getTvgName()));
}
}
}
}

@ -28,6 +28,8 @@ public class LiveParser {
private static final Pattern CATCHUP = Pattern.compile(".*catchup=\"(.?|.+?)\".*");
private static final Pattern TVG_NAME = Pattern.compile(".*tvg-name=\"(.?|.+?)\".*");
private static final Pattern TVG_LOGO = Pattern.compile(".*tvg-logo=\"(.?|.+?)\".*");
private static final Pattern TVG_URL = Pattern.compile(".*x-tvg-url=\"(.?|.+?)\".*");
private static final Pattern GROUP = Pattern.compile(".*group-title=\"(.?|.+?)\".*");
private static final Pattern NAME = Pattern.compile(".*,(.+?)$");
@ -78,6 +80,7 @@ public class LiveParser {
} else if (line.startsWith("#EXTM3U")) {
catchup.setType(extract(line, CATCHUP));
catchup.setSource(extract(line, CATCHUP_SOURCE));
if (live.getEpg().isEmpty()) live.setEpg(extract(line, TVG_URL));
} else if (line.startsWith("#EXTINF:")) {
Group group = live.find(Group.create(extract(line, GROUP), live.isPass()));
channel = group.find(Channel.create(extract(line, NAME)));

@ -1,7 +1,11 @@
package com.fongmi.android.tv.api.config;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
@ -10,15 +14,17 @@ import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.impl.Callback;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.Notify;
import com.fongmi.android.tv.utils.ResUtil;
import com.github.catvod.net.OkHttp;
import com.github.catvod.utils.Asset;
import com.github.catvod.utils.Path;
import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
public class WallConfig {
private Drawable drawable;
private Config config;
private boolean sync;
@ -38,6 +44,12 @@ public class WallConfig {
return get().getConfig().getDesc();
}
public static Drawable drawable(File file) {
if (get().drawable != null) return get().drawable;
get().setDrawable(Drawable.createFromPath(file.getAbsolutePath()));
return get().drawable;
}
public static void load(Config config, Callback callback) {
get().clear().config(config).load(callback);
}
@ -62,6 +74,10 @@ public class WallConfig {
return config == null ? Config.wall() : config;
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
}
public void load(Callback callback) {
App.execute(() -> loadConfig(callback));
}
@ -80,12 +96,22 @@ public class WallConfig {
}
}
private File write(File file) throws IOException {
private File write(File file) throws Exception {
if (getUrl().startsWith("file")) Path.copy(Path.local(getUrl()), file);
else if (getUrl().startsWith("assets")) Path.copy(Asset.open(getUrl()), file);
else if (getUrl().startsWith("http")) Path.write(file, OkHttp.newCall(getUrl()).execute().body().bytes());
else file.delete();
return file;
return resize(file);
}
private File resize(File file) {
try {
Bitmap bitmap = Glide.with(App.get()).asBitmap().load(file).centerCrop().override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).submit().get();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));
bitmap.recycle();
return file;
} catch (Exception e) {
return file;
}
}
public boolean needSync(String url) {

@ -336,8 +336,8 @@ public class Channel {
if (!live.getCatchup().isEmpty() && getCatchup().isEmpty()) setCatchup(live.getCatchup());
if (live.getReferer().length() > 0 && getReferer().isEmpty()) setReferer(live.getReferer());
if (live.getPlayerType() != -1 && getPlayerType() == -1) setPlayerType(live.getPlayerType());
if (!getEpg().startsWith("http")) setEpg(live.getEpg().replace("{name}", getTvgName()).replace("{epg}", getEpg()));
if (!getLogo().startsWith("http")) setLogo(live.getLogo().replace("{name}", getTvgName()).replace("{logo}", getLogo()));
if (!getEpg().startsWith("http") && live.getEpg().contains("{")) setEpg(live.getEpg().replace("{name}", getTvgName()).replace("{epg}", getEpg()));
if (!getLogo().startsWith("http") && live.getLogo().contains("{")) setLogo(live.getLogo().replace("{name}", getTvgName()).replace("{logo}", getLogo()));
}
public void setLine(String line) {

@ -35,8 +35,16 @@ public class Epg {
}
}
public static Epg create(String key, String date) {
Epg item = new Epg();
item.setKey(key);
item.setDate(date);
item.setList(new ArrayList<>());
return item;
}
public String getKey() {
return key;
return TextUtils.isEmpty(key) ? "" : key;
}
public void setKey(String key) {
@ -47,6 +55,10 @@ public class Epg {
return TextUtils.isEmpty(date) ? "" : date;
}
public void setDate(String date) {
this.date = date;
}
public List<EpgData> getList() {
return list == null ? Collections.emptyList() : list;
}

@ -36,10 +36,18 @@ public class EpgData {
return TextUtils.isEmpty(start) ? "" : start;
}
public void setStart(String start) {
this.start = start;
}
public String getEnd() {
return TextUtils.isEmpty(end) ? "" : end;
}
public void setEnd(String end) {
this.end = end;
}
public boolean isSelected() {
return selected;
}

@ -184,6 +184,10 @@ public class Live {
return TextUtils.isEmpty(epg) ? "" : epg;
}
public void setEpg(String epg) {
this.epg = epg;
}
public String getUa() {
return TextUtils.isEmpty(ua) ? "" : ua;
}

@ -0,0 +1,90 @@
package com.fongmi.android.tv.bean;
import android.text.TextUtils;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.Collections;
import java.util.List;
@Root(name = "tv", strict = false)
public class Tv {
@ElementList(entry = "channel", inline = true)
private List<Channel> channel;
@ElementList(entry = "programme", inline = true)
private List<Programme> programme;
public List<Channel> getChannel() {
return channel == null ? Collections.emptyList() : channel;
}
public List<Programme> getProgramme() {
return programme == null ? Collections.emptyList() : programme;
}
@Root(name = "channel")
public static class Channel {
@Attribute(name = "id")
private String id;
@Element(name = "display-name")
private String displayName;
public String getId() {
return TextUtils.isEmpty(id) ? "" : id;
}
public String getDisplayName() {
return TextUtils.isEmpty(displayName) ? "" : displayName;
}
}
@Root(name = "programme")
public static class Programme {
@Attribute(name = "start")
private String start;
@Attribute(name = "stop")
private String stop;
@Attribute(name = "channel")
private String channel;
@Element(name = "title")
private String title;
@Element(name = "date", required = false)
private String date;
public String getStart() {
return TextUtils.isEmpty(start) ? "" : start;
}
public String getStop() {
return TextUtils.isEmpty(stop) ? "" : stop;
}
public String getChannel() {
return TextUtils.isEmpty(channel) ? "" : channel;
}
public String getTitle() {
return TextUtils.isEmpty(title) ? "" : title;
}
public String getDate() {
return TextUtils.isEmpty(date) ? "" : date;
}
public boolean equals(String date) {
return getDate().isEmpty() || getDate().equals(date);
}
}
}

@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.fongmi.android.tv.Constant;
import com.fongmi.android.tv.api.EpgParser;
import com.fongmi.android.tv.api.LiveParser;
import com.fongmi.android.tv.api.config.VodConfig;
import com.fongmi.android.tv.bean.Channel;
@ -53,6 +54,7 @@ public class LiveViewModel extends ViewModel {
execute(LIVE, () -> {
VodConfig.get().setRecent(item.getJar());
LiveParser.start(item);
EpgParser.start(item);
verify(item);
return item;
});
@ -62,7 +64,7 @@ public class LiveViewModel extends ViewModel {
String date = formatDate.format(new Date());
String url = item.getEpg().replace("{date}", date);
execute(EPG, () -> {
if (!item.getData().equal(date)) item.setData(Epg.objectFrom(OkHttp.string(url), item.getName(), formatTime));
if (!item.getData().equal(date)) item.setData(Epg.objectFrom(OkHttp.string(url), item.getTvgName(), formatTime));
return item.getData().selected();
});
}

@ -111,9 +111,9 @@ public class ParseJob implements ParseCallback {
private void jsonParse(Parse item, String webUrl, boolean error) throws Exception {
String body = OkHttp.newCall(item.getUrl() + webUrl, Headers.of(item.getHeaders())).execute().body().string();
JsonObject object = Json.parse(body).getAsJsonObject();
object = object.has("data") ? object.getAsJsonObject("data") : object;
boolean illegal = body.contains("不存在") || body.contains("已过期");
String url = illegal ? "" : Json.safeString(object, "url");
String url = Json.safeString(object, "url");
object = object.getAsJsonObject("data");
if (url.isEmpty()) url = Json.safeString(object, "url");
checkResult(getHeader(object), url, item.getName(), error);
}

@ -24,8 +24,10 @@ import master.flame.danmaku.danmaku.util.DanmakuUtils;
public class Parser extends BaseDanmakuParser {
private final Danmu danmu;
private BaseDanmaku item;
private float scaleX;
private float scaleY;
private int index;
public Parser(String path) {
this.danmu = Danmu.fromXml(getContent(path));
@ -43,9 +45,11 @@ public class Parser extends BaseDanmakuParser {
for (Danmu.Data data : danmu.getData()) {
String[] values = data.getParam().split(",");
if (values.length < 4) continue;
BaseDanmaku item = createDanmaku(values);
setText(item, data.getText());
result.addItem(item);
setParam(values);
setText(data.getText());
synchronized (result.obtainSynchronizer()) {
result.addItem(item);
}
}
return result;
}
@ -58,27 +62,27 @@ public class Parser extends BaseDanmakuParser {
return this;
}
private BaseDanmaku createDanmaku(String[] values) {
private void setParam(String[] values) {
int type = Integer.parseInt(values[1]);
long time = (long) (Float.parseFloat(values[0]) * 1000);
float size = Float.parseFloat(values[2]) * (mDispDensity - 0.6f);
int color = (int) ((0x00000000ff000000L | Long.parseLong(values[3])) & 0x00000000ffffffffL);
BaseDanmaku item = mContext.mDanmakuFactory.createDanmaku(type, mContext);
item = mContext.mDanmakuFactory.createDanmaku(type, mContext);
item.setTime(time);
item.setTimer(mTimer);
item.textSize = size;
item.textColor = color;
item.textShadowColor = color <= Color.BLACK ? Color.WHITE : Color.BLACK;
item.flags = mContext.mGlobalFlagValues;
return item;
}
private void setText(BaseDanmaku item, String text) {
private void setText(String text) {
item.index = index++;
DanmakuUtils.fillText(item, decodeXmlString(text));
if (item.getType() == BaseDanmaku.TYPE_SPECIAL && text.startsWith("[") && text.endsWith("]")) setSpecial(item);
if (item.getType() == BaseDanmaku.TYPE_SPECIAL && text.startsWith("[") && text.endsWith("]")) setSpecial();
}
private void setSpecial(BaseDanmaku item) {
private void setSpecial() {
String[] textArr = null;
try {
JSONArray jsonArray = new JSONArray(item.text);

@ -128,10 +128,10 @@ public class CollectActivity extends BaseActivity implements CustomScroller.Call
mBinding.recycler.setHasFixedSize(true);
mBinding.recycler.addOnScrollListener(mScroller);
mBinding.recycler.setAdapter(mSearchAdapter = new SearchAdapter(this));
mBinding.wordRecycler.setHasFixedSize(true);
mBinding.wordRecycler.setHasFixedSize(false);
mBinding.wordRecycler.setAdapter(mWordAdapter = new WordAdapter(this));
mBinding.wordRecycler.setLayoutManager(new FlexboxLayoutManager(this, FlexDirection.ROW));
mBinding.recordRecycler.setHasFixedSize(true);
mBinding.recordRecycler.setHasFixedSize(false);
mBinding.recordRecycler.setAdapter(mRecordAdapter = new RecordAdapter(this));
mBinding.recordRecycler.setLayoutManager(new FlexboxLayoutManager(this, FlexDirection.ROW));
}

@ -493,8 +493,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
hideEpg();
}
@Override
public void showEpg(Channel item) {
private void showEpg(Channel item) {
if (mChannel == null || mChannel.getData().getList().isEmpty() || mEpgDataAdapter.getItemCount() == 0 || !mChannel.equals(item)) return;
mBinding.widget.epgData.scrollToPosition(item.getData().getSelected());
mBinding.widget.epg.setVisibility(View.VISIBLE);
@ -638,14 +637,18 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
@Override
public void onItemClick(Channel item) {
mGroup.setPosition(mChannelAdapter.setSelected(item.group(mGroup)));
mPlayers.setPlayer(getPlayerType(item.getPlayerType()));
setArtwork(item.getLogo());
mChannel = item;
setPlayerView();
showInfo();
hideUI();
fetch();
if (item.getData().getList().size() > 0 && item.isSelected() && mChannel != null) {
showEpg(item);
} else {
mGroup.setPosition(mChannelAdapter.setSelected(item.group(mGroup)));
mPlayers.setPlayer(getPlayerType(item.getPlayerType()));
setArtwork(item.getLogo());
mChannel = item;
setPlayerView();
showInfo();
hideUI();
fetch();
}
}
@Override
@ -711,7 +714,7 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
}
private void setEpg(Epg epg) {
if (mChannel != null && mChannel.getName().equals(epg.getKey())) setEpg();
if (mChannel != null && mChannel.getTvgName().equals(epg.getKey())) setEpg();
}
private void fetch() {
@ -843,7 +846,11 @@ public class LiveActivity extends BaseActivity implements Clock.Callback, Custom
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title);
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist);
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
try {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
} catch (Exception e) {
e.printStackTrace();
}
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration());
mPlayers.setMetadata(builder.build());
ActionEvent.update();

@ -1322,7 +1322,11 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title);
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist);
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
try {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, getIjk().getDefaultArtwork());
} catch (Exception e) {
e.printStackTrace();
}
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, mPlayers.getDuration());
mPlayers.setMetadata(builder.build());
ActionEvent.update();

@ -25,8 +25,6 @@ public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.ViewHold
public interface OnClickListener {
void showEpg(Channel item);
void onItemClick(Channel item);
boolean onLongClick(Channel item);
@ -86,7 +84,6 @@ public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.ViewHold
holder.binding.name.setText(item.getName());
holder.binding.number.setText(item.getNumber());
holder.binding.getRoot().setSelected(item.isSelected());
holder.binding.epg.setOnClickListener(view -> mListener.showEpg(item));
holder.binding.getRoot().setOnClickListener(view -> mListener.onItemClick(item));
holder.binding.getRoot().setOnLongClickListener(view -> mListener.onLongClick(item));
holder.binding.epg.setVisibility(item.getData().getList().isEmpty() || !item.isSelected() ? View.GONE : View.VISIBLE);

@ -1,9 +1,7 @@
package com.fongmi.android.tv.ui.base;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.DisplayCutout;
@ -12,19 +10,12 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewbinding.ViewBinding;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey;
import com.fongmi.android.tv.App;
import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.api.config.WallConfig;
import com.fongmi.android.tv.event.RefreshEvent;
import com.fongmi.android.tv.utils.FileUtil;
import com.fongmi.android.tv.utils.ResUtil;
@ -129,40 +120,18 @@ public abstract class BaseActivity extends AppCompatActivity {
try {
if (!customWall()) return;
File file = FileUtil.getWall(Setting.getWall());
if (file.exists() && file.length() > 0) loadWall(file);
if (file.exists() && file.length() > 0) getWindow().setBackgroundDrawable(WallConfig.drawable(file));
else getWindow().setBackgroundDrawableResource(ResUtil.getDrawable(file.getName()));
} catch (Exception e) {
getWindow().setBackgroundDrawableResource(R.drawable.wallpaper_1);
}
}
private void loadWall(File file) {
Glide.with(App.get()).load(file).centerCrop().signature(new ObjectKey(file.lastModified())).apply(new RequestOptions().override(ResUtil.getScreenWidth(), ResUtil.getScreenHeight())).into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable drawable, @Nullable Transition<? super Drawable> transition) {
getWindow().setBackgroundDrawable(drawable);
}
@Override
public void onLoadFailed(@Nullable Drawable error) {
getWindow().setBackgroundDrawableResource(R.drawable.wallpaper_1);
}
@Override
public void onLoadCleared(@Nullable Drawable drawable) {
}
});
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
if (getRequestedOrientation() != newConfig.orientation) refreshWall();
super.onConfigurationChanged(newConfig);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRefreshEvent(RefreshEvent event) {
if (event.getType() == RefreshEvent.Type.WALL) refreshWall();
if (event.getType() != RefreshEvent.Type.WALL) return;
WallConfig.get().setDrawable(null);
refreshWall();
}
@Override

@ -50,64 +50,72 @@
</LinearLayout>
<LinearLayout
<androidx.core.widget.NestedScrollView
android:id="@+id/agent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fillViewport="true"
tools:visibility="gone">
<TextView
android:id="@+id/record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/search_record"
android:textColor="@color/white"
android:textSize="18sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recordRecycler"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingBottom="8dp"
tools:itemCount="5"
tools:listitem="@layout/adapter_collect_record" />
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/word"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/search_hot"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/search_record"
android:textColor="@color/white"
android:textSize="18sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/wordRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingBottom="8dp"
tools:itemCount="5"
tools:listitem="@layout/adapter_collect_word" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recordRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingBottom="8dp"
tools:itemCount="5"
tools:listitem="@layout/adapter_collect_record" />
</LinearLayout>
<TextView
android:id="@+id/word"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/search_hot"
android:textColor="@color/white"
android:textSize="18sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/wordRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingBottom="8dp"
tools:itemCount="5"
tools:listitem="@layout/adapter_collect_word" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<RelativeLayout
android:id="@+id/result"

Loading…
Cancel
Save