From 03233562cf7242e6ceacda9f74ec7db0a0649d22 Mon Sep 17 00:00:00 2001 From: FongMi Date: Sun, 30 Jun 2024 13:31:17 +0800 Subject: [PATCH] Update gradle --- .gitignore | 9 +- app/build.gradle | 32 ++- .../com/fongmi/android/tv/api/Decoder.java | 6 +- .../com/fongmi/android/tv/utils/UrlUtil.java | 5 + build.gradle | 5 +- catvod/build.gradle | 9 +- .../java/com/github/catvod/utils/UriUtil.java | 231 ++++++++++++++++++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- ijkplayer/build.gradle | 3 +- .../com/fongmi/quickjs/crawler/Spider.java | 3 +- .../com/fongmi/quickjs/method/Global.java | 2 +- .../java/com/fongmi/quickjs/utils/Parser.java | 3 +- settings.gradle | 3 - 14 files changed, 279 insertions(+), 36 deletions(-) create mode 100644 catvod/src/main/java/com/github/catvod/utils/UriUtil.java diff --git a/.gitignore b/.gitignore index 29a48243c..79a68503c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ -.gradle .idea -*build +.gradle *.jks -/local.properties +*.aar +*build /media* -/Release \ No newline at end of file +/Release +/local.properties \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b14a8125c..75269c19f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -98,17 +98,7 @@ dependencies { implementation project(':jianpian') implementation project(':forcetech') pythonImplementation project(':chaquo') - implementation project(':media-lib-datasource-okhttp') - implementation project(':media-lib-datasource-rtmp') - implementation project(':media-lib-decoder-ffmpeg') - implementation project(':media-lib-decoder-av1') - implementation project(':media-lib-exoplayer') - implementation project(':media-lib-exoplayer-dash') - implementation project(':media-lib-exoplayer-hls') - implementation project(':media-lib-exoplayer-rtsp') - implementation project(':media-lib-exoplayer-smoothstreaming') - implementation project(':media-lib-ui') - implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.media:media:1.7.0' implementation 'androidx.room:room-runtime:2.6.1' implementation 'cat.ereza:customactivityoncrash:2.4.0' @@ -134,10 +124,26 @@ dependencies { implementation 'org.greenrobot:eventbus:3.3.1' implementation('org.simpleframework:simple-xml:2.7.1') { exclude group: 'stax', module: 'stax-api' exclude group: 'xpp3', module: 'xpp3' } implementation(ext: 'aar', name: 'dlna-core', group: 'fongmi', version: 'release') - leanbackImplementation(ext: 'aar', name: 'dlna-dmr', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'dlna-dmc', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'dlna-dmr', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-common-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-container-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-database-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-datasource-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-datasource-okhttp-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-datasource-rtmp-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-decoder-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-decoder-av1-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-decoder-ffmpeg-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-exoplayer-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-exoplayer-dash-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-exoplayer-hls-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-exoplayer-rtsp-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-exoplayer-smoothstreaming-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-extractor-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-ui-release', group: 'fongmi', version: 'release') leanbackImplementation 'androidx.leanback:leanback:1.2.0-alpha04' leanbackImplementation 'me.jessyan:autosize:1.2.1' - mobileImplementation(ext: 'aar', name: 'dlna-dmc', group: 'fongmi', version: 'release') mobileImplementation 'androidx.biometric:biometric:1.1.0' mobileImplementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' mobileImplementation 'com.google.android.flexbox:flexbox:3.0.0' diff --git a/app/src/main/java/com/fongmi/android/tv/api/Decoder.java b/app/src/main/java/com/fongmi/android/tv/api/Decoder.java index 42e4f8951..08ae18c00 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/Decoder.java +++ b/app/src/main/java/com/fongmi/android/tv/api/Decoder.java @@ -2,8 +2,6 @@ package com.fongmi.android.tv.api; import android.util.Base64; -import androidx.media3.common.util.UriUtil; - import com.fongmi.android.tv.utils.UrlUtil; import com.github.catvod.net.OkHttp; import com.github.catvod.utils.Asset; @@ -36,8 +34,8 @@ public class Decoder { private static String fix(String url, String data) { if (url.startsWith("file") || url.startsWith("assets")) url = UrlUtil.convert(url); - if (data.contains("../")) data = data.replace("../", UriUtil.resolve(url, "../")); - if (data.contains("./")) data = data.replace("./", UriUtil.resolve(url, "./")); + if (data.contains("../")) data = data.replace("../", UrlUtil.resolve(url, "../")); + if (data.contains("./")) data = data.replace("./", UrlUtil.resolve(url, "./")); return data; } diff --git a/app/src/main/java/com/fongmi/android/tv/utils/UrlUtil.java b/app/src/main/java/com/fongmi/android/tv/utils/UrlUtil.java index 084f3978e..75a351f42 100644 --- a/app/src/main/java/com/fongmi/android/tv/utils/UrlUtil.java +++ b/app/src/main/java/com/fongmi/android/tv/utils/UrlUtil.java @@ -3,6 +3,7 @@ package com.fongmi.android.tv.utils; import android.net.Uri; import com.fongmi.android.tv.server.Server; +import com.github.catvod.utils.UriUtil; import com.google.common.net.HttpHeaders; public class UrlUtil { @@ -34,6 +35,10 @@ public class UrlUtil { return path == null ? "" : path.trim(); } + public static String resolve(String baseUri, String referenceUri) { + return UriUtil.resolve(baseUri, referenceUri); + } + public static String convert(String url) { String scheme = scheme(url); if ("local".equals(scheme)) return url.replace("local://", Server.get().getAddress("")); diff --git a/build.gradle b/build.gradle index 793442f38..1c8029dfb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,6 @@ plugins { - id 'org.jetbrains.kotlin.android' version '1.9.0' apply false - id 'com.android.application' version '8.0.1' apply false - id 'com.android.library' version '8.0.1' apply false + id 'com.android.application' version '8.5.0' apply false + id 'com.android.library' version '8.5.0' apply false id 'com.chaquo.python' version '14.0.2' apply false } diff --git a/catvod/build.gradle b/catvod/build.gradle index 844c566dc..87d1a51fd 100644 --- a/catvod/build.gradle +++ b/catvod/build.gradle @@ -14,7 +14,6 @@ android { } dependencies { - api project(':media-lib-common') api 'androidx.annotation:annotation:' + annotationVersion api 'androidx.preference:preference:1.2.1' api 'com.google.code.gson:gson:' + gsonVersion @@ -24,4 +23,12 @@ dependencies { api 'com.squareup.okhttp3:okhttp:' + okhttpVersion api 'com.squareup.okhttp3:okhttp-dnsoverhttps:' + okhttpVersion api 'com.squareup.okhttp3:logging-interceptor:' + okhttpVersion + api('com.google.guava:guava:33.2.1-android') { + exclude group: 'com.google.code.findbugs', module: 'jsr305' + exclude group: 'org.checkerframework', module: 'checker-compat-qual' + exclude group: 'org.checkerframework', module: 'checker-qual' + exclude group: 'com.google.errorprone', module: 'error_prone_annotations' + exclude group: 'com.google.j2objc', module: 'j2objc-annotations' + exclude group: 'org.codehaus.mojo', module: 'animal-sniffer-annotations' + } } \ No newline at end of file diff --git a/catvod/src/main/java/com/github/catvod/utils/UriUtil.java b/catvod/src/main/java/com/github/catvod/utils/UriUtil.java new file mode 100644 index 000000000..0b07bf974 --- /dev/null +++ b/catvod/src/main/java/com/github/catvod/utils/UriUtil.java @@ -0,0 +1,231 @@ +package com.github.catvod.utils; + +import android.text.TextUtils; + +import androidx.annotation.Nullable; + +/** + * Utility methods for manipulating URIs. + */ +public final class UriUtil { + + /** + * The length of arrays returned by {@link #getUriIndices(String)}. + */ + private static final int INDEX_COUNT = 4; + + /** + * An index into an array returned by {@link #getUriIndices(String)}. + * + *

