diff --git a/app/build.gradle b/app/build.gradle index 17ba180b6..40947b2b9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { //noinspection ExpiredTargetSdkVersion targetSdk 28 versionCode 265 - versionName "1208" + versionName "1208v2" javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java index 0ae0c78eb..f6846e059 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java +++ b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java @@ -53,9 +53,8 @@ public class LiveParser { public static void text(Live live, String text) { int number = 0; if (!live.getGroups().isEmpty()) return; - if (M3U.matcher(text).find()) m3u(live, text); - else if (live.isXtream()) xtream(live); - else txt(live, text); + if (M3U.matcher(text).find()) m3u(live, text); else txt(live, text); + if (live.isXtream()) xtream(live); for (Group group : live.getGroups()) { for (Channel channel : group.getChannel()) { channel.setNumber(++number); @@ -112,10 +111,11 @@ public class LiveParser { private static void xtream(Live live) { XInfo info = XtreamParser.getInfo(live); - live.setTimeZone(info.getServerInfo().getTimezone()); - List streamList = XtreamParser.getStreamList(live); + if (live.getEpg().isEmpty()) live.setEpg(XtreamParser.getEpgUrl(live)); + if (live.getTimeZone().isEmpty()) live.setTimeZone(info.getServerInfo().getTimezone()); + if (!live.getGroups().isEmpty()) return; List categoryList = XtreamParser.getCategoryList(live); - List formats = info.getUserInfo().getAllowedOutputFormats(); + List streamList = XtreamParser.getStreamList(live); Map categoryMap = new HashMap<>(); for (XCategory category : categoryList) { categoryMap.put(category.getCategoryId(), category.getCategoryName()); @@ -126,8 +126,7 @@ public class LiveParser { Channel channel = group.find(Channel.create(stream.getName())); if (!stream.getStreamIcon().isEmpty()) channel.setLogo(stream.getStreamIcon()); if (!stream.getEpgChannelId().isEmpty()) channel.setTvgName(stream.getEpgChannelId()); - if (formats.isEmpty()) channel.getUrls().add(XtreamParser.getPlayUrl(live, stream.getStreamId(), "ts")); - for (String format : formats) channel.getUrls().add(XtreamParser.getPlayUrl(live, stream.getStreamId(), format)); + channel.getUrls().addAll(stream.getPlayUrl(live, info.getUserInfo().getAllowedOutputFormats())); } } @@ -151,7 +150,8 @@ public class LiveParser { } private static String getText(Live live) { - return XtreamParser.isApiUrl(live.getUrl()) ? "" : getText(live.getUrl(), live.getHeaders()).replace("\r\n", "\n"); + if (live.isXtream() && !XtreamParser.isGetUrl(live.getUrl())) return ""; + return getText(live.getUrl(), live.getHeaders()).replace("\r\n", "\n"); } private static String getText(String url, Map header) { diff --git a/app/src/main/java/com/fongmi/android/tv/api/XtreamParser.java b/app/src/main/java/com/fongmi/android/tv/api/XtreamParser.java index 0ca3de782..b4458896d 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/XtreamParser.java +++ b/app/src/main/java/com/fongmi/android/tv/api/XtreamParser.java @@ -31,6 +31,14 @@ public class XtreamParser { return uri.getPath() != null && uri.getQueryParameter("username") != null && uri.getQueryParameter("password") != null && uri.getPath().contains("player_api.php"); } + public static boolean isGetUrl(String url) { + return isGetUrl(Uri.parse(url)); + } + + public static boolean isGetUrl(Uri uri) { + return uri.getPath() != null && uri.getQueryParameter("username") != null && uri.getQueryParameter("password") != null && uri.getPath().contains("get.php"); + } + public static String getEpgUrl(Live live) { return getBuilder(live).addPathSegment("xmltv.php").addQueryParameter("username", live.getUsername()).addQueryParameter("password", live.getPassword()).build().toString(); } @@ -43,19 +51,35 @@ public class XtreamParser { return getBuilder(live).addPathSegment("player_api.php").addQueryParameter("username", live.getUsername()).addQueryParameter("password", live.getPassword()).addQueryParameter("action", action).build().toString(); } - public static String getPlayUrl(Live live, String id, String format) { - return getBuilder(live).addPathSegment("live").addPathSegment(live.getUsername()).addPathSegment(live.getPassword()).addPathSegment(id + "." + format + "$" + format.toUpperCase()).build().toString(); - } - public static XInfo getInfo(Live live) { return XInfo.objectFrom(OkHttp.string(getApiUrl(live))); } - public static List getCategoryList(Live live) { + public static List getLiveCategoryList(Live live) { return XCategory.arrayFrom(OkHttp.string(getApiUrl(live, "get_live_categories"))); } - public static List getStreamList(Live live) { + public static List getLiveStreamList(Live live) { return XStream.arrayFrom(OkHttp.string(getApiUrl(live, "get_live_streams"))); } + + public static List getVodCategoryList(Live live) { + return XCategory.arrayFrom(OkHttp.string(getApiUrl(live, "get_vod_categories"))); + } + + public static List getVodStreamList(Live live) { + return XStream.arrayFrom(OkHttp.string(getApiUrl(live, "get_vod_streams"))); + } + + public static List getCategoryList(Live live) { + List categoryList = XtreamParser.getLiveCategoryList(live); + categoryList.addAll(XtreamParser.getVodCategoryList(live)); + return categoryList; + } + + public static List getStreamList(Live live) { + List streamList = XtreamParser.getLiveStreamList(live); + streamList.addAll(XtreamParser.getVodStreamList(live)); + return streamList; + } } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Live.java b/app/src/main/java/com/fongmi/android/tv/bean/Live.java index 2541ac137..a4877ec40 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Live.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Live.java @@ -348,7 +348,6 @@ public class Live { boolean xtream = XtreamParser.isVerify(uri); if (xtream) setUsername(uri.getQueryParameter("username")); if (xtream) setPassword(uri.getQueryParameter("password")); - if (isXtream() && getEpg().isEmpty()) setEpg(XtreamParser.getEpgUrl(this)); return this; } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/XInfo.java b/app/src/main/java/com/fongmi/android/tv/bean/XInfo.java index 3c77ba1f9..968eb2497 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/XInfo.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/XInfo.java @@ -5,7 +5,7 @@ import android.text.TextUtils; import com.fongmi.android.tv.App; import com.google.gson.annotations.SerializedName; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; public class XInfo { @@ -34,8 +34,10 @@ public class XInfo { private List allowedOutputFormats; public List getAllowedOutputFormats() { - if (allowedOutputFormats != null) allowedOutputFormats.remove("rtmp"); - return allowedOutputFormats == null ? Collections.emptyList() : allowedOutputFormats; + if (allowedOutputFormats == null) allowedOutputFormats = new ArrayList<>(); + if (allowedOutputFormats.isEmpty()) allowedOutputFormats.add("ts"); + allowedOutputFormats.remove("rtmp"); + return allowedOutputFormats; } } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/XStream.java b/app/src/main/java/com/fongmi/android/tv/bean/XStream.java index 10c6e906a..d2e91fdcb 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/XStream.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/XStream.java @@ -3,10 +3,12 @@ package com.fongmi.android.tv.bean; import android.text.TextUtils; import com.fongmi.android.tv.App; +import com.fongmi.android.tv.api.XtreamParser; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -16,15 +18,20 @@ public class XStream { private String name; @SerializedName("stream_id") private String streamId; + @SerializedName("stream_type") + private String streamType; @SerializedName("stream_icon") private String streamIcon; @SerializedName("epg_channel_id") private String epgChannelId; @SerializedName("category_id") private String categoryId; + @SerializedName("container_extension") + private String containerExtension; public static List arrayFrom(String str) { - Type listType = new TypeToken>() {}.getType(); + Type listType = new TypeToken>() { + }.getType(); List items = App.gson().fromJson(str, listType); return items == null ? Collections.emptyList() : items; } @@ -37,6 +44,10 @@ public class XStream { return TextUtils.isEmpty(streamId) ? "" : streamId; } + public String getStreamType() { + return TextUtils.isEmpty(streamType) ? "" : streamType; + } + public String getStreamIcon() { return TextUtils.isEmpty(streamIcon) ? "" : streamIcon; } @@ -48,4 +59,15 @@ public class XStream { public String getCategoryId() { return TextUtils.isEmpty(categoryId) ? "" : categoryId; } + + public String getContainerExtension() { + return TextUtils.isEmpty(containerExtension) ? "" : containerExtension; + } + + public List getPlayUrl(Live live, List formats) { + List urls = new ArrayList<>(); + if (!getContainerExtension().isEmpty()) urls.add(XtreamParser.getBuilder(live).addPathSegment(getStreamType()).addPathSegment(live.getUsername()).addPathSegment(live.getPassword()).addPathSegment(getStreamId() + "." + getContainerExtension()).build().toString()); + else for (String format : formats) urls.add(XtreamParser.getBuilder(live).addPathSegment(getStreamType()).addPathSegment(live.getUsername()).addPathSegment(live.getPassword()).addPathSegment(getStreamId() + "." + format + "$" + format.toUpperCase()).build().toString()); + return urls; + } }