The value at this position in the array is the index of the ':' after the scheme. Equals -1 + * if the URI is a relative reference (no scheme). The hier-part starts at (schemeColon + 1), + * including when the URI has no scheme. + */ + private static final int SCHEME_COLON = 0; + + /** + * An index into an array returned by {@link #getUriIndices(String)}. + * + *

The value at this position in the array is the index of the path part. Equals (schemeColon + + * 1) if no authority part, (schemeColon + 3) if the authority part consists of just "//", and + * (query) if no path part. The characters starting at this index can be "//" only if the + * authority part is non-empty (in this case the double-slash means the first segment is empty). + */ + private static final int PATH = 1; + + /** + * An index into an array returned by {@link #getUriIndices(String)}. + * + *

The value at this position in the array is the index of the query part, including the '?' + * before the query. Equals fragment if no query part, and (fragment - 1) if the query part is a + * single '?' with no data. + */ + private static final int QUERY = 2; + + /** + * An index into an array returned by {@link #getUriIndices(String)}. + * + *

The value at this position in the array is the index of the fragment part, including the '#' + * before the fragment. Equal to the length of the URI if no fragment part, and (length - 1) if + * the fragment part is a single '#' with no data. + */ + private static final int FRAGMENT = 3; + + /** + * Performs relative resolution of a {@code referenceUri} with respect to a {@code baseUri}. + * + *

The resolution is performed as specified by RFC-3986. + * + * @param baseUri The base URI. + * @param referenceUri The reference URI to resolve. + */ + public static String resolve(@Nullable String baseUri, @Nullable String referenceUri) { + StringBuilder uri = new StringBuilder(); + + // Map null onto empty string, to make the following logic simpler. + baseUri = baseUri == null ? "" : baseUri; + referenceUri = referenceUri == null ? "" : referenceUri; + + int[] refIndices = getUriIndices(referenceUri); + if (refIndices[SCHEME_COLON] != -1) { + // The reference is absolute. The target Uri is the reference. + uri.append(referenceUri); + removeDotSegments(uri, refIndices[PATH], refIndices[QUERY]); + return uri.toString(); + } + + int[] baseIndices = getUriIndices(baseUri); + if (refIndices[FRAGMENT] == 0) { + // The reference is empty or contains just the fragment part, then the target Uri is the + // concatenation of the base Uri without its fragment, and the reference. + return uri.append(baseUri, 0, baseIndices[FRAGMENT]).append(referenceUri).toString(); + } + + if (refIndices[QUERY] == 0) { + // The reference starts with the query part. The target is the base up to (but excluding) the + // query, plus the reference. + return uri.append(baseUri, 0, baseIndices[QUERY]).append(referenceUri).toString(); + } + + if (refIndices[PATH] != 0) { + // The reference has authority. The target is the base scheme plus the reference. + int baseLimit = baseIndices[SCHEME_COLON] + 1; + uri.append(baseUri, 0, baseLimit).append(referenceUri); + return removeDotSegments(uri, baseLimit + refIndices[PATH], baseLimit + refIndices[QUERY]); + } + + if (referenceUri.charAt(refIndices[PATH]) == '/') { + // The reference path is rooted. The target is the base scheme and authority (if any), plus + // the reference. + uri.append(baseUri, 0, baseIndices[PATH]).append(referenceUri); + return removeDotSegments(uri, baseIndices[PATH], baseIndices[PATH] + refIndices[QUERY]); + } + + // The target Uri is the concatenation of the base Uri up to (but excluding) the last segment, + // and the reference. This can be split into 2 cases: + if (baseIndices[SCHEME_COLON] + 2 < baseIndices[PATH] && baseIndices[PATH] == baseIndices[QUERY]) { + // Case 1: The base hier-part is just the authority, with an empty path. An additional '/' is + // needed after the authority, before appending the reference. + uri.append(baseUri, 0, baseIndices[PATH]).append('/').append(referenceUri); + return removeDotSegments(uri, baseIndices[PATH], baseIndices[PATH] + refIndices[QUERY] + 1); + } else { + // Case 2: Otherwise, find the last '/' in the base hier-part and append the reference after + // it. If base hier-part has no '/', it could only mean that it is completely empty or + // contains only one segment, in which case the whole hier-part is excluded and the reference + // is appended right after the base scheme colon without an added '/'. + int lastSlashIndex = baseUri.lastIndexOf('/', baseIndices[QUERY] - 1); + int baseLimit = lastSlashIndex == -1 ? baseIndices[PATH] : lastSlashIndex + 1; + uri.append(baseUri, 0, baseLimit).append(referenceUri); + return removeDotSegments(uri, baseIndices[PATH], baseLimit + refIndices[QUERY]); + } + } + + /** + * Removes dot segments from the path of a URI. + * + * @param uri A {@link StringBuilder} containing the URI. + * @param offset The index of the start of the path in {@code uri}. + * @param limit The limit (exclusive) of the path in {@code uri}. + */ + private static String removeDotSegments(StringBuilder uri, int offset, int limit) { + if (offset >= limit) { + // Nothing to do. + return uri.toString(); + } + if (uri.charAt(offset) == '/') { + // If the path starts with a /, always retain it. + offset++; + } + // The first character of the current path segment. + int segmentStart = offset; + int i = offset; + while (i <= limit) { + int nextSegmentStart; + if (i == limit) { + nextSegmentStart = i; + } else if (uri.charAt(i) == '/') { + nextSegmentStart = i + 1; + } else { + i++; + continue; + } + // We've encountered the end of a segment or the end of the path. If the final segment was + // "." or "..", remove the appropriate segments of the path. + if (i == segmentStart + 1 && uri.charAt(segmentStart) == '.') { + // Given "abc/def/./ghi", remove "./" to get "abc/def/ghi". + uri.delete(segmentStart, nextSegmentStart); + limit -= nextSegmentStart - segmentStart; + i = segmentStart; + } else if (i == segmentStart + 2 && uri.charAt(segmentStart) == '.' && uri.charAt(segmentStart + 1) == '.') { + // Given "abc/def/../ghi", remove "def/../" to get "abc/ghi". + int prevSegmentStart = uri.lastIndexOf("/", segmentStart - 2) + 1; + int removeFrom = prevSegmentStart > offset ? prevSegmentStart : offset; + uri.delete(removeFrom, nextSegmentStart); + limit -= nextSegmentStart - removeFrom; + segmentStart = prevSegmentStart; + i = prevSegmentStart; + } else { + i++; + segmentStart = i; + } + } + return uri.toString(); + } + + /** + * Calculates indices of the constituent components of a URI. + * + * @param uriString The URI as a string. + * @return The corresponding indices. + */ + private static int[] getUriIndices(String uriString) { + int[] indices = new int[INDEX_COUNT]; + if (TextUtils.isEmpty(uriString)) { + indices[SCHEME_COLON] = -1; + return indices; + } + + // Determine outer structure from right to left. + // Uri = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + int length = uriString.length(); + int fragmentIndex = uriString.indexOf('#'); + if (fragmentIndex == -1) { + fragmentIndex = length; + } + int queryIndex = uriString.indexOf('?'); + if (queryIndex == -1 || queryIndex > fragmentIndex) { + // '#' before '?': '?' is within the fragment. + queryIndex = fragmentIndex; + } + // Slashes are allowed only in hier-part so any colon after the first slash is part of the + // hier-part, not the scheme colon separator. + int schemeIndexLimit = uriString.indexOf('/'); + if (schemeIndexLimit == -1 || schemeIndexLimit > queryIndex) { + schemeIndexLimit = queryIndex; + } + int schemeIndex = uriString.indexOf(':'); + if (schemeIndex > schemeIndexLimit) { + // '/' before ':' + schemeIndex = -1; + } + + // Determine hier-part structure: hier-part = "//" authority path / path + // This block can also cope with schemeIndex == -1. + boolean hasAuthority = schemeIndex + 2 < queryIndex && uriString.charAt(schemeIndex + 1) == '/' && uriString.charAt(schemeIndex + 2) == '/'; + int pathIndex; + if (hasAuthority) { + pathIndex = uriString.indexOf('/', schemeIndex + 3); // find first '/' after "://" + if (pathIndex == -1 || pathIndex > queryIndex) { + pathIndex = queryIndex; + } + } else { + pathIndex = schemeIndex + 1; + } + + indices[SCHEME_COLON] = schemeIndex; + indices[PATH] = pathIndex; + indices[QUERY] = queryIndex; + indices[FRAGMENT] = fragmentIndex; + return indices; + } +} diff --git a/gradle.properties b/gradle.properties index 49ee7fd76..641d729b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,5 +20,5 @@ android.enableJetifier=true # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.useFullClasspathForDexingTransform=true -android.nonTransitiveRClass=true +android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f99022d23..3cd67b81e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Mar 29 12:54:35 CST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/ijkplayer/build.gradle b/ijkplayer/build.gradle index 9124b4210..3e4a29dd2 100644 --- a/ijkplayer/build.gradle +++ b/ijkplayer/build.gradle @@ -19,5 +19,6 @@ android { dependencies { implementation project(':catvod') - implementation project(':media-lib-ui') + implementation(ext: 'aar', name: 'lib-ui-release', group: 'fongmi', version: 'release') + implementation(ext: 'aar', name: 'lib-common-release', group: 'fongmi', version: 'release') } \ No newline at end of file diff --git a/quickjs/src/main/java/com/fongmi/quickjs/crawler/Spider.java b/quickjs/src/main/java/com/fongmi/quickjs/crawler/Spider.java index 4a20fdcfc..6002b758e 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/crawler/Spider.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/crawler/Spider.java @@ -2,8 +2,6 @@ package com.fongmi.quickjs.crawler; import android.content.Context; -import androidx.media3.common.util.UriUtil; - import com.fongmi.quickjs.bean.Res; import com.fongmi.quickjs.method.Async; import com.fongmi.quickjs.method.Console; @@ -13,6 +11,7 @@ import com.fongmi.quickjs.utils.JSUtil; import com.fongmi.quickjs.utils.Module; import com.github.catvod.utils.Asset; import com.github.catvod.utils.Json; +import com.github.catvod.utils.UriUtil; import com.github.catvod.utils.Util; import com.whl.quickjs.wrapper.JSArray; import com.whl.quickjs.wrapper.JSMethod; diff --git a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java index b39d47f31..512b455d7 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/method/Global.java @@ -2,7 +2,6 @@ package com.fongmi.quickjs.method; import androidx.annotation.Keep; import androidx.annotation.NonNull; -import androidx.media3.common.util.UriUtil; import com.fongmi.quickjs.bean.Req; import com.fongmi.quickjs.utils.Connect; @@ -11,6 +10,7 @@ import com.fongmi.quickjs.utils.JSUtil; import com.fongmi.quickjs.utils.Parser; import com.github.catvod.Proxy; import com.github.catvod.utils.Trans; +import com.github.catvod.utils.UriUtil; import com.orhanobut.logger.Logger; import com.whl.quickjs.wrapper.JSArray; import com.whl.quickjs.wrapper.JSFunction; diff --git a/quickjs/src/main/java/com/fongmi/quickjs/utils/Parser.java b/quickjs/src/main/java/com/fongmi/quickjs/utils/Parser.java index 1aece436d..4df4b1444 100644 --- a/quickjs/src/main/java/com/fongmi/quickjs/utils/Parser.java +++ b/quickjs/src/main/java/com/fongmi/quickjs/utils/Parser.java @@ -2,10 +2,9 @@ package com.fongmi.quickjs.utils; import android.text.TextUtils; -import androidx.media3.common.util.UriUtil; - import com.fongmi.quickjs.bean.Cache; import com.fongmi.quickjs.bean.Info; +import com.github.catvod.utils.UriUtil; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; diff --git a/settings.gradle b/settings.gradle index a2b4fa007..a1705bf40 100644 --- a/settings.gradle +++ b/settings.gradle @@ -30,7 +30,4 @@ include ':thunder' include ':youtube' include ':jianpian' include ':forcetech' -include ':ijkplayer' rootProject.name = "TV" -gradle.ext.androidxMediaModulePrefix = 'media-' -apply from: file("/media/core_settings.gradle")