diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 14164b64fe..047baf8343 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -31,5 +31,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 470028385e..fbe5affca0 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,16 @@
-
+
+
+
+
+
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index e497da9998..0000000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 24f8eefd90..c8eca69732 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -68,6 +68,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
+ implementation files('libs\\thunder.jar')
annotationProcessor 'androidx.room:room-compiler:2.3.0'
implementation 'androidx.room:room-runtime:2.3.0'
@@ -85,15 +86,13 @@ dependencies {
implementation 'org.greenrobot:eventbus:3.2.0'
implementation 'com.orhanobut:hawk:2.0.1'
+ implementation project(":player")
+
implementation('org.xwalk:xwalk_shared_library:23.53.589.4') {
exclude group: 'com.android.support'
}
implementation 'com.lzy.net:okgo:3.0.4'
// implementation 'com.tencent.bugly:crashreport_upgrade:latest.release'
- implementation 'com.github.dueeeke.dkplayer:dkplayer-java:3.2.6'
- implementation 'com.github.dueeeke.dkplayer:dkplayer-ui:3.2.6'
- implementation 'com.github.dueeeke.dkplayer:player-exo:3.2.6'
- implementation 'com.github.dueeeke.dkplayer:player-ijk:3.2.6'
implementation 'com.owen:tv-recyclerview:3.0.0'
implementation 'com.github.getActivity:XXPermissions:13.6'
diff --git a/app/libs/thunder.jar b/app/libs/thunder.jar
new file mode 100644
index 0000000000..d5c06f797d
Binary files /dev/null and b/app/libs/thunder.jar differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index e355110255..1902c50053 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -90,6 +90,16 @@
public (android.content.Context, android.util.AttributeSet, int);
}
+-keep public class * extends androidx.recyclerview.widget.RecyclerView$LayoutManager{
+ *** get*();
+ void set*(***);
+ public (android.content.Context);
+ public (android.content.Context, android.util.AttributeSet);
+ public (android.content.Context, android.util.AttributeSet, int);
+}
+
+-keep class com.orhanobut.hawk.** { *; }
+
# 保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
diff --git a/app/schemas/com.github.tvbox.osc.data.AppDataBase/1.json b/app/schemas/com.github.tvbox.osc.data.AppDataBase/1.json
index 731560edb5..1c844a7aba 100644
--- a/app/schemas/com.github.tvbox.osc.data.AppDataBase/1.json
+++ b/app/schemas/com.github.tvbox.osc.data.AppDataBase/1.json
@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
- "identityHash": "7eeed1930e952258dac040695df9dd32",
+ "identityHash": "d1c2780b5424f0e960fe2364f63c86b8",
"entities": [
{
"tableName": "cache",
@@ -32,7 +32,7 @@
},
{
"tableName": "vodRecord",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `vodId` TEXT, `updateTime` INTEGER NOT NULL, `sourceKey` TEXT, `data` BLOB, `dataJson` TEXT, `testMigration` INTEGER NOT NULL)",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `vodId` TEXT, `updateTime` INTEGER NOT NULL, `sourceKey` TEXT, `dataJson` TEXT)",
"fields": [
{
"fieldPath": "id",
@@ -58,23 +58,11 @@
"affinity": "TEXT",
"notNull": false
},
- {
- "fieldPath": "data",
- "columnName": "data",
- "affinity": "BLOB",
- "notNull": false
- },
{
"fieldPath": "dataJson",
"columnName": "dataJson",
"affinity": "TEXT",
"notNull": false
- },
- {
- "fieldPath": "testMigration",
- "columnName": "testMigration",
- "affinity": "INTEGER",
- "notNull": true
}
],
"primaryKey": {
@@ -87,39 +75,51 @@
"foreignKeys": []
},
{
- "tableName": "sourceState",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceKey` TEXT NOT NULL, `home` INTEGER NOT NULL, `active` INTEGER NOT NULL, `tidSort` TEXT, PRIMARY KEY(`sourceKey`))",
+ "tableName": "vodCollect",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `vodId` TEXT, `updateTime` INTEGER NOT NULL, `sourceKey` TEXT, `name` TEXT, `pic` TEXT)",
"fields": [
{
- "fieldPath": "sourceKey",
- "columnName": "sourceKey",
- "affinity": "TEXT",
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
"notNull": true
},
{
- "fieldPath": "home",
- "columnName": "home",
- "affinity": "INTEGER",
- "notNull": true
+ "fieldPath": "vodId",
+ "columnName": "vodId",
+ "affinity": "TEXT",
+ "notNull": false
},
{
- "fieldPath": "active",
- "columnName": "active",
+ "fieldPath": "updateTime",
+ "columnName": "updateTime",
"affinity": "INTEGER",
"notNull": true
},
{
- "fieldPath": "tidSort",
- "columnName": "tidSort",
+ "fieldPath": "sourceKey",
+ "columnName": "sourceKey",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "pic",
+ "columnName": "pic",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
- "sourceKey"
+ "id"
],
- "autoGenerate": false
+ "autoGenerate": true
},
"indices": [],
"foreignKeys": []
@@ -128,7 +128,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7eeed1930e952258dac040695df9dd32')"
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd1c2780b5424f0e960fe2364f63c86b8')"
]
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 322280fe9f..93a0e81914 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,6 +14,7 @@
+
@@ -44,7 +46,7 @@
android:name=".ui.activity.PlayActivity"
android:screenOrientation="landscape" />
+
@@ -66,11 +71,6 @@
-
-
-
-
-
sourceBeanList;
+ private LinkedHashMap sourceBeanList;
private SourceBean mHomeSource;
private ParseBean mDefaultParse;
- private List channelList;
+ private List liveChannelGroupList;
private List parseBeanList;
private List vipParseFlags;
private List ijkCodes;
@@ -55,8 +62,8 @@ public class ApiConfig {
private ApiConfig() {
- sourceBeanList = new ArrayList<>();
- channelList = new ArrayList<>();
+ sourceBeanList = new LinkedHashMap<>();
+ liveChannelGroupList = new ArrayList<>();
parseBeanList = new ArrayList<>();
}
@@ -71,45 +78,22 @@ public static ApiConfig get() {
return instance;
}
- public void loadConfig(LoadConfigCallback callback, Activity activity) {
- /*boolean isSourceModeLocal = Hawk.get(HawkConfig.SOURCE_MODE_LOCAL, false);
- if (isSourceModeLocal) {
- loadConfigLocal(callback, activity);
- } else {
- loadConfigServer(callback, activity);
- }*/
- loadConfigServer(callback, activity);
- }
-
-
- public void loadJar(String spider, LoadConfigCallback callback) {
- OkGo.get(spider).execute(new AbsCallback() {
- @Override
- public byte[] convertResponse(okhttp3.Response response) {
- try {
- return response.body().bytes();
- } catch (Throwable th) {
- return null;
- }
- }
-
- @Override
- public void onFinish() {
- super.onFinish();
+ public void loadConfig(boolean useCache, LoadConfigCallback callback, Activity activity) {
+ String apiUrl = Hawk.get(HawkConfig.API_URL, "");
+ if (apiUrl.isEmpty()) {
+ callback.error("-1");
+ return;
+ }
+ File cache = new File(App.getInstance().getFilesDir().getAbsolutePath() + "/" + MD5.encode(apiUrl));
+ if (useCache && cache.exists()) {
+ try {
+ parseJson(apiUrl, cache);
callback.success();
+ return;
+ } catch (Throwable th) {
+ th.printStackTrace();
}
-
- @Override
- public void onSuccess(Response response) {
- if (response != null && response.body() != null) {
- jarLoader.load(response.body());
- }
- }
- });
- }
-
- private void loadConfigServer(LoadConfigCallback callback, Activity activity) {
- String apiUrl = Hawk.get(HawkConfig.API_URL, "");
+ }
String apiFix = apiUrl;
if (apiUrl.startsWith("clan://")) {
apiFix = clanToAddress(apiUrl);
@@ -119,7 +103,21 @@ private void loadConfigServer(LoadConfigCallback callback, Activity activity) {
@Override
public void onSuccess(Response response) {
try {
+ String json = response.body();
parseJson(apiUrl, response.body());
+ try {
+ File cacheDir = cache.getParentFile();
+ if (!cacheDir.exists())
+ cacheDir.mkdirs();
+ if (cache.exists())
+ cache.delete();
+ FileOutputStream fos = new FileOutputStream(cache);
+ fos.write(json.getBytes("UTF-8"));
+ fos.flush();
+ fos.close();
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
callback.success();
} catch (Throwable th) {
th.printStackTrace();
@@ -130,7 +128,16 @@ public void onSuccess(Response response) {
@Override
public void onError(Response response) {
super.onError(response);
- callback.error("拉取配置失败");
+ if (cache.exists()) {
+ try {
+ parseJson(apiUrl, cache);
+ callback.success();
+ return;
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
+ }
+ callback.error("拉取配置失败\n" + (response.getException() != null ? response.getException().getMessage() : ""));
}
public String convertResponse(okhttp3.Response response) throws Throwable {
@@ -148,38 +155,104 @@ public String convertResponse(okhttp3.Response response) throws Throwable {
});
}
+
+ public void loadJar(boolean useCache, String spider, LoadConfigCallback callback) {
+ String[] urls = spider.split(";md5;");
+ String jarUrl = urls[0];
+ String md5 = urls.length > 1 ? urls[1].trim() : "";
+ File cache = new File(App.getInstance().getFilesDir().getAbsolutePath() + "/csp.jar");
+
+ if (!md5.isEmpty() || useCache) {
+ if (cache.exists() && (useCache || MD5.getFileMd5(cache).equalsIgnoreCase(md5))) {
+ if (jarLoader.load(cache.getAbsolutePath())) {
+ callback.success();
+ } else {
+ callback.error("");
+ }
+ return;
+ }
+ }
+
+ OkGo.get(jarUrl).execute(new AbsCallback() {
+
+ @Override
+ public File convertResponse(okhttp3.Response response) throws Throwable {
+ File cacheDir = cache.getParentFile();
+ if (!cacheDir.exists())
+ cacheDir.mkdirs();
+ if (cache.exists())
+ cache.delete();
+ FileOutputStream fos = new FileOutputStream(cache);
+ fos.write(response.body().bytes());
+ fos.flush();
+ fos.close();
+ return cache;
+ }
+
+ @Override
+ public void onSuccess(Response response) {
+ if (response.body().exists()) {
+ if (jarLoader.load(response.body().getAbsolutePath())) {
+ callback.success();
+ } else {
+ callback.error("");
+ }
+ } else {
+ callback.error("");
+ }
+ }
+
+ @Override
+ public void onError(Response response) {
+ super.onError(response);
+ callback.error("");
+ }
+ });
+ }
+
+ private void parseJson(String apiUrl, File f) throws Throwable {
+ System.out.println("从本地缓存加载" + f.getAbsolutePath());
+ BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
+ StringBuilder sb = new StringBuilder();
+ String s = "";
+ while ((s = bReader.readLine()) != null) {
+ sb.append(s + "\n");
+ }
+ bReader.close();
+ parseJson(apiUrl, sb.toString());
+ }
+
private void parseJson(String apiUrl, String jsonStr) {
JsonObject infoJson = new Gson().fromJson(jsonStr, JsonObject.class);
// spider
spider = DefaultConfig.safeJsonString(infoJson, "spider", "");
- spider = spider.split(";md5;")[0];
// 远端站点源
+ SourceBean firstSite = null;
for (JsonElement opt : infoJson.get("sites").getAsJsonArray()) {
JsonObject obj = (JsonObject) opt;
SourceBean sb = new SourceBean();
- sb.setKey(obj.get("key").getAsString().trim());
+ String siteKey = obj.get("key").getAsString().trim();
+ sb.setKey(siteKey);
sb.setName(obj.get("name").getAsString().trim());
sb.setType(obj.get("type").getAsInt());
sb.setApi(obj.get("api").getAsString().trim());
sb.setSearchable(DefaultConfig.safeJsonInt(obj, "searchable", 1));
- sb.setSearchable(DefaultConfig.safeJsonInt(obj, "quickSearch", 1));
+ sb.setQuickSearch(DefaultConfig.safeJsonInt(obj, "quickSearch", 1));
sb.setFilterable(DefaultConfig.safeJsonInt(obj, "filterable", 1));
sb.setPlayerUrl(DefaultConfig.safeJsonString(obj, "playUrl", ""));
sb.setExt(DefaultConfig.safeJsonString(obj, "ext", ""));
- sourceBeanList.add(sb);
+ sb.setCategories(DefaultConfig.safeJsonStringList(obj, "categories"));
+ if (firstSite == null)
+ firstSite = sb;
+ sourceBeanList.put(siteKey, sb);
}
if (sourceBeanList != null && sourceBeanList.size() > 0) {
- // 获取启用状态
- HashMap sourceStates = RoomDataManger.getAllSourceState();
- for (SourceBean sb : sourceBeanList) {
- if (sourceStates.containsKey(sb.getKey()))
- sb.setState(sourceStates.get(sb.getKey()));
- if (sb.isHome())
- setSourceBean(sb);
- }
- // 如果没有home source 使用第一个
- if (mHomeSource == null)
- setSourceBean(sourceBeanList.get(0));
+ String home = Hawk.get(HawkConfig.HOME_API, "");
+ SourceBean sh = getSource(home);
+ if (sh == null)
+ setSourceBean(firstSite);
+ else
+ setSourceBean(sh);
}
// 需要使用vip解析的flag
vipParseFlags = DefaultConfig.safeJsonStringList(infoJson, "flags");
@@ -206,35 +279,30 @@ private void parseJson(String apiUrl, String jsonStr) {
setDefaultParse(parseBeanList.get(0));
}
// 直播源
+ liveChannelGroupList.clear(); //修复从后台切换重复加载频道列表
try {
- int lcIdx = 0;
- for (JsonElement opt : infoJson.get("lives").getAsJsonArray()) {
- for (JsonElement optChl : ((JsonObject) opt).get("channels").getAsJsonArray()) {
- JsonObject obj = (JsonObject) optChl;
- LiveChannel lc = new LiveChannel();
- lc.setName(obj.get("name").getAsString().trim());
- ArrayList urls = DefaultConfig.safeJsonStringList(obj, "urls");
- if (urls.size() > 0) {
- String url = urls.get(0);
- if (url.startsWith("proxy://")) {
- String fix = url.replace("proxy://", "http://0.0.0.0/?");
- String extUrl = Uri.parse(fix).getQueryParameter("ext");
- if (extUrl != null && !extUrl.isEmpty()) {
- String extUrlFix = new String(Base64.decode(extUrl, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8");
- if (extUrlFix.startsWith("clan://")) {
- extUrlFix = clanContentFix(clanToAddress(apiUrl), extUrlFix);
- extUrlFix = Base64.encodeToString(extUrlFix.getBytes("UTF-8"), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP);
- fix = url.replace(extUrl, extUrlFix);
- urls.set(0, fix);
- }
- }
- }
+ String lives = infoJson.get("lives").getAsJsonArray().toString();
+ int index = lives.indexOf("proxy://");
+ if (index != -1) {
+ int endIndex = lives.lastIndexOf("\"");
+ String url = lives.substring(index, endIndex);
+ url = DefaultConfig.checkReplaceProxy(url);
+
+ //clan
+ String extUrl = Uri.parse(url).getQueryParameter("ext");
+ if (extUrl != null && !extUrl.isEmpty()) {
+ String extUrlFix = new String(Base64.decode(extUrl, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), "UTF-8");
+ if (extUrlFix.startsWith("clan://")) {
+ extUrlFix = clanContentFix(clanToAddress(apiUrl), extUrlFix);
+ extUrlFix = Base64.encodeToString(extUrlFix.getBytes("UTF-8"), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP);
+ url = url.replace(extUrl, extUrlFix);
}
- lc.setUrls(urls);
- // 暂时不考虑分组问题
- lc.setChannelNum(lcIdx++);
- channelList.add(lc);
}
+ LiveChannelGroup liveChannelGroup = new LiveChannelGroup();
+ liveChannelGroup.setGroupName(url);
+ liveChannelGroupList.add(liveChannelGroup);
+ } else {
+ loadLives(infoJson.get("lives").getAsJsonArray());
}
} catch (Throwable th) {
th.printStackTrace();
@@ -274,12 +342,56 @@ private void parseJson(String apiUrl, String jsonStr) {
}
}
+ public void loadLives(JsonArray livesArray) {
+ liveChannelGroupList.clear();
+ int groupIndex = 0;
+ int channelIndex = 0;
+ int channelNum = 0;
+ for (JsonElement groupElement : livesArray) {
+ LiveChannelGroup liveChannelGroup = new LiveChannelGroup();
+ liveChannelGroup.setLiveChannels(new ArrayList());
+ liveChannelGroup.setGroupIndex(groupIndex++);
+ String groupName = ((JsonObject) groupElement).get("group").getAsString().trim();
+ String[] splitGroupName = groupName.split("_", 2);
+ liveChannelGroup.setGroupName(splitGroupName[0]);
+ if (splitGroupName.length > 1)
+ liveChannelGroup.setGroupPassword(splitGroupName[1]);
+ else
+ liveChannelGroup.setGroupPassword("");
+ channelIndex = 0;
+ for (JsonElement channelElement : ((JsonObject) groupElement).get("channels").getAsJsonArray()) {
+ JsonObject obj = (JsonObject) channelElement;
+ LiveChannelItem liveChannelItem = new LiveChannelItem();
+ liveChannelItem.setChannelName(obj.get("name").getAsString().trim());
+ liveChannelItem.setChannelIndex(channelIndex++);
+ liveChannelItem.setChannelNum(++channelNum);
+ ArrayList urls = DefaultConfig.safeJsonStringList(obj, "urls");
+ ArrayList sourceNames = new ArrayList<>();
+ ArrayList sourceUrls = new ArrayList<>();
+ int sourceIndex = 1;
+ for (String url : urls) {
+ String[] splitText = url.split("\\$", 2);
+ sourceUrls.add(splitText[0]);
+ if (splitText.length > 1)
+ sourceNames.add(splitText[1]);
+ else
+ sourceNames.add("源" + Integer.toString(sourceIndex));
+ sourceIndex++;
+ }
+ liveChannelItem.setChannelSourceNames(sourceNames);
+ liveChannelItem.setChannelUrls(sourceUrls);
+ liveChannelGroup.getLiveChannels().add(liveChannelItem);
+ }
+ liveChannelGroupList.add(liveChannelGroup);
+ }
+ }
+
public String getSpider() {
return spider;
}
public Spider getCSP(SourceBean sourceBean) {
- return jarLoader.getSpider(sourceBean.getApi(), sourceBean.getExt());
+ return jarLoader.getSpider(sourceBean.getKey(), sourceBean.getApi(), sourceBean.getExt());
}
public Object[] proxyLocal(Map param) {
@@ -309,18 +421,14 @@ public interface FastParseCallback {
}
public SourceBean getSource(String key) {
- for (SourceBean bean : sourceBeanList) {
- if (bean.getKey().equals(key))
- return bean;
- }
- return null;
+ if (!sourceBeanList.containsKey(key))
+ return null;
+ return sourceBeanList.get(key);
}
public void setSourceBean(SourceBean sourceBean) {
- if (this.mHomeSource != null)
- this.mHomeSource.setHome(false);
this.mHomeSource = sourceBean;
- sourceBean.setHome(true);
+ Hawk.put(HawkConfig.HOME_API, sourceBean.getKey());
}
public void setDefaultParse(ParseBean parseBean) {
@@ -336,7 +444,7 @@ public ParseBean getDefaultParse() {
}
public List getSourceBeanList() {
- return sourceBeanList;
+ return new ArrayList<>(sourceBeanList.values());
}
public List getParseBeanList() {
@@ -351,8 +459,8 @@ public SourceBean getHomeSourceBean() {
return mHomeSource == null ? emptyHome : mHomeSource;
}
- public List getChannelList() {
- return channelList;
+ public List getChannelGroupList() {
+ return liveChannelGroupList;
}
public List getIjkCodes() {
@@ -361,8 +469,12 @@ public List getIjkCodes() {
public IJKCode getCurrentIJKCode() {
String codeName = Hawk.get(HawkConfig.IJK_CODEC, "");
+ return getIJKCodec(codeName);
+ }
+
+ public IJKCode getIJKCodec(String name) {
for (IJKCode code : ijkCodes) {
- if (code.getName().equals(codeName))
+ if (code.getName().equals(name))
return code;
}
return ijkCodes.get(0);
diff --git a/app/src/main/java/com/github/tvbox/osc/base/App.java b/app/src/main/java/com/github/tvbox/osc/base/App.java
index 5fce938be4..6cbded39ea 100644
--- a/app/src/main/java/com/github/tvbox/osc/base/App.java
+++ b/app/src/main/java/com/github/tvbox/osc/base/App.java
@@ -12,6 +12,7 @@
import com.kingja.loadsir.core.LoadSir;
import com.orhanobut.hawk.Hawk;
+import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.unit.Subunits;
@@ -38,7 +39,7 @@ public void onCreate() {
.addCallback(new EmptyCallback())
.addCallback(new LoadingCallback())
.commit();
- AutoSizeConfig.getInstance().getUnitsManager()
+ AutoSizeConfig.getInstance().setCustomFragment(true).getUnitsManager()
.setSupportDP(false)
.setSupportSP(false)
.setSupportSubunits(Subunits.MM);
diff --git a/app/src/main/java/com/github/tvbox/osc/base/BaseActivity.java b/app/src/main/java/com/github/tvbox/osc/base/BaseActivity.java
index 46454ffded..88bf660c5b 100644
--- a/app/src/main/java/com/github/tvbox/osc/base/BaseActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/base/BaseActivity.java
@@ -4,8 +4,10 @@
import android.content.Intent;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
+import android.util.DisplayMetrics;
import android.view.View;
import androidx.annotation.Nullable;
@@ -24,18 +26,32 @@
import java.io.InputStreamReader;
import me.jessyan.autosize.AutoSizeCompat;
+import me.jessyan.autosize.internal.CustomAdapt;
/**
* @author pj567
* @date :2020/12/17
* @description:
*/
-public abstract class BaseActivity extends AppCompatActivity {
+public abstract class BaseActivity extends AppCompatActivity implements CustomAdapt {
protected Context mContext;
private LoadService mLoadService;
+ private static float screenRatio = -100.0f;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
+ try {
+ if (screenRatio < 0) {
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(dm);
+ int screenWidth = dm.widthPixels;
+ int screenHeight = dm.heightPixels;
+ screenRatio = (float) Math.max(screenWidth, screenHeight) / (float) Math.min(screenWidth, screenHeight);
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
super.onCreate(savedInstanceState);
setContentView(getLayoutResID());
mContext = this;
@@ -43,10 +59,29 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
init();
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ hideSysBar();
+ }
+
+ public void hideSysBar() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ int uiOptions = getWindow().getDecorView().getSystemUiVisibility();
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
+ uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ getWindow().getDecorView().setSystemUiVisibility(uiOptions);
+ }
+ }
+
@Override
public Resources getResources() {
if (Looper.myLooper() == Looper.getMainLooper()) {
- AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources());
+ AutoSizeCompat.autoConvertDensityOfCustomAdapt(super.getResources(), this);
}
return super.getResources();
}
@@ -125,4 +160,15 @@ protected String getAssetText(String fileName) {
}
return "";
}
+
+ @Override
+ public float getSizeInDp() {
+ return isBaseOnWidth() ? 1280 : 720;
+ }
+
+ @Override
+ public boolean isBaseOnWidth() {
+ return !(screenRatio >= 4.0f);
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/base/BaseLazyFragment.java b/app/src/main/java/com/github/tvbox/osc/base/BaseLazyFragment.java
index 677a670773..36752f2685 100644
--- a/app/src/main/java/com/github/tvbox/osc/base/BaseLazyFragment.java
+++ b/app/src/main/java/com/github/tvbox/osc/base/BaseLazyFragment.java
@@ -65,7 +65,7 @@ public void onAttach(@NonNull Context context) {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- AutoSize.autoConvertDensity(getActivity(), getSizeInDp(), true);
+ AutoSize.autoConvertDensity(getActivity(), getSizeInDp(), isBaseOnWidth());
if (null == rootView) {
rootView = inflater.inflate(getLayoutResID(), container, false);
}
@@ -198,7 +198,7 @@ private boolean isSupportVisible() {
*/
@Override
public void onResume() {
- AutoSize.autoConvertDensity(getActivity(), getSizeInDp(), true);
+ AutoSize.autoConvertDensity(getActivity(), getSizeInDp(), isBaseOnWidth());
super.onResume();
// 如果不是第一次可见
if (!mIsFirstVisible) {
@@ -286,11 +286,15 @@ public void jumpActivity(Class extends BaseActivity> clazz, Bundle bundle) {
@Override
public float getSizeInDp() {
- return 1280;
+ if (getActivity() != null && getActivity() instanceof CustomAdapt)
+ return ((CustomAdapt) getActivity()).getSizeInDp();
+ return 0;
}
@Override
public boolean isBaseOnWidth() {
+ if (getActivity() != null && getActivity() instanceof CustomAdapt)
+ return ((CustomAdapt) getActivity()).isBaseOnWidth();
return true;
}
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/AbsJson.java b/app/src/main/java/com/github/tvbox/osc/bean/AbsJson.java
index f00b42706d..961face383 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/AbsJson.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/AbsJson.java
@@ -126,7 +126,7 @@ public Movie.Video toXmlVideo() {
video.actor = vod_actor;
video.director = vod_director;
Movie.Video.UrlBean urlBean = new Movie.Video.UrlBean();
- if(vod_play_from != null) {
+ if (vod_play_from != null && vod_play_url != null) {
String[] playFlags = vod_play_from.split("\\$\\$\\$");
String[] playUrls = vod_play_url.split("\\$\\$\\$");
List infoList = new ArrayList<>();
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/AbsSortJson.java b/app/src/main/java/com/github/tvbox/osc/bean/AbsSortJson.java
index 6393c6d475..c51e1d636d 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/AbsSortJson.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/AbsSortJson.java
@@ -8,19 +8,33 @@
public class AbsSortJson implements Serializable {
@SerializedName(value = "class")
- public ArrayList classList;
+ public ArrayList classes;
+
+ @SerializedName(value = "list")
+ public ArrayList list;
public AbsSortXml toAbsSortXml() {
AbsSortXml absSortXml = new AbsSortXml();
MovieSort movieSort = new MovieSort();
movieSort.sortList = new ArrayList<>();
- for (AbsJsonClass cls : classList) {
+ for (AbsJsonClass cls : classes) {
MovieSort.SortData sortData = new MovieSort.SortData();
sortData.id = cls.type_id;
sortData.name = cls.type_name;
movieSort.sortList.add(sortData);
}
- absSortXml.movieSort = movieSort;
+ if (list != null && !list.isEmpty()) {
+ Movie movie = new Movie();
+ ArrayList videos = new ArrayList<>();
+ for (AbsJson.AbsJsonVod vod : list) {
+ videos.add(vod.toXmlVideo());
+ }
+ movie.videoList = videos;
+ absSortXml.list = movie;
+ } else {
+ absSortXml.list = null;
+ }
+ absSortXml.classes = movieSort;
return absSortXml;
}
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/AbsSortXml.java b/app/src/main/java/com/github/tvbox/osc/bean/AbsSortXml.java
index 4fb3adb878..2a318a24d9 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/AbsSortXml.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/AbsSortXml.java
@@ -3,6 +3,7 @@
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.io.Serializable;
+import java.util.List;
/**
* @author pj567
@@ -12,5 +13,10 @@
@XStreamAlias("rss")
public class AbsSortXml implements Serializable {
@XStreamAlias("class")
- public MovieSort movieSort;
+ public MovieSort classes;
+
+ @XStreamAlias("list")
+ public Movie list;
+
+ public List videoList;
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LiveChannel.java b/app/src/main/java/com/github/tvbox/osc/bean/LiveChannel.java
deleted file mode 100644
index bd06c2e036..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/bean/LiveChannel.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.github.tvbox.osc.bean;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2021/1/12
- * @description:
- */
-public class LiveChannel {
- /**
- * channelNum : 1
- * channelName : CCTV-1 综合
- * channelUrl : http://117.148.187.37/PLTV/88888888/224/3221226154/index.m3u8
- * channelLogo : https://upload.wikimedia.org/wikipedia/zh/6/65/CCTV-1_Logo.png
- */
-
- private int channelNum;
- private String name;
- private ArrayList urls;
- private boolean isDefault;
- public int sourceIdx = 0;
-
- public void setChannelNum(int channelNum) {
- this.channelNum = channelNum;
- }
-
- public int getChannelNum() {
- return channelNum;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public String getUrls() {
- if (sourceIdx <= 0 || sourceIdx >= urls.size())
- sourceIdx = 0;
- return urls.get(sourceIdx);
- }
-
- public boolean isDefault() {
- return isDefault;
- }
-
- public void setDefault(boolean b) {
- isDefault = b;
- }
-
- public void setUrls(ArrayList urls) {
- this.urls = urls;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelGroup.java b/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelGroup.java
new file mode 100644
index 0000000000..44b8ff773c
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelGroup.java
@@ -0,0 +1,47 @@
+package com.github.tvbox.osc.bean;
+
+import java.util.ArrayList;
+
+public class LiveChannelGroup {
+ /**
+ * groupIndex : 分组索引号
+ * groupName : 分组名称
+ * password : 分组密码
+ */
+ private int groupIndex;
+ private String groupName;
+ private String groupPassword;
+ private ArrayList liveChannelItems;
+
+ public int getGroupIndex() {
+ return groupIndex;
+ }
+
+ public void setGroupIndex(int groupIndex) {
+ this.groupIndex = groupIndex;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public ArrayList getLiveChannels() {
+ return liveChannelItems;
+ }
+
+ public void setLiveChannels(ArrayList liveChannelItems) {
+ this.liveChannelItems = liveChannelItems;
+ }
+
+ public String getGroupPassword() {
+ return groupPassword;
+ }
+
+ public void setGroupPassword(String groupPassword) {
+ this.groupPassword = groupPassword;
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelItem.java b/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelItem.java
new file mode 100644
index 0000000000..bb567305e5
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/bean/LiveChannelItem.java
@@ -0,0 +1,95 @@
+package com.github.tvbox.osc.bean;
+
+import java.util.ArrayList;
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveChannelItem {
+ /**
+ * channelIndex : 频道索引号
+ * channelNum : 频道名称
+ * channelSourceNames : 频道源名称
+ * channelUrls : 频道源地址
+ * sourceIndex : 频道源索引
+ * sourceNum : 频道源总数
+ */
+ private int channelIndex;
+ private int channelNum;
+ private String channelName;
+ private ArrayList channelSourceNames;
+ private ArrayList channelUrls;
+ public int sourceIndex = 0;
+ public int sourceNum = 0;
+
+ public void setChannelIndex(int channelIndex) {
+ this.channelIndex = channelIndex;
+ }
+
+ public int getChannelIndex() {
+ return channelIndex;
+ }
+
+ public void setChannelNum(int channelNum) {
+ this.channelNum = channelNum;
+ }
+
+ public int getChannelNum() {
+ return channelNum;
+ }
+
+ public void setChannelName(String channelName) {
+ this.channelName = channelName;
+ }
+
+ public String getChannelName() {
+ return channelName;
+ }
+
+ public ArrayList getChannelUrls() {
+ return channelUrls;
+ }
+
+ public void setChannelUrls(ArrayList channelUrls) {
+ this.channelUrls = channelUrls;
+ sourceNum = channelUrls.size();
+ }
+ public void preSource() {
+ sourceIndex--;
+ if (sourceIndex < 0) sourceIndex = sourceNum - 1;
+ }
+ public void nextSource() {
+ sourceIndex++;
+ if (sourceIndex == sourceNum) sourceIndex = 0;
+ }
+
+ public void setSourceIndex(int sourceIndex) {
+ this.sourceIndex = sourceIndex;
+ }
+
+ public int getSourceIndex() {
+ return sourceIndex;
+ }
+
+ public String getUrl() {
+ return channelUrls.get(sourceIndex);
+ }
+
+ public int getSourceNum() {
+ return sourceNum;
+ }
+
+ public ArrayList getChannelSourceNames() {
+ return channelSourceNames;
+ }
+
+ public void setChannelSourceNames(ArrayList channelSourceNames) {
+ this.channelSourceNames = channelSourceNames;
+ }
+
+ public String getSourceName() {
+ return channelSourceNames.get(sourceIndex);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LivePlayerManager.java b/app/src/main/java/com/github/tvbox/osc/bean/LivePlayerManager.java
new file mode 100644
index 0000000000..1c4b23e44a
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/bean/LivePlayerManager.java
@@ -0,0 +1,153 @@
+package com.github.tvbox.osc.bean;
+
+import androidx.annotation.NonNull;
+import androidx.exifinterface.media.ExifInterface;
+
+import com.github.tvbox.osc.api.ApiConfig;
+import com.github.tvbox.osc.util.HawkConfig;
+import com.github.tvbox.osc.util.PlayerHelper;
+import com.orhanobut.hawk.Hawk;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Objects;
+
+import xyz.doikki.videoplayer.player.VideoView;
+
+public class LivePlayerManager {
+ JSONObject defaultPlayerConfig = new JSONObject();
+ JSONObject currentPlayerConfig;
+
+ public void init(VideoView videoView) {
+ try {
+ defaultPlayerConfig.put("pl", Hawk.get(HawkConfig.PLAY_TYPE, 0));
+ defaultPlayerConfig.put("ijk", Hawk.get(HawkConfig.IJK_CODEC, "软解码"));
+ defaultPlayerConfig.put("pr", Hawk.get(HawkConfig.PLAY_RENDER, 0));
+ defaultPlayerConfig.put("sc", Hawk.get(HawkConfig.PLAY_SCALE, 0));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ getDefaultLiveChannelPlayer(videoView);
+ }
+
+ public void getDefaultLiveChannelPlayer(VideoView videoView) {
+ PlayerHelper.updateCfg(videoView, defaultPlayerConfig);
+ try {
+ currentPlayerConfig = new JSONObject(defaultPlayerConfig.toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void getLiveChannelPlayer(VideoView videoView, String channelName) {
+ JSONObject playerConfig = Hawk.get(channelName, null);
+ if (playerConfig == null) {
+ if (!currentPlayerConfig.toString().equals(defaultPlayerConfig.toString()))
+ getDefaultLiveChannelPlayer(videoView);
+ return;
+ }
+ if (playerConfig.toString().equals(currentPlayerConfig.toString()))
+ return;
+
+ try {
+ if (playerConfig.getInt("pl") == currentPlayerConfig.getInt("pl")
+ && playerConfig.getInt("pr") == currentPlayerConfig.getInt("pr")
+ && playerConfig.getString("ijk").equals(currentPlayerConfig.getString("ijk"))) {
+ videoView.setScreenScaleType(playerConfig.getInt("sc"));
+ } else {
+ PlayerHelper.updateCfg(videoView, playerConfig);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ currentPlayerConfig = playerConfig;
+ }
+
+ public int getLivePlayerType() {
+ int playerTypeIndex = 0;
+ try {
+ int playerType = currentPlayerConfig.getInt("pl");
+ String ijkCodec = currentPlayerConfig.getString("ijk");
+ switch (playerType) {
+ case 0:
+ playerTypeIndex = 0;
+ break;
+ case 1:
+ if (ijkCodec.equals("硬解码"))
+ playerTypeIndex = 1;
+ else
+ playerTypeIndex = 2;
+ break;
+ case 2:
+ playerTypeIndex = 3;
+ break;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return playerTypeIndex;
+ }
+
+ public int getLivePlayerScale() {
+ try {
+ return currentPlayerConfig.getInt("sc");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ public void changeLivePlayerType(VideoView videoView, int playerType, String channelName) {
+ JSONObject playerConfig = currentPlayerConfig;
+ try {
+ switch (playerType) {
+ case 0:
+ playerConfig.put("pl", 0);
+ playerConfig.put("ijk", "软解码");
+ break;
+ case 1:
+ playerConfig.put("pl", 1);
+ playerConfig.put("ijk", "硬解码");
+ break;
+ case 2:
+ playerConfig.put("pl", 1);
+ playerConfig.put("ijk", "软解码");
+ break;
+ case 3:
+ playerConfig.put("pl", 2);
+ playerConfig.put("ijk", "软解码");
+ break;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ PlayerHelper.updateCfg(videoView, playerConfig);
+
+ if (playerConfig.toString().equals(defaultPlayerConfig.toString()))
+ Hawk.delete(channelName);
+ else
+ Hawk.put(channelName, playerConfig);
+
+ currentPlayerConfig = playerConfig;
+ }
+
+ public void changeLivePlayerScale(@NonNull VideoView videoView, int playerScale, String channelName){
+ videoView.setScreenScaleType(playerScale);
+
+ JSONObject playerConfig = currentPlayerConfig;
+ try {
+ playerConfig.put("sc", playerScale);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ if (playerConfig.toString().equals(defaultPlayerConfig.toString()))
+ Hawk.delete(channelName);
+ else
+ Hawk.put(channelName, playerConfig);
+
+ currentPlayerConfig = playerConfig;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingGroup.java b/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingGroup.java
new file mode 100644
index 0000000000..b8b25d0efe
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingGroup.java
@@ -0,0 +1,33 @@
+package com.github.tvbox.osc.bean;
+
+import java.util.ArrayList;
+
+public class LiveSettingGroup {
+ private int groupIndex;
+ private String groupName;
+ private ArrayList liveSettingItems;
+
+ public int getGroupIndex() {
+ return groupIndex;
+ }
+
+ public void setGroupIndex(int groupIndex) {
+ this.groupIndex = groupIndex;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public ArrayList getLiveSettingItems() {
+ return liveSettingItems;
+ }
+
+ public void setLiveSettingItems(ArrayList liveSettingItems) {
+ this.liveSettingItems = liveSettingItems;
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingItem.java b/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingItem.java
new file mode 100644
index 0000000000..741134aa81
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/bean/LiveSettingItem.java
@@ -0,0 +1,36 @@
+package com.github.tvbox.osc.bean;
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveSettingItem {
+ private int itemIndex;
+ private String itemName;
+ private boolean itemSelected = false;
+
+ public int getItemIndex() {
+ return itemIndex;
+ }
+
+ public void setItemIndex(int itemIndex) {
+ this.itemIndex = itemIndex;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+
+ public boolean isItemSelected() {
+ return itemSelected;
+ }
+
+ public void setItemSelected(boolean itemSelected) {
+ this.itemSelected = itemSelected;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/MovieSort.java b/app/src/main/java/com/github/tvbox/osc/bean/MovieSort.java
index f578c96dfc..c0f1abf9b5 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/MovieSort.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/MovieSort.java
@@ -7,6 +7,9 @@
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
/**
@@ -27,6 +30,8 @@ public static class SortData implements Serializable, Comparable {
public String name;
public int sort = -1;
public boolean select = false;
+ public ArrayList filters = new ArrayList<>();
+ public HashMap filterSelect = new HashMap<>();
public SortData() {
}
@@ -42,4 +47,11 @@ public int compareTo(SortData o) {
return this.sort - o.sort;
}
}
+
+ public static class SortFilter {
+ public String key;
+ public String name;
+ public LinkedHashMap values;
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/ParseBean.java b/app/src/main/java/com/github/tvbox/osc/bean/ParseBean.java
index 06e807c89f..5b76b0e149 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/ParseBean.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/ParseBean.java
@@ -2,6 +2,8 @@
import android.util.Base64;
+import com.github.tvbox.osc.util.DefaultConfig;
+
/**
* @author pj567
* @date :2021/3/8
@@ -25,7 +27,7 @@ public void setName(String name) {
}
public String getUrl() {
- return url;
+ return DefaultConfig.checkReplaceProxy(url);
}
public void setUrl(String url) {
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/SourceBean.java b/app/src/main/java/com/github/tvbox/osc/bean/SourceBean.java
index 498259542f..8d9a8f5a22 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/SourceBean.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/SourceBean.java
@@ -1,30 +1,8 @@
package com.github.tvbox.osc.bean;
-import com.github.tvbox.osc.cache.RoomDataManger;
-import com.github.tvbox.osc.cache.SourceState;
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.HashMap;
-
-/**
- * @author pj567
- * @date :2020/12/18
- * @description:
- */
-public class SourceBean {
- public static SourceBean speedTestBean = new SourceBean();
-
- static {
- speedTestBean.key = "_source_speed_test";
- speedTestBean.api = "";
- }
+import java.util.ArrayList;
- /**
- * name : 最大资源网
- * api : http://www.zdziyuan.com/inc/api.php
- * download : http://www.zdziyuan.com/inc/apidown.php
- */
+public class SourceBean {
private String key;
private String name;
private String api;
@@ -34,7 +12,7 @@ public class SourceBean {
private int filterable; // 可筛选?
private String playerUrl; // 站点解析Url
private String ext; // 扩展数据
- private SourceState state;
+ private ArrayList categories = null; // 分类&排序
public String getKey() {
return key;
@@ -68,42 +46,6 @@ public String getPlayerUrl() {
return playerUrl;
}
- public void setState(SourceState state) {
- this.state = state;
- }
-
- public SourceState getState() {
- if (state == null) {
- state = new SourceState();
- state.sourceKey = getKey();
- state.active = true;
- state.home = false;
- }
- return state;
- }
-
- public boolean isHome() {
- return getState().home;
- }
-
- public void setHome(boolean home) {
- getState().home = home;
- RoomDataManger.addSourceState(getState());
- }
-
- public boolean isActive() {
- return getState().active;
- }
-
- public void setActive(boolean act) {
- getState().active = act;
- RoomDataManger.addSourceState(getState());
- }
-
- public boolean isAddition() {
- return this == speedTestBean;
- }
-
public int getType() {
return type;
}
@@ -112,26 +54,16 @@ public void setType(int type) {
this.type = type;
}
- public void setTidSort(HashMap tidSort) {
- getState().tidSort = new Gson().toJson(tidSort);
- RoomDataManger.addSourceState(getState());
- }
-
- public HashMap getTidSort() {
- return new Gson().fromJson(state.tidSort, new TypeToken>() {
- }.getType());
- }
-
- public int getSearchable() {
- return searchable;
+ public boolean isSearchable() {
+ return searchable != 0;
}
public void setSearchable(int searchable) {
this.searchable = searchable;
}
- public int getQuickSearch() {
- return quickSearch;
+ public boolean isQuickSearch() {
+ return quickSearch != 0;
}
public void setQuickSearch(int quickSearch) {
@@ -153,4 +85,12 @@ public String getExt() {
public void setExt(String ext) {
this.ext = ext;
}
+
+ public ArrayList getCategories() {
+ return categories;
+ }
+
+ public void setCategories(ArrayList categories) {
+ this.categories = categories;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/SourceBeanSpeed.java b/app/src/main/java/com/github/tvbox/osc/bean/SourceBeanSpeed.java
deleted file mode 100644
index aa950f4753..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/bean/SourceBeanSpeed.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.github.tvbox.osc.bean;
-
-public class SourceBeanSpeed implements Comparable {
- private SourceBean bean;
- private int speed = 0;
-
- public SourceBeanSpeed(SourceBean bean) {
- this.bean = bean;
- }
-
- public void setBean(SourceBean bean) {
- this.bean = bean;
- }
-
- public SourceBean getBean() {
- return bean;
- }
-
- public void setSpeed(int speed) {
- this.speed = speed;
- }
-
- public int getSpeed() {
- return speed;
- }
-
- @Override
- public int compareTo(Object o) {
- return this.speed - ((SourceBeanSpeed) o).speed;
- }
-}
diff --git a/app/src/main/java/com/github/tvbox/osc/bean/VodInfo.java b/app/src/main/java/com/github/tvbox/osc/bean/VodInfo.java
index 7e21738776..e60a5fb5b9 100644
--- a/app/src/main/java/com/github/tvbox/osc/bean/VodInfo.java
+++ b/app/src/main/java/com/github/tvbox/osc/bean/VodInfo.java
@@ -8,6 +8,7 @@
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Set;
/**
* @author pj567
@@ -46,7 +47,10 @@ public class VodInfo implements Serializable {
public String des;// flags = seriesMap.keySet();
+ for (String flag : flags) {
+ Collections.reverse(seriesMap.get(flag));
+ }
+ }
+
public static class VodSeriesFlag implements Serializable {
public String name;
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/RoomDataManger.java b/app/src/main/java/com/github/tvbox/osc/cache/RoomDataManger.java
index b111ad3168..ae6743e2f5 100644
--- a/app/src/main/java/com/github/tvbox/osc/cache/RoomDataManger.java
+++ b/app/src/main/java/com/github/tvbox/osc/cache/RoomDataManger.java
@@ -13,7 +13,6 @@
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
/**
@@ -52,7 +51,6 @@ record = new VodRecord();
record.sourceKey = sourceKey;
record.vodId = vodInfo.id;
record.updateTime = System.currentTimeMillis();
- record.data = null;
record.dataJson = getVodInfoGson().toJson(vodInfo);
AppDataManager.get().getVodRecordDao().insert(record);
}
@@ -63,7 +61,7 @@ public static VodInfo getVodInfo(String sourceKey, String vodId) {
if (record != null && record.dataJson != null && !TextUtils.isEmpty(record.dataJson)) {
VodInfo vodInfo = getVodInfoGson().fromJson(record.dataJson, new TypeToken() {
}.getType());
- if (vodInfo.name == null || vodInfo.type == null)
+ if (vodInfo.name == null)
return null;
return vodInfo;
}
@@ -80,8 +78,8 @@ public static void deleteVodRecord(String sourceKey, VodInfo vodInfo) {
}
}
- public static List getAllVodRecord() {
- List recordList = AppDataManager.get().getVodRecordDao().getAll();
+ public static List getAllVodRecord(int limit) {
+ List recordList = AppDataManager.get().getVodRecordDao().getAll(limit);
List vodInfoList = new ArrayList<>();
if (recordList != null) {
for (VodRecord record : recordList) {
@@ -92,7 +90,7 @@ public static List getAllVodRecord() {
}.getType());
info.sourceKey = record.sourceKey;
SourceBean sourceBean = ApiConfig.get().getSource(info.sourceKey);
- if (sourceBean == null || !sourceBean.isActive() || info.name == null || info.type == null)
+ if (sourceBean == null || info.name == null)
info = null;
}
} catch (Exception e) {
@@ -105,20 +103,25 @@ public static List getAllVodRecord() {
return vodInfoList;
}
- public static HashMap getAllSourceState() {
- HashMap result = new HashMap<>();
- for (SourceState state : AppDataManager.get().getSourceStateDao().getAll()) {
- result.put(state.sourceKey, state);
+ public static void insertVodCollect(String sourceKey, VodInfo vodInfo) {
+ VodCollect record = AppDataManager.get().getVodCollectDao().getVodCollect(sourceKey, vodInfo.id);
+ if (record != null) {
+ return;
}
- return result;
+ record = new VodCollect();
+ record.sourceKey = sourceKey;
+ record.vodId = vodInfo.id;
+ record.updateTime = System.currentTimeMillis();
+ record.name = vodInfo.name;
+ record.pic = vodInfo.pic;
+ AppDataManager.get().getVodCollectDao().insert(record);
}
- public static void addSourceState(SourceState ss) {
- AppDataManager.get().getSourceStateDao().insert(ss);
+ public static void deleteVodCollect(int id) {
+ AppDataManager.get().getVodCollectDao().delete(id);
}
- public static void delSourceState(SourceState ss) {
- AppDataManager.get().getSourceStateDao().delete(ss);
+ public static List getAllVodCollect() {
+ return AppDataManager.get().getVodCollectDao().getAll();
}
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/SourceState.java b/app/src/main/java/com/github/tvbox/osc/cache/SourceState.java
deleted file mode 100644
index 279e96a5eb..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/cache/SourceState.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.github.tvbox.osc.cache;
-
-import androidx.annotation.NonNull;
-import androidx.room.Entity;
-import androidx.room.PrimaryKey;
-
-import java.io.Serializable;
-
-/**
- * @author pj567
- * @date :2021/1/7
- * @description:
- */
-@Entity(tableName = "sourceState")
-public class SourceState implements Serializable {
- @PrimaryKey(autoGenerate = false)
- @NonNull
- public String sourceKey;
- public boolean home;
- public boolean active;
- public String tidSort;
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/SourceStateDao.java b/app/src/main/java/com/github/tvbox/osc/cache/SourceStateDao.java
deleted file mode 100644
index cd7aedd798..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/cache/SourceStateDao.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.github.tvbox.osc.cache;
-
-import androidx.room.Dao;
-import androidx.room.Delete;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-/**
- * @author pj567
- * @date :2021/1/7
- * @description:
- */
-@Dao
-public interface SourceStateDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- long insert(SourceState state);
-
- @Query("select * from sourceState")
- List getAll();
-
- @Delete
- int delete(SourceState state);
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/VodCollect.java b/app/src/main/java/com/github/tvbox/osc/cache/VodCollect.java
new file mode 100644
index 0000000000..42434aa976
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/cache/VodCollect.java
@@ -0,0 +1,31 @@
+package com.github.tvbox.osc.cache;
+
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+import java.io.Serializable;
+
+@Entity(tableName = "vodCollect")
+public class VodCollect implements Serializable {
+ @PrimaryKey(autoGenerate = true)
+ private int id;
+ @ColumnInfo(name = "vodId")
+ public String vodId;
+ @ColumnInfo(name = "updateTime")
+ public long updateTime;
+ @ColumnInfo(name = "sourceKey")
+ public String sourceKey;
+ @ColumnInfo(name = "name")
+ public String name;
+ @ColumnInfo(name = "pic")
+ public String pic;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/VodCollectDao.java b/app/src/main/java/com/github/tvbox/osc/cache/VodCollectDao.java
new file mode 100644
index 0000000000..86b699a83d
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/cache/VodCollectDao.java
@@ -0,0 +1,35 @@
+package com.github.tvbox.osc.cache;
+
+import androidx.room.Dao;
+import androidx.room.Delete;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+
+import java.util.List;
+
+/**
+ * @author pj567
+ * @date :2021/1/7
+ * @description:
+ */
+@Dao
+public interface VodCollectDao {
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ long insert(VodCollect record);
+
+ @Query("select * from vodCollect order by updateTime desc")
+ List getAll();
+
+ @Query("select * from vodCollect where `id`=:id")
+ VodCollect getVodCollect(int id);
+
+ @Query("delete from vodCollect where `id`=:id")
+ void delete(int id);
+
+ @Query("select * from vodCollect where `sourceKey`=:sourceKey and `vodId`=:vodId")
+ VodCollect getVodCollect(String sourceKey, String vodId);
+
+ @Delete
+ int delete(VodCollect record);
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/VodRecord.java b/app/src/main/java/com/github/tvbox/osc/cache/VodRecord.java
index a41566717a..75a781d2ab 100644
--- a/app/src/main/java/com/github/tvbox/osc/cache/VodRecord.java
+++ b/app/src/main/java/com/github/tvbox/osc/cache/VodRecord.java
@@ -21,11 +21,8 @@ public class VodRecord implements Serializable {
public long updateTime;
@ColumnInfo(name = "sourceKey")
public String sourceKey;
- public byte[] data;
public String dataJson;
- public int testMigration;
-
public int getId() {
return id;
}
diff --git a/app/src/main/java/com/github/tvbox/osc/cache/VodRecordDao.java b/app/src/main/java/com/github/tvbox/osc/cache/VodRecordDao.java
index 7f814ff0d7..9484b6ae47 100644
--- a/app/src/main/java/com/github/tvbox/osc/cache/VodRecordDao.java
+++ b/app/src/main/java/com/github/tvbox/osc/cache/VodRecordDao.java
@@ -18,8 +18,8 @@ public interface VodRecordDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(VodRecord record);
- @Query("select * from vodRecord order by updateTime desc")
- List getAll();
+ @Query("select * from vodRecord order by updateTime desc limit :size")
+ List getAll(int size);
@Query("select * from vodRecord where `sourceKey`=:sourceKey and `vodId`=:vodId")
VodRecord getVodRecord(String sourceKey, String vodId);
diff --git a/app/src/main/java/com/github/tvbox/osc/callback/EmptyCallback.java b/app/src/main/java/com/github/tvbox/osc/callback/EmptyCallback.java
index 9eead8f48f..d07e2c1b38 100644
--- a/app/src/main/java/com/github/tvbox/osc/callback/EmptyCallback.java
+++ b/app/src/main/java/com/github/tvbox/osc/callback/EmptyCallback.java
@@ -11,6 +11,6 @@
public class EmptyCallback extends Callback {
@Override
protected int onCreateView() {
- return R.layout.empty_layout;
+ return R.layout.loadsir_empty_layout;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/callback/LoadingCallback.java b/app/src/main/java/com/github/tvbox/osc/callback/LoadingCallback.java
index fdaf7ea85f..61fbed8e6a 100644
--- a/app/src/main/java/com/github/tvbox/osc/callback/LoadingCallback.java
+++ b/app/src/main/java/com/github/tvbox/osc/callback/LoadingCallback.java
@@ -11,6 +11,6 @@
public class LoadingCallback extends Callback {
@Override
protected int onCreateView() {
- return R.layout.loading_layout;
+ return R.layout.loadsir_loading_layout;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/data/AppDataBase.java b/app/src/main/java/com/github/tvbox/osc/data/AppDataBase.java
index ef267098d8..da5e3fe9ad 100644
--- a/app/src/main/java/com/github/tvbox/osc/data/AppDataBase.java
+++ b/app/src/main/java/com/github/tvbox/osc/data/AppDataBase.java
@@ -5,8 +5,8 @@
import com.github.tvbox.osc.cache.Cache;
import com.github.tvbox.osc.cache.CacheDao;
-import com.github.tvbox.osc.cache.SourceState;
-import com.github.tvbox.osc.cache.SourceStateDao;
+import com.github.tvbox.osc.cache.VodCollect;
+import com.github.tvbox.osc.cache.VodCollectDao;
import com.github.tvbox.osc.cache.VodRecord;
import com.github.tvbox.osc.cache.VodRecordDao;
@@ -17,11 +17,11 @@
* @author pj567
* @since 2020/5/15
*/
-@Database(entities = {Cache.class, VodRecord.class, SourceState.class}, version = 1)
+@Database(entities = {Cache.class, VodRecord.class, VodCollect.class}, version = 1)
public abstract class AppDataBase extends RoomDatabase {
public abstract CacheDao getCacheDao();
public abstract VodRecordDao getVodRecordDao();
- public abstract SourceStateDao getSourceStateDao();
+ public abstract VodCollectDao getVodCollectDao();
}
diff --git a/app/src/main/java/com/github/tvbox/osc/data/AppDataManager.java b/app/src/main/java/com/github/tvbox/osc/data/AppDataManager.java
index 6f83bd8c17..a5a85486f2 100644
--- a/app/src/main/java/com/github/tvbox/osc/data/AppDataManager.java
+++ b/app/src/main/java/com/github/tvbox/osc/data/AppDataManager.java
@@ -10,6 +10,10 @@
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.github.tvbox.osc.base.App;
+import com.github.tvbox.osc.util.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
/**
@@ -19,7 +23,8 @@
* @since 2020/5/15
*/
public class AppDataManager {
- private static final String DB_NAME = "tvbox.db";
+ private static final int DB_FILE_VERSION = 3;
+ private static final String DB_NAME = "tvbox";
private static AppDataManager manager;
private static AppDataBase dbInstance;
@@ -101,14 +106,19 @@ public void migrate(SupportSQLiteDatabase database) {
}
};
+ static String dbPath() {
+ return DB_NAME + ".v" + DB_FILE_VERSION + ".db";
+ }
+
public static AppDataBase get() {
if (manager == null) {
throw new RuntimeException("AppDataManager is no init");
}
if (dbInstance == null)
- dbInstance = Room.databaseBuilder(App.getInstance(), AppDataBase.class, DB_NAME)
- .addMigrations(MIGRATION_1_2)
- .addMigrations(MIGRATION_2_3)
+ dbInstance = Room.databaseBuilder(App.getInstance(), AppDataBase.class, dbPath())
+ .setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
+ //.addMigrations(MIGRATION_1_2)
+ //.addMigrations(MIGRATION_2_3)
//.addMigrations(MIGRATION_3_4)
//.addMigrations(MIGRATION_4_5)
.addCallback(new RoomDatabase.Callback() {
@@ -127,4 +137,31 @@ public void onOpen(@NonNull SupportSQLiteDatabase db) {
.build();
return dbInstance;
}
+
+ public static boolean backup(File path) throws IOException {
+ if (dbInstance != null && dbInstance.isOpen()) {
+ dbInstance.close();
+ }
+ File db = App.getInstance().getDatabasePath(dbPath());
+ if (db.exists()) {
+ FileUtils.copyFile(db, path);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean restore(File path) throws IOException {
+ if (dbInstance != null && dbInstance.isOpen()) {
+ dbInstance.close();
+ }
+ File db = App.getInstance().getDatabasePath(dbPath());
+ if (db.exists()) {
+ db.delete();
+ }
+ if (!db.getParentFile().exists())
+ db.getParentFile().mkdirs();
+ FileUtils.copyFile(path, db);
+ return true;
+ }
}
diff --git a/app/src/main/java/com/github/tvbox/osc/event/RefreshEvent.java b/app/src/main/java/com/github/tvbox/osc/event/RefreshEvent.java
index b04ac3e25b..aa9be925e7 100644
--- a/app/src/main/java/com/github/tvbox/osc/event/RefreshEvent.java
+++ b/app/src/main/java/com/github/tvbox/osc/event/RefreshEvent.java
@@ -15,6 +15,7 @@ public class RefreshEvent {
public static final int TYPE_SEARCH_RESULT = 6;
public static final int TYPE_QUICK_SEARCH_RESULT = 7;
public static final int TYPE_API_URL_CHANGE = 8;
+ public static final int TYPE_PUSH_URL = 9;
public int type;
public Object obj;
diff --git a/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java b/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java
index ce4f86a18e..6293ed7545 100644
--- a/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java
+++ b/app/src/main/java/com/github/tvbox/osc/picasso/RoundTransformation.java
@@ -5,6 +5,8 @@
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
@@ -24,7 +26,7 @@
* @since 2020/12/22
*/
public class RoundTransformation implements Transformation {
- private int viewWidth, viewHeight;
+ private int viewWidth, viewHeight, bottomShapeHeight = 0;
@RoundType
private int mRoundType = RoundType.NONE;
private int diameter;
@@ -47,6 +49,11 @@ public RoundTransformation centerCorp(boolean centerCorp) {
return this;
}
+ public RoundTransformation bottomShapeHeight(int shapeHeight) {
+ this.bottomShapeHeight = shapeHeight;
+ return this;
+ }
+
public RoundTransformation roundRadius(int radius, @RoundType int mRoundType) {
this.radius = radius;
this.diameter = radius * 2;
@@ -84,11 +91,70 @@ public Bitmap transform(Bitmap source) {
bitmap.setHasAlpha(true);
Canvas mCanvas = new Canvas(bitmap);
mPaint.setShader(mBitmapShader);
+ // mPaint.setAntiAlias(true);
+ mCanvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
drawRoundRect(mCanvas, mPaint, width, height);
source.recycle();
return bitmap;
}
+ static Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
+ Path path = new Path();
+ if (rx < 0) rx = 0;
+ if (ry < 0) ry = 0;
+ float width = right - left;
+ float height = bottom - top;
+ if (rx > width / 2) rx = width / 2;
+ if (ry > height / 2) ry = height / 2;
+ float widthMinusCorners = (width - (2 * rx));
+ float heightMinusCorners = (height - (2 * ry));
+
+ path.moveTo(right, top + ry);
+ if (tr)
+ path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
+ else {
+ path.rLineTo(0, -ry);
+ path.rLineTo(-rx, 0);
+ }
+ path.rLineTo(-widthMinusCorners, 0);
+ if (tl)
+ path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
+ else {
+ path.rLineTo(-rx, 0);
+ path.rLineTo(0, ry);
+ }
+ path.rLineTo(0, heightMinusCorners);
+
+ if (bl)
+ path.rQuadTo(0, ry, rx, ry);//bottom-left corner
+ else {
+ path.rLineTo(0, ry);
+ path.rLineTo(rx, 0);
+ }
+
+ path.rLineTo(widthMinusCorners, 0);
+ if (br)
+ path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
+ else {
+ path.rLineTo(rx, 0);
+ path.rLineTo(0, -ry);
+ }
+
+ path.rLineTo(0, -heightMinusCorners);
+
+ path.close();//Given close, last lineto can be removed.
+
+ return path;
+ }
+
+ private void drawBottomLabel(Canvas mCanvas, Paint mPaint, float left, float top, float right, float bottom) {
+ if (bottomShapeHeight <= 0)
+ return;
+ mPaint.setShader(null);
+ mPaint.setColor(0x99000000);
+ mCanvas.drawPath(RoundedRect(left, bottom - bottomShapeHeight * 2, right, bottom, radius, radius, false, false, true, true), mPaint);
+ }
+
private void drawRoundRect(Canvas mCanvas, Paint mPaint, float width, float height) {
switch (mRoundType) {
case RoundType.NONE:
@@ -113,18 +179,22 @@ private void drawRoundRect(Canvas mCanvas, Paint mPaint, float width, float heig
case RoundType.ALL:
if (viewWidth == width && viewHeight == height) {
mCanvas.drawRoundRect(new RectF(0, 0, viewWidth, viewHeight), radius, radius, mPaint);
+ drawBottomLabel(mCanvas, mPaint, 0, 0, viewWidth, viewHeight);
} else if (viewWidth == width && viewHeight != height) {
float dis = (height - viewHeight) / 2f;
if (isCenterCorp) {
mCanvas.translate(0, -dis);
mCanvas.drawRoundRect(new RectF(0, dis, viewWidth, viewHeight + dis), radius, radius, mPaint);
+ drawBottomLabel(mCanvas, mPaint, 0, dis, viewWidth, viewHeight + dis);
} else {
mCanvas.drawRoundRect(new RectF(0, 0, viewWidth, viewHeight), radius, radius, mPaint);
+ drawBottomLabel(mCanvas, mPaint, 0, 0, viewWidth, viewHeight);
}
} else {
float dis = (width - viewWidth) / 2f;
mCanvas.translate(-dis, 0);
mCanvas.drawRoundRect(new RectF(dis, 0, viewWidth + dis, viewHeight), radius, radius, mPaint);
+ drawBottomLabel(mCanvas, mPaint, dis, 0, viewWidth + dis, viewHeight);
}
break;
case RoundType.TOP:
diff --git a/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java b/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java
index 2e1289a0f5..6d72390cba 100644
--- a/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java
+++ b/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java
@@ -3,24 +3,28 @@
import android.content.Context;
import android.text.TextUtils;
-import com.dueeeke.videoplayer.ijk.IjkPlayer;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.bean.IJKCode;
import java.util.LinkedHashMap;
import java.util.Map;
+import xyz.doikki.videoplayer.ijk.IjkPlayer;
+
public class IjkMediaPlayer extends IjkPlayer {
- public IjkMediaPlayer(Context context) {
+ private IJKCode codec = null;
+
+ public IjkMediaPlayer(Context context, IJKCode codec) {
super(context);
+ this.codec = codec;
}
@Override
public void setOptions() {
super.setOptions();
- IJKCode codec = ApiConfig.get().getCurrentIJKCode();
- LinkedHashMap options = codec.getOption();
+ IJKCode codecTmp = this.codec == null ? ApiConfig.get().getCurrentIJKCode() : this.codec;
+ LinkedHashMap options = codecTmp.getOption();
if (options != null) {
for (String key : options.keySet()) {
String value = options.get(key);
diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java
new file mode 100644
index 0000000000..342fea80ad
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/player/controller/BaseController.java
@@ -0,0 +1,433 @@
+package com.github.tvbox.osc.player.controller;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Map;
+
+import xyz.doikki.videoplayer.controller.BaseVideoController;
+import xyz.doikki.videoplayer.controller.IControlComponent;
+import xyz.doikki.videoplayer.controller.IGestureComponent;
+import xyz.doikki.videoplayer.player.VideoView;
+import xyz.doikki.videoplayer.util.PlayerUtils;
+
+public abstract class BaseController extends BaseVideoController implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, View.OnTouchListener {
+ private GestureDetector mGestureDetector;
+ private AudioManager mAudioManager;
+ private boolean mIsGestureEnabled = true;
+ private int mStreamVolume;
+ private float mBrightness;
+ private int mSeekPosition;
+ private boolean mFirstTouch;
+ private boolean mChangePosition;
+ private boolean mChangeBrightness;
+ private boolean mChangeVolume;
+ private boolean mCanChangePosition = true;
+ private boolean mEnableInNormal;
+ private boolean mCanSlide;
+ private int mCurPlayState;
+
+ protected Handler mHandler;
+
+ protected HandlerCallback mHandlerCallback;
+
+ protected interface HandlerCallback {
+ void callback(Message msg);
+ }
+
+ private boolean mIsDoubleTapTogglePlayEnabled = true;
+
+
+ public BaseController(@NonNull Context context) {
+ super(context);
+ mHandler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(@NonNull Message msg) {
+ int what = msg.what;
+ switch (what) {
+ case 100: { // 亮度+音量调整
+ mSlideInfo.setVisibility(VISIBLE);
+ mSlideInfo.setText(msg.obj.toString());
+ break;
+ }
+
+ case 101: { // 亮度+音量调整 关闭
+ mSlideInfo.setVisibility(GONE);
+ break;
+ }
+ default: {
+ if (mHandlerCallback != null)
+ mHandlerCallback.callback(msg);
+ break;
+ }
+ }
+ return false;
+ }
+ });
+ }
+
+ public BaseController(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BaseController(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ private TextView mSlideInfo;
+ private ProgressBar mLoading;
+ private ViewGroup mPauseRoot;
+ private TextView mPauseTime;
+
+ @Override
+ protected void initView() {
+ super.initView();
+ mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ mGestureDetector = new GestureDetector(getContext(), this);
+ setOnTouchListener(this);
+ mSlideInfo = findViewWithTag("vod_control_slide_info");
+ mLoading = findViewWithTag("vod_control_loading");
+ mPauseRoot = findViewWithTag("vod_control_pause");
+ mPauseTime = findViewWithTag("vod_control_pause_t");
+ }
+
+ @Override
+ protected void setProgress(int duration, int position) {
+ super.setProgress(duration, position);
+ mPauseTime.setText(PlayerUtils.stringForTime(position) + " / " + PlayerUtils.stringForTime(duration));
+ }
+
+ @Override
+ protected void onPlayStateChanged(int playState) {
+ super.onPlayStateChanged(playState);
+ switch (playState) {
+ case VideoView.STATE_IDLE:
+ mLoading.setVisibility(GONE);
+ break;
+ case VideoView.STATE_PLAYING:
+ mPauseRoot.setVisibility(GONE);
+ mLoading.setVisibility(GONE);
+ break;
+ case VideoView.STATE_PAUSED:
+ mPauseRoot.setVisibility(VISIBLE);
+ mLoading.setVisibility(GONE);
+ break;
+ case VideoView.STATE_PREPARED:
+ case VideoView.STATE_ERROR:
+ case VideoView.STATE_BUFFERED:
+ mLoading.setVisibility(GONE);
+ break;
+ case VideoView.STATE_PREPARING:
+ case VideoView.STATE_BUFFERING:
+ mLoading.setVisibility(VISIBLE);
+ break;
+ case VideoView.STATE_PLAYBACK_COMPLETED:
+ mLoading.setVisibility(GONE);
+ mPauseRoot.setVisibility(GONE);
+ break;
+ }
+ }
+
+ /**
+ * 设置是否可以滑动调节进度,默认可以
+ */
+ public void setCanChangePosition(boolean canChangePosition) {
+ mCanChangePosition = canChangePosition;
+ }
+
+ /**
+ * 是否在竖屏模式下开始手势控制,默认关闭
+ */
+ public void setEnableInNormal(boolean enableInNormal) {
+ mEnableInNormal = enableInNormal;
+ }
+
+ /**
+ * 是否开启手势控制,默认开启,关闭之后,手势调节进度,音量,亮度功能将关闭
+ */
+ public void setGestureEnabled(boolean gestureEnabled) {
+ mIsGestureEnabled = gestureEnabled;
+ }
+
+ /**
+ * 是否开启双击播放/暂停,默认开启
+ */
+ public void setDoubleTapTogglePlayEnabled(boolean enabled) {
+ mIsDoubleTapTogglePlayEnabled = enabled;
+ }
+
+ @Override
+ public void setPlayerState(int playerState) {
+ super.setPlayerState(playerState);
+ if (playerState == VideoView.PLAYER_NORMAL) {
+ mCanSlide = mEnableInNormal;
+ } else if (playerState == VideoView.PLAYER_FULL_SCREEN) {
+ mCanSlide = true;
+ }
+ }
+
+ @Override
+ public void setPlayState(int playState) {
+ super.setPlayState(playState);
+ mCurPlayState = playState;
+ }
+
+ protected boolean isInPlaybackState() {
+ return mControlWrapper != null
+ && mCurPlayState != VideoView.STATE_ERROR
+ && mCurPlayState != VideoView.STATE_IDLE
+ && mCurPlayState != VideoView.STATE_PREPARING
+ && mCurPlayState != VideoView.STATE_PREPARED
+ && mCurPlayState != VideoView.STATE_START_ABORT
+ && mCurPlayState != VideoView.STATE_PLAYBACK_COMPLETED;
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mGestureDetector.onTouchEvent(event);
+ }
+
+ /**
+ * 手指按下的瞬间
+ */
+ @Override
+ public boolean onDown(MotionEvent e) {
+ if (!isInPlaybackState() //不处于播放状态
+ || !mIsGestureEnabled //关闭了手势
+ || PlayerUtils.isEdge(getContext(), e)) //处于屏幕边沿
+ return true;
+ mStreamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ Activity activity = PlayerUtils.scanForActivity(getContext());
+ if (activity == null) {
+ mBrightness = 0;
+ } else {
+ mBrightness = activity.getWindow().getAttributes().screenBrightness;
+ }
+ mFirstTouch = true;
+ mChangePosition = false;
+ mChangeBrightness = false;
+ mChangeVolume = false;
+ return true;
+ }
+
+ /**
+ * 单击
+ */
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (isInPlaybackState()) {
+ mControlWrapper.toggleShowState();
+ }
+ return true;
+ }
+
+ /**
+ * 双击
+ */
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mIsDoubleTapTogglePlayEnabled && !isLocked() && isInPlaybackState()) togglePlay();
+ return true;
+ }
+
+ /**
+ * 在屏幕上滑动
+ */
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ if (!isInPlaybackState() //不处于播放状态
+ || !mIsGestureEnabled //关闭了手势
+ || !mCanSlide //关闭了滑动手势
+ || isLocked() //锁住了屏幕
+ || PlayerUtils.isEdge(getContext(), e1)) //处于屏幕边沿
+ return true;
+ float deltaX = e1.getX() - e2.getX();
+ float deltaY = e1.getY() - e2.getY();
+ if (mFirstTouch) {
+ mChangePosition = Math.abs(distanceX) >= Math.abs(distanceY);
+ if (!mChangePosition) {
+ //半屏宽度
+ int halfScreen = PlayerUtils.getScreenWidth(getContext(), true) / 2;
+ if (e2.getX() > halfScreen) {
+ mChangeVolume = true;
+ } else {
+ mChangeBrightness = true;
+ }
+ }
+
+ if (mChangePosition) {
+ //根据用户设置是否可以滑动调节进度来决定最终是否可以滑动调节进度
+ mChangePosition = mCanChangePosition;
+ }
+
+ if (mChangePosition || mChangeBrightness || mChangeVolume) {
+ for (Map.Entry next : mControlComponents.entrySet()) {
+ IControlComponent component = next.getKey();
+ if (component instanceof IGestureComponent) {
+ ((IGestureComponent) component).onStartSlide();
+ }
+ }
+ }
+ mFirstTouch = false;
+ }
+ if (mChangePosition) {
+ slideToChangePosition(deltaX);
+ } else if (mChangeBrightness) {
+ slideToChangeBrightness(deltaY);
+ } else if (mChangeVolume) {
+ slideToChangeVolume(deltaY);
+ }
+ return true;
+ }
+
+ protected void slideToChangePosition(float deltaX) {
+ deltaX = -deltaX;
+ int width = getMeasuredWidth();
+ int duration = (int) mControlWrapper.getDuration();
+ int currentPosition = (int) mControlWrapper.getCurrentPosition();
+ int position = (int) (deltaX / width * 120000 + currentPosition);
+ if (position > duration) position = duration;
+ if (position < 0) position = 0;
+ for (Map.Entry next : mControlComponents.entrySet()) {
+ IControlComponent component = next.getKey();
+ if (component instanceof IGestureComponent) {
+ ((IGestureComponent) component).onPositionChange(position, currentPosition, duration);
+ }
+ }
+ updateSeekUI(currentPosition, position, duration);
+ mSeekPosition = position;
+ }
+
+ protected void updateSeekUI(int curr, int seekTo, int duration) {
+
+ }
+
+ protected void slideToChangeBrightness(float deltaY) {
+ Activity activity = PlayerUtils.scanForActivity(getContext());
+ if (activity == null) return;
+ Window window = activity.getWindow();
+ WindowManager.LayoutParams attributes = window.getAttributes();
+ int height = getMeasuredHeight();
+ if (mBrightness == -1.0f) mBrightness = 0.5f;
+ float brightness = deltaY * 2 / height * 1.0f + mBrightness;
+ if (brightness < 0) {
+ brightness = 0f;
+ }
+ if (brightness > 1.0f) brightness = 1.0f;
+ int percent = (int) (brightness * 100);
+ attributes.screenBrightness = brightness;
+ window.setAttributes(attributes);
+ for (Map.Entry next : mControlComponents.entrySet()) {
+ IControlComponent component = next.getKey();
+ if (component instanceof IGestureComponent) {
+ ((IGestureComponent) component).onBrightnessChange(percent);
+ }
+ }
+ Message msg = Message.obtain();
+ msg.what = 100;
+ msg.obj = "亮度" + percent + "%";
+ mHandler.sendMessage(msg);
+ mHandler.removeMessages(101);
+ mHandler.sendEmptyMessageDelayed(101, 1000);
+ }
+
+ protected void slideToChangeVolume(float deltaY) {
+ int streamMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ int height = getMeasuredHeight();
+ float deltaV = deltaY * 2 / height * streamMaxVolume;
+ float index = mStreamVolume + deltaV;
+ if (index > streamMaxVolume) index = streamMaxVolume;
+ if (index < 0) index = 0;
+ int percent = (int) (index / streamMaxVolume * 100);
+ mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) index, 0);
+ for (Map.Entry next : mControlComponents.entrySet()) {
+ IControlComponent component = next.getKey();
+ if (component instanceof IGestureComponent) {
+ ((IGestureComponent) component).onVolumeChange(percent);
+ }
+ }
+ Message msg = Message.obtain();
+ msg.what = 100;
+ msg.obj = "音量" + percent + "%";
+ mHandler.sendMessage(msg);
+ mHandler.removeMessages(101);
+ mHandler.sendEmptyMessageDelayed(101, 1000);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ //滑动结束时事件处理
+ if (!mGestureDetector.onTouchEvent(event)) {
+ int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ stopSlide();
+ if (mSeekPosition > 0) {
+ mControlWrapper.seekTo(mSeekPosition);
+ mSeekPosition = 0;
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ stopSlide();
+ mSeekPosition = 0;
+ break;
+ }
+ }
+ return super.onTouchEvent(event);
+ }
+
+ private void stopSlide() {
+ for (Map.Entry next : mControlComponents.entrySet()) {
+ IControlComponent component = next.getKey();
+ if (component instanceof IGestureComponent) {
+ ((IGestureComponent) component).onStopSlide();
+ }
+ }
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ return false;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+
+ }
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ return false;
+ }
+
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return false;
+ }
+
+ public boolean onKeyEvent(KeyEvent event) {
+ return false;
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVideoController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVideoController.java
deleted file mode 100644
index 9b0918bede..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVideoController.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.github.tvbox.osc.player.controller;
-
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.Animation;
-import android.widget.ProgressBar;
-
-import androidx.annotation.AttrRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.dueeeke.videoplayer.controller.GestureVideoController;
-import com.dueeeke.videoplayer.controller.IControlComponent;
-import com.dueeeke.videoplayer.player.VideoView;
-import com.dueeeke.videoplayer.player.VideoViewManager;
-import com.github.tvbox.osc.R;
-
-import java.util.Map;
-
-/**
- * 直播/点播控制器
- * 注意:此控制器仅做一个参考,如果想定制ui,你可以直接继承GestureVideoController或者BaseVideoController实现
- * 你自己的控制器
- * Created by dueeeke on 2017/4/7.
- */
-
-public class BoxVideoController extends GestureVideoController implements View.OnClickListener {
-
- protected ProgressBar mLoadingProgress;
-
- public BoxVideoController(@NonNull Context context) {
- this(context, null);
- VideoViewManager.instance().setPlayOnMobileNetwork(true);
- }
-
- public BoxVideoController(@NonNull Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public BoxVideoController(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- protected int getLayoutId() {
- return R.layout.box_standard_controller;
- }
-
- @Override
- protected void initView() {
- super.initView();
- mLoadingProgress = findViewById(R.id.loading);
- }
-
- @Override
- public void onClick(View v) {
- int i = v.getId();
- }
-
-
- @Override
- protected void onVisibilityChanged(boolean isVisible, Animation anim) {
- if (mControlWrapper.isFullScreen()) {
- if (isVisible) {
- } else {
- }
- }
- }
-
- @Override
- protected void onPlayStateChanged(int playState) {
- super.onPlayStateChanged(playState);
- switch (playState) {
- //调用release方法会回到此状态
- case VideoView.STATE_IDLE:
- mLoadingProgress.setVisibility(GONE);
- break;
- case VideoView.STATE_PLAYING:
- case VideoView.STATE_PAUSED:
- case VideoView.STATE_PREPARED:
- case VideoView.STATE_ERROR:
- case VideoView.STATE_BUFFERED:
- mLoadingProgress.setVisibility(GONE);
- break;
- case VideoView.STATE_PREPARING:
- case VideoView.STATE_BUFFERING:
- mLoadingProgress.setVisibility(VISIBLE);
- break;
- case VideoView.STATE_PLAYBACK_COMPLETED:
- mLoadingProgress.setVisibility(GONE);
- break;
- }
- }
-
- private OnScreenTapListener screenTapListener;
-
- public interface OnScreenTapListener {
- void tap();
- }
-
- public void setScreenTapListener(OnScreenTapListener screenTapListener) {
- this.screenTapListener = screenTapListener;
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- if (screenTapListener != null)
- screenTapListener.tap();
- return super.onSingleTapConfirmed(e);
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- return super.onScroll(e1, e2, distanceX, distanceY);
- }
-
- private boolean simSlideStart = false;
- private int simSeekPosition = 0;
- private long simSlideOffset = 0;
-
- public boolean isBoxTVBottomShow() {
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- return ((BoxVodControlView) component).isTVBottomShow();
- }
- }
- return false;
- }
-
- public void boxTVBottomToggle() {
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVBottomToggle();
- }
- }
- }
-
- public void boxTVTogglePlay() {
- if (mControlWrapper.isPlaying()) {
- mControlWrapper.pause();
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVPause();
- }
- }
- } else {
- mControlWrapper.start();
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVPlay();
- }
- }
- }
- }
-
- public void boxTVRefreshInfo(String title) {
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVInfo(title);
- }
- }
- }
-
- public void boxTVSlideStop() {
- if (!simSlideStart)
- return;
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVStopSlide();
- }
- }
- mControlWrapper.seekTo(simSeekPosition);
- if (!mControlWrapper.isPlaying())
- mControlWrapper.start();
- simSlideStart = false;
- simSeekPosition = 0;
- simSlideOffset = 0;
- }
-
- public void boxTVSlideStart(int dir) {
- int duration = (int) mControlWrapper.getDuration();
- if (duration <= 0)
- return;
- if (!simSlideStart) {
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVStartSlide();
- }
- }
- simSlideStart = true;
- }
- // 每次10秒
- simSlideOffset += (10000.0f * dir);
- int currentPosition = (int) mControlWrapper.getCurrentPosition();
- int position = (int) (simSlideOffset + currentPosition);
- if (position > duration) position = duration;
- if (position < 0) position = 0;
- for (Map.Entry next : mControlComponents.entrySet()) {
- IControlComponent component = next.getKey();
- if (component instanceof BoxVodControlView) {
- ((BoxVodControlView) component).onTVPositionChange(position, currentPosition, duration);
- }
- }
- simSeekPosition = position;
- }
-}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVodControlView.java b/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVodControlView.java
deleted file mode 100644
index 93f37addab..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/player/controller/BoxVodControlView.java
+++ /dev/null
@@ -1,492 +0,0 @@
-package com.github.tvbox.osc.player.controller;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.dueeeke.videoplayer.controller.ControlWrapper;
-import com.dueeeke.videoplayer.controller.IControlComponent;
-import com.dueeeke.videoplayer.player.VideoView;
-import com.github.tvbox.osc.R;
-
-import static com.dueeeke.videoplayer.util.PlayerUtils.stringForTime;
-
-/**
- * 点播底部控制栏
- */
-public class BoxVodControlView extends FrameLayout implements IControlComponent, View.OnClickListener, SeekBar.OnSeekBarChangeListener {
-
- protected ControlWrapper mControlWrapper;
-
- private TextView mTotalTime, mCurrTime;
- private LinearLayout mBottomContainer;
- private LinearLayout mCenterContainer;
- private SeekBar mVideoProgress;
- private ProgressBar mBottomProgress;
- private ImageView mPlayButton;
- private TextView mPlayNext;
- private TextView mPlayPre;
- private TextView mPlaySize;
- private TextView mPlaySpeed;
- private boolean mIsDragging;
-
- private boolean mIsShowBottomProgress = false;
-
- // tv 相关控制
- private ImageView mTVProgressIcon;
- private TextView mTVProgressText;
- private TextView mTVName;
- private TextView mTVHint;
- private TextView mTVPauseProgressText;
-
- private LinearLayout mTVProgressContainer;
- private LinearLayout mTVPauseContainer;
- private LinearLayout mTVBottomContainer;
- private FrameLayout mTVInfoContainer;
- private TextView mTvPlayNext;
- private TextView mTvPlayPre;
- private TextView mTvPlaySize;
- private TextView mTvPlaySpeed;
-
- public BoxVodControlView(@NonNull Context context) {
- super(context);
- }
-
- public BoxVodControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- }
-
- public BoxVodControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
-
- {
- LayoutInflater.from(getContext()).inflate(getLayoutId(), this, true);
- mBottomContainer = findViewById(R.id.bottom_container);
- mCenterContainer = findViewById(R.id.center_container);
- mVideoProgress = findViewById(R.id.seekBar);
- mVideoProgress.setOnSeekBarChangeListener(this);
- mTotalTime = findViewById(R.id.total_time);
- mCurrTime = findViewById(R.id.curr_time);
- mPlayButton = findViewById(R.id.iv_play);
- mPlayButton.setOnClickListener(this);
- mBottomProgress = findViewById(R.id.bottom_progress);
- mPlayNext = findViewById(R.id.play_next);
- mPlayPre = findViewById(R.id.play_pre);
- mPlaySize = findViewById(R.id.video_size);
- mPlaySpeed = findViewById(R.id.video_speed);
- mPlayNext.setOnClickListener(this);
- mPlayPre.setOnClickListener(this);
- mPlaySize.setOnClickListener(this);
- mPlaySpeed.setOnClickListener(this);
-
- //5.1以下系统SeekBar高度需要设置成WRAP_CONTENT
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
- mVideoProgress.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
- }
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mBottomProgress.setVisibility(GONE);
-
- // tv 相关控制
- mTVProgressContainer = findViewById(R.id.tv_progress_container);
- mTVProgressIcon = findViewById(R.id.tv_progress_icon);
- mTVProgressText = findViewById(R.id.tv_progress_text);
- mTVPauseContainer = findViewById(R.id.tv_pause_container);
- mTVPauseProgressText = findViewById(R.id.tv_pause_progress_text);
- mTVBottomContainer = findViewById(R.id.tv_bottom_container);
- mTVInfoContainer = findViewById(R.id.tv_info_container);
- mTVName = findViewById(R.id.tv_info_name);
- mTVHint = findViewById(R.id.tv_info_hint);
- mTvPlayNext = findViewById(R.id.tv_play_next);
- mTvPlayPre = findViewById(R.id.tv_play_pre);
- mTvPlayNext.setOnClickListener(this);
- mTvPlayPre.setOnClickListener(this);
- mTvPlaySize = findViewById(R.id.tv_video_size);
- mTvPlaySpeed = findViewById(R.id.tv_video_speed);
- mTvPlaySize.setOnClickListener(this);
- mTvPlaySpeed.setOnClickListener(this);
- mTVInfoContainer.setVisibility(GONE);
- }
-
- protected int getLayoutId() {
- return R.layout.box_vod_control_view;
- }
-
- /**
- * 是否显示底部进度条,默认显示
- */
- public void showBottomProgress(boolean isShow) {
- mIsShowBottomProgress = isShow;
- }
-
- @Override
- public void attach(@NonNull ControlWrapper controlWrapper) {
- mControlWrapper = controlWrapper;
- refreshScaleAndSpeed();
- }
-
- @Override
- public View getView() {
- return this;
- }
-
- @Override
- public void onVisibilityChanged(boolean isVisible, Animation anim) {
- if (isVisible) {
- mBottomContainer.setVisibility(VISIBLE);
- mCenterContainer.setVisibility(VISIBLE);
- mTVInfoContainer.setVisibility(VISIBLE);
- if (anim != null) {
- mBottomContainer.startAnimation(anim);
- }
- if (mIsShowBottomProgress) {
- mBottomProgress.setVisibility(GONE);
- }
- } else {
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- if (anim != null) {
- mBottomContainer.startAnimation(anim);
- }
- if (mIsShowBottomProgress) {
- mBottomProgress.setVisibility(VISIBLE);
- AlphaAnimation animation = new AlphaAnimation(0f, 1f);
- animation.setDuration(300);
- mBottomProgress.startAnimation(animation);
- }
- }
- }
-
- @Override
- public void onPlayStateChanged(int playState) {
- switch (playState) {
- case VideoView.STATE_IDLE:
- case VideoView.STATE_PLAYBACK_COMPLETED:
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- mBottomProgress.setVisibility(GONE);
- mBottomProgress.setProgress(0);
- mBottomProgress.setSecondaryProgress(0);
- mVideoProgress.setProgress(0);
- mVideoProgress.setSecondaryProgress(0);
- break;
- case VideoView.STATE_START_ABORT:
- case VideoView.STATE_PREPARING:
- case VideoView.STATE_PREPARED:
- case VideoView.STATE_ERROR:
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- mBottomProgress.setVisibility(GONE);
- break;
- case VideoView.STATE_PLAYING:
- mPlayButton.setSelected(true);
- if (mIsShowBottomProgress) {
- if (mControlWrapper.isShowing()) {
- mBottomProgress.setVisibility(GONE);
- mBottomContainer.setVisibility(VISIBLE);
- mCenterContainer.setVisibility(VISIBLE);
- mTVInfoContainer.setVisibility(VISIBLE);
- } else {
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- mBottomProgress.setVisibility(VISIBLE);
- }
- } else {
- mBottomContainer.setVisibility(GONE);
- mCenterContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- }
- //开始刷新进度
- mControlWrapper.startProgress();
- break;
- case VideoView.STATE_PAUSED:
- mPlayButton.setSelected(false);
- break;
- case VideoView.STATE_BUFFERING:
- case VideoView.STATE_BUFFERED:
- mPlayButton.setSelected(mControlWrapper.isPlaying());
- break;
- }
- }
-
- @Override
- public void onPlayerStateChanged(int playerState) {
- }
-
- @Override
- public void setProgress(int duration, int position) {
- if (mIsDragging) {
- return;
- }
-
- if (mVideoProgress != null) {
- if (duration > 0) {
- mVideoProgress.setEnabled(true);
- int pos = (int) (position * 1.0 / duration * mVideoProgress.getMax());
- mVideoProgress.setProgress(pos);
- mBottomProgress.setProgress(pos);
- } else {
- mVideoProgress.setEnabled(false);
- }
- int percent = mControlWrapper.getBufferedPercentage();
- if (percent >= 95) { //解决缓冲进度不能100%问题
- mVideoProgress.setSecondaryProgress(mVideoProgress.getMax());
- mBottomProgress.setSecondaryProgress(mBottomProgress.getMax());
- } else {
- mVideoProgress.setSecondaryProgress(percent * 10);
- mBottomProgress.setSecondaryProgress(percent * 10);
- }
- }
-
- if (mTotalTime != null)
- mTotalTime.setText(stringForTime(duration));
- if (mCurrTime != null)
- mCurrTime.setText(stringForTime(position));
- }
-
- @Override
- public void onLockStateChanged(boolean isLocked) {
- onVisibilityChanged(!isLocked, null);
- }
-
- @Override
- public void onClick(View v) {
- int id = v.getId();
- if (id == R.id.iv_play) {
- mControlWrapper.togglePlay();
- } else if (id == R.id.play_next) {
- hideTvPause();
- vodControlListener.playNext();
- } else if (id == R.id.play_pre) {
- hideTvPause();
- vodControlListener.playPre();
- } else if (id == R.id.video_size) {
- changeScale();
- } else if (id == R.id.video_speed) {
- changeSpeed();
- } else if (id == R.id.tv_play_next) {
- onTVBottomToggle();
- hideTvPause();
- vodControlListener.playNext();
- } else if (id == R.id.tv_play_pre) {
- onTVBottomToggle();
- hideTvPause();
- vodControlListener.playPre();
- } else if (id == R.id.tv_video_size) {
- changeScale();
- } else if (id == R.id.tv_video_speed) {
- changeSpeed();
- }
- }
-
- private int screenScaleType = VideoView.SCREEN_SCALE_DEFAULT;
- private float videoSpeed = 1.0f;
-
- private void changeScale() {
- screenScaleType += 1;
- if (screenScaleType > VideoView.SCREEN_SCALE_CENTER_CROP) {
- screenScaleType = 0;
- }
- mControlWrapper.setScreenScaleType(screenScaleType);
- refreshScaleAndSpeed();
- }
-
- private void changeSpeed() {
- videoSpeed += 0.25f;
- if (videoSpeed > 2.1) {
- videoSpeed = 0.5f;
- }
- mControlWrapper.setSpeed(videoSpeed);
- refreshScaleAndSpeed();
- }
-
- private void refreshScaleAndSpeed() {
- String scaleText = "默认";
- switch (screenScaleType) {
- case VideoView.SCREEN_SCALE_DEFAULT:
- scaleText = "默认";
- break;
- case VideoView.SCREEN_SCALE_16_9:
- scaleText = "16:9";
- break;
- case VideoView.SCREEN_SCALE_4_3:
- scaleText = "4:3";
- break;
- case VideoView.SCREEN_SCALE_MATCH_PARENT:
- scaleText = "填充";
- break;
- case VideoView.SCREEN_SCALE_ORIGINAL:
- scaleText = "原始";
- break;
- case VideoView.SCREEN_SCALE_CENTER_CROP:
- scaleText = "裁剪";
- break;
- }
- String speedText = "x" + videoSpeed;
- mPlaySize.setText(scaleText);
- mPlaySpeed.setText(speedText);
- mTvPlaySize.setText(scaleText);
- mTvPlaySpeed.setText(speedText);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mIsDragging = true;
- mControlWrapper.stopProgress();
- mControlWrapper.stopFadeOut();
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- long duration = mControlWrapper.getDuration();
- long newPosition = (duration * seekBar.getProgress()) / mVideoProgress.getMax();
- mControlWrapper.seekTo((int) newPosition);
- mIsDragging = false;
- mControlWrapper.startProgress();
- mControlWrapper.startFadeOut();
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (!fromUser) {
- return;
- }
-
- long duration = mControlWrapper.getDuration();
- long newPosition = (duration * progress) / mVideoProgress.getMax();
- if (mCurrTime != null)
- mCurrTime.setText(stringForTime((int) newPosition));
- }
-
- // tv 相关控制
- public void onTVStartSlide() {
- mControlWrapper.hide();
- mTVProgressContainer.animate()
- .alpha(1f)
- .setDuration(0)
- .setListener(null);
- mTVProgressContainer.setVisibility(VISIBLE);
- mTVInfoContainer.setVisibility(VISIBLE);
- // 快进快退 隐藏暂停 因为结束 会 结束自动开始播放
- hideTvPause();
- }
-
-
- public void onTVStopSlide() {
- mTVProgressContainer.animate()
- .alpha(0f)
- .setDuration(300)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mTVProgressContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- }
- })
- .start();
- }
-
- public void onTVPositionChange(int slidePosition, int currentPosition, int duration) {
- if (slidePosition > currentPosition) {
- mTVProgressIcon.setImageResource(R.drawable.ic_pre);
- } else {
- mTVProgressIcon.setImageResource(R.drawable.ic_back);
- }
- mTVProgressText.setText(String.format("%s/%s", stringForTime(slidePosition), stringForTime(duration)));
- }
-
- private void hideTvPause() {
- mTVPauseContainer.animate()
- .alpha(0f)
- .setDuration(0)
- .setListener(null);
- }
-
- public void onTVPause() {
- int duration = (int) mControlWrapper.getDuration();
- int currentPosition = (int) mControlWrapper.getCurrentPosition();
- mTVPauseProgressText.setText(String.format("%s/%s", stringForTime(currentPosition), stringForTime(duration)));
- mTVPauseContainer.setVisibility(VISIBLE);
- mTVInfoContainer.setVisibility(VISIBLE);
- mTVPauseContainer.setAlpha(1f);
- }
-
- public void onTVBottomToggle() {
- boolean show = mTVBottomContainer.getVisibility() == GONE;
- // mTVPauseContainer 显示时 不显示底部控制菜单
- if (show && mTVPauseContainer.getVisibility() == VISIBLE)
- return;
- mTVBottomContainer.setVisibility(show ? VISIBLE : GONE);
- }
-
- public boolean isTVBottomShow() {
- return mTVBottomContainer.getVisibility() == VISIBLE;
- }
-
- public void onTVPlay() {
- mTVPauseContainer.animate()
- .alpha(0f)
- .setDuration(300)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mTVPauseContainer.setVisibility(GONE);
- mTVInfoContainer.setVisibility(GONE);
- }
- })
- .start();
- }
-
- public void onTVInfo(String title) {
- mTVName.setText(title);
- }
-
- public void hideNextPre() {
- mPlayNext.setVisibility(GONE);
- mPlayPre.setVisibility(GONE);
- mTVHint.setVisibility(GONE);
- mTvPlayNext.setVisibility(GONE);
- mTvPlayPre.setVisibility(GONE);
- ViewGroup.LayoutParams layoutParams = mTVName.getLayoutParams();
- if (layoutParams instanceof FrameLayout.LayoutParams) {
- ((LayoutParams) layoutParams).gravity = Gravity.CENTER;
- }
- }
-
- public interface BoxVodControlListener {
- void playNext();
-
- void playPre();
- }
-
- private BoxVodControlListener vodControlListener;
-
- public void setVodControlListener(BoxVodControlListener vodControlListener) {
- this.vodControlListener = vodControlListener;
- }
-}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/LiveController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/LiveController.java
new file mode 100644
index 0000000000..745fff3d19
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/player/controller/LiveController.java
@@ -0,0 +1,85 @@
+package com.github.tvbox.osc.player.controller;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.base.App;
+
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * 直播控制器
+ */
+
+public class LiveController extends BaseController {
+ protected ProgressBar mLoading;
+ private int minFlingDistance = 100; //最小识别距离
+ private int minFlingVelocity = 10; //最小识别速度
+
+ public LiveController(@NotNull Context context) {
+ super(context);
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.player_live_control_view;
+ }
+
+ @Override
+ protected void initView() {
+ super.initView();
+ mLoading = findViewById(R.id.loading);
+ }
+
+ public interface LiveControlListener {
+ boolean singleTap();
+
+ void longPress();
+
+ void playStateChanged(int playState);
+
+ void changeSource(int direction);
+ }
+
+ private LiveController.LiveControlListener listener = null;
+
+ public void setListener(LiveController.LiveControlListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (listener.singleTap())
+ return true;
+ return super.onSingleTapConfirmed(e);
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ listener.longPress();
+ super.onLongPress(e);
+ }
+
+ @Override
+ protected void onPlayStateChanged(int playState) {
+ super.onPlayStateChanged(playState);
+ listener.playStateChanged(playState);
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if (e1.getX() - e2.getX() > minFlingDistance && Math.abs(velocityX) > minFlingVelocity) {
+ listener.changeSource(-1); //左滑
+ } else if (e2.getX() - e1.getX() > minFlingDistance && Math.abs(velocityX) > minFlingVelocity) {
+ listener.changeSource(1); //右滑
+ } else if (e1.getY() - e2.getY() > minFlingDistance && Math.abs(velocityY) > minFlingVelocity) {
+ } else if (e2.getY() - e1.getY() > minFlingDistance && Math.abs(velocityY) > minFlingVelocity) {
+ }
+ return false;
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java
new file mode 100644
index 0000000000..fe22096db4
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java
@@ -0,0 +1,585 @@
+package com.github.tvbox.osc.player.controller;
+
+import android.content.Context;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.api.ApiConfig;
+import com.github.tvbox.osc.bean.IJKCode;
+import com.github.tvbox.osc.bean.ParseBean;
+import com.github.tvbox.osc.player.thirdparty.MXPlayer;
+import com.github.tvbox.osc.player.thirdparty.ReexPlayer;
+import com.github.tvbox.osc.ui.adapter.ParseAdapter;
+import com.github.tvbox.osc.util.HawkConfig;
+import com.github.tvbox.osc.util.PlayerHelper;
+import com.orhanobut.hawk.Hawk;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
+
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.List;
+
+import xyz.doikki.videoplayer.player.VideoView;
+import xyz.doikki.videoplayer.util.PlayerUtils;
+
+import static xyz.doikki.videoplayer.util.PlayerUtils.stringForTime;
+
+public class VodController extends BaseController {
+ public VodController(@NonNull @NotNull Context context) {
+ super(context);
+ mHandlerCallback = new HandlerCallback() {
+ @Override
+ public void callback(Message msg) {
+ switch (msg.what) {
+ case 1000: { // seek 刷新
+ mProgressRoot.setVisibility(VISIBLE);
+ break;
+ }
+ case 1001: { // seek 关闭
+ mProgressRoot.setVisibility(GONE);
+ break;
+ }
+ case 1002: { // 显示底部菜单
+ mBottomRoot.setVisibility(VISIBLE);
+ break;
+ }
+ case 1003: { // 隐藏底部菜单
+ mBottomRoot.setVisibility(GONE);
+ break;
+ }
+ case 1004: { // 设置速度
+ if (isInPlaybackState()) {
+ try {
+ float speed = (float) mPlayerConfig.getDouble("sp");
+ mControlWrapper.setSpeed(speed);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ } else
+ mHandler.sendEmptyMessageDelayed(1004, 100);
+ break;
+ }
+ }
+ }
+ };
+ }
+
+ SeekBar mSeekBar;
+ TextView mCurrentTime;
+ TextView mTotalTime;
+ boolean mIsDragging;
+ LinearLayout mProgressRoot;
+ TextView mProgressText;
+ ImageView mProgressIcon;
+ LinearLayout mBottomRoot;
+ LinearLayout mParseRoot;
+ TvRecyclerView mGridView;
+ TextView mPlayTitle;
+ TextView mNextBtn;
+ TextView mPreBtn;
+ TextView mPlayerScaleBtn;
+ TextView mPlayerSpeedBtn;
+ TextView mPlayerBtn;
+ TextView mPlayerIJKBtn;
+ TextView mPlayerRetry;
+ TextView mPlayerTimeStartBtn;
+ TextView mPlayerTimeSkipBtn;
+ TextView mPlayerTimeStepBtn;
+
+ @Override
+ protected void initView() {
+ super.initView();
+ mCurrentTime = findViewById(R.id.curr_time);
+ mTotalTime = findViewById(R.id.total_time);
+ mPlayTitle = findViewById(R.id.tv_info_name);
+ mSeekBar = findViewById(R.id.seekBar);
+ mProgressRoot = findViewById(R.id.tv_progress_container);
+ mProgressIcon = findViewById(R.id.tv_progress_icon);
+ mProgressText = findViewById(R.id.tv_progress_text);
+ mBottomRoot = findViewById(R.id.bottom_container);
+ mParseRoot = findViewById(R.id.parse_root);
+ mGridView = findViewById(R.id.mGridView);
+ mPlayerRetry = findViewById(R.id.play_retry);
+ mNextBtn = findViewById(R.id.play_next);
+ mPreBtn = findViewById(R.id.play_pre);
+ mPlayerScaleBtn = findViewById(R.id.play_scale);
+ mPlayerSpeedBtn = findViewById(R.id.play_speed);
+ mPlayerBtn = findViewById(R.id.play_player);
+ mPlayerIJKBtn = findViewById(R.id.play_ijk);
+ mPlayerTimeStartBtn = findViewById(R.id.play_time_start);
+ mPlayerTimeSkipBtn = findViewById(R.id.play_time_end);
+ mPlayerTimeStepBtn = findViewById(R.id.play_time_step);
+
+ mGridView.setLayoutManager(new V7LinearLayoutManager(getContext(), 0, false));
+ ParseAdapter parseAdapter = new ParseAdapter();
+ parseAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ ParseBean parseBean = parseAdapter.getItem(position);
+ // 当前默认解析需要刷新
+ int currentDefault = parseAdapter.getData().indexOf(ApiConfig.get().getDefaultParse());
+ parseAdapter.notifyItemChanged(currentDefault);
+ ApiConfig.get().setDefaultParse(parseBean);
+ parseAdapter.notifyItemChanged(position);
+ listener.changeParse(parseBean);
+ hideBottom();
+ }
+ });
+ mGridView.setAdapter(parseAdapter);
+ parseAdapter.setNewData(ApiConfig.get().getParseBeanList());
+
+ mParseRoot.setVisibility(VISIBLE);
+
+ mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (!fromUser) {
+ return;
+ }
+
+ long duration = mControlWrapper.getDuration();
+ long newPosition = (duration * progress) / seekBar.getMax();
+ if (mCurrentTime != null)
+ mCurrentTime.setText(stringForTime((int) newPosition));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mIsDragging = true;
+ mControlWrapper.stopProgress();
+ mControlWrapper.stopFadeOut();
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ long duration = mControlWrapper.getDuration();
+ long newPosition = (duration * seekBar.getProgress()) / seekBar.getMax();
+ mControlWrapper.seekTo((int) newPosition);
+ mIsDragging = false;
+ mControlWrapper.startProgress();
+ mControlWrapper.startFadeOut();
+ }
+ });
+ mPlayerRetry.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ listener.replay();
+ hideBottom();
+ }
+ });
+ mNextBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ listener.playNext(false);
+ hideBottom();
+ }
+ });
+ mPreBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ listener.playPre();
+ hideBottom();
+ }
+ });
+ mPlayerScaleBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ int scaleType = mPlayerConfig.getInt("sc");
+ scaleType++;
+ if (scaleType > 5)
+ scaleType = 0;
+ mPlayerConfig.put("sc", scaleType);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ mControlWrapper.setScreenScaleType(scaleType);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerSpeedBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ float speed = (float) mPlayerConfig.getDouble("sp");
+ speed += 0.25f;
+ if (speed > 3)
+ speed = 0.5f;
+ mPlayerConfig.put("sp", speed);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ mControlWrapper.setSpeed(speed);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ int playerType = mPlayerConfig.getInt("pl");
+ boolean playerVail = false;
+ do {
+ playerType++;
+ if (playerType <= 2) {
+ playerVail = true;
+ } else if (playerType == 10) {
+ playerVail = mxPlayerExist;
+ } else if (playerType == 11) {
+ playerVail = reexPlayerExist;
+ } else if (playerType > 11) {
+ playerType = 0;
+ playerVail = true;
+ }
+ } while (!playerVail);
+ mPlayerConfig.put("pl", playerType);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ listener.replay();
+ // hideBottom();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerIJKBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ String ijk = mPlayerConfig.getString("ijk");
+ List codecs = ApiConfig.get().getIjkCodes();
+ for (int i = 0; i < codecs.size(); i++) {
+ if (ijk.equals(codecs.get(i).getName())) {
+ if (i >= codecs.size() - 1)
+ ijk = codecs.get(0).getName();
+ else {
+ ijk = codecs.get(i + 1).getName();
+ }
+ break;
+ }
+ }
+ mPlayerConfig.put("ijk", ijk);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ listener.replay();
+ hideBottom();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerTimeStartBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ int step = Hawk.get(HawkConfig.PLAY_TIME_STEP, 5);
+ int st = mPlayerConfig.getInt("st");
+ st += step;
+ if (st > 60 * 10)
+ st = 0;
+ mPlayerConfig.put("st", st);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerTimeSkipBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ int step = Hawk.get(HawkConfig.PLAY_TIME_STEP, 5);
+ int et = mPlayerConfig.getInt("et");
+ et += step;
+ if (et > 60 * 10)
+ et = 0;
+ mPlayerConfig.put("et", et);
+ updatePlayerCfgView();
+ listener.updatePlayerCfg();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ mPlayerTimeStepBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int step = Hawk.get(HawkConfig.PLAY_TIME_STEP, 5);
+ step += 5;
+ if (step > 30) {
+ step = 5;
+ }
+ Hawk.put(HawkConfig.PLAY_TIME_STEP, step);
+ updatePlayerCfgView();
+ }
+ });
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.player_vod_control_view;
+ }
+
+ public void showParse(boolean userJxList) {
+ mParseRoot.setVisibility(userJxList ? VISIBLE : GONE);
+ }
+
+ private JSONObject mPlayerConfig = null;
+
+ private boolean mxPlayerExist = false;
+ private boolean reexPlayerExist = false;
+
+ public void setPlayerConfig(JSONObject playerCfg) {
+ this.mPlayerConfig = playerCfg;
+ updatePlayerCfgView();
+ mxPlayerExist = MXPlayer.getPackageInfo() != null;
+ reexPlayerExist = ReexPlayer.getPackageInfo() != null;
+ }
+
+ void updatePlayerCfgView() {
+ try {
+ int playerType = mPlayerConfig.getInt("pl");
+ mPlayerBtn.setText(PlayerHelper.getPlayerName(playerType));
+ mPlayerScaleBtn.setText(PlayerHelper.getScaleName(mPlayerConfig.getInt("sc")));
+ mPlayerIJKBtn.setText(mPlayerConfig.getString("ijk"));
+ mPlayerIJKBtn.setVisibility(playerType == 1 ? VISIBLE : GONE);
+ mPlayerScaleBtn.setText(PlayerHelper.getScaleName(mPlayerConfig.getInt("sc")));
+ mPlayerSpeedBtn.setText("x" + mPlayerConfig.getDouble("sp"));
+ mPlayerTimeStartBtn.setText(PlayerUtils.stringForTime(mPlayerConfig.getInt("st") * 1000));
+ mPlayerTimeSkipBtn.setText(PlayerUtils.stringForTime(mPlayerConfig.getInt("et") * 1000));
+ mPlayerTimeStepBtn.setText(Hawk.get(HawkConfig.PLAY_TIME_STEP, 5) + "s");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setTitle(String playTitleInfo) {
+ mPlayTitle.setText(playTitleInfo);
+ }
+
+ public void resetSpeed() {
+ skipEnd = true;
+ mHandler.removeMessages(1004);
+ mHandler.sendEmptyMessageDelayed(1004, 100);
+ }
+
+ public interface VodControlListener {
+ void playNext(boolean rmProgress);
+
+ void playPre();
+
+ void changeParse(ParseBean pb);
+
+ void updatePlayerCfg();
+
+ void replay();
+
+ void errReplay();
+ }
+
+ public void setListener(VodControlListener listener) {
+ this.listener = listener;
+ }
+
+ private VodControlListener listener;
+
+ private boolean skipEnd = true;
+
+ @Override
+ protected void setProgress(int duration, int position) {
+ if (mIsDragging) {
+ return;
+ }
+ super.setProgress(duration, position);
+ if (skipEnd && position != 0 && duration != 0) {
+ int et = 0;
+ try {
+ et = mPlayerConfig.getInt("et");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ if (et > 0 && position + (et * 1000) >= duration) {
+ skipEnd = false;
+ listener.playNext(true);
+ }
+ }
+ mCurrentTime.setText(PlayerUtils.stringForTime(position));
+ mTotalTime.setText(PlayerUtils.stringForTime(duration));
+ if (duration > 0) {
+ mSeekBar.setEnabled(true);
+ int pos = (int) (position * 1.0 / duration * mSeekBar.getMax());
+ mSeekBar.setProgress(pos);
+ } else {
+ mSeekBar.setEnabled(false);
+ }
+ int percent = mControlWrapper.getBufferedPercentage();
+ if (percent >= 95) {
+ mSeekBar.setSecondaryProgress(mSeekBar.getMax());
+ } else {
+ mSeekBar.setSecondaryProgress(percent * 10);
+ }
+ }
+
+ private boolean simSlideStart = false;
+ private int simSeekPosition = 0;
+ private long simSlideOffset = 0;
+
+ public void tvSlideStop() {
+ if (!simSlideStart)
+ return;
+ mControlWrapper.seekTo(simSeekPosition);
+ if (!mControlWrapper.isPlaying())
+ mControlWrapper.start();
+ simSlideStart = false;
+ simSeekPosition = 0;
+ simSlideOffset = 0;
+ }
+
+ public void tvSlideStart(int dir) {
+ int duration = (int) mControlWrapper.getDuration();
+ if (duration <= 0)
+ return;
+ if (!simSlideStart) {
+ simSlideStart = true;
+ }
+ // 每次10秒
+ simSlideOffset += (10000.0f * dir);
+ int currentPosition = (int) mControlWrapper.getCurrentPosition();
+ int position = (int) (simSlideOffset + currentPosition);
+ if (position > duration) position = duration;
+ if (position < 0) position = 0;
+ updateSeekUI(currentPosition, position, duration);
+ simSeekPosition = position;
+ }
+
+ @Override
+ protected void updateSeekUI(int curr, int seekTo, int duration) {
+ super.updateSeekUI(curr, seekTo, duration);
+ if (seekTo > curr) {
+ mProgressIcon.setImageResource(R.drawable.icon_pre);
+ } else {
+ mProgressIcon.setImageResource(R.drawable.icon_back);
+ }
+ mProgressText.setText(PlayerUtils.stringForTime(seekTo) + " / " + PlayerUtils.stringForTime(duration));
+ mHandler.sendEmptyMessage(1000);
+ mHandler.removeMessages(1001);
+ mHandler.sendEmptyMessageDelayed(1001, 1000);
+ }
+
+ @Override
+ protected void onPlayStateChanged(int playState) {
+ super.onPlayStateChanged(playState);
+ switch (playState) {
+ case VideoView.STATE_IDLE:
+ break;
+ case VideoView.STATE_PLAYING:
+ startProgress();
+ break;
+ case VideoView.STATE_PAUSED:
+ break;
+ case VideoView.STATE_ERROR:
+ listener.errReplay();
+ break;
+ case VideoView.STATE_PREPARED:
+ case VideoView.STATE_BUFFERED:
+ break;
+ case VideoView.STATE_PREPARING:
+ case VideoView.STATE_BUFFERING:
+ break;
+ case VideoView.STATE_PLAYBACK_COMPLETED:
+ listener.playNext(true);
+ break;
+ }
+ }
+
+ boolean isBottomVisible() {
+ return mBottomRoot.getVisibility() == VISIBLE;
+ }
+
+ void showBottom() {
+ mHandler.removeMessages(1003);
+ mHandler.sendEmptyMessage(1002);
+ }
+
+ void hideBottom() {
+ mHandler.removeMessages(1002);
+ mHandler.sendEmptyMessage(1003);
+ }
+
+ @Override
+ public boolean onKeyEvent(KeyEvent event) {
+ if (super.onKeyEvent(event)) {
+ return true;
+ }
+ if (isBottomVisible()) {
+ return super.dispatchKeyEvent(event);
+ }
+ boolean isInPlayback = isInPlaybackState();
+ int keyCode = event.getKeyCode();
+ int action = event.getAction();
+ if (action == KeyEvent.ACTION_DOWN) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+ if (isInPlayback) {
+ tvSlideStart(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : -1);
+ return true;
+ }
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
+ if (isInPlayback) {
+ togglePlay();
+ return true;
+ }
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (!isBottomVisible()) {
+ showBottom();
+ }
+ }
+ } else if (action == KeyEvent.ACTION_UP) {
+ if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
+ if (isInPlayback) {
+ tvSlideStop();
+ return true;
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (!isBottomVisible()) {
+ showBottom();
+ } else {
+ hideBottom();
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onBackPressed() {
+ if (super.onBackPressed()) {
+ return true;
+ }
+ if (isBottomVisible()) {
+ hideBottom();
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderView.java b/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderView.java
index 5f60848353..684b28de3f 100644
--- a/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderView.java
+++ b/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderView.java
@@ -10,9 +10,9 @@
import androidx.annotation.NonNull;
-import com.dueeeke.videoplayer.player.AbstractPlayer;
-import com.dueeeke.videoplayer.render.IRenderView;
-import com.dueeeke.videoplayer.render.MeasureHelper;
+import xyz.doikki.videoplayer.player.AbstractPlayer;
+import xyz.doikki.videoplayer.render.IRenderView;
+import xyz.doikki.videoplayer.render.MeasureHelper;
public class SurfaceRenderView extends SurfaceView implements IRenderView, SurfaceHolder.Callback {
private MeasureHelper mMeasureHelper;
diff --git a/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderViewFactory.java b/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderViewFactory.java
index 81c59737b3..37a82a0845 100644
--- a/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderViewFactory.java
+++ b/app/src/main/java/com/github/tvbox/osc/player/render/SurfaceRenderViewFactory.java
@@ -2,8 +2,8 @@
import android.content.Context;
-import com.dueeeke.videoplayer.render.IRenderView;
-import com.dueeeke.videoplayer.render.RenderViewFactory;
+import xyz.doikki.videoplayer.render.IRenderView;
+import xyz.doikki.videoplayer.render.RenderViewFactory;
public class SurfaceRenderViewFactory extends RenderViewFactory {
diff --git a/app/src/main/java/com/github/tvbox/osc/player/thirdparty/MXPlayer.java b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/MXPlayer.java
new file mode 100644
index 0000000000..0132f08329
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/MXPlayer.java
@@ -0,0 +1,112 @@
+package com.github.tvbox.osc.player.thirdparty;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Parcelable;
+import android.util.Log;
+
+import com.github.tvbox.osc.base.App;
+
+import java.util.HashMap;
+
+public class MXPlayer {
+ public static final String TAG = "ThirdParty.MXPlayer";
+
+ private static final String PACKAGE_NAME_PRO = "com.mxtech.videoplayer.pro";
+ private static final String PACKAGE_NAME_AD = "com.mxtech.videoplayer.ad";
+ private static final String PLAYBACK_ACTIVITY_PRO = "com.mxtech.videoplayer.ActivityScreen";
+ private static final String PLAYBACK_ACTIVITY_AD = "com.mxtech.videoplayer.ad.ActivityScreen";
+
+ private static class MXPackageInfo {
+ final String packageName;
+ final String activityName;
+
+ MXPackageInfo(String packageName, String activityName) {
+ this.packageName = packageName;
+ this.activityName = activityName;
+ }
+ }
+
+ private static final MXPackageInfo[] PACKAGES = {
+ new MXPackageInfo(PACKAGE_NAME_PRO, PLAYBACK_ACTIVITY_PRO),
+ new MXPackageInfo(PACKAGE_NAME_AD, PLAYBACK_ACTIVITY_AD),
+ };
+
+ /**
+ * @return null if any MX Player packages not exist.
+ */
+ public static MXPackageInfo getPackageInfo() {
+ for (MXPackageInfo pkg : PACKAGES) {
+ try {
+ ApplicationInfo info = App.getInstance().getPackageManager().getApplicationInfo(pkg.packageName, 0);
+ if (info.enabled)
+ return pkg;
+ else
+ Log.v(TAG, "MX Player package `" + pkg.packageName + "` is disabled.");
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.v(TAG, "MX Player package `" + pkg.packageName + "` does not exist.");
+ }
+ }
+ return null;
+ }
+
+ private static class Subtitle {
+ final Uri uri;
+ String name;
+ String filename;
+
+ Subtitle(Uri uri) {
+ if (uri.getScheme() == null)
+ throw new IllegalStateException("Scheme is missed for subtitle URI " + uri);
+
+ this.uri = uri;
+ }
+
+ Subtitle(String uriStr) {
+ this(Uri.parse(uriStr));
+ }
+ }
+
+
+ public static boolean run(Activity activity, String url, String title, String subtitle, HashMap headers) {
+ MXPackageInfo packageInfo = getPackageInfo();
+ if (packageInfo == null)
+ return false;
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setPackage(packageInfo.packageName);
+ intent.setClassName(packageInfo.packageName, packageInfo.activityName);
+
+ intent.setData(Uri.parse(url));
+ intent.putExtra("title", title);
+ if (headers != null && headers.size() > 0) {
+ String[] hds = new String[headers.size() * 2];
+ int idx = 0;
+ for (String hk : headers.keySet()) {
+ hds[idx] = hk;
+ hds[idx + 1] = headers.get(hk).trim();
+ idx += 2;
+ }
+ intent.putExtra("headers", headers);
+ }
+
+ if (subtitle != null && !subtitle.isEmpty()) {
+ Parcelable[] parcels = new Parcelable[1];
+ parcels[0] = Uri.parse(subtitle);
+ intent.putExtra("subs", parcels);
+ intent.putExtra("subs.enable", parcels);
+ }
+
+ try {
+ activity.startActivity(intent);
+ return true;
+ } catch (ActivityNotFoundException ex) {
+ Log.e(TAG, "Can't run MX Player(Pro)", ex);
+ return false;
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/player/thirdparty/ReexPlayer.java b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/ReexPlayer.java
new file mode 100644
index 0000000000..7fca28b7c9
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/player/thirdparty/ReexPlayer.java
@@ -0,0 +1,88 @@
+package com.github.tvbox.osc.player.thirdparty;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.util.Log;
+
+import com.github.tvbox.osc.base.App;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+
+public class ReexPlayer {
+ public static final String TAG = "ThirdParty.Reex";
+
+ private static final String PACKAGE_NAME = "xyz.re.player.ex";
+ private static final String PLAYBACK_ACTIVITY = "xyz.re.player.ex.MainActivity";
+
+ private static class ReexPackageInfo {
+ final String packageName;
+ final String activityName;
+
+ ReexPackageInfo(String packageName, String activityName) {
+ this.packageName = packageName;
+ this.activityName = activityName;
+ }
+ }
+
+ private static final ReexPackageInfo[] PACKAGES = {
+ new ReexPackageInfo(PACKAGE_NAME, PLAYBACK_ACTIVITY),
+ };
+
+ public static ReexPackageInfo getPackageInfo() {
+ for (ReexPackageInfo pkg : PACKAGES) {
+ try {
+ ApplicationInfo info = App.getInstance().getPackageManager().getApplicationInfo(pkg.packageName, 0);
+ if (info.enabled)
+ return pkg;
+ else
+ Log.v(TAG, "Reex Player package `" + pkg.packageName + "` is disabled.");
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.v(TAG, "Reex Player package `" + pkg.packageName + "` does not exist.");
+ }
+ }
+ return null;
+ }
+
+ public static boolean run(Activity activity, String url, String title, String subtitle, HashMap headers) {
+ ReexPackageInfo packageInfo = getPackageInfo();
+ if (packageInfo == null)
+ return false;
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setPackage(packageInfo.packageName);
+ intent.setComponent(new ComponentName(packageInfo.packageName, packageInfo.activityName));
+ intent.setData(Uri.parse(url));
+ intent.putExtra("title", title);
+ intent.putExtra("name", title);
+ intent.putExtra("reex.extra.title", title);
+ if (headers != null && headers.size() > 0) {
+ try {
+ JSONObject json = new JSONObject();
+ for (String key : headers.keySet()) {
+ json.put(key, headers.get(key).trim());
+ }
+ intent.putExtra("reex.extra.http_header", json.toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ if (subtitle != null && !subtitle.isEmpty()) {
+ intent.putExtra("reex.extra.subtitle", subtitle);
+ }
+ try {
+ activity.startActivity(intent);
+ return true;
+ } catch (ActivityNotFoundException ex) {
+ Log.e(TAG, "Can't run Reex Player(Pro)", ex);
+ return false;
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/receiver/ProjectionReceiver.java b/app/src/main/java/com/github/tvbox/osc/receiver/ProjectionReceiver.java
deleted file mode 100644
index 292b36dae2..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/receiver/ProjectionReceiver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.github.tvbox.osc.receiver;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-import com.github.tvbox.osc.ui.activity.ProjectionPlayActivity;
-import com.github.tvbox.osc.util.AppManager;
-
-/**
- * @author pj567
- * @date :2021/3/5
- * @description:
- */
-public class ProjectionReceiver extends BroadcastReceiver {
- public static String action = "android.content.movie.projection.Action";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (action.equals(intent.getAction()) && intent.getExtras() != null) {
- AppManager.getInstance().finishActivity(ProjectionPlayActivity.class);
- Intent newIntent = new Intent(context, ProjectionPlayActivity.class);
- newIntent.putExtra("html", intent.getExtras().getString("html"));
- newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- context.startActivity(newIntent);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/server/ControlManager.java b/app/src/main/java/com/github/tvbox/osc/server/ControlManager.java
index 541e79490d..5337055cf1 100644
--- a/app/src/main/java/com/github/tvbox/osc/server/ControlManager.java
+++ b/app/src/main/java/com/github/tvbox/osc/server/ControlManager.java
@@ -15,6 +15,8 @@
import java.io.IOException;
+import tv.danmaku.ijk.media.player.IjkMediaPlayer;
+
/**
* @author pj567
* @date :2021/1/4
@@ -71,12 +73,17 @@ public void onTextReceived(String text) {
@Override
public void onApiReceived(String url) {
- Hawk.put(HawkConfig.API_URL, url);
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_API_URL_CHANGE, url));
}
+
+ @Override
+ public void onPushReceived(String url) {
+ EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_PUSH_URL, url));
+ }
});
try {
mServer.start();
+ IjkMediaPlayer.setDotPort(Hawk.get(HawkConfig.DOH_URL, 0) > 0, RemoteServer.serverPort);
break;
} catch (IOException ex) {
RemoteServer.serverPort++;
diff --git a/app/src/main/java/com/github/tvbox/osc/server/DataReceiver.java b/app/src/main/java/com/github/tvbox/osc/server/DataReceiver.java
index 5177942bc1..8e15dba9d0 100644
--- a/app/src/main/java/com/github/tvbox/osc/server/DataReceiver.java
+++ b/app/src/main/java/com/github/tvbox/osc/server/DataReceiver.java
@@ -14,4 +14,6 @@ public interface DataReceiver {
void onApiReceived(String url);
+
+ void onPushReceived(String url);
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/server/InputRequestProcess.java b/app/src/main/java/com/github/tvbox/osc/server/InputRequestProcess.java
index 90c0f02347..82d444d818 100644
--- a/app/src/main/java/com/github/tvbox/osc/server/InputRequestProcess.java
+++ b/app/src/main/java/com/github/tvbox/osc/server/InputRequestProcess.java
@@ -47,6 +47,8 @@ public NanoHTTPD.Response doResponse(NanoHTTPD.IHTTPSession session, String file
}
case "push": {
// 暂未实现
+ mDataReceiver.onPushReceived(params.get("url").trim());
+ break;
}
}
}
diff --git a/app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java b/app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java
index 7619ad762d..63065c08c9 100644
--- a/app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java
+++ b/app/src/main/java/com/github/tvbox/osc/server/RemoteServer.java
@@ -8,18 +8,20 @@
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.event.ServerEvent;
+import com.github.tvbox.osc.util.FileUtils;
+import com.github.tvbox.osc.util.OkGoHelper;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.greenrobot.eventbus.EventBus;
import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -137,6 +139,15 @@ public Response serve(IHTTPSession session) {
} catch (Throwable th) {
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, th.getMessage());
}
+ } else if (fileName.equals("/dns-query")) {
+ String name = session.getParms().get("name");
+ byte[] rs = null;
+ try {
+ rs = OkGoHelper.dnsOverHttps.lookupHttpsForwardSync(name);
+ } catch (Throwable th) {
+ rs = new byte[0];
+ }
+ return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, "application/dns-message", new ByteArrayInputStream(rs), rs.length);
}
} else if (session.getMethod() == Method.POST) {
Map files = new HashMap();
@@ -182,7 +193,7 @@ public Response serve(IHTTPSession session) {
if (fn.toLowerCase().endsWith(".zip")) {
unzip(tmp, root + "/" + path);
} else {
- copyFile(tmp, file);
+ FileUtils.copyFile(tmp, file);
}
}
if (tmp.exists())
@@ -207,7 +218,7 @@ public Response serve(IHTTPSession session) {
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(root + "/" + path);
if (file.exists()) {
- recursiveDelete(file);
+ FileUtils.recursiveDelete(file);
}
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_PLAINTEXT, "OK");
} else if (fileName.equals("/delFile")) {
@@ -359,7 +370,7 @@ void unzip(File zipFilePath, String destDirectory) throws Throwable {
}
}
- private void extractFile(InputStream inputStream, String destFilePath) throws Throwable {
+ void extractFile(InputStream inputStream, String destFilePath) throws Throwable {
File dst = new File(destFilePath);
if (dst.exists())
dst.delete();
@@ -373,38 +384,4 @@ private void extractFile(InputStream inputStream, String destFilePath) throws Th
bos.close();
}
- private void copyFile(File source, File dest) throws IOException {
- InputStream is = null;
- OutputStream os = null;
- try {
- is = new FileInputStream(source);
- os = new FileOutputStream(dest);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
- os.write(buffer, 0, length);
- }
- } finally {
- is.close();
- os.close();
- }
- }
-
- public void recursiveDelete(File file) {
- // 结束递归循环
- if (!file.exists())
- return;
-
- // 如果是目录,请进入内部并递归调用
- if (file.isDirectory()) {
- for (File f : file.listFiles()) {
- // 调用递归
- recursiveDelete(f);
- }
- }
- // 调用delete删除文件和空目录
- file.delete();
- System.out.println("Deleted file/folder: " + file.getAbsolutePath());
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/CollectActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/CollectActivity.java
new file mode 100644
index 0000000000..205fcd326b
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/CollectActivity.java
@@ -0,0 +1,152 @@
+package com.github.tvbox.osc.ui.activity;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.view.animation.BounceInterpolator;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.api.ApiConfig;
+import com.github.tvbox.osc.base.BaseActivity;
+import com.github.tvbox.osc.cache.RoomDataManger;
+import com.github.tvbox.osc.cache.VodCollect;
+import com.github.tvbox.osc.event.RefreshEvent;
+import com.github.tvbox.osc.ui.adapter.CollectAdapter;
+import com.github.tvbox.osc.util.FastClickCheckUtil;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CollectActivity extends BaseActivity {
+ private TextView tvDel;
+ private TextView tvDelTip;
+ private TvRecyclerView mGridView;
+ private CollectAdapter collectAdapter;
+ private boolean delMode = false;
+
+ @Override
+ protected int getLayoutResID() {
+ return R.layout.activity_collect;
+ }
+
+ @Override
+ protected void init() {
+ initView();
+ initData();
+ }
+
+ private void toggleDelMode() {
+ delMode = !delMode;
+ tvDelTip.setVisibility(delMode ? View.VISIBLE : View.GONE);
+ tvDel.setTextColor(delMode ? getResources().getColor(R.color.color_FF0057) : Color.WHITE);
+ }
+
+ private void initView() {
+ EventBus.getDefault().register(this);
+ tvDel = findViewById(R.id.tvDel);
+ tvDelTip = findViewById(R.id.tvDelTip);
+ mGridView = findViewById(R.id.mGridView);
+ mGridView.setHasFixedSize(true);
+ mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, isBaseOnWidth() ? 5 : 6));
+ collectAdapter = new CollectAdapter();
+ mGridView.setAdapter(collectAdapter);
+ tvDel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ toggleDelMode();
+ }
+ });
+ mGridView.setOnInBorderKeyEventListener(new TvRecyclerView.OnInBorderKeyEventListener() {
+ @Override
+ public boolean onInBorderKeyEvent(int direction, View focused) {
+ if (direction == View.FOCUS_UP) {
+ tvDel.setFocusable(true);
+ tvDel.requestFocus();
+ }
+ return false;
+ }
+ });
+ mGridView.setOnItemListener(new TvRecyclerView.OnItemListener() {
+ @Override
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
+ itemView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
+ }
+
+ @Override
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ itemView.animate().scaleX(1.05f).scaleY(1.05f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+
+ }
+ });
+ collectAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ FastClickCheckUtil.check(view);
+ VodCollect vodInfo = collectAdapter.getData().get(position);
+ if (vodInfo != null) {
+ if (delMode) {
+ collectAdapter.remove(position);
+ RoomDataManger.deleteVodCollect(vodInfo.getId());
+ } else {
+ if (ApiConfig.get().getSource(vodInfo.sourceKey) != null) {
+ Bundle bundle = new Bundle();
+ bundle.putString("id", vodInfo.vodId);
+ bundle.putString("sourceKey", vodInfo.sourceKey);
+ jumpActivity(DetailActivity.class, bundle);
+ } else {
+ Intent newIntent = new Intent(mContext, SearchActivity.class);
+ newIntent.putExtra("title", vodInfo.name);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(newIntent);
+ }
+ }
+ }
+ }
+ });
+ }
+
+ private void initData() {
+ List allVodRecord = RoomDataManger.getAllVodCollect();
+ List vodInfoList = new ArrayList<>();
+ for (VodCollect vodInfo : allVodRecord) {
+ vodInfoList.add(vodInfo);
+ }
+ collectAdapter.setNewData(vodInfoList);
+ }
+
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void refresh(RefreshEvent event) {
+ if (event.type == RefreshEvent.TYPE_HISTORY_REFRESH) {
+ initData();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (delMode) {
+ toggleDelMode();
+ return;
+ }
+ super.onBackPressed();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java
index 4e96d5f6cc..1820939c82 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java
@@ -1,5 +1,6 @@
package com.github.tvbox.osc.ui.activity;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
@@ -8,6 +9,7 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
@@ -26,7 +28,9 @@
import com.github.tvbox.osc.ui.adapter.SeriesAdapter;
import com.github.tvbox.osc.ui.adapter.SeriesFlagAdapter;
import com.github.tvbox.osc.ui.dialog.QuickSearchDialog;
+import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.FastClickCheckUtil;
+import com.github.tvbox.osc.util.MD5;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
@@ -42,6 +46,7 @@
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
+import org.json.JSONObject;
import java.net.URLEncoder;
import java.util.ArrayList;
@@ -69,7 +74,9 @@ public class DetailActivity extends BaseActivity {
private TextView tvDirector;
private TextView tvDes;
private TextView tvPlay;
+ private TextView tvSort;
private TextView tvQuickSearch;
+ private TextView tvCollect;
private TvRecyclerView mGridViewFlag;
private TvRecyclerView mGridView;
private LinearLayout mEmptyPlayList;
@@ -109,11 +116,13 @@ private void initView() {
tvDirector = findViewById(R.id.tvDirector);
tvDes = findViewById(R.id.tvDes);
tvPlay = findViewById(R.id.tvPlay);
+ tvSort = findViewById(R.id.tvSort);
+ tvCollect = findViewById(R.id.tvCollect);
tvQuickSearch = findViewById(R.id.tvQuickSearch);
mEmptyPlayList = findViewById(R.id.mEmptyPlaylist);
mGridView = findViewById(R.id.mGridView);
mGridView.setHasFixedSize(true);
- mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, 6));
+ mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, isBaseOnWidth() ? 6 : 7));
seriesAdapter = new SeriesAdapter();
mGridView.setAdapter(seriesAdapter);
mGridViewFlag = findViewById(R.id.mGridViewFlag);
@@ -121,6 +130,17 @@ private void initView() {
mGridViewFlag.setLayoutManager(new V7LinearLayoutManager(this.mContext, 0, false));
seriesFlagAdapter = new SeriesFlagAdapter();
mGridViewFlag.setAdapter(seriesFlagAdapter);
+ tvSort.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (vodInfo != null && vodInfo.seriesMap.size() > 0) {
+ vodInfo.reverseSort = !vodInfo.reverseSort;
+ vodInfo.reverse();
+ insertVod(sourceKey, vodInfo);
+ seriesAdapter.notifyDataSetChanged();
+ }
+ }
+ });
tvPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -132,10 +152,38 @@ public void onClick(View v) {
@Override
public void onClick(View v) {
startQuickSearch();
- QuickSearchDialog quickSearchDialog = new QuickSearchDialog().build(DetailActivity.this);
+ QuickSearchDialog quickSearchDialog = new QuickSearchDialog(DetailActivity.this);
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH, quickSearchData));
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, quickSearchWord));
quickSearchDialog.show();
+ if (pauseRunnable != null && pauseRunnable.size() > 0) {
+ searchExecutorService = Executors.newFixedThreadPool(5);
+ for (Runnable runnable : pauseRunnable) {
+ searchExecutorService.execute(runnable);
+ }
+ pauseRunnable.clear();
+ pauseRunnable = null;
+ }
+ quickSearchDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ try {
+ if (searchExecutorService != null) {
+ pauseRunnable = searchExecutorService.shutdownNow();
+ searchExecutorService = null;
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
+ }
+ });
+ }
+ });
+ tvCollect.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ RoomDataManger.insertVodCollect(sourceKey, vodInfo);
+ Toast.makeText(DetailActivity.this, "已加入收藏夹", Toast.LENGTH_SHORT).show();
}
});
mGridView.setOnItemListener(new TvRecyclerView.OnItemListener() {
@@ -155,13 +203,7 @@ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
}
});
mGridViewFlag.setOnItemListener(new TvRecyclerView.OnItemListener() {
- @Override
- public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
-
- }
-
- @Override
- public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ private void refresh(View itemView, int position) {
String newFlag = seriesFlagAdapter.getData().get(position).name;
if (vodInfo != null && !vodInfo.playFlag.equals(newFlag)) {
for (int i = 0; i < vodInfo.seriesFlags.size(); i++) {
@@ -182,14 +224,18 @@ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
}
@Override
- public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
}
- });
- seriesFlagAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+
@Override
- public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
- FastClickCheckUtil.check(view);
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ refresh(itemView, position);
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ refresh(itemView, position);
}
});
seriesAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@@ -213,6 +259,8 @@ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
setLoadSir(llLayout);
}
+ private List pauseRunnable = null;
+
private void jumpToPlay() {
if (vodInfo != null && vodInfo.seriesMap.get(vodInfo.playFlag).size() > 0) {
Bundle bundle = new Bundle();
@@ -242,6 +290,21 @@ public void run() {
}, 100);
}
+ private void setTextShow(TextView view, String tag, String info) {
+ if (info == null || info.trim().isEmpty()) {
+ view.setVisibility(View.GONE);
+ return;
+ }
+ view.setVisibility(View.VISIBLE);
+ view.setText(Html.fromHtml(getHtml(tag, info)));
+ }
+
+ private String removeHtmlTag(String info) {
+ if (info == null)
+ return "";
+ return info.replaceAll("\\<.*?\\>", "").replaceAll("\\s", "");
+ }
+
private void initViewModel() {
sourceViewModel = new ViewModelProvider(this).get(SourceViewModel.class);
sourceViewModel.detailResult.observe(this, new Observer() {
@@ -255,26 +318,26 @@ public void onChanged(AbsXml absXml) {
vodInfo.sourceKey = mVideo.sourceKey;
tvName.setText(mVideo.name);
- tvSite.setText(Html.fromHtml(getHtml("来源:", mVideo.sourceKey)));
- tvYear.setText(Html.fromHtml(getHtml("年份:", String.valueOf(mVideo.year))));
- tvArea.setText(Html.fromHtml(getHtml("地区:", mVideo.area)));
- tvLang.setText(Html.fromHtml(getHtml("语言:", mVideo.lang)));
- tvType.setText(Html.fromHtml(getHtml("类型:", mVideo.type)));
- tvActor.setText(Html.fromHtml(getHtml("演员:", mVideo.actor)));
- tvDirector.setText(Html.fromHtml(getHtml("导演:", mVideo.director)));
- tvDes.setText(Html.fromHtml(getHtml("内容简介:", mVideo.des)));
+ setTextShow(tvSite, "来源:", ApiConfig.get().getSource(mVideo.sourceKey).getName());
+ setTextShow(tvYear, "年份:", mVideo.year == 0 ? "" : String.valueOf(mVideo.year));
+ setTextShow(tvArea, "地区:", mVideo.area);
+ setTextShow(tvLang, "语言:", mVideo.lang);
+ setTextShow(tvType, "类型:", mVideo.type);
+ setTextShow(tvActor, "演员:", mVideo.actor);
+ setTextShow(tvDirector, "导演:", mVideo.director);
+ setTextShow(tvDes, "内容简介:", removeHtmlTag(mVideo.des));
if (!TextUtils.isEmpty(mVideo.pic)) {
Picasso.get()
- .load(mVideo.pic)
- .transform(new RoundTransformation(mVideo.pic)
+ .load(DefaultConfig.checkReplaceProxy(mVideo.pic))
+ .transform(new RoundTransformation(MD5.string2MD5(mVideo.pic + mVideo.name))
.centerCorp(true)
.override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
.roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
- .placeholder(R.drawable.error_all_loading)
- .error(R.drawable.error_all_loading)
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
.into(ivThumb);
} else {
- ivThumb.setImageResource(R.drawable.error_all_loading);
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
}
if (vodInfo.seriesMap != null && vodInfo.seriesMap.size() > 0) {
@@ -288,9 +351,17 @@ public void onChanged(AbsXml absXml) {
if (vodInfoRecord != null) {
vodInfo.playIndex = Math.max(vodInfoRecord.playIndex, 0);
vodInfo.playFlag = vodInfoRecord.playFlag;
+ vodInfo.playerCfg = vodInfoRecord.playerCfg;
+ vodInfo.reverseSort = vodInfoRecord.reverseSort;
} else {
vodInfo.playIndex = 0;
vodInfo.playFlag = null;
+ vodInfo.playerCfg = "";
+ vodInfo.reverseSort = false;
+ }
+
+ if (vodInfo.reverseSort) {
+ vodInfo.reverse();
}
if (vodInfo.playFlag == null || !vodInfo.seriesMap.containsKey(vodInfo.playFlag))
@@ -325,6 +396,9 @@ public void onChanged(AbsXml absXml) {
}
private String getHtml(String label, String content) {
+ if (content == null) {
+ content = "";
+ }
return label + "" + content + "";
}
@@ -349,17 +423,24 @@ private void loadDetail(String vid, String key) {
public void refresh(RefreshEvent event) {
if (event.type == RefreshEvent.TYPE_REFRESH) {
if (event.obj != null) {
- int index = (int) event.obj;
- if (index != vodInfo.playIndex) {
- seriesAdapter.getData().get(vodInfo.playIndex).selected = false;
- seriesAdapter.notifyItemChanged(vodInfo.playIndex);
- seriesAdapter.getData().get(index).selected = true;
- seriesAdapter.notifyItemChanged(index);
- mGridView.setSelection(index);
- vodInfo.playIndex = index;
+ if (event.obj instanceof Integer) {
+ int index = (int) event.obj;
+ if (index != vodInfo.playIndex) {
+ seriesAdapter.getData().get(vodInfo.playIndex).selected = false;
+ seriesAdapter.notifyItemChanged(vodInfo.playIndex);
+ seriesAdapter.getData().get(index).selected = true;
+ seriesAdapter.notifyItemChanged(index);
+ mGridView.setSelection(index);
+ vodInfo.playIndex = index;
+ //保存历史
+ insertVod(sourceKey, vodInfo);
+ }
+ } else if (event.obj instanceof JSONObject) {
+ vodInfo.playerCfg = ((JSONObject) event.obj).toString();
//保存历史
insertVod(sourceKey, vodInfo);
}
+
}
} else if (event.type == RefreshEvent.TYPE_QUICK_SEARCH_SELECT) {
if (event.obj != null) {
@@ -372,9 +453,6 @@ public void refresh(RefreshEvent event) {
switchSearchWord(word);
}
} else if (event.type == RefreshEvent.TYPE_QUICK_SEARCH_RESULT) {
- synchronized (lockObj) {
- threadRunCount--;
- }
try {
searchData(event.obj == null ? null : (AbsXml) event.obj);
} catch (Exception e) {
@@ -387,10 +465,7 @@ public void refresh(RefreshEvent event) {
private boolean hadQuickStart = false;
private List quickSearchData = new ArrayList<>();
private List quickSearchWord = new ArrayList<>();
- private final ExecutorService searchExecutorService = Executors.newFixedThreadPool(5);
- private static final int maxThreadRun = 5;
- private int threadRunCount = 0;
- private final Object lockObj = new Object();
+ private ExecutorService searchExecutorService = null;
private void switchSearchWord(String word) {
OkGo.getInstance().cancelTag("quick_search");
@@ -446,40 +521,32 @@ public void onError(Response response) {
}
private void searchResult() {
- synchronized (lockObj) {
- threadRunCount = 0;
+ try {
+ if (searchExecutorService != null) {
+ searchExecutorService.shutdownNow();
+ searchExecutorService = null;
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
}
+ searchExecutorService = Executors.newFixedThreadPool(5);
List searchRequestList = new ArrayList<>();
searchRequestList.addAll(ApiConfig.get().getSourceBeanList());
SourceBean home = ApiConfig.get().getHomeSourceBean();
searchRequestList.remove(home);
searchRequestList.add(0, home);
+
+ ArrayList siteKey = new ArrayList<>();
for (SourceBean bean : searchRequestList) {
- if (!bean.isActive() || bean.isAddition()) {
+ if (!bean.isSearchable() || !bean.isQuickSearch()) {
continue;
}
- String key = bean.getKey();
+ siteKey.add(bean.getKey());
+ }
+ for (String key : siteKey) {
searchExecutorService.execute(new Runnable() {
@Override
public void run() {
- while (true) {
- int tempCount = 0;
- synchronized (lockObj) {
- tempCount = threadRunCount;
- }
- if (tempCount >= maxThreadRun) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- } else {
- break;
- }
- }
- synchronized (lockObj) {
- threadRunCount++;
- }
sourceViewModel.getQuickSearch(key, searchTitle);
}
});
@@ -491,7 +558,7 @@ private void searchData(AbsXml absXml) {
List data = new ArrayList<>();
for (Movie.Video video : absXml.movie.videoList) {
// 去除当前相同的影片
- if (video.sourceKey.equals(sourceKey) && video.id == vodId)
+ if (video.sourceKey.equals(sourceKey) && video.id.equals(vodId))
continue;
data.add(video);
}
@@ -501,6 +568,11 @@ private void searchData(AbsXml absXml) {
}
private void insertVod(String sourceKey, VodInfo vodInfo) {
+ try {
+ vodInfo.playNote = vodInfo.seriesMap.get(vodInfo.playFlag).get(vodInfo.playIndex).name;
+ } catch (Throwable th) {
+ vodInfo.playNote = "";
+ }
RoomDataManger.insertVodRecord(sourceKey, vodInfo);
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_HISTORY_REFRESH));
}
@@ -508,6 +580,14 @@ private void insertVod(String sourceKey, VodInfo vodInfo) {
@Override
protected void onDestroy() {
super.onDestroy();
+ try {
+ if (searchExecutorService != null) {
+ searchExecutorService.shutdownNow();
+ searchExecutorService = null;
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
OkGo.getInstance().cancelTag("fenci");
OkGo.getInstance().cancelTag("detail");
OkGo.getInstance().cancelTag("quick_search");
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/HistoryActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/HistoryActivity.java
index 52f98a14b8..c2578d3ca8 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/HistoryActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/HistoryActivity.java
@@ -59,7 +59,7 @@ private void initView() {
tvDelTip = findViewById(R.id.tvDelTip);
mGridView = findViewById(R.id.mGridView);
mGridView.setHasFixedSize(true);
- mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, 5));
+ mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, isBaseOnWidth() ? 5 : 6));
historyAdapter = new HistoryAdapter();
mGridView.setAdapter(historyAdapter);
tvDel.setOnClickListener(new View.OnClickListener() {
@@ -86,7 +86,7 @@ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position
@Override
public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
- itemView.animate().scaleX(1.1f).scaleY(1.1f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
+ itemView.animate().scaleX(1.05f).scaleY(1.05f).setDuration(300).setInterpolator(new BounceInterpolator()).start();
}
@Override
@@ -142,7 +142,7 @@ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
}
private void initData() {
- List allVodRecord = RoomDataManger.getAllVodRecord();
+ List allVodRecord = RoomDataManger.getAllVodRecord(100);
List vodInfoList = new ArrayList<>();
for (VodInfo vodInfo : allVodRecord) {
vodInfoList.add(vodInfo);
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/HomeActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/HomeActivity.java
index fcc3a90e63..596de2be8c 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/HomeActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/HomeActivity.java
@@ -6,8 +6,8 @@
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
@@ -22,7 +22,6 @@
import androidx.lifecycle.ViewModelProvider;
import androidx.viewpager.widget.ViewPager;
-import com.chad.library.adapter.base.BaseQuickAdapter;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.base.BaseActivity;
@@ -33,6 +32,7 @@
import com.github.tvbox.osc.server.ControlManager;
import com.github.tvbox.osc.ui.adapter.HomePageAdapter;
import com.github.tvbox.osc.ui.adapter.SortAdapter;
+import com.github.tvbox.osc.ui.dialog.TipDialog;
import com.github.tvbox.osc.ui.fragment.GridFragment;
import com.github.tvbox.osc.ui.fragment.UserFragment;
import com.github.tvbox.osc.ui.tv.widget.DefaultTransformer;
@@ -41,9 +41,10 @@
import com.github.tvbox.osc.ui.tv.widget.ViewObj;
import com.github.tvbox.osc.util.AppManager;
import com.github.tvbox.osc.util.DefaultConfig;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
+import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.util.LOG;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
+import com.orhanobut.hawk.Hawk;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
@@ -93,12 +94,20 @@ protected int getLayoutResID() {
return R.layout.activity_home;
}
+ boolean useCacheConfig = false;
+
@Override
protected void init() {
EventBus.getDefault().register(this);
ControlManager.get().startServer();
initView();
initViewModel();
+ useCacheConfig = false;
+ Intent intent = getIntent();
+ if (intent != null && intent.getExtras() != null) {
+ Bundle bundle = intent.getExtras();
+ useCacheConfig = bundle.getBoolean("useCache", false);
+ }
initData();
}
@@ -120,6 +129,7 @@ public void onItemPreSelected(TvRecyclerView tvRecyclerView, View view, int posi
textView.getPaint().setFakeBoldText(false);
textView.setTextColor(HomeActivity.this.getResources().getColor(R.color.color_BBFFFFFF));
textView.invalidate();
+ view.findViewById(R.id.tvFilter).setVisibility(View.GONE);
}
}
@@ -132,14 +142,23 @@ public void onItemSelected(TvRecyclerView tvRecyclerView, View view, int positio
textView.getPaint().setFakeBoldText(true);
textView.setTextColor(HomeActivity.this.getResources().getColor(R.color.color_FFFFFF));
textView.invalidate();
+ if (!sortAdapter.getItem(position).filters.isEmpty())
+ view.findViewById(R.id.tvFilter).setVisibility(View.VISIBLE);
HomeActivity.this.sortFocusView = view;
HomeActivity.this.sortFocused = position;
+ mHandler.removeCallbacks(mDataRunnable);
+ mHandler.postDelayed(mDataRunnable, 200);
}
}
@Override
public void onItemClick(TvRecyclerView parent, View itemView, int position) {
-
+ if (itemView != null && currentSelected == position && !sortAdapter.getItem(position).filters.isEmpty()) { // 弹出筛选
+ BaseLazyFragment baseLazyFragment = fragments.get(currentSelected);
+ if ((baseLazyFragment instanceof GridFragment)) {
+ ((GridFragment) baseLazyFragment).showFilter();
+ }
+ }
}
});
this.mGridView.setOnInBorderKeyEventListener(new TvRecyclerView.OnInBorderKeyEventListener() {
@@ -158,43 +177,8 @@ public final boolean onInBorderKeyEvent(int direction, View view) {
return false;
}
});
- this.sortAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
- public final void onItemChildClick(BaseQuickAdapter baseQuickAdapter, View view, int position) {
- if (view.getId() == R.id.tvTitle) {
- FastClickCheckUtil.check(view);
- mGridView.smoothScrollToPosition(position);
- if (view.getParent() != null) {
- ViewGroup viewGroup = (ViewGroup) view.getParent();
- sortFocusView = viewGroup;
- viewGroup.requestFocus();
- sortFocused = position;
- if (position != currentSelected) {
- currentSelected = position;
- mViewPager.setCurrentItem(position, false);
- if (position == 0) {
- changeTop(false);
- } else {
- changeTop(true);
- }
- }
- }
- }
-
- }
- });
setLoadSir(this.contentLayout);
//mHandler.postDelayed(mFindFocus, 500);
- /*
- if (!Hawk.contains("update_hint_v14")) {
- UpdateHintDialog updateHintDialog = new UpdateHintDialog().OnSureListener(new UpdateHintDialog.OnSureListener() {
- @Override
- public void sure() {
- Hawk.put("update_hint_v14", true);
- }
- }).build(this);
- updateHintDialog.show();
- }
- */
}
private void initViewModel() {
@@ -203,12 +187,12 @@ private void initViewModel() {
@Override
public void onChanged(AbsSortXml absXml) {
showSuccess();
- if (absXml != null && absXml.movieSort != null && absXml.movieSort.sortList != null) {
- sortAdapter.setNewData(DefaultConfig.adjustSort(ApiConfig.get().getHomeSourceBean().getKey(), absXml.movieSort.sortList, true));
+ if (absXml != null && absXml.classes != null && absXml.classes.sortList != null) {
+ sortAdapter.setNewData(DefaultConfig.adjustSort(ApiConfig.get().getHomeSourceBean().getKey(), absXml.classes.sortList, true));
} else {
sortAdapter.setNewData(DefaultConfig.adjustSort(ApiConfig.get().getHomeSourceBean().getKey(), new ArrayList<>(), true));
}
- initViewPager();
+ initViewPager(absXml);
}
});
}
@@ -228,15 +212,17 @@ private void initData() {
return;
}
showLoading();
- if (dataInitOk) {
+ if (dataInitOk && !jarInitOk) {
if (!ApiConfig.get().getSpider().isEmpty()) {
- ApiConfig.get().loadJar(ApiConfig.get().getSpider(), new ApiConfig.LoadConfigCallback() {
+ ApiConfig.get().loadJar(useCacheConfig, ApiConfig.get().getSpider(), new ApiConfig.LoadConfigCallback() {
@Override
public void success() {
jarInitOk = true;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
+ if (!useCacheConfig)
+ Toast.makeText(HomeActivity.this, "自定义jar加载成功", Toast.LENGTH_SHORT).show();
initData();
}
}, 50);
@@ -249,13 +235,21 @@ public void retry() {
@Override
public void error(String msg) {
+ jarInitOk = true;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(HomeActivity.this, "jar加载失败", Toast.LENGTH_SHORT).show();
+ initData();
+ }
+ });
}
});
}
return;
}
- ApiConfig.get().loadConfig(new ApiConfig.LoadConfigCallback() {
- AlertDialog dialog = null;
+ ApiConfig.get().loadConfig(useCacheConfig, new ApiConfig.LoadConfigCallback() {
+ TipDialog dialog = null;
@Override
public void retry() {
@@ -283,38 +277,59 @@ public void run() {
@Override
public void error(String msg) {
+ if (msg.equalsIgnoreCase("-1")) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ dataInitOk = true;
+ jarInitOk = true;
+ initData();
+ }
+ });
+ return;
+ }
mHandler.post(new Runnable() {
@Override
public void run() {
if (dialog == null)
- dialog = new AlertDialog.Builder(HomeActivity.this).setTitle("提示")
- .setMessage(msg + "\n\n请重试!")
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
+ dialog = new TipDialog(HomeActivity.this, msg, "重试", "取消", new TipDialog.OnListener() {
+ @Override
+ public void left() {
+ mHandler.post(new Runnable() {
@Override
- public void onClick(DialogInterface dialogInterface, int i) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- initData();
- }
- });
+ public void run() {
+ initData();
+ dialog.hide();
}
- })
- .setNegativeButton("取消", new DialogInterface.OnClickListener() {
+ });
+ }
+
+ @Override
+ public void right() {
+ dataInitOk = true;
+ jarInitOk = true;
+ mHandler.post(new Runnable() {
@Override
- public void onClick(DialogInterface dialog, int which) {
- dataInitOk = true;
- jarInitOk = true;
+ public void run() {
initData();
+ dialog.hide();
}
- })
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ });
+ }
+
+ @Override
+ public void cancel() {
+ dataInitOk = true;
+ jarInitOk = true;
+ mHandler.post(new Runnable() {
@Override
- public void onCancel(DialogInterface dialog) {
- dataInitOk = true;
- jarInitOk = true;
+ public void run() {
+ initData();
+ dialog.hide();
}
- }).create();
+ });
+ }
+ });
if (!dialog.isShowing())
dialog.show();
}
@@ -323,13 +338,17 @@ public void onCancel(DialogInterface dialog) {
}, this);
}
- private void initViewPager() {
+ private void initViewPager(AbsSortXml absXml) {
if (sortAdapter.getData().size() > 0) {
for (MovieSort.SortData data : sortAdapter.getData()) {
if (data.id.equals("my0")) {
- fragments.add(UserFragment.newInstance());
+ if (Hawk.get(HawkConfig.HOME_REC, 0) == 1 && absXml != null && absXml.videoList != null && absXml.videoList.size() > 0) {
+ fragments.add(UserFragment.newInstance(absXml.videoList));
+ } else {
+ fragments.add(UserFragment.newInstance(null));
+ }
} else {
- fragments.add(GridFragment.newInstance(data.id));
+ fragments.add(GridFragment.newInstance(data));
}
}
pageAdapter = new HomePageAdapter(getSupportFragmentManager(), fragments);
@@ -393,8 +412,14 @@ protected void onPause() {
@Subscribe(threadMode = ThreadMode.MAIN)
public void refresh(RefreshEvent event) {
- if (event.type == RefreshEvent.TYPE_API_URL_CHANGE) {
- Toast.makeText(mContext, "配置地址设置为" + (String) event.obj + ",重启应用生效!", Toast.LENGTH_SHORT).show();
+ if (event.type == RefreshEvent.TYPE_PUSH_URL) {
+ if (ApiConfig.get().getSource("push_agent") != null) {
+ Intent newIntent = new Intent(mContext, DetailActivity.class);
+ newIntent.putExtra("id", (String) event.obj);
+ newIntent.putExtra("sourceKey", "push_agent");
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ HomeActivity.this.startActivity(newIntent);
+ }
}
}
@@ -421,9 +446,9 @@ public boolean dispatchKeyEvent(KeyEvent event) {
if (topHide < 0)
return false;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
- mHandler.removeCallbacks(mDataRunnable);
+
} else if (event.getAction() == KeyEvent.ACTION_UP) {
- mHandler.postDelayed(mDataRunnable, 200);
+
}
return super.dispatchKeyEvent(event);
}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java
index c452d13983..48e0353621 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/LivePlayActivity.java
@@ -5,33 +5,40 @@
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.os.Handler;
-import android.text.TextUtils;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.dueeeke.videocontroller.component.GestureView;
-import com.dueeeke.videoplayer.player.VideoView;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
+import com.github.tvbox.osc.base.App;
import com.github.tvbox.osc.base.BaseActivity;
-import com.github.tvbox.osc.bean.LiveChannel;
-import com.github.tvbox.osc.player.controller.BoxVideoController;
-import com.github.tvbox.osc.ui.adapter.LiveChannelAdapter;
+import com.github.tvbox.osc.bean.LiveChannelGroup;
+import com.github.tvbox.osc.bean.LiveChannelItem;
+import com.github.tvbox.osc.bean.LivePlayerManager;
+import com.github.tvbox.osc.bean.LiveSettingGroup;
+import com.github.tvbox.osc.bean.LiveSettingItem;
+import com.github.tvbox.osc.player.controller.LiveController;
+import com.github.tvbox.osc.ui.adapter.LiveChannelGroupAdapter;
+import com.github.tvbox.osc.ui.adapter.LiveChannelItemAdapter;
+import com.github.tvbox.osc.ui.adapter.LiveSettingGroupAdapter;
+import com.github.tvbox.osc.ui.adapter.LiveSettingItemAdapter;
+import com.github.tvbox.osc.ui.dialog.LivePasswordDialog;
import com.github.tvbox.osc.ui.tv.widget.ViewObj;
-import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.FastClickCheckUtil;
import com.github.tvbox.osc.util.HawkConfig;
-import com.github.tvbox.osc.util.PlayerHelper;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.Response;
@@ -39,8 +46,14 @@
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
import java.util.List;
+import java.util.Locale;
+
+import xyz.doikki.videoplayer.player.VideoView;
/**
* @author pj567
@@ -49,13 +62,32 @@
*/
public class LivePlayActivity extends BaseActivity {
private VideoView mVideoView;
- private TextView tvHint;
- private TextView tvUrl;
- private TextView tvChannel;
- private TvRecyclerView mGridView;
- private LiveChannelAdapter channelAdapter;
+ private TextView tvChannelInfo;
+ private TextView tvTime;
+ private TextView tvNetSpeed;
+ private LinearLayout tvLeftChannelListLayout;
+ private TvRecyclerView mChannelGroupView;
+ private TvRecyclerView mLiveChannelView;
+ private LiveChannelGroupAdapter liveChannelGroupAdapter;
+ private LiveChannelItemAdapter liveChannelItemAdapter;
+
+ private LinearLayout tvRightSettingLayout;
+ private TvRecyclerView mSettingGroupView;
+ private TvRecyclerView mSettingItemView;
+ private LiveSettingGroupAdapter liveSettingGroupAdapter;
+ private LiveSettingItemAdapter liveSettingItemAdapter;
+ private List liveSettingGroupList = new ArrayList<>();
+
private Handler mHandler = new Handler();
+ private List liveChannelGroupList = new ArrayList<>();
+ private int currentChannelGroupIndex = 0;
+ private int currentLiveChannelIndex = -1;
+ private int currentLiveChangeSourceTimes = 0;
+ private LiveChannelItem currentLiveChannelItem = null;
+ private LivePlayerManager livePlayerManager = new LivePlayerManager();
+ private ArrayList channelGroupPasswordConfirmed = new ArrayList<>();
+
@Override
protected int getLayoutResID() {
return R.layout.activity_live_play;
@@ -65,40 +97,39 @@ protected int getLayoutResID() {
protected void init() {
setLoadSir(findViewById(R.id.live_root));
mVideoView = findViewById(R.id.mVideoView);
- PlayerHelper.updateCfg(mVideoView);
-// ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
-// layoutParams.width = 100;
-// layoutParams.height = 50;
-// mVideoView.setLayoutParams(layoutParams);
- mGridView = findViewById(R.id.mGridView);
- tvChannel = findViewById(R.id.tvChannel);
- tvHint = findViewById(R.id.tvHint);
- tvUrl = findViewById(R.id.tvUrl);
-
- mGridView.setHasFixedSize(true);
- mGridView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
- BoxVideoController controller = new BoxVideoController(this);
- controller.setScreenTapListener(new BoxVideoController.OnScreenTapListener() {
- @Override
- public void tap() {
- showChannelList();
- }
- });
- controller.addControlComponent(new GestureView(this));
- controller.setCanChangePosition(false);
- controller.setEnableInNormal(true);
- controller.setGestureEnabled(true);
- mVideoView.setVideoController(controller);
- mVideoView.setProgressManager(null);
- initChannelList();
+ tvLeftChannelListLayout = findViewById(R.id.tvLeftChannnelListLayout);
+ mChannelGroupView = findViewById(R.id.mGroupGridView);
+ mLiveChannelView = findViewById(R.id.mChannelGridView);
+ tvRightSettingLayout = findViewById(R.id.tvRightSettingLayout);
+ mSettingGroupView = findViewById(R.id.mSettingGroupView);
+ mSettingItemView = findViewById(R.id.mSettingItemView);
+ tvChannelInfo = findViewById(R.id.tvChannel);
+ tvTime = findViewById(R.id.tvTime);
+ tvNetSpeed = findViewById(R.id.tvNetSpeed);
+
+ initVideoView();
+ initChannelGroupView();
+ initLiveChannelView();
+ initSettingGroupView();
+ initSettingItemView();
+ initLiveChannelList();
+ initLiveSettingGroupList();
}
@Override
public void onBackPressed() {
- if (mGridView.getVisibility() == View.VISIBLE) {
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideChannelListRun);
mHandler.post(mHideChannelListRun);
- } else {
+ }
+ else if (tvRightSettingLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.post(mHideSettingLayoutRun);
+ }
+ else {
+ mHandler.removeCallbacks(mConnectTimeoutChangeSourceRun);
+ mHandler.removeCallbacks(mUpdateNetSpeedRun);
super.onBackPressed();
}
}
@@ -107,54 +138,36 @@ public void onBackPressed() {
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
int keyCode = event.getKeyCode();
- if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN && mGridView.getVisibility() == View.INVISIBLE) {
- playNext();
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP && mGridView.getVisibility() == View.INVISIBLE) {
- playPrevious();
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && mGridView.getVisibility() == View.INVISIBLE) {
- preSourceUrl();
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && mGridView.getVisibility() == View.INVISIBLE) {
- nextSourceUrl();
- } else if (((Hawk.get(HawkConfig.DEBUG_OPEN, false) && keyCode == KeyEvent.KEYCODE_0) || keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE/* || keyCode == KeyEvent.KEYCODE_0*/) && mGridView.getVisibility() == View.INVISIBLE) {
- showChannelList();
- } else if (mGridView.getVisibility() == View.INVISIBLE) {
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ showSettingGroup();
+ } else if (!isListOrSettingLayoutVisible()) {
switch (keyCode) {
- case KeyEvent.KEYCODE_0:
- inputChannelNum("0");
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (Hawk.get(HawkConfig.LIVE_CHANNEL_REVERSE, false))
+ playNext();
+ else
+ playPrevious();
break;
- case KeyEvent.KEYCODE_1:
- inputChannelNum("1");
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (Hawk.get(HawkConfig.LIVE_CHANNEL_REVERSE, false))
+ playPrevious();
+ else
+ playNext();
break;
- case KeyEvent.KEYCODE_2:
- inputChannelNum("2");
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ playPreSource();
break;
- case KeyEvent.KEYCODE_3:
- inputChannelNum("3");
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ playNextSource();
break;
- case KeyEvent.KEYCODE_4:
- inputChannelNum("4");
- break;
- case KeyEvent.KEYCODE_5:
- inputChannelNum("5");
- break;
- case KeyEvent.KEYCODE_6:
- inputChannelNum("6");
- break;
- case KeyEvent.KEYCODE_7:
- inputChannelNum("7");
- break;
- case KeyEvent.KEYCODE_8:
- inputChannelNum("8");
- break;
- case KeyEvent.KEYCODE_9:
- inputChannelNum("9");
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ showChannelList();
break;
}
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
- if (mGridView.getVisibility() == View.VISIBLE) {
- mHandler.postDelayed(mHideChannelListRun, 5000);
- }
}
return super.dispatchKeyEvent(event);
}
@@ -165,18 +178,15 @@ protected void onResume() {
if (mVideoView != null) {
mVideoView.resume();
}
- if (mGridView.getVisibility() == View.VISIBLE) {
- mHandler.postDelayed(mHideChannelListRun, 5000);
- }
}
+
@Override
protected void onPause() {
super.onPause();
if (mVideoView != null) {
mVideoView.pause();
}
- mHandler.removeCallbacksAndMessages(null);
}
@Override
@@ -184,117 +194,71 @@ protected void onDestroy() {
super.onDestroy();
if (mVideoView != null) {
mVideoView.release();
+ mVideoView = null;
}
}
- private List channelList = new ArrayList<>();
- private LiveChannel currentChannel = null;
-
- private void initChannelList() {
- channelAdapter = new LiveChannelAdapter();
- mGridView.setAdapter(channelAdapter);
- mGridView.addOnScrollListener(new RecyclerView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
- super.onScrollStateChanged(recyclerView, newState);
- mHandler.removeCallbacks(mHideChannelListRun);
- mHandler.postDelayed(mHideChannelListRun, 5000);
- }
- });
- channelAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
- @Override
- public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
- FastClickCheckUtil.check(view);
- if (playChannel(channelList.get(position), false)) {
- mHandler.post(mHideChannelListRun);
- }
- }
- });
- List list = ApiConfig.get().getChannelList();
- if (list.isEmpty())
- return;
- if (list.size() > 0 && list.get(0).getUrls().startsWith("proxy://")) {
- showLoading();
- String url = DefaultConfig.checkReplaceProxy(list.get(0).getUrls());
- OkGo.get(url).execute(new AbsCallback() {
-
- @Override
- public String convertResponse(okhttp3.Response response) throws Throwable {
- return response.body().string();
- }
-
- @Override
- public void onSuccess(Response response) {
- List list = new ArrayList<>();
- JsonArray lives = new Gson().fromJson(response.body(), JsonArray.class);
- int lcIdx = 0;
- for (JsonElement opt : lives) {
- for (JsonElement optChl : ((JsonObject) opt).get("channels").getAsJsonArray()) {
- JsonObject obj = (JsonObject) optChl;
- LiveChannel lc = new LiveChannel();
- lc.setName(obj.get("name").getAsString().trim());
- lc.setUrls(DefaultConfig.safeJsonStringList(obj, "urls"));
- // 暂时不考虑分组问题
- lc.setChannelNum(lcIdx++);
- list.add(lc);
- }
- }
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- LivePlayActivity.this.showSuccess();
- initList(list);
- }
- });
- }
- });
+ private void showChannelList() {
+ if (tvRightSettingLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.post(mHideSettingLayoutRun);
+ }
+ if (tvLeftChannelListLayout.getVisibility() == View.INVISIBLE) {
+ //重新载入上一次状态
+ liveChannelItemAdapter.setNewData(getLiveChannels(currentChannelGroupIndex));
+ if (currentLiveChannelIndex > -1)
+ mLiveChannelView.scrollToPosition(currentLiveChannelIndex);
+ mLiveChannelView.setSelection(currentLiveChannelIndex);
+ mChannelGroupView.scrollToPosition(currentChannelGroupIndex);
+ mChannelGroupView.setSelection(currentChannelGroupIndex);
+ mHandler.postDelayed(mFocusCurrentChannelAndShowChannelList, 200);
} else {
- showSuccess();
- initList(list);
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.post(mHideChannelListRun);
}
}
- private void initList(List list) {
- LiveChannel lastChannel = null;
- String lastChannelName = Hawk.get(HawkConfig.LIVE_CHANNEL, "");
- channelList.clear();
- channelList.addAll(list);
- for (LiveChannel lc : channelList) {
- if (lc.getName().equals(lastChannelName)) {
- lastChannel = lc;
- break;
+ private Runnable mFocusCurrentChannelAndShowChannelList = new Runnable() {
+ @Override
+ public void run() {
+ if (mChannelGroupView.isScrolling() || mLiveChannelView.isScrolling() || mChannelGroupView.isComputingLayout() || mLiveChannelView.isComputingLayout()) {
+ mHandler.postDelayed(this, 100);
+ } else {
+ liveChannelGroupAdapter.setSelectedGroupIndex(currentChannelGroupIndex);
+ liveChannelItemAdapter.setSelectedChannelIndex(currentLiveChannelIndex);
+ RecyclerView.ViewHolder holder = mLiveChannelView.findViewHolderForAdapterPosition(currentLiveChannelIndex);
+ if (holder != null)
+ holder.itemView.requestFocus();
+ tvLeftChannelListLayout.setVisibility(View.VISIBLE);
+ ViewObj viewObj = new ViewObj(tvLeftChannelListLayout, (ViewGroup.MarginLayoutParams) tvLeftChannelListLayout.getLayoutParams());
+ ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginLeft", new IntEvaluator(), -tvLeftChannelListLayout.getLayoutParams().width, 0);
+ animator.setDuration(200);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+ });
+ animator.start();
}
}
- if (lastChannel == null)
- lastChannel = channelList.get(0);
-
- mGridView.setVisibility(View.INVISIBLE);
- tvHint.setVisibility(View.INVISIBLE);
- tvUrl.setVisibility(Hawk.get(HawkConfig.DEBUG_OPEN, false) ? View.VISIBLE : View.INVISIBLE);
-
- channelAdapter.setNewData(channelList);
- playChannel(lastChannel, false);
- }
-
- private void refreshTextInfo() {
- tvUrl.setText(currentChannel.getUrls());
- tvChannel.setText(String.format("%d", currentChannel.getChannelNum()));
- }
+ };
private Runnable mHideChannelListRun = new Runnable() {
@Override
public void run() {
- ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mGridView.getLayoutParams();
- if (mGridView.getVisibility() == View.VISIBLE) {
- ViewObj viewObj = new ViewObj(mGridView, params);
- ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginLeft", new IntEvaluator(), 0, -mGridView.getLayoutParams().width);
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) tvLeftChannelListLayout.getLayoutParams();
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ ViewObj viewObj = new ViewObj(tvLeftChannelListLayout, params);
+ ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginLeft", new IntEvaluator(), 0, -tvLeftChannelListLayout.getLayoutParams().width);
animator.setDuration(200);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mGridView.setVisibility(View.INVISIBLE);
- tvHint.setVisibility(View.INVISIBLE);
+ tvLeftChannelListLayout.setVisibility(View.INVISIBLE);
}
});
animator.start();
@@ -302,131 +266,803 @@ public void onAnimationEnd(Animator animation) {
}
};
- private Runnable mPlayUserInputChannelRun = new Runnable() {
+ private void showChannelInfo() {
+ tvChannelInfo.setText(String.format(Locale.getDefault(), "%d %s %s(%d/%d)", currentLiveChannelItem.getChannelNum(),
+ currentLiveChannelItem.getChannelName(), currentLiveChannelItem.getSourceName(),
+ currentLiveChannelItem.getSourceIndex() + 1, currentLiveChannelItem.getSourceNum()));
+
+ FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ if (tvRightSettingLayout.getVisibility() == View.VISIBLE) {
+ lParams.gravity = Gravity.LEFT;
+ lParams.leftMargin = 60;
+ lParams.topMargin = 30;
+ } else {
+ lParams.gravity = Gravity.RIGHT;
+ lParams.rightMargin = 60;
+ lParams.topMargin = 30;
+ }
+ tvChannelInfo.setLayoutParams(lParams);
+
+ tvChannelInfo.setVisibility(View.VISIBLE);
+ mHandler.removeCallbacks(mHideChannelInfoRun);
+ mHandler.postDelayed(mHideChannelInfoRun, 3000);
+ }
+
+ private Runnable mHideChannelInfoRun = new Runnable() {
@Override
public void run() {
- if (!TextUtils.isEmpty(userInputChannelNum)) {
- playChannelByNum(Integer.parseInt(userInputChannelNum));
- userInputChannelNum = "";
- }
- mHandler.postDelayed(mHideChannelNumRun, 4000);
+ tvChannelInfo.setVisibility(View.INVISIBLE);
}
};
- private Runnable mHideChannelNumRun = new Runnable() {
+ private boolean playChannel(int channelGroupIndex, int liveChannelIndex, boolean changeSource) {
+ if ((channelGroupIndex == currentChannelGroupIndex && liveChannelIndex == currentLiveChannelIndex && !changeSource)
+ || (changeSource && currentLiveChannelItem.getSourceNum() == 1)) {
+ showChannelInfo();
+ return true;
+ }
+ mVideoView.release();
+ if (!changeSource) {
+ currentChannelGroupIndex = channelGroupIndex;
+ currentLiveChannelIndex = liveChannelIndex;
+ currentLiveChannelItem = getLiveChannels(currentChannelGroupIndex).get(currentLiveChannelIndex);
+ Hawk.put(HawkConfig.LIVE_CHANNEL, currentLiveChannelItem.getChannelName());
+ livePlayerManager.getLiveChannelPlayer(mVideoView, currentLiveChannelItem.getChannelName());
+ }
+ mVideoView.setUrl(currentLiveChannelItem.getUrl());
+ showChannelInfo();
+ mVideoView.start();
+ return true;
+ }
+
+ private void playNext() {
+ if (!isCurrentLiveChannelValid()) return;
+ Integer[] groupChannelIndex = getNextChannel(1);
+ playChannel(groupChannelIndex[0], groupChannelIndex[1], false);
+ }
+
+ private void playPrevious() {
+ if (!isCurrentLiveChannelValid()) return;
+ Integer[] groupChannelIndex = getNextChannel(-1);
+ playChannel(groupChannelIndex[0], groupChannelIndex[1], false);
+ }
+
+ public void playPreSource() {
+ if (!isCurrentLiveChannelValid()) return;
+ currentLiveChannelItem.preSource();
+ playChannel(currentChannelGroupIndex, currentLiveChannelIndex, true);
+ }
+
+ public void playNextSource() {
+ if (!isCurrentLiveChannelValid()) return;
+ currentLiveChannelItem.nextSource();
+ playChannel(currentChannelGroupIndex, currentLiveChannelIndex, true);
+ }
+
+ //显示设置列表
+ private void showSettingGroup() {
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.post(mHideChannelListRun);
+ }
+ if (tvRightSettingLayout.getVisibility() == View.INVISIBLE) {
+ if (!isCurrentLiveChannelValid()) return;
+ //重新载入默认状态
+ loadCurrentSourceList();
+ liveSettingGroupAdapter.setNewData(liveSettingGroupList);
+ selectSettingGroup(0, false);
+ mSettingGroupView.scrollToPosition(0);
+ mSettingItemView.scrollToPosition(currentLiveChannelItem.getSourceIndex());
+ mHandler.postDelayed(mFocusAndShowSettingGroup, 200);
+ } else {
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.post(mHideSettingLayoutRun);
+ }
+ }
+
+ private Runnable mFocusAndShowSettingGroup = new Runnable() {
@Override
public void run() {
- tvChannel.setVisibility(View.INVISIBLE);
- refreshTextInfo();
+ if (mSettingGroupView.isScrolling() || mSettingItemView.isScrolling() || mSettingGroupView.isComputingLayout() || mSettingItemView.isComputingLayout()) {
+ mHandler.postDelayed(this, 100);
+ } else {
+ RecyclerView.ViewHolder holder = mSettingGroupView.findViewHolderForAdapterPosition(0);
+ if (holder != null)
+ holder.itemView.requestFocus();
+ tvRightSettingLayout.setVisibility(View.VISIBLE);
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) tvRightSettingLayout.getLayoutParams();
+ if (tvRightSettingLayout.getVisibility() == View.VISIBLE) {
+ ViewObj viewObj = new ViewObj(tvRightSettingLayout, params);
+ ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginRight", new IntEvaluator(), -tvRightSettingLayout.getLayoutParams().width, 0);
+ animator.setDuration(200);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
+ }
+ });
+ animator.start();
+ }
+ }
}
};
- private Runnable showListAfterScrollOk = new Runnable() {
+ private Runnable mHideSettingLayoutRun = new Runnable() {
@Override
public void run() {
- if (mGridView.isScrolling()) {
- mHandler.postDelayed(this, 100);
- } else {
- ViewObj viewObj = new ViewObj(mGridView, (ViewGroup.MarginLayoutParams) mGridView.getLayoutParams());
- ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginLeft", new IntEvaluator(), -mGridView.getLayoutParams().width, 0);
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) tvRightSettingLayout.getLayoutParams();
+ if (tvRightSettingLayout.getVisibility() == View.VISIBLE) {
+ ViewObj viewObj = new ViewObj(tvRightSettingLayout, params);
+ ObjectAnimator animator = ObjectAnimator.ofObject(viewObj, "marginRight", new IntEvaluator(), 0, -tvRightSettingLayout.getLayoutParams().width);
animator.setDuration(200);
- animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
+ tvRightSettingLayout.setVisibility(View.INVISIBLE);
+ liveSettingGroupAdapter.setSelectedGroupIndex(-1);
}
});
- mHandler.removeCallbacks(mHideChannelListRun);
- mHandler.postDelayed(mHideChannelListRun, 5000);
+ animator.start();
}
}
};
- private void showChannelList() {
- if (mGridView.getVisibility() == View.INVISIBLE) {
- tvHint.setVisibility(View.VISIBLE);
- mGridView.setVisibility(View.VISIBLE);
- mGridView.setSelection(channelList.indexOf(currentChannel));
- mHandler.postDelayed(showListAfterScrollOk, 100);
+ private void initVideoView() {
+ LiveController controller = new LiveController(this);
+ controller.setListener(new LiveController.LiveControlListener() {
+ @Override
+ public boolean singleTap() {
+ showChannelList();
+ return true;
+ }
+
+ @Override
+ public void longPress() {
+ showSettingGroup();
+ }
+
+ @Override
+ public void playStateChanged(int playState) {
+ switch (playState) {
+ case VideoView.STATE_IDLE:
+ case VideoView.STATE_PAUSED:
+ break;
+ case VideoView.STATE_PREPARED:
+ case VideoView.STATE_BUFFERED:
+ case VideoView.STATE_PLAYING:
+ currentLiveChangeSourceTimes = 0;
+ mHandler.removeCallbacks(mConnectTimeoutChangeSourceRun);
+ break;
+ case VideoView.STATE_ERROR:
+ case VideoView.STATE_PLAYBACK_COMPLETED:
+ mHandler.removeCallbacks(mConnectTimeoutChangeSourceRun);
+ mHandler.post(mConnectTimeoutChangeSourceRun);
+ break;
+ case VideoView.STATE_PREPARING:
+ case VideoView.STATE_BUFFERING:
+ mHandler.removeCallbacks(mConnectTimeoutChangeSourceRun);
+ mHandler.postDelayed(mConnectTimeoutChangeSourceRun, (Hawk.get(HawkConfig.LIVE_CONNECT_TIMEOUT, 1) + 1) * 5000);
+ break;
+ }
+ }
+
+ @Override
+ public void changeSource(int direction) {
+ if (direction > 0)
+ playNextSource();
+ else
+ playPreSource();
+ }
+ });
+ controller.setCanChangePosition(false);
+ controller.setEnableInNormal(true);
+ controller.setGestureEnabled(true);
+ controller.setDoubleTapTogglePlayEnabled(false);
+ mVideoView.setVideoController(controller);
+ mVideoView.setProgressManager(null);
+ }
+
+ private Runnable mConnectTimeoutChangeSourceRun = new Runnable() {
+ @Override
+ public void run() {
+ currentLiveChangeSourceTimes++;
+ if (currentLiveChannelItem.getSourceNum() == currentLiveChangeSourceTimes) {
+ currentLiveChangeSourceTimes = 0;
+ Integer[] groupChannelIndex = getNextChannel(Hawk.get(HawkConfig.LIVE_CHANNEL_REVERSE, false) ? -1 : 1);
+ playChannel(groupChannelIndex[0], groupChannelIndex[1], false);
+ } else {
+ playNextSource();
+ }
}
+ };
+
+ private void initChannelGroupView() {
+ mChannelGroupView.setHasFixedSize(true);
+ mChannelGroupView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
+
+ liveChannelGroupAdapter = new LiveChannelGroupAdapter();
+ mChannelGroupView.setAdapter(liveChannelGroupAdapter);
+ mChannelGroupView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+ });
+
+ //电视
+ mChannelGroupView.setOnItemListener(new TvRecyclerView.OnItemListener() {
+ @Override
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
+ }
+
+ @Override
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ selectChannelGroup(position, true, -1);
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ if (isNeedInputPassword(position)) {
+ showPasswordDialog(position, -1);
+ }
+ }
+ });
+
+ //手机/模拟器
+ liveChannelGroupAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ FastClickCheckUtil.check(view);
+ selectChannelGroup(position, false, -1);
+ }
+ });
}
- private String userInputChannelNum = "";
+ private void selectChannelGroup(int groupIndex, boolean focus, int liveChannelIndex) {
+ if (focus) {
+ liveChannelGroupAdapter.setFocusedGroupIndex(groupIndex);
+ liveChannelItemAdapter.setFocusedChannelIndex(-1);
+ }
+ if ((groupIndex > -1 && groupIndex != liveChannelGroupAdapter.getSelectedGroupIndex()) || isNeedInputPassword(groupIndex)) {
+ liveChannelGroupAdapter.setSelectedGroupIndex(groupIndex);
+ if (isNeedInputPassword(groupIndex)) {
+ showPasswordDialog(groupIndex, liveChannelIndex);
+ return;
+ }
+ loadChannelGroupDataAndPlay(groupIndex, liveChannelIndex);
+ }
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+ }
+
+ private void initLiveChannelView() {
+ mLiveChannelView.setHasFixedSize(true);
+ mLiveChannelView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
- private void inputChannelNum(String add) {
- if (userInputChannelNum.length() < 4) {
- mHandler.removeCallbacks(mPlayUserInputChannelRun);
- mHandler.removeCallbacks(mHideChannelNumRun);
- tvChannel.setVisibility(View.VISIBLE);
- userInputChannelNum = String.format("%s%s", userInputChannelNum, add);
- tvChannel.setText(userInputChannelNum);
- mHandler.postDelayed(mPlayUserInputChannelRun, 1000);
+ liveChannelItemAdapter = new LiveChannelItemAdapter();
+ mLiveChannelView.setAdapter(liveChannelItemAdapter);
+ mLiveChannelView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+ });
+
+ //电视
+ mLiveChannelView.setOnItemListener(new TvRecyclerView.OnItemListener() {
+ @Override
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
+ }
+
+ @Override
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ if (position < 0) return;
+ liveChannelGroupAdapter.setFocusedGroupIndex(-1);
+ liveChannelItemAdapter.setFocusedChannelIndex(position);
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ clickLiveChannel(position);
+ }
+ });
+
+ //手机/模拟器
+ liveChannelItemAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ FastClickCheckUtil.check(view);
+ clickLiveChannel(position);
+ }
+ });
+ }
+
+ private void clickLiveChannel(int position) {
+ liveChannelItemAdapter.setSelectedChannelIndex(position);
+ playChannel(liveChannelGroupAdapter.getSelectedGroupIndex(), position, false);
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ mHandler.removeCallbacks(mHideChannelListRun);
+ mHandler.postDelayed(mHideChannelListRun, 5000);
}
}
- private void showChannelNum() {
- refreshTextInfo();
- tvChannel.setVisibility(View.VISIBLE);
- mHandler.postDelayed(mHideChannelNumRun, 4000);
+ private void initSettingGroupView() {
+ mSettingGroupView.setHasFixedSize(true);
+ mSettingGroupView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
+
+ liveSettingGroupAdapter = new LiveSettingGroupAdapter();
+ mSettingGroupView.setAdapter(liveSettingGroupAdapter);
+ mSettingGroupView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
+ }
+ });
+
+ //电视
+ mSettingGroupView.setOnItemListener(new TvRecyclerView.OnItemListener() {
+ @Override
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
+ }
+
+ @Override
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ selectSettingGroup(position, true);
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ }
+ });
+
+ //手机/模拟器
+ liveSettingGroupAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ FastClickCheckUtil.check(view);
+ selectSettingGroup(position, false);
+ }
+ });
}
- private boolean playChannel(LiveChannel channel, boolean changeSource) {
- if ((channel == currentChannel && !changeSource) || channel == null)
- return false;
- if (currentChannel != null)
- currentChannel.setDefault(false);
- channelAdapter.notifyItemChanged(channelList.indexOf(currentChannel));
- currentChannel = channel;
- currentChannel.setDefault(true);
- channelAdapter.notifyItemChanged(channelList.indexOf(currentChannel));
- showChannelNum();
- Hawk.put(HawkConfig.LIVE_CHANNEL, channel.getName());
- mVideoView.release();
- mVideoView.setUrl(channel.getUrls());
- mVideoView.start();
- return true;
+ private void selectSettingGroup(int position, boolean focus) {
+ if (!isCurrentLiveChannelValid()) return;
+ if (focus) {
+ liveSettingGroupAdapter.setFocusedGroupIndex(position);
+ liveSettingItemAdapter.setFocusedItemIndex(-1);
+ }
+ if (position == liveSettingGroupAdapter.getSelectedGroupIndex() || position < -1)
+ return;
+
+ liveSettingGroupAdapter.setSelectedGroupIndex(position);
+ liveSettingItemAdapter.setNewData(liveSettingGroupList.get(position).getLiveSettingItems());
+
+ switch (position) {
+ case 0:
+ liveSettingItemAdapter.selectItem(currentLiveChannelItem.getSourceIndex(), true, false);
+ break;
+ case 1:
+ liveSettingItemAdapter.selectItem(livePlayerManager.getLivePlayerScale(), true, true);
+ break;
+ case 2:
+ liveSettingItemAdapter.selectItem(livePlayerManager.getLivePlayerType(), true, true);
+ break;
+ }
+ int scrollToPosition = liveSettingItemAdapter.getSelectedItemIndex();
+ if (scrollToPosition < 0) scrollToPosition = 0;
+ mSettingItemView.scrollToPosition(scrollToPosition);
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
}
- private boolean playChannelByNum(int channelNum) {
- LiveChannel tempChannel = null;
- for (int i = 0; i < channelList.size(); i++) {
- LiveChannel channel = channelList.get(i);
- if (channel.getChannelNum() == channelNum) {
- tempChannel = channel;
+ private void initSettingItemView() {
+ mSettingItemView.setHasFixedSize(true);
+ mSettingItemView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
+
+ liveSettingItemAdapter = new LiveSettingItemAdapter();
+ mSettingItemView.setAdapter(liveSettingItemAdapter);
+ mSettingItemView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
+ }
+ });
+
+ //电视
+ mSettingItemView.setOnItemListener(new TvRecyclerView.OnItemListener() {
+ @Override
+ public void onItemPreSelected(TvRecyclerView parent, View itemView, int position) {
+ }
+
+ @Override
+ public void onItemSelected(TvRecyclerView parent, View itemView, int position) {
+ if (position < 0) return;
+ liveSettingGroupAdapter.setFocusedGroupIndex(-1);
+ liveSettingItemAdapter.setFocusedItemIndex(position);
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
+ }
+
+ @Override
+ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
+ clickSettingItem(position);
+ }
+ });
+
+ //手机/模拟器
+ liveSettingItemAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ FastClickCheckUtil.check(view);
+ clickSettingItem(position);
+ }
+ });
+ }
+
+ private void clickSettingItem(int position) {
+ int settingGroupIndex = liveSettingGroupAdapter.getSelectedGroupIndex();
+ if (settingGroupIndex < 4) {
+ if (position == liveSettingItemAdapter.getSelectedItemIndex())
+ return;
+ liveSettingItemAdapter.selectItem(position, true, true);
+ }
+ switch (settingGroupIndex) {
+ case 0://线路切换
+ currentLiveChannelItem.setSourceIndex(position);
+ playChannel(currentChannelGroupIndex, currentLiveChannelIndex,true);
+ break;
+ case 1://画面比例
+ livePlayerManager.changeLivePlayerScale(mVideoView, position, currentLiveChannelItem.getChannelName());
+ break;
+ case 2://播放解码
+ mVideoView.release();
+ livePlayerManager.changeLivePlayerType(mVideoView, position, currentLiveChannelItem.getChannelName());
+ mVideoView.setUrl(currentLiveChannelItem.getUrl());
+ mVideoView.start();
+ break;
+ case 3://超时换源
+ Hawk.put(HawkConfig.LIVE_CONNECT_TIMEOUT, position);
break;
+ case 4://超时换源
+ boolean select = false;
+ switch (position) {
+ case 0:
+ select = !Hawk.get(HawkConfig.LIVE_SHOW_TIME, false);
+ Hawk.put(HawkConfig.LIVE_SHOW_TIME, select);
+ showTime();
+ break;
+ case 1:
+ select = !Hawk.get(HawkConfig.LIVE_SHOW_NET_SPEED, false);
+ Hawk.put(HawkConfig.LIVE_SHOW_NET_SPEED, select);
+ showNetSpeed();
+ break;
+ case 2:
+ select = !Hawk.get(HawkConfig.LIVE_CHANNEL_REVERSE, false);
+ Hawk.put(HawkConfig.LIVE_CHANNEL_REVERSE, select);
+ break;
+ case 3:
+ select = !Hawk.get(HawkConfig.LIVE_CROSS_GROUP, false);
+ Hawk.put(HawkConfig.LIVE_CROSS_GROUP, select);
+ break;
+ }
+ liveSettingItemAdapter.selectItem(position, select, false);
+ break;
+ }
+ mHandler.removeCallbacks(mHideSettingLayoutRun);
+ mHandler.postDelayed(mHideSettingLayoutRun, 5000);
+ }
+
+ private void initLiveChannelList() {
+ List list = ApiConfig.get().getChannelGroupList();
+ if (list.isEmpty()) {
+ Toast.makeText(App.getInstance(), "频道列表为空", Toast.LENGTH_SHORT).show();
+ finish();
+ return;
+ }
+
+ if (list.size() == 1 && list.get(0).getGroupName().startsWith("http://127.0.0.1")) {
+ showLoading();
+ loadProxyLives(list.get(0).getGroupName());
+ }
+ else {
+ liveChannelGroupList.clear();
+ liveChannelGroupList.addAll(list);
+ showSuccess();
+ initLiveState();
+ }
+ }
+
+ public void loadProxyLives(String url) {
+ OkGo.get(url).execute(new AbsCallback() {
+
+ @Override
+ public String convertResponse(okhttp3.Response response) throws Throwable {
+ return response.body().string();
+ }
+
+ @Override
+ public void onSuccess(Response response) {
+ JsonArray livesArray = new Gson().fromJson(response.body(), JsonArray.class);
+ ApiConfig.get().loadLives(livesArray);
+ List list = ApiConfig.get().getChannelGroupList();
+ if (list.isEmpty()) {
+ Toast.makeText(App.getInstance(), "频道列表为空", Toast.LENGTH_SHORT).show();
+ finish();
+ return;
+ }
+ liveChannelGroupList.clear();
+ liveChannelGroupList.addAll(list);
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ LivePlayActivity.this.showSuccess();
+ initLiveState();
+ }
+ });
+ }
+ });
+ }
+
+ private void initLiveState() {
+ String lastChannelName = Hawk.get(HawkConfig.LIVE_CHANNEL, "");
+
+ int lastChannelGroupIndex = -1;
+ int lastLiveChannelIndex = -1;
+ for (LiveChannelGroup liveChannelGroup : liveChannelGroupList) {
+ for (LiveChannelItem liveChannelItem : liveChannelGroup.getLiveChannels()) {
+ if (liveChannelItem.getChannelName().equals(lastChannelName)) {
+ lastChannelGroupIndex = liveChannelGroup.getGroupIndex();
+ lastLiveChannelIndex = liveChannelItem.getChannelIndex();
+ break;
+ }
}
+ if (lastChannelGroupIndex != -1) break;
}
- if (tempChannel == null)
- return false;
- return playChannel(tempChannel, false);
+ if (lastChannelGroupIndex == -1) {
+ lastChannelGroupIndex = getFirstNoPasswordChannelGroup();
+ if (lastChannelGroupIndex == -1)
+ lastChannelGroupIndex = 0;
+ lastLiveChannelIndex = 0;
+ }
+
+ livePlayerManager.init(mVideoView);
+ showTime();
+ showNetSpeed();
+ tvLeftChannelListLayout.setVisibility(View.INVISIBLE);
+ tvRightSettingLayout.setVisibility(View.INVISIBLE);
+
+ liveChannelGroupAdapter.setNewData(liveChannelGroupList);
+ selectChannelGroup(lastChannelGroupIndex, false, lastLiveChannelIndex);
}
- private void playNext() {
- int playIndex = channelList.indexOf(currentChannel);
- playIndex++;
- if (playIndex >= channelList.size()) {
- playIndex = 0;
+ private boolean isListOrSettingLayoutVisible() {
+ return tvLeftChannelListLayout.getVisibility() == View.VISIBLE || tvRightSettingLayout.getVisibility() == View.VISIBLE;
+ }
+
+ private void initLiveSettingGroupList() {
+ ArrayList groupNames = new ArrayList<>(Arrays.asList("线路选择", "画面比例", "播放解码", "超时换源", "偏好设置"));
+ ArrayList> itemsArrayList = new ArrayList<>();
+ ArrayList sourceItems = new ArrayList<>();
+ ArrayList scaleItems = new ArrayList<>(Arrays.asList("默认", "16:9", "4:3", "填充", "原始", "裁剪"));
+ ArrayList playerDecoderItems = new ArrayList<>(Arrays.asList("系统", "ijk硬解", "ijk软解", "exo"));
+ ArrayList timeoutItems = new ArrayList<>(Arrays.asList("5s", "10s", "15s", "20s", "25s", "30s"));
+ ArrayList personalSettingItems = new ArrayList<>(Arrays.asList("显示时间", "显示网速", "换台反转", "跨选分类"));
+ itemsArrayList.add(sourceItems);
+ itemsArrayList.add(scaleItems);
+ itemsArrayList.add(playerDecoderItems);
+ itemsArrayList.add(timeoutItems);
+ itemsArrayList.add(personalSettingItems);
+
+ liveSettingGroupList.clear();
+ for (int i = 0; i < groupNames.size(); i++) {
+ LiveSettingGroup liveSettingGroup = new LiveSettingGroup();
+ ArrayList liveSettingItemList = new ArrayList<>();
+ liveSettingGroup.setGroupIndex(i);
+ liveSettingGroup.setGroupName(groupNames.get(i));
+ for (int j = 0; j < itemsArrayList.get(i).size(); j++) {
+ LiveSettingItem liveSettingItem = new LiveSettingItem();
+ liveSettingItem.setItemIndex(j);
+ liveSettingItem.setItemName(itemsArrayList.get(i).get(j));
+ liveSettingItemList.add(liveSettingItem);
+ }
+ liveSettingGroup.setLiveSettingItems(liveSettingItemList);
+ liveSettingGroupList.add(liveSettingGroup);
}
- playChannel(channelList.get(playIndex), false);
+ liveSettingGroupList.get(3).getLiveSettingItems().get(Hawk.get(HawkConfig.LIVE_CONNECT_TIMEOUT, 1)).setItemSelected(true);
+ liveSettingGroupList.get(4).getLiveSettingItems().get(0).setItemSelected(Hawk.get(HawkConfig.LIVE_SHOW_TIME, false));
+ liveSettingGroupList.get(4).getLiveSettingItems().get(1).setItemSelected(Hawk.get(HawkConfig.LIVE_SHOW_NET_SPEED, false));
+ liveSettingGroupList.get(4).getLiveSettingItems().get(2).setItemSelected(Hawk.get(HawkConfig.LIVE_CHANNEL_REVERSE, false));
+ liveSettingGroupList.get(4).getLiveSettingItems().get(3).setItemSelected(Hawk.get(HawkConfig.LIVE_CROSS_GROUP, false));
}
- private void playPrevious() {
- int playIndex = channelList.indexOf(currentChannel);
- playIndex--;
- if (playIndex < 0) {
- playIndex = channelList.size() - 1;
+ private void loadCurrentSourceList() {
+ ArrayList currentSourceNames = currentLiveChannelItem.getChannelSourceNames();
+ ArrayList liveSettingItemList = new ArrayList<>();
+ for (int j = 0; j < currentSourceNames.size(); j++) {
+ LiveSettingItem liveSettingItem = new LiveSettingItem();
+ liveSettingItem.setItemIndex(j);
+ liveSettingItem.setItemName(currentSourceNames.get(j));
+ liveSettingItemList.add(liveSettingItem);
+ }
+ liveSettingGroupList.get(0).setLiveSettingItems(liveSettingItemList);
+ }
+
+ void showTime() {
+ if (Hawk.get(HawkConfig.LIVE_SHOW_TIME, false)) {
+ mHandler.post(mUpdateTimeRun);
+ tvTime.setVisibility(View.VISIBLE);
+ } else {
+ mHandler.removeCallbacks(mUpdateTimeRun);
+ tvTime.setVisibility(View.GONE);
+ }
+ }
+
+ private Runnable mUpdateTimeRun = new Runnable() {
+ @Override
+ public void run() {
+ Date day=new Date();
+ SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
+ tvTime.setText(df.format(day));
+ mHandler.postDelayed(this, 1000);
+ }
+ };
+
+ private void showNetSpeed() {
+ if (Hawk.get(HawkConfig.LIVE_SHOW_NET_SPEED, false)) {
+ mHandler.post(mUpdateNetSpeedRun);
+ tvNetSpeed.setVisibility(View.VISIBLE);
+ } else {
+ mHandler.removeCallbacks(mUpdateNetSpeedRun);
+ tvNetSpeed.setVisibility(View.GONE);
}
- playChannel(channelList.get(playIndex), false);
}
- public void preSourceUrl() {
- currentChannel.sourceIdx--;
- playChannel(currentChannel, true);
+ private Runnable mUpdateNetSpeedRun = new Runnable() {
+ @Override
+ public void run() {
+ if (mVideoView == null) return;
+ tvNetSpeed.setText(String.format("%.2fMB/s", (float)mVideoView.getTcpSpeed() / 1024.0 / 1024.0));
+ mHandler.postDelayed(this, 1000);
+ }
+ };
+
+ private void showPasswordDialog(int groupIndex, int liveChannelIndex) {
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE)
+ mHandler.removeCallbacks(mHideChannelListRun);
+
+ LivePasswordDialog dialog = new LivePasswordDialog(this);
+ dialog.setOnListener(new LivePasswordDialog.OnListener() {
+ @Override
+ public void onChange(String password) {
+ if (password.equals(liveChannelGroupList.get(groupIndex).getGroupPassword())) {
+ channelGroupPasswordConfirmed.add(groupIndex);
+ loadChannelGroupDataAndPlay(groupIndex, liveChannelIndex);
+ } else {
+ Toast.makeText(App.getInstance(), "密码错误", Toast.LENGTH_SHORT).show();
+ }
+
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE)
+ mHandler.postDelayed(mHideChannelListRun, 5000);
+ }
+
+ @Override
+ public void onCancel() {
+ if (tvLeftChannelListLayout.getVisibility() == View.VISIBLE) {
+ int groupIndex = liveChannelGroupAdapter.getSelectedGroupIndex();
+ liveChannelItemAdapter.setNewData(getLiveChannels(groupIndex));
+ }
+ }
+ });
+ dialog.show();
+ }
+
+ private void loadChannelGroupDataAndPlay(int groupIndex, int liveChannelIndex) {
+ liveChannelItemAdapter.setNewData(getLiveChannels(groupIndex));
+ if (groupIndex == currentChannelGroupIndex) {
+ if (currentLiveChannelIndex > -1)
+ mLiveChannelView.scrollToPosition(currentLiveChannelIndex);
+ liveChannelItemAdapter.setSelectedChannelIndex(currentLiveChannelIndex);
+ }
+ else {
+ mLiveChannelView.scrollToPosition(0);
+ liveChannelItemAdapter.setSelectedChannelIndex(-1);
+ }
+
+ if (liveChannelIndex > -1) {
+ clickLiveChannel(liveChannelIndex);
+ mChannelGroupView.scrollToPosition(groupIndex);
+ mLiveChannelView.scrollToPosition(liveChannelIndex);
+ playChannel(groupIndex, liveChannelIndex, false);
+ }
}
- public void nextSourceUrl() {
- currentChannel.sourceIdx++;
- playChannel(currentChannel, true);
+ private boolean isNeedInputPassword(int groupIndex) {
+ return !liveChannelGroupList.get(groupIndex).getGroupPassword().isEmpty()
+ && !isPasswordConfirmed(groupIndex);
+ }
+
+ private boolean isPasswordConfirmed(int groupIndex) {
+ for (Integer confirmedNum : channelGroupPasswordConfirmed) {
+ if (confirmedNum == groupIndex)
+ return true;
+ }
+ return false;
+ }
+
+ private ArrayList getLiveChannels(int groupIndex) {
+ if (!isNeedInputPassword(groupIndex)) {
+ return liveChannelGroupList.get(groupIndex).getLiveChannels();
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ private Integer[] getNextChannel(int direction) {
+ int channelGroupIndex = currentChannelGroupIndex;
+ int liveChannelIndex = currentLiveChannelIndex;
+
+ //跨选分组模式下跳过加密频道分组(遥控器上下键换台/超时换源)
+ if (direction > 0) {
+ liveChannelIndex++;
+ if (liveChannelIndex >= getLiveChannels(channelGroupIndex).size()) {
+ liveChannelIndex = 0;
+ if (Hawk.get(HawkConfig.LIVE_CROSS_GROUP, false)) {
+ do {
+ channelGroupIndex++;
+ if (channelGroupIndex >= liveChannelGroupList.size())
+ channelGroupIndex = 0;
+ } while (!liveChannelGroupList.get(channelGroupIndex).getGroupPassword().isEmpty() || channelGroupIndex == currentChannelGroupIndex);
+ }
+ }
+ } else {
+ liveChannelIndex--;
+ if (liveChannelIndex < 0) {
+ if (Hawk.get(HawkConfig.LIVE_CROSS_GROUP, false)) {
+ do {
+ channelGroupIndex--;
+ if (channelGroupIndex < 0)
+ channelGroupIndex = liveChannelGroupList.size() - 1;
+ } while (!liveChannelGroupList.get(channelGroupIndex).getGroupPassword().isEmpty() || channelGroupIndex == currentChannelGroupIndex);
+ }
+ liveChannelIndex = getLiveChannels(channelGroupIndex).size() - 1;
+ }
+ }
+
+ Integer[] groupChannelIndex = new Integer[2];
+ groupChannelIndex[0] = channelGroupIndex;
+ groupChannelIndex[1] = liveChannelIndex;
+
+ return groupChannelIndex;
+ }
+
+ private int getFirstNoPasswordChannelGroup() {
+ for (LiveChannelGroup liveChannelGroup : liveChannelGroupList) {
+ if (liveChannelGroup.getGroupPassword().isEmpty())
+ return liveChannelGroup.getGroupIndex();
+ }
+ return -1;
+ }
+
+ private boolean isCurrentLiveChannelValid() {
+ if (currentLiveChannelItem == null) {
+ Toast.makeText(App.getInstance(), "请先选择频道", Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java
index 7650cf1050..2040af3d6c 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java
@@ -1,41 +1,97 @@
package com.github.tvbox.osc.ui.activity;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
+import android.graphics.Color;
+import android.net.http.SslError;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.ConsoleMessage;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
-import com.dueeeke.videocontroller.component.GestureView;
-import com.dueeeke.videoplayer.player.VideoView;
+import com.github.catvod.crawler.Spider;
import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.base.BaseActivity;
+import com.github.tvbox.osc.bean.ParseBean;
+import com.github.tvbox.osc.bean.SourceBean;
import com.github.tvbox.osc.bean.VodInfo;
+import com.github.tvbox.osc.cache.CacheManager;
import com.github.tvbox.osc.event.RefreshEvent;
-import com.github.tvbox.osc.player.controller.BoxVideoController;
-import com.github.tvbox.osc.player.controller.BoxVodControlView;
-import com.github.tvbox.osc.ui.dialog.ParseDialog;
+import com.github.tvbox.osc.player.controller.VodController;
+import com.github.tvbox.osc.player.thirdparty.MXPlayer;
+import com.github.tvbox.osc.player.thirdparty.ReexPlayer;
+import com.github.tvbox.osc.util.AdBlocker;
+import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.HawkConfig;
+import com.github.tvbox.osc.util.LOG;
+import com.github.tvbox.osc.util.MD5;
import com.github.tvbox.osc.util.PlayerHelper;
+import com.github.tvbox.osc.util.XWalkUtils;
+import com.github.tvbox.osc.util.thunder.Thunder;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
+import com.lzy.okgo.OkGo;
+import com.lzy.okgo.callback.AbsCallback;
+import com.lzy.okgo.model.HttpHeaders;
+import com.lzy.okgo.model.Response;
import com.orhanobut.hawk.Hawk;
import org.greenrobot.eventbus.EventBus;
+import org.json.JSONException;
import org.json.JSONObject;
+import org.xwalk.core.XWalkJavascriptResult;
+import org.xwalk.core.XWalkResourceClient;
+import org.xwalk.core.XWalkSettings;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+import org.xwalk.core.XWalkWebResourceRequest;
+import org.xwalk.core.XWalkWebResourceResponse;
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import me.jessyan.autosize.AutoSize;
+import xyz.doikki.videoplayer.player.ProgressManager;
+import xyz.doikki.videoplayer.player.VideoView;
-/**
- * @author pj567
- * @date :2020/12/22
- * @description:
- */
public class PlayActivity extends BaseActivity {
private VideoView mVideoView;
- private BoxVideoController controller;
+ private TextView mPlayLoadTip;
+ private ImageView mPlayLoadErr;
+ private ProgressBar mPlayLoading;
+ private VodController mController;
private SourceViewModel sourceViewModel;
+ private Handler mHandler;
@Override
protected int getLayoutResID() {
@@ -50,93 +106,209 @@ protected void init() {
}
private void initView() {
- setLoadSir(findViewById(R.id.rootLayout));
- mVideoView = findViewById(R.id.mVideoView);
- PlayerHelper.updateCfg(mVideoView);
-// ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
-// layoutParams.width = 100;
-// layoutParams.height = 50;
-// mVideoView.setLayoutParams(layoutParams);
-
- mVideoView.addOnStateChangeListener(new VideoView.SimpleOnStateChangeListener() {
+ mHandler = new Handler(new Handler.Callback() {
@Override
- public void onPlayStateChanged(int state) {
- switch (state) {
- case VideoView.STATE_IDLE:
- case VideoView.STATE_PREPARED:
- case VideoView.STATE_PLAYING:
- case VideoView.STATE_BUFFERED:
- case VideoView.STATE_PAUSED:
- case VideoView.STATE_BUFFERING:
- case VideoView.STATE_PREPARING:
- break;
- case VideoView.STATE_PLAYBACK_COMPLETED:
- playNext();
- break;
- case VideoView.STATE_ERROR:
- Toast.makeText(mContext, "播放错误", Toast.LENGTH_SHORT).show();
- finish();
- tryDismissParse();
+ public boolean handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case 100:
+ stopParse();
+ errorWithRetry("嗅探错误", false);
break;
}
+ return false;
}
});
+ mVideoView = findViewById(R.id.mVideoView);
+ mPlayLoadTip = findViewById(R.id.play_load_tip);
+ mPlayLoading = findViewById(R.id.play_loading);
+ mPlayLoadErr = findViewById(R.id.play_load_error);
+ mController = new VodController(this);
+ mController.setCanChangePosition(true);
+ mController.setEnableInNormal(true);
+ mController.setGestureEnabled(true);
+ ProgressManager progressManager = new ProgressManager() {
+ @Override
+ public void saveProgress(String url, long progress) {
+ CacheManager.save(MD5.string2MD5(url), progress);
+ }
- controller = new BoxVideoController(this);
-
- controller.addControlComponent(new GestureView(this));
- BoxVodControlView boxVodControlView = new BoxVodControlView(this);
- controller.addControlComponent(boxVodControlView);
- boxVodControlView.setVodControlListener(new BoxVodControlView.BoxVodControlListener() {
@Override
- public void playNext() {
+ public long getSavedProgress(String url) {
+ int st = 0;
+ try {
+ st = mVodPlayerCfg.getInt("st");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ long skip = st * 1000;
+ if (CacheManager.getCache(MD5.string2MD5(url)) == null) {
+ return skip;
+ }
+ long rec = (long) CacheManager.getCache(MD5.string2MD5(url));
+ if (rec < skip)
+ return skip;
+ return rec;
+ }
+ };
+ mVideoView.setProgressManager(progressManager);
+ mController.setListener(new VodController.VodControlListener() {
+ @Override
+ public void playNext(boolean rmProgress) {
+ String preProgressKey = progressKey;
PlayActivity.this.playNext();
+ if (rmProgress && preProgressKey != null)
+ CacheManager.delete(MD5.string2MD5(preProgressKey), 0);
}
@Override
public void playPre() {
PlayActivity.this.playPrevious();
}
+
+ @Override
+ public void changeParse(ParseBean pb) {
+ autoRetryCount = 0;
+ doParse(pb);
+ }
+
+ @Override
+ public void updatePlayerCfg() {
+ mVodInfo.playerCfg = mVodPlayerCfg.toString();
+ EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_REFRESH, mVodPlayerCfg));
+ }
+
+ @Override
+ public void replay() {
+ autoRetryCount = 0;
+ play();
+ }
+
+ @Override
+ public void errReplay() {
+ errorWithRetry("视频播放出错", false);
+ }
+ });
+ mVideoView.setVideoController(mController);
+ }
+
+ void setTip(String msg, boolean loading, boolean err) {
+ mPlayLoadTip.setText(msg);
+ mPlayLoadTip.setVisibility(View.VISIBLE);
+ mPlayLoading.setVisibility(loading ? View.VISIBLE : View.GONE);
+ mPlayLoadErr.setVisibility(err ? View.VISIBLE : View.GONE);
+ }
+
+ void hideTip() {
+ mPlayLoadTip.setVisibility(View.GONE);
+ mPlayLoading.setVisibility(View.GONE);
+ mPlayLoadErr.setVisibility(View.GONE);
+ }
+
+ void errorWithRetry(String err, boolean finish) {
+ if (!autoRetry()) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (finish) {
+ Toast.makeText(mContext, err, Toast.LENGTH_SHORT).show();
+ finish();
+ } else {
+ setTip(err, false, true);
+ }
+ }
+ });
+ }
+ }
+
+ void playUrl(String url, HashMap headers) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ stopParse();
+ if (mVideoView != null) {
+ mVideoView.release();
+ if (url != null) {
+ try {
+ int playerType = mVodPlayerCfg.getInt("pl");
+ if (playerType >= 10) {
+ VodInfo.VodSeries vs = mVodInfo.seriesMap.get(mVodInfo.playFlag).get(mVodInfo.playIndex);
+ String playTitle = mVodInfo.name + " " + vs.name;
+ setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + "进行播放", true, false);
+ boolean callResult = false;
+ switch (playerType) {
+ case 10: {
+ callResult = MXPlayer.run(PlayActivity.this, url, playTitle, playSubtitle, headers);
+ break;
+ }
+ case 11: {
+ callResult = ReexPlayer.run(PlayActivity.this, url, playTitle, playSubtitle, headers);
+ break;
+ }
+ }
+ setTip("调用外部播放器" + PlayerHelper.getPlayerName(playerType) + (callResult ? "成功" : "失败"), callResult, !callResult);
+ return;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ hideTip();
+ PlayerHelper.updateCfg(mVideoView, mVodPlayerCfg);
+ mVideoView.setProgressKey(progressKey);
+ if (headers != null) {
+ mVideoView.setUrl(url, headers);
+ } else {
+ mVideoView.setUrl(url);
+ }
+ mVideoView.start();
+ mController.resetSpeed();
+ }
+ }
+ }
});
- controller.setCanChangePosition(true);
- controller.setEnableInNormal(true);
- controller.setGestureEnabled(true);
- mVideoView.setVideoController(controller);
}
private void initViewModel() {
sourceViewModel = new ViewModelProvider(this).get(SourceViewModel.class);
sourceViewModel.playResult.observe(this, new Observer() {
@Override
- public void onChanged(JSONObject object) {
- showSuccess();
- if (object != null && object.optString("key", "").equals(parseKey)) {
- parseDialog.parse(sourceKey, object, new ParseDialog.ParseCallback() {
- @Override
- public void success(String playUrl, Map headers) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (mVideoView != null) {
- mVideoView.release();
- if (headers != null) {
- mVideoView.setUrl(playUrl, headers);
- } else {
- mVideoView.setUrl(playUrl);
- }
- mVideoView.start();
+ public void onChanged(JSONObject info) {
+ if (info != null) {
+ try {
+ progressKey = info.optString("proKey", null);
+ boolean parse = info.optString("parse", "1").equals("1");
+ boolean jx = info.optString("jx", "0").equals("1");
+ playSubtitle = info.optString("subt", /*"https://dash.akamaized.net/akamai/test/caption_test/ElephantsDream/ElephantsDream_en.vtt"*/"");
+ String playUrl = info.optString("playUrl", "");
+ String flag = info.optString("flag");
+ String url = info.getString("url");
+ HashMap headers = null;
+ if (info.has("header")) {
+ try {
+ JSONObject hds = new JSONObject(info.getString("header"));
+ Iterator keys = hds.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (headers == null) {
+ headers = new HashMap<>();
}
- tryDismissParse();
+ headers.put(key, hds.getString(key));
}
- });
- }
+ } catch (Throwable th) {
- @Override
- public void fail() {
-// PlayActivity.this.finish();
-// tryDismissParse();
+ }
}
- });
+ if (parse || jx) {
+ boolean userJxList = (playUrl.isEmpty() && ApiConfig.get().getVipParseFlags().contains(flag)) || jx;
+ initParse(flag, userJxList, playUrl, url);
+ } else {
+ mController.showParse(false);
+ playUrl(playUrl + url, headers);
+ }
+ } catch (Throwable th) {
+ errorWithRetry("获取播放信息错误", true);
+ }
+ } else {
+ errorWithRetry("获取播放信息错误", true);
}
}
});
@@ -148,43 +320,59 @@ private void initData() {
Bundle bundle = intent.getExtras();
mVodInfo = (VodInfo) bundle.getSerializable("VodInfo");
sourceKey = bundle.getString("sourceKey");
+ sourceBean = ApiConfig.get().getSource(sourceKey);
+ initPlayerCfg();
play();
}
}
+ void initPlayerCfg() {
+ try {
+ mVodPlayerCfg = new JSONObject(mVodInfo.playerCfg);
+ } catch (Throwable th) {
+ mVodPlayerCfg = new JSONObject();
+ }
+ try {
+ if (!mVodPlayerCfg.has("pl")) {
+ mVodPlayerCfg.put("pl", Hawk.get(HawkConfig.PLAY_TYPE, 1));
+ }
+ if (!mVodPlayerCfg.has("pr")) {
+ mVodPlayerCfg.put("pr", Hawk.get(HawkConfig.PLAY_RENDER, 0));
+ }
+ if (!mVodPlayerCfg.has("ijk")) {
+ mVodPlayerCfg.put("ijk", Hawk.get(HawkConfig.IJK_CODEC, ""));
+ }
+ if (!mVodPlayerCfg.has("sc")) {
+ mVodPlayerCfg.put("sc", Hawk.get(HawkConfig.PLAY_SCALE, 0));
+ }
+ if (!mVodPlayerCfg.has("sp")) {
+ mVodPlayerCfg.put("sp", 1.0f);
+ }
+ if (!mVodPlayerCfg.has("st")) {
+ mVodPlayerCfg.put("st", 0);
+ }
+ if (!mVodPlayerCfg.has("et")) {
+ mVodPlayerCfg.put("et", 0);
+ }
+ } catch (Throwable th) {
+
+ }
+ mController.setPlayerConfig(mVodPlayerCfg);
+ }
+
@Override
public void onBackPressed() {
- if (controller.isBoxTVBottomShow()) {
- controller.boxTVBottomToggle();
- } else {
- super.onBackPressed();
+ if (mController.onBackPressed()) {
+ return;
}
+ super.onBackPressed();
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- int keyCode = event.getKeyCode();
- int action = event.getAction();
-
- if (controller.isBoxTVBottomShow()) {
- return super.dispatchKeyEvent(event);
- }
-
- if (action == KeyEvent.ACTION_DOWN) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
- controller.boxTVSlideStart(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : -1);
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || (Hawk.get(HawkConfig.DEBUG_OPEN, false) && keyCode == KeyEvent.KEYCODE_0)) {
- controller.boxTVTogglePlay();
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
-// playPrevious();
- controller.boxTVBottomToggle();
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
-// playNext();
- controller.boxTVBottomToggle();
- }
- } else if (action == KeyEvent.ACTION_UP) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
- controller.boxTVSlideStop();
+ if (event != null) {
+ if (mController.onKeyEvent(event)) {
+ return true;
}
}
return super.dispatchKeyEvent(event);
@@ -214,11 +402,14 @@ protected void onDestroy() {
mVideoView.release();
mVideoView = null;
}
- tryDismissParse();
+ stopLoadWebView(true);
+ stopParse();
}
private VodInfo mVodInfo;
+ private JSONObject mVodPlayerCfg;
private String sourceKey;
+ private SourceBean sourceBean;
private void playNext() {
boolean hasNext = true;
@@ -250,40 +441,773 @@ private void playPrevious() {
play();
}
- ParseDialog parseDialog = null;
+ private int autoRetryCount = 0;
+
+ boolean autoRetry() {
+ if (autoRetryCount < 3) {
+ autoRetryCount++;
+ play();
+ return true;
+ } else {
+ autoRetryCount = 0;
+ return false;
+ }
+ }
+
+ public void play() {
+ VodInfo.VodSeries vs = mVodInfo.seriesMap.get(mVodInfo.playFlag).get(mVodInfo.playIndex);
+ EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_REFRESH, mVodInfo.playIndex));
+ setTip("正在获取播放信息", true, false);
+ String playTitleInfo = mVodInfo.name + " " + vs.name;
+ mController.setTitle(playTitleInfo);
- void tryDismissParse() {
- if (parseDialog != null) {
+ playUrl(null, null);
+ String progressKey = mVodInfo.sourceKey + mVodInfo.id + mVodInfo.playFlag + mVodInfo.playIndex;
+ if (Thunder.play(vs.url, new Thunder.ThunderCallback() {
+ @Override
+ public void status(int code, String info) {
+ if (code < 0) {
+ setTip(info, false, true);
+ } else {
+ setTip(info, true, false);
+ }
+ }
+
+ @Override
+ public void list(String playList) {
+ }
+
+ @Override
+ public void play(String url) {
+ playUrl(url, null);
+ }
+ })) {
+ mController.showParse(false);
+ return;
+ }
+ sourceViewModel.getPlay(sourceKey, mVodInfo.playFlag, progressKey, vs.url);
+ }
+
+ private String playSubtitle;
+ private String progressKey;
+ private String parseFlag;
+ private String webUrl;
+
+ private void initParse(String flag, boolean useParse, String playUrl, final String url) {
+ parseFlag = flag;
+ webUrl = url;
+ ParseBean parseBean = null;
+ mController.showParse(useParse);
+ if (useParse) {
+ parseBean = ApiConfig.get().getDefaultParse();
+ } else {
+ if (playUrl.startsWith("json:")) {
+ parseBean = new ParseBean();
+ parseBean.setType(1);
+ parseBean.setUrl(playUrl.substring(5));
+ } else if (playUrl.startsWith("parse:")) {
+ String parseRedirect = playUrl.substring(6);
+ for (ParseBean pb : ApiConfig.get().getParseBeanList()) {
+ if (pb.getName().equals(parseRedirect)) {
+ parseBean = pb;
+ break;
+ }
+ }
+ }
+ if (parseBean == null) {
+ parseBean = new ParseBean();
+ parseBean.setType(0);
+ parseBean.setUrl(playUrl);
+ }
+ }
+ loadFound = false;
+ doParse(parseBean);
+ }
+
+ JSONObject jsonParse(String input, String json) throws JSONException {
+ JSONObject jsonPlayData = new JSONObject(json);
+ String url = jsonPlayData.getString("url");
+ String msg = jsonPlayData.optString("msg", "");
+ if (url.startsWith("//")) {
+ url = "https:" + url;
+ }
+ if (!url.startsWith("http")) {
+ return null;
+ }
+ JSONObject headers = new JSONObject();
+ String ua = jsonPlayData.optString("user-agent", "");
+ if (ua.trim().length() > 0) {
+ headers.put("User-Agent", " " + ua);
+ }
+ String referer = jsonPlayData.optString("referer", "");
+ if (referer.trim().length() > 0) {
+ headers.put("Referer", " " + referer);
+ }
+ JSONObject taskResult = new JSONObject();
+ taskResult.put("header", headers);
+ taskResult.put("url", url);
+ return taskResult;
+ }
+
+ void stopParse() {
+ mHandler.removeMessages(100);
+ stopLoadWebView(false);
+ loadFound = false;
+ OkGo.getInstance().cancelTag("json_jx");
+ if (parseThreadPool != null) {
try {
- parseDialog.dismiss();
+ parseThreadPool.shutdown();
+ parseThreadPool = null;
} catch (Throwable th) {
th.printStackTrace();
}
}
}
+ ExecutorService parseThreadPool;
- private volatile String parseKey = null;
+ private void doParse(ParseBean pb) {
+ stopParse();
+ if (pb.getType() == 0) {
+ setTip("正在嗅探播放地址", true, false);
+ mHandler.removeMessages(100);
+ mHandler.sendEmptyMessageDelayed(100, 20 * 1000);
+ loadWebView(pb.getUrl() + webUrl);
+ } else if (pb.getType() == 1) { // json 解析
+ setTip("正在解析播放地址", true, false);
+ // 解析ext
+ HttpHeaders reqHeaders = new HttpHeaders();
+ try {
+ JSONObject jsonObject = new JSONObject(pb.getExt());
+ if (jsonObject.has("header")) {
+ JSONObject headerJson = jsonObject.optJSONObject("header");
+ Iterator keys = headerJson.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ reqHeaders.put(key, headerJson.optString(key, ""));
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ OkGo.get(pb.getUrl() + webUrl)
+ .tag("json_jx")
+ .headers(reqHeaders)
+ .execute(new AbsCallback() {
+ @Override
+ public String convertResponse(okhttp3.Response response) throws Throwable {
+ if (response.body() != null) {
+ return response.body().string();
+ } else {
+ throw new IllegalStateException("网络请求错误");
+ }
+ }
- public void play() {
- VodInfo.VodSeries vs = mVodInfo.seriesMap.get(mVodInfo.playFlag).get(mVodInfo.playIndex);
- EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_REFRESH, mVodInfo.playIndex));
- controller.boxTVRefreshInfo(mVodInfo.name + " " + vs.name + (Hawk.get(HawkConfig.DEBUG_OPEN, false) ? vs.url : ""));
+ @Override
+ public void onSuccess(Response response) {
+ String json = response.body();
+ try {
+ JSONObject rs = jsonParse(webUrl, json);
+ HashMap headers = null;
+ if (rs.has("header")) {
+ try {
+ JSONObject hds = rs.getJSONObject("header");
+ Iterator keys = hds.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (headers == null) {
+ headers = new HashMap<>();
+ }
+ headers.put(key, hds.getString(key));
+ }
+ } catch (Throwable th) {
+
+ }
+ }
+ playUrl(rs.getString("url"), headers);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ errorWithRetry("解析错误", false);
+ }
+ }
+
+ @Override
+ public void onError(Response response) {
+ super.onError(response);
+ errorWithRetry("解析错误", false);
+ }
+ });
+ } else if (pb.getType() == 2) { // json 扩展
+ setTip("正在解析播放地址", true, false);
+ parseThreadPool = Executors.newSingleThreadExecutor();
+ LinkedHashMap jxs = new LinkedHashMap<>();
+ for (ParseBean p : ApiConfig.get().getParseBeanList()) {
+ if (p.getType() == 1) {
+ jxs.put(p.getName(), p.mixUrl());
+ }
+ }
+ parseThreadPool.execute(new Runnable() {
+ @Override
+ public void run() {
+ JSONObject rs = ApiConfig.get().jsonExt(pb.getUrl(), jxs, webUrl);
+ if (rs == null || !rs.has("url")) {
+ errorWithRetry("解析错误", false);
+ } else {
+ HashMap headers = null;
+ if (rs.has("header")) {
+ try {
+ JSONObject hds = rs.getJSONObject("header");
+ Iterator keys = hds.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (headers == null) {
+ headers = new HashMap<>();
+ }
+ headers.put(key, hds.getString(key));
+ }
+ } catch (Throwable th) {
+
+ }
+ }
+ if (rs.has("jxFrom")) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(mContext, "解析来自:" + rs.optString("jxFrom"), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ boolean parseWV = rs.optInt("parse", 0) == 1;
+ if (parseWV) {
+ String wvUrl = DefaultConfig.checkReplaceProxy(rs.optString("url", ""));
+ loadUrl(wvUrl);
+ } else {
+ playUrl(rs.optString("url", ""), headers);
+ }
+ }
+ }
+ });
+ } else if (pb.getType() == 3) { // json 聚合
+ setTip("正在解析播放地址", true, false);
+ parseThreadPool = Executors.newSingleThreadExecutor();
+ LinkedHashMap> jxs = new LinkedHashMap<>();
+ String extendName = "";
+ for (ParseBean p : ApiConfig.get().getParseBeanList()) {
+ HashMap data = new HashMap();
+ data.put("url", p.getUrl());
+ if (p.getUrl().equals(pb.getUrl())) {
+ extendName = p.getName();
+ }
+ data.put("type", p.getType() + "");
+ data.put("ext", p.getExt());
+ jxs.put(p.getName(), data);
+ }
+ String finalExtendName = extendName;
+ parseThreadPool.execute(new Runnable() {
+ @Override
+ public void run() {
+ JSONObject rs = ApiConfig.get().jsonExtMix(parseFlag + "111", pb.getUrl(), finalExtendName, jxs, webUrl);
+ if (rs == null || !rs.has("url")) {
+ errorWithRetry("解析错误", false);
+ } else {
+ if (rs.has("parse") && rs.optInt("parse", 0) == 1) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String mixParseUrl = DefaultConfig.checkReplaceProxy(rs.optString("url", ""));
+ stopParse();
+ setTip("正在嗅探播放地址", true, false);
+ mHandler.removeMessages(100);
+ mHandler.sendEmptyMessageDelayed(100, 20 * 1000);
+ loadWebView(mixParseUrl);
+ }
+ });
+ } else {
+ HashMap headers = null;
+ if (rs.has("header")) {
+ try {
+ JSONObject hds = rs.getJSONObject("header");
+ Iterator keys = hds.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (headers == null) {
+ headers = new HashMap<>();
+ }
+ headers.put(key, hds.getString(key));
+ }
+ } catch (Throwable th) {
+
+ }
+ }
+ if (rs.has("jxFrom")) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(mContext, "解析来自:" + rs.optString("jxFrom"), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ playUrl(rs.optString("url", ""), headers);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ // webview
+ private XWalkView mXwalkWebView;
+ private XWalkWebClient mX5WebClient;
+ private WebView mSysWebView;
+ private SysWebClient mSysWebClient;
+ private Map loadedUrls = new HashMap<>();
+ private boolean loadFound = false;
+
+ void loadWebView(String url) {
+ if (mSysWebView == null && mXwalkWebView == null) {
+ boolean useSystemWebView = Hawk.get(HawkConfig.PARSE_WEBVIEW, true);
+ if (!useSystemWebView) {
+ XWalkUtils.tryUseXWalk(mContext, new XWalkUtils.XWalkState() {
+ @Override
+ public void success() {
+ initWebView(false);
+ loadUrl(url);
+ }
+
+ @Override
+ public void fail() {
+ Toast.makeText(mContext, "XWalkView不兼容,已替换为系统自带WebView", Toast.LENGTH_SHORT).show();
+ initWebView(true);
+ loadUrl(url);
+ }
+
+ @Override
+ public void ignore() {
+ Toast.makeText(mContext, "XWalkView运行组件未下载,已替换为系统自带WebView", Toast.LENGTH_SHORT).show();
+ initWebView(true);
+ loadUrl(url);
+ }
+ });
+ } else {
+ initWebView(true);
+ loadUrl(url);
+ }
+ } else {
+ loadUrl(url);
+ }
+ }
+
+ void initWebView(boolean useSystemWebView) {
+ if (useSystemWebView) {
+ mSysWebView = new MyWebView(mContext);
+ configWebViewSys(mSysWebView);
+ } else {
+ mXwalkWebView = new MyXWalkView(mContext);
+ configWebViewX5(mXwalkWebView);
+ }
+ }
+
+ void loadUrl(String url) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mXwalkWebView != null) {
+ mXwalkWebView.stopLoading();
+ mXwalkWebView.clearCache(true);
+ mXwalkWebView.loadUrl(url);
+ }
+ if (mSysWebView != null) {
+ mSysWebView.stopLoading();
+ mSysWebView.clearCache(true);
+ mSysWebView.loadUrl(url);
+ }
+ }
+ });
+ }
+
+ void stopLoadWebView(boolean destroy) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+
+ if (mXwalkWebView != null) {
+ mXwalkWebView.stopLoading();
+ mXwalkWebView.loadUrl("about:blank");
+ if (destroy) {
+ mXwalkWebView.clearCache(true);
+ mXwalkWebView.removeAllViews();
+ mXwalkWebView.onDestroy();
+ mXwalkWebView = null;
+ }
+ }
+ if (mSysWebView != null) {
+ mSysWebView.stopLoading();
+ mSysWebView.loadUrl("about:blank");
+ if (destroy) {
+ mSysWebView.clearCache(true);
+ mSysWebView.removeAllViews();
+ mSysWebView.destroy();
+ mSysWebView = null;
+ }
+ }
+ }
+ });
+ }
+
+ boolean checkVideoFormat(String url) {
+ if (sourceBean.getType() == 3) {
+ Spider sp = ApiConfig.get().getCSP(sourceBean);
+ if (sp != null && sp.manualVideoCheck())
+ return sp.isVideoFormat(url);
+ }
+ return DefaultConfig.isVideoFormat(url);
+ }
+
+ class MyWebView extends WebView {
+ public MyWebView(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ public void setOverScrollMode(int mode) {
+ super.setOverScrollMode(mode);
+ if (mContext instanceof Activity)
+ AutoSize.autoConvertDensityOfCustomAdapt((Activity) mContext, PlayActivity.this);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return false;
+ }
+ }
+
+ class MyXWalkView extends XWalkView {
+ public MyXWalkView(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void setOverScrollMode(int mode) {
+ super.setOverScrollMode(mode);
+ if (mContext instanceof Activity)
+ AutoSize.autoConvertDensityOfCustomAdapt((Activity) mContext, PlayActivity.this);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ return false;
+ }
+ }
+
+ private void configWebViewSys(WebView webView) {
+ if (webView == null) {
+ return;
+ }
+ ViewGroup.LayoutParams layoutParams = Hawk.get(HawkConfig.DEBUG_OPEN, false)
+ ? new ViewGroup.LayoutParams(800, 400) :
+ new ViewGroup.LayoutParams(1, 1);
+ webView.setFocusable(false);
+ webView.setFocusableInTouchMode(false);
+ webView.clearFocus();
+ webView.setOverScrollMode(View.OVER_SCROLL_ALWAYS);
+ addContentView(webView, layoutParams);
+ /* 添加webView配置 */
+ final WebSettings settings = webView.getSettings();
+ settings.setNeedInitialFocus(false);
+ settings.setAllowContentAccess(true);
+ settings.setAllowFileAccess(true);
+ settings.setAllowUniversalAccessFromFileURLs(true);
+ settings.setAllowFileAccessFromFileURLs(true);
+ settings.setDatabaseEnabled(true);
+ settings.setDomStorageEnabled(true);
+ settings.setJavaScriptEnabled(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ settings.setMediaPlaybackRequiresUserGesture(false);
+ }
+ if (Hawk.get(HawkConfig.DEBUG_OPEN, false)) {
+ settings.setBlockNetworkImage(false);
+ } else {
+ settings.setBlockNetworkImage(true);
+ }
+ settings.setUseWideViewPort(true);
+ settings.setDomStorageEnabled(true);
+ settings.setJavaScriptCanOpenWindowsAutomatically(true);
+ settings.setSupportMultipleWindows(false);
+ settings.setLoadWithOverviewMode(true);
+ settings.setBuiltInZoomControls(true);
+ settings.setSupportZoom(false);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+ }
+ settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+ /* 添加webView配置 */
+ //设置编码
+ settings.setDefaultTextEncodingName("utf-8");
+ settings.setUserAgentString(webView.getSettings().getUserAgentString());
+ // settings.setUserAgentString(ANDROID_UA);
+
+ webView.setWebChromeClient(new WebChromeClient() {
+ @Override
+ public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+ return false;
+ }
+
+ @Override
+ public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
+ return true;
+ }
+
+ @Override
+ public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
+ return true;
+ }
+
+ @Override
+ public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
+ return true;
+ }
+ });
+ mSysWebClient = new SysWebClient();
+ webView.setWebViewClient(mSysWebClient);
+ webView.setBackgroundColor(Color.BLACK);
+ }
+
+ private class SysWebClient extends WebViewClient {
+
+ @Override
+ public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) {
+ sslErrorHandler.proceed();
+ }
+
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+ return false;
+ }
+
+ WebResourceResponse checkIsVideo(String url, HashMap headers) {
+ if (url.endsWith("/favicon.ico")) {
+ return new WebResourceResponse("image/png", null, null);
+ }
+ LOG.i("shouldInterceptRequest url:" + url);
+ boolean ad;
+ if (!loadedUrls.containsKey(url)) {
+ ad = AdBlocker.isAd(url);
+ loadedUrls.put(url, ad);
+ } else {
+ ad = loadedUrls.get(url);
+ }
+
+ if (!ad && !loadFound) {
+ if (checkVideoFormat(url)) {
+ mHandler.removeMessages(100);
+ loadFound = true;
+ if (headers != null && !headers.isEmpty()) {
+ playUrl(url, headers);
+ } else {
+ playUrl(url, null);
+ }
+ stopLoadWebView(false);
+ }
+ }
+
+ return ad || loadFound ?
+ AdBlocker.createEmptyResource() :
+ null;
+ }
- tryDismissParse();
+ @Nullable
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+ WebResourceResponse response = checkIsVideo(url, null);
+ if (response == null)
+ return super.shouldInterceptRequest(view, url);
+ else
+ return response;
+ }
+
+ @Nullable
+ @Override
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
+ String url = "";
+ try {
+ url = request.getUrl().toString();
+ } catch (Throwable th) {
+
+ }
+ HashMap webHeaders = new HashMap<>();
+ try {
+ Map hds = request.getRequestHeaders();
+ for (String k : hds.keySet()) {
+ if (k.equalsIgnoreCase("user-agent")
+ || k.equalsIgnoreCase("referer")
+ || k.equalsIgnoreCase("origin")) {
+ webHeaders.put(k, " " + hds.get(k));
+ }
+ }
+ } catch (Throwable th) {
+
+ }
+ WebResourceResponse response = checkIsVideo(url, webHeaders);
+ if (response == null)
+ return super.shouldInterceptRequest(view, request);
+ else
+ return response;
+ }
+
+ @Override
+ public void onLoadResource(WebView webView, String url) {
+ super.onLoadResource(webView, url);
+ }
+ }
+
+ private void configWebViewX5(XWalkView webView) {
+ if (webView == null) {
+ return;
+ }
+ ViewGroup.LayoutParams layoutParams = Hawk.get(HawkConfig.DEBUG_OPEN, false)
+ ? new ViewGroup.LayoutParams(800, 400) :
+ new ViewGroup.LayoutParams(1, 1);
+ webView.setFocusable(false);
+ webView.setFocusableInTouchMode(false);
+ webView.clearFocus();
+ webView.setOverScrollMode(View.OVER_SCROLL_ALWAYS);
+ addContentView(webView, layoutParams);
+ /* 添加webView配置 */
+ final XWalkSettings settings = webView.getSettings();
+ settings.setAllowContentAccess(true);
+ settings.setAllowFileAccess(true);
+ settings.setAllowUniversalAccessFromFileURLs(true);
+ settings.setAllowFileAccessFromFileURLs(true);
+ settings.setDatabaseEnabled(true);
+ settings.setDomStorageEnabled(true);
+ settings.setJavaScriptEnabled(true);
+
+ if (Hawk.get(HawkConfig.DEBUG_OPEN, false)) {
+ settings.setBlockNetworkImage(false);
+ } else {
+ settings.setBlockNetworkImage(true);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ settings.setMediaPlaybackRequiresUserGesture(false);
+ }
+ settings.setUseWideViewPort(true);
+ settings.setDomStorageEnabled(true);
+ settings.setJavaScriptCanOpenWindowsAutomatically(true);
+ settings.setSupportMultipleWindows(false);
+ settings.setLoadWithOverviewMode(true);
+ settings.setBuiltInZoomControls(true);
+ settings.setSupportZoom(false);
+ settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+ // settings.setUserAgentString(ANDROID_UA);
+
+ webView.setBackgroundColor(Color.BLACK);
+ webView.setUIClient(new XWalkUIClient(webView) {
+ @Override
+ public boolean onConsoleMessage(XWalkView view, String message, int lineNumber, String sourceId, ConsoleMessageType messageType) {
+ return false;
+ }
+
+ @Override
+ public boolean onJsAlert(XWalkView view, String url, String message, XWalkJavascriptResult result) {
+ return true;
+ }
+
+ @Override
+ public boolean onJsConfirm(XWalkView view, String url, String message, XWalkJavascriptResult result) {
+ return true;
+ }
- parseDialog = new ParseDialog().build(this, new ParseDialog.BackPress() {
@Override
- public void onBack() {
- PlayActivity.this.finish();
- tryDismissParse();
+ public boolean onJsPrompt(XWalkView view, String url, String message, String defaultValue, XWalkJavascriptResult result) {
+ return true;
}
});
+ mX5WebClient = new XWalkWebClient(webView);
+ webView.setResourceClient(mX5WebClient);
+ }
+
+ private class XWalkWebClient extends XWalkResourceClient {
+ public XWalkWebClient(XWalkView view) {
+ super(view);
+ }
+
+ @Override
+ public void onDocumentLoadedInFrame(XWalkView view, long frameId) {
+ super.onDocumentLoadedInFrame(view, frameId);
+ }
+
+ @Override
+ public void onLoadStarted(XWalkView view, String url) {
+ super.onLoadStarted(view, url);
+ }
+
+ @Override
+ public void onLoadFinished(XWalkView view, String url) {
+ super.onLoadFinished(view, url);
+ }
+
+ @Override
+ public void onProgressChanged(XWalkView view, int progressInPercent) {
+ super.onProgressChanged(view, progressInPercent);
+ }
+
+ @Override
+ public XWalkWebResourceResponse shouldInterceptLoadRequest(XWalkView view, XWalkWebResourceRequest request) {
+ String url = request.getUrl().toString();
+ // suppress favicon requests as we don't display them anywhere
+ if (url.endsWith("/favicon.ico")) {
+ return createXWalkWebResourceResponse("image/png", null, null);
+ }
+ LOG.i("shouldInterceptLoadRequest url:" + url);
+ boolean ad;
+ if (!loadedUrls.containsKey(url)) {
+ ad = AdBlocker.isAd(url);
+ loadedUrls.put(url, ad);
+ } else {
+ ad = loadedUrls.get(url);
+ }
+ if (!ad && !loadFound) {
+ if (checkVideoFormat(url)) {
+ mHandler.removeMessages(100);
+ loadFound = true;
+ HashMap webHeaders = new HashMap<>();
+ try {
+ Map hds = request.getRequestHeaders();
+ for (String k : hds.keySet()) {
+ if (k.equalsIgnoreCase("user-agent")
+ || k.equalsIgnoreCase("referer")
+ || k.equalsIgnoreCase("origin")) {
+ webHeaders.put(k, " " + hds.get(k));
+ }
+ }
+ } catch (Throwable th) {
- parseDialog.show();
+ }
+ if (webHeaders != null && !webHeaders.isEmpty()) {
+ playUrl(url, webHeaders);
+ } else {
+ playUrl(url, null);
+ }
+ stopLoadWebView(false);
+ }
+ }
+ return ad || loadFound ?
+ createXWalkWebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes())) :
+ super.shouldInterceptLoadRequest(view, request);
+ }
- parseKey = vs.url;
- showLoading();
- sourceViewModel.getPlay(sourceKey, mVodInfo.playFlag, vs.url);
+ @Override
+ public boolean shouldOverrideUrlLoading(XWalkView view, String s) {
+ return false;
+ }
+
+ @Override
+ public void onReceivedSslError(XWalkView view, ValueCallback callback, SslError error) {
+ callback.onReceiveValue(true);
+ }
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/ProjectionPlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/ProjectionPlayActivity.java
deleted file mode 100644
index 027b7a5cf9..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/ProjectionPlayActivity.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.github.tvbox.osc.ui.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.widget.Toast;
-
-import com.dueeeke.videocontroller.component.GestureView;
-import com.dueeeke.videoplayer.player.VideoView;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.base.BaseActivity;
-import com.github.tvbox.osc.player.controller.BoxVideoController;
-import com.github.tvbox.osc.player.controller.BoxVodControlView;
-import com.github.tvbox.osc.ui.dialog.ParseDialog;
-import com.github.tvbox.osc.util.HawkConfig;
-import com.github.tvbox.osc.util.PlayerHelper;
-import com.orhanobut.hawk.Hawk;
-
-import java.util.Map;
-
-/**
- * @author pj567
- * @date :2021/3/5
- * @description:
- */
-public class ProjectionPlayActivity extends BaseActivity {
- private VideoView mVideoView;
- private BoxVideoController controller;
-
- @Override
- protected int getLayoutResID() {
- return R.layout.activity_projection_play;
- }
-
- @Override
- protected void init() {
- initView();
- initData();
- }
-
- private void initView() {
- mVideoView = findViewById(R.id.mVideoView);
- PlayerHelper.updateCfg(mVideoView);
-
-// ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
-// layoutParams.width = 100;
-// layoutParams.height = 50;
-// mVideoView.setLayoutParams(layoutParams);
-
- mVideoView.addOnStateChangeListener(new VideoView.SimpleOnStateChangeListener() {
- @Override
- public void onPlayStateChanged(int state) {
- switch (state) {
- case VideoView.STATE_IDLE:
- case VideoView.STATE_PREPARED:
- case VideoView.STATE_PLAYING:
- case VideoView.STATE_BUFFERED:
- case VideoView.STATE_PAUSED:
- case VideoView.STATE_BUFFERING:
- case VideoView.STATE_PREPARING:
- break;
- case VideoView.STATE_PLAYBACK_COMPLETED:
- finish();
- break;
- case VideoView.STATE_ERROR:
- finish();
- tryDismissParse();
- Toast.makeText(mContext, "播放错误", Toast.LENGTH_SHORT).show();
- break;
- }
- }
- });
-
- controller = new BoxVideoController(this);
-
- controller.addControlComponent(new GestureView(this));
- BoxVodControlView boxVodControlView = new BoxVodControlView(this);
- boxVodControlView.hideNextPre();
- controller.addControlComponent(boxVodControlView);
- controller.setCanChangePosition(true);
- controller.setEnableInNormal(true);
- controller.setGestureEnabled(true);
- mVideoView.setVideoController(controller);
- }
-
- ParseDialog parseDialog = null;
-
- void tryDismissParse() {
- if (parseDialog != null) {
- try {
- parseDialog.dismiss();
- } catch (Throwable th) {
- th.printStackTrace();
- }
- }
- }
-
- private void initData() {
- Intent intent = getIntent();
- if (intent != null && intent.getExtras() != null) {
- Bundle bundle = intent.getExtras();
- String html = bundle.getString("html");
-
- tryDismissParse();
-
- parseDialog = new ParseDialog().build(this, new ParseDialog.BackPress() {
- @Override
- public void onBack() {
- ProjectionPlayActivity.this.finish();
- tryDismissParse();
- }
- });
-
- parseDialog.show();
-
-/* parseDialog.parse("", "", html, new ParseDialog.ParseCallback() {
- @Override
- public void success(String playUrl, Map headers) {
- controller.boxTVRefreshInfo(playUrl);
- if (mVideoView != null) {
- mVideoView.release();
- mVideoView.setUrl(playUrl);
- mVideoView.start();
- }
- tryDismissParse();
- }
-
- @Override
- public void fail() {
- ProjectionPlayActivity.this.finish();
- tryDismissParse();
- }
- });*/
- }
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- int keyCode = event.getKeyCode();
- int action = event.getAction();
- if (action == KeyEvent.ACTION_DOWN) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
- controller.boxTVSlideStart(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : -1);
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || (Hawk.get(HawkConfig.DEBUG_OPEN, false) && keyCode == KeyEvent.KEYCODE_0)) {
- controller.boxTVTogglePlay();
- }
- } else if (action == KeyEvent.ACTION_UP) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
- controller.boxTVSlideStop();
- }
- }
- return super.dispatchKeyEvent(event);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (mVideoView != null) {
- mVideoView.resume();
- }
- }
-
-
- @Override
- protected void onPause() {
- super.onPause();
- if (mVideoView != null) {
- mVideoView.pause();
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (mVideoView != null) {
- mVideoView.release();
- mVideoView = null;
- }
- tryDismissParse();
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/PushActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/PushActivity.java
new file mode 100644
index 0000000000..4c96302c63
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/PushActivity.java
@@ -0,0 +1,68 @@
+package com.github.tvbox.osc.ui.activity;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.base.BaseActivity;
+import com.github.tvbox.osc.server.ControlManager;
+import com.github.tvbox.osc.ui.tv.QRCodeGen;
+
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
+public class PushActivity extends BaseActivity {
+ private ImageView ivQRCode;
+ private TextView tvAddress;
+
+ @Override
+ protected int getLayoutResID() {
+ return R.layout.activity_push;
+ }
+
+ @Override
+ protected void init() {
+ initView();
+ initData();
+ }
+
+ private void initView() {
+ ivQRCode = findViewById(R.id.ivQRCode);
+ tvAddress = findViewById(R.id.tvAddress);
+ refreshQRCode();
+ findViewById(R.id.pushLocal).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ try {
+ ClipboardManager manager = (ClipboardManager) PushActivity.this.getSystemService(Context.CLIPBOARD_SERVICE);
+ if (manager != null) {
+ if (manager.hasPrimaryClip() && manager.getPrimaryClip() != null && manager.getPrimaryClip().getItemCount() > 0) {
+ ClipData.Item addedText = manager.getPrimaryClip().getItemAt(0);
+ Intent newIntent = new Intent(mContext, DetailActivity.class);
+ newIntent.putExtra("id", addedText.getText().toString().trim());
+ newIntent.putExtra("sourceKey", "push_agent");
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ PushActivity.this.startActivity(newIntent);
+ }
+ }
+ } catch (Throwable th) {
+
+ }
+ }
+ });
+ }
+
+ private void refreshQRCode() {
+ String address = ControlManager.get().getAddress(false);
+ tvAddress.setText(String.format("手机/电脑扫描上方二维码或者直接浏览器访问地址\n%s", address));
+ ivQRCode.setImageBitmap(QRCodeGen.generateBitmap(address, AutoSizeUtils.mm2px(this, 300), AutoSizeUtils.mm2px(this, 300), 4));
+ }
+
+ private void initData() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/SearchActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/SearchActivity.java
index 00b04ad36a..91019c4ff4 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/SearchActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/SearchActivity.java
@@ -28,6 +28,7 @@
import com.github.tvbox.osc.ui.tv.QRCodeGen;
import com.github.tvbox.osc.ui.tv.widget.SearchKeyboard;
import com.github.tvbox.osc.util.FastClickCheckUtil;
+import com.github.tvbox.osc.util.HawkConfig;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@@ -36,7 +37,9 @@
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.Response;
+import com.orhanobut.hawk.Hawk;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
+import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
import org.greenrobot.eventbus.EventBus;
@@ -81,6 +84,22 @@ protected void init() {
initData();
}
+ private List pauseRunnable = null;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (pauseRunnable != null && pauseRunnable.size() > 0) {
+ searchExecutorService = Executors.newFixedThreadPool(5);
+ allRunCount.set(pauseRunnable.size());
+ for (Runnable runnable : pauseRunnable) {
+ searchExecutorService.execute(runnable);
+ }
+ pauseRunnable.clear();
+ pauseRunnable = null;
+ }
+ }
+
private void initView() {
EventBus.getDefault().register(this);
llLayout = findViewById(R.id.llLayout);
@@ -103,7 +122,12 @@ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
}
});
mGridView.setHasFixedSize(true);
- mGridView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
+ // lite
+ if (Hawk.get(HawkConfig.SEARCH_VIEW, 0) == 0)
+ mGridView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
+ // with preview
+ else
+ mGridView.setLayoutManager(new V7GridLayoutManager(this.mContext, 3));
searchAdapter = new SearchAdapter();
mGridView.setAdapter(searchAdapter);
searchAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@@ -112,6 +136,14 @@ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
FastClickCheckUtil.check(view);
Movie.Video video = searchAdapter.getData().get(position);
if (video != null) {
+ try {
+ if (searchExecutorService != null) {
+ pauseRunnable = searchExecutorService.shutdownNow();
+ searchExecutorService = null;
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
Bundle bundle = new Bundle();
bundle.putString("id", video.id);
bundle.putString("sourceKey", video.sourceKey);
@@ -158,7 +190,7 @@ public void onSearchKey(int pos, String key) {
loadRec(text);
}
} else if (pos == 0) {
- RemoteDialog remoteDialog = new RemoteDialog().build(mContext);
+ RemoteDialog remoteDialog = new RemoteDialog(mContext);
remoteDialog.show();
}
}
@@ -282,6 +314,7 @@ private void searchResult() {
try {
if (searchExecutorService != null) {
searchExecutorService.shutdownNow();
+ searchExecutorService = null;
}
} catch (Throwable th) {
th.printStackTrace();
@@ -298,7 +331,7 @@ private void searchResult() {
ArrayList siteKey = new ArrayList<>();
for (SourceBean bean : searchRequestList) {
- if (!bean.isActive() || bean.isAddition()) {
+ if (!bean.isSearchable()) {
continue;
}
siteKey.add(bean.getKey());
@@ -347,6 +380,14 @@ private void cancel() {
protected void onDestroy() {
super.onDestroy();
cancel();
+ try {
+ if (searchExecutorService != null) {
+ searchExecutorService.shutdownNow();
+ searchExecutorService = null;
+ }
+ } catch (Throwable th) {
+ th.printStackTrace();
+ }
EventBus.getDefault().unregister(this);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/SettingActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/SettingActivity.java
index a1c090ebf3..8fe585f4bf 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/activity/SettingActivity.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/SettingActivity.java
@@ -1,6 +1,7 @@
package com.github.tvbox.osc.ui.activity;
import android.graphics.Color;
+import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
@@ -14,10 +15,9 @@
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.base.BaseActivity;
import com.github.tvbox.osc.base.BaseLazyFragment;
+import com.github.tvbox.osc.ui.adapter.SettingMenuAdapter;
import com.github.tvbox.osc.ui.adapter.SettingPageAdapter;
-import com.github.tvbox.osc.ui.adapter.SettingSortAdapter;
import com.github.tvbox.osc.ui.fragment.ModelSettingFragment;
-import com.github.tvbox.osc.ui.fragment.SourceSettingFragment;
import com.github.tvbox.osc.util.AppManager;
import com.github.tvbox.osc.util.HawkConfig;
import com.orhanobut.hawk.Hawk;
@@ -35,7 +35,7 @@
public class SettingActivity extends BaseActivity {
private TvRecyclerView mGridView;
private ViewPager mViewPager;
- private SettingSortAdapter sortAdapter;
+ private SettingMenuAdapter sortAdapter;
private SettingPageAdapter pageAdapter;
private List fragments = new ArrayList<>();
private boolean sortChange = false;
@@ -44,7 +44,8 @@ public class SettingActivity extends BaseActivity {
private Handler mHandler = new Handler();
private String homeSourceKey;
private String currentApi;
- private String homeSourceSort;
+ private int homeRec;
+ private int dnsOpt;
@Override
protected int getLayoutResID() {
@@ -60,7 +61,7 @@ protected void init() {
private void initView() {
mGridView = findViewById(R.id.mGridView);
mViewPager = findViewById(R.id.mViewPager);
- sortAdapter = new SettingSortAdapter();
+ sortAdapter = new SettingMenuAdapter();
mGridView.setAdapter(sortAdapter);
mGridView.setLayoutManager(new V7LinearLayoutManager(this.mContext, 1, false));
sortAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@@ -107,18 +108,15 @@ public void onItemClick(TvRecyclerView parent, View itemView, int position) {
private void initData() {
currentApi = Hawk.get(HawkConfig.API_URL, "");
homeSourceKey = ApiConfig.get().getHomeSourceBean().getKey();
- homeSourceSort = ApiConfig.get().getHomeSourceBean().getState().tidSort;
- if (homeSourceSort == null)
- homeSourceSort = "";
+ homeRec = Hawk.get(HawkConfig.HOME_REC, 0);
+ dnsOpt = Hawk.get(HawkConfig.DOH_URL, 0);
List sortList = new ArrayList<>();
- sortList.add("数据源");
sortList.add("设置其他");
sortAdapter.setNewData(sortList);
initViewPager();
}
private void initViewPager() {
- fragments.add(SourceSettingFragment.newInstance());
fragments.add(ModelSettingFragment.newInstance());
pageAdapter = new SettingPageAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(pageAdapter);
@@ -179,15 +177,18 @@ public boolean dispatchKeyEvent(KeyEvent event) {
@Override
public void onBackPressed() {
- String newHomeSourceSort = ApiConfig.get().getHomeSourceBean().getState().tidSort;
- if (newHomeSourceSort == null)
- newHomeSourceSort = "";
-
- if ((homeSourceKey != null && !homeSourceKey.equals(ApiConfig.get().getHomeSourceBean().getKey())) ||
+ if ((homeSourceKey != null && !homeSourceKey.equals(Hawk.get(HawkConfig.HOME_API, ""))) ||
!currentApi.equals(Hawk.get(HawkConfig.API_URL, "")) ||
- !homeSourceSort.equals(newHomeSourceSort)) {
+ homeRec != Hawk.get(HawkConfig.HOME_REC, 0) ||
+ dnsOpt != Hawk.get(HawkConfig.DOH_URL, 0)) {
AppManager.getInstance().finishAllActivity();
- jumpActivity(HomeActivity.class);
+ if (currentApi.equals(Hawk.get(HawkConfig.API_URL, ""))) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("useCache", true);
+ jumpActivity(HomeActivity.class, bundle);
+ } else {
+ jumpActivity(HomeActivity.class);
+ }
} else {
super.onBackPressed();
}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/ApiHistoryDialogAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/ApiHistoryDialogAdapter.java
new file mode 100644
index 0000000000..3d986b8e3d
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/ApiHistoryDialogAdapter.java
@@ -0,0 +1,104 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.ListAdapter;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.github.tvbox.osc.R;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ApiHistoryDialogAdapter extends ListAdapter {
+
+ class SelectViewHolder extends RecyclerView.ViewHolder {
+
+ public SelectViewHolder(@NonNull @NotNull View itemView) {
+ super(itemView);
+ }
+ }
+
+ public interface SelectDialogInterface {
+ void click(String value);
+
+ void del(String value, ArrayList data);
+ }
+
+
+ private ArrayList data = new ArrayList<>();
+
+ private String select = "";
+
+ private SelectDialogInterface dialogInterface = null;
+
+ public ApiHistoryDialogAdapter(SelectDialogInterface dialogInterface) {
+ super(new DiffUtil.ItemCallback() {
+ @Override
+ public boolean areItemsTheSame(@NonNull @NotNull String oldItem, @NonNull @NotNull String newItem) {
+ return oldItem.equals(newItem);
+ }
+
+ @Override
+ public boolean areContentsTheSame(@NonNull @NotNull String oldItem, @NonNull @NotNull String newItem) {
+ return oldItem.equals(newItem);
+ }
+ });
+ this.dialogInterface = dialogInterface;
+ }
+
+ public void setData(List newData, int defaultSelect) {
+ data.clear();
+ data.addAll(newData);
+ select = data.get(defaultSelect);
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemCount() {
+ return data.size();
+ }
+
+
+ @Override
+ public ApiHistoryDialogAdapter.SelectViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
+ return new ApiHistoryDialogAdapter.SelectViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dialog_api_history, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull @NotNull ApiHistoryDialogAdapter.SelectViewHolder holder, int position) {
+ String value = data.get(position);
+ String name = value;
+ if (select.equals(value))
+ name = "√ " + name;
+ ((TextView) holder.itemView.findViewById(R.id.tvName)).setText(name);
+ holder.itemView.findViewById(R.id.tvName).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (select.equals(value))
+ return;
+ notifyItemChanged(data.indexOf(select));
+ select = value;
+ notifyItemChanged(data.indexOf(value));
+ dialogInterface.click(value);
+ }
+ });
+ holder.itemView.findViewById(R.id.tvDel).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (select.equals(value))
+ return;
+ notifyItemRemoved(data.indexOf(value));
+ data.remove(value);
+ dialogInterface.del(value, data);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/BackupAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/BackupAdapter.java
new file mode 100644
index 0000000000..cc080162e2
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/BackupAdapter.java
@@ -0,0 +1,19 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+
+import java.util.ArrayList;
+
+public class BackupAdapter extends BaseQuickAdapter {
+ public BackupAdapter() {
+ super(R.layout.item_dialog_backup, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, String item) {
+ helper.setText(R.id.tvName, item);
+ helper.addOnClickListener(R.id.tvName);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/CollectAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/CollectAdapter.java
new file mode 100644
index 0000000000..33ccd51d6d
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/CollectAdapter.java
@@ -0,0 +1,47 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.text.TextUtils;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.cache.VodCollect;
+import com.github.tvbox.osc.picasso.RoundTransformation;
+import com.github.tvbox.osc.util.DefaultConfig;
+import com.github.tvbox.osc.util.MD5;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
+public class CollectAdapter extends BaseQuickAdapter {
+ public CollectAdapter() {
+ super(R.layout.item_grid, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, VodCollect item) {
+ helper.setVisible(R.id.tvYear, false);
+ helper.setVisible(R.id.tvLang, false);
+ helper.setVisible(R.id.tvArea, false);
+ helper.setVisible(R.id.tvNote, false);
+ helper.setText(R.id.tvName, item.name);
+ ImageView ivThumb = helper.getView(R.id.ivThumb);
+ //由于部分电视机使用glide报错
+ if (!TextUtils.isEmpty(item.pic)) {
+ Picasso.get()
+ .load(DefaultConfig.checkReplaceProxy(item.pic))
+ .transform(new RoundTransformation(MD5.string2MD5(item.pic + item.name))
+ .centerCorp(true)
+ .override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
+ .roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
+ .into(ivThumb);
+ } else {
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridAdapter.java
index 63a9f97fb6..317a9e9eee 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridAdapter.java
@@ -10,6 +10,7 @@
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.bean.Movie;
import com.github.tvbox.osc.picasso.RoundTransformation;
+import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.MD5;
import com.squareup.picasso.Picasso;
@@ -24,7 +25,7 @@
*/
public class GridAdapter extends BaseQuickAdapter {
public GridAdapter() {
- super(R.layout.item_grid_layout, new ArrayList<>());
+ super(R.layout.item_grid, new ArrayList<>());
}
@Override
@@ -37,19 +38,21 @@ protected void convert(BaseViewHolder helper, Movie.Video item) {
tvYear.setVisibility(View.VISIBLE);
}
TextView tvLang = helper.getView(R.id.tvLang);
- if (TextUtils.isEmpty(item.lang)) {
+ tvLang.setVisibility(View.GONE);
+ /*if (TextUtils.isEmpty(item.lang)) {
tvLang.setVisibility(View.GONE);
} else {
tvLang.setText(item.lang);
tvLang.setVisibility(View.VISIBLE);
- }
+ }*/
TextView tvArea = helper.getView(R.id.tvArea);
- if (TextUtils.isEmpty(item.area)) {
+ tvArea.setVisibility(View.GONE);
+ /*if (TextUtils.isEmpty(item.area)) {
tvArea.setVisibility(View.GONE);
} else {
tvArea.setText(item.area);
tvArea.setVisibility(View.VISIBLE);
- }
+ }*/
if (TextUtils.isEmpty(item.note)) {
helper.setVisible(R.id.tvNote, false);
} else {
@@ -62,16 +65,16 @@ protected void convert(BaseViewHolder helper, Movie.Video item) {
//由于部分电视机使用glide报错
if (!TextUtils.isEmpty(item.pic)) {
Picasso.get()
- .load(item.pic)
+ .load(DefaultConfig.checkReplaceProxy(item.pic))
.transform(new RoundTransformation(MD5.string2MD5(item.pic + "position=" + helper.getLayoutPosition()))
.centerCorp(true)
.override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
.roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
- .placeholder(R.drawable.error_loading)
- .error(R.drawable.error_loading)
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
.into(ivThumb);
} else {
- ivThumb.setImageResource(R.drawable.error_loading);
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridFilterKVAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridFilterKVAdapter.java
new file mode 100644
index 0000000000..ed9d8f5b8f
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/GridFilterKVAdapter.java
@@ -0,0 +1,18 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+
+import java.util.ArrayList;
+
+public class GridFilterKVAdapter extends BaseQuickAdapter {
+ public GridFilterKVAdapter() {
+ super(R.layout.item_grid_filter_value, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, String item) {
+ helper.setText(R.id.filterValue, item);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/HistoryAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/HistoryAdapter.java
index 21bf438baf..869dffec3e 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/HistoryAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/HistoryAdapter.java
@@ -1,15 +1,16 @@
package com.github.tvbox.osc.ui.adapter;
import android.text.TextUtils;
-import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.bean.VodInfo;
import com.github.tvbox.osc.picasso.RoundTransformation;
+import com.github.tvbox.osc.util.DefaultConfig;
import com.github.tvbox.osc.util.MD5;
import com.squareup.picasso.Picasso;
@@ -24,19 +25,20 @@
*/
public class HistoryAdapter extends BaseQuickAdapter {
public HistoryAdapter() {
- super(R.layout.item_grid_layout, new ArrayList<>());
+ super(R.layout.item_grid, new ArrayList<>());
}
@Override
protected void convert(BaseViewHolder helper, VodInfo item) {
TextView tvYear = helper.getView(R.id.tvYear);
- if (item.year <= 0) {
+ /*if (item.year <= 0) {
tvYear.setVisibility(View.GONE);
} else {
tvYear.setText(String.valueOf(item.year));
tvYear.setVisibility(View.VISIBLE);
- }
- TextView tvLang = helper.getView(R.id.tvLang);
+ }*/
+ tvYear.setText(ApiConfig.get().getSource(item.sourceKey).getName());
+ /*TextView tvLang = helper.getView(R.id.tvLang);
if (TextUtils.isEmpty(item.lang)) {
tvLang.setVisibility(View.GONE);
} else {
@@ -50,23 +52,33 @@ protected void convert(BaseViewHolder helper, VodInfo item) {
tvArea.setText(item.area);
tvArea.setVisibility(View.VISIBLE);
}
- helper.setText(R.id.tvNote, item.note);
+
+ TextView tvNote = helper.getView(R.id.tvNote);
+ if (TextUtils.isEmpty(item.note)) {
+ tvNote.setVisibility(View.GONE);
+ } else {
+ tvNote.setText(item.note);
+ tvNote.setVisibility(View.VISIBLE);
+ }*/
+ helper.setVisible(R.id.tvLang, false);
+ helper.setVisible(R.id.tvArea, false);
+ helper.setVisible(R.id.tvNote, false);
helper.setText(R.id.tvName, item.name);
- helper.setText(R.id.tvActor, item.actor);
+ // helper.setText(R.id.tvActor, item.actor);
ImageView ivThumb = helper.getView(R.id.ivThumb);
//由于部分电视机使用glide报错
if (!TextUtils.isEmpty(item.pic)) {
Picasso.get()
- .load(item.pic)
- .transform(new RoundTransformation(MD5.string2MD5(item.pic + item.note))
+ .load(DefaultConfig.checkReplaceProxy(item.pic))
+ .transform(new RoundTransformation(MD5.string2MD5(item.pic + item.name))
.centerCorp(true)
.override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
.roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
- .placeholder(R.drawable.error_loading)
- .error(R.drawable.error_loading)
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
.into(ivThumb);
} else {
- ivThumb.setImageResource(R.drawable.error_loading);
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/HomeHotVodAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/HomeHotVodAdapter.java
new file mode 100644
index 0000000000..68cffaddef
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/HomeHotVodAdapter.java
@@ -0,0 +1,53 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.Movie;
+import com.github.tvbox.osc.picasso.RoundTransformation;
+import com.github.tvbox.osc.util.DefaultConfig;
+import com.github.tvbox.osc.util.MD5;
+import com.squareup.picasso.Picasso;
+
+import java.util.ArrayList;
+
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
+public class HomeHotVodAdapter extends BaseQuickAdapter {
+
+ public HomeHotVodAdapter() {
+ super(R.layout.item_user_hot_vod, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, Movie.Video item) {
+ TextView tvRate = helper.getView(R.id.tvNote);
+ if (item.note == null || item.note.isEmpty()) {
+ tvRate.setVisibility(View.GONE);
+ } else {
+ tvRate.setText(item.note);
+ tvRate.setVisibility(View.VISIBLE);
+ }
+ helper.setText(R.id.tvName, item.name);
+ ImageView ivThumb = helper.getView(R.id.ivThumb);
+ //由于部分电视机使用glide报错
+ if (!TextUtils.isEmpty(item.pic)) {
+ Picasso.get()
+ .load(DefaultConfig.checkReplaceProxy(item.pic))
+ .transform(new RoundTransformation(MD5.string2MD5(item.pic + "position=" + helper.getLayoutPosition()))
+ .centerCorp(true)
+ .override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
+ .roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
+ .into(ivThumb);
+ } else {
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/IJKOptionAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/IJKOptionAdapter.java
deleted file mode 100644
index 3865fca4ef..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/IJKOptionAdapter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.github.tvbox.osc.ui.adapter;
-
-import android.graphics.Color;
-import android.widget.TextView;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.IJKCode;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2020/12/22
- * @description:
- */
-public class IJKOptionAdapter extends BaseQuickAdapter {
- public IJKOptionAdapter() {
- super(R.layout.item_ijk_codec_layout, new ArrayList<>());
- }
-
- @Override
- protected void convert(BaseViewHolder helper, IJKCode item) {
- TextView codeName = helper.getView(R.id.tvIJKCodecName);
- if (item.isSelected()) {
- codeName.setTextColor(mContext.getResources().getColor(R.color.color_058AF4));
- } else {
- codeName.setTextColor(Color.BLACK);
- }
- codeName.setText(item.getName());
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelAdapter.java
deleted file mode 100644
index 96e59e1253..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelAdapter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.github.tvbox.osc.ui.adapter;
-
-import android.graphics.Color;
-import android.widget.TextView;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.LiveChannel;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2021/1/12
- * @description:
- */
-public class LiveChannelAdapter extends BaseQuickAdapter {
- public LiveChannelAdapter() {
- super(R.layout.item_live_channel_layout, new ArrayList<>());
- }
-
- @Override
- protected void convert(BaseViewHolder helper, LiveChannel item) {
- TextView tvChannelNum = helper.getView(R.id.tvChannelNum);
- TextView tvChannel = helper.getView(R.id.tvChannel);
- tvChannelNum.setText(String.format("%s", item.getChannelNum()));
- tvChannel.setText(String.format("%s", item.getName()));
- if (item.isDefault()) {
- tvChannelNum.setTextColor(mContext.getResources().getColor(R.color.color_02F8E1));
- tvChannel.setTextColor(mContext.getResources().getColor(R.color.color_02F8E1));
- } else {
- tvChannelNum.setTextColor(Color.WHITE);
- tvChannel.setTextColor(Color.WHITE);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelGroupAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelGroupAdapter.java
new file mode 100644
index 0000000000..c52f79c52e
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelGroupAdapter.java
@@ -0,0 +1,60 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.graphics.Color;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.LiveChannelGroup;
+
+import java.util.ArrayList;
+
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveChannelGroupAdapter extends BaseQuickAdapter {
+ private int selectedGroupIndex = -1;
+ private int focusedGroupIndex = -1;
+
+ public LiveChannelGroupAdapter() {
+ super(R.layout.item_live_channel_group, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder holder, LiveChannelGroup item) {
+ TextView tvGroupName = holder.getView(R.id.tvChannelGroupName);
+ tvGroupName.setText(item.getGroupName());
+ int groupIndex = item.getGroupIndex();
+ if (groupIndex == selectedGroupIndex && groupIndex != focusedGroupIndex) {
+ tvGroupName.setTextColor(mContext.getResources().getColor(R.color.color_1890FF));
+ } else {
+ tvGroupName.setTextColor(Color.WHITE);
+ }
+ }
+
+ public void setSelectedGroupIndex(int selectedGroupIndex) {
+ if (selectedGroupIndex == this.selectedGroupIndex) return;
+ int preSelectedGroupIndex = this.selectedGroupIndex;
+ this.selectedGroupIndex = selectedGroupIndex;
+ if (preSelectedGroupIndex != -1)
+ notifyItemChanged(preSelectedGroupIndex);
+ if (this.selectedGroupIndex != -1)
+ notifyItemChanged(this.selectedGroupIndex);
+ }
+
+ public int getSelectedGroupIndex() {
+ return selectedGroupIndex;
+ }
+
+ public void setFocusedGroupIndex(int focusedGroupIndex) {
+ this.focusedGroupIndex = focusedGroupIndex;
+ if (this.focusedGroupIndex != -1)
+ notifyItemChanged(this.focusedGroupIndex);
+ else if (this.selectedGroupIndex != -1)
+ notifyItemChanged(this.selectedGroupIndex);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelItemAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelItemAdapter.java
new file mode 100644
index 0000000000..122c4bdd59
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveChannelItemAdapter.java
@@ -0,0 +1,63 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.graphics.Color;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.LiveChannelItem;
+
+import java.util.ArrayList;
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveChannelItemAdapter extends BaseQuickAdapter {
+ private int selectedChannelIndex = -1;
+ private int focusedChannelIndex = -1;
+
+ public LiveChannelItemAdapter() {
+ super(R.layout.item_live_channel, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder holder, LiveChannelItem item) {
+ TextView tvChannelNum = holder.getView(R.id.tvChannelNum);
+ TextView tvChannel = holder.getView(R.id.tvChannelName);
+ tvChannelNum.setText(String.format("%s", item.getChannelNum()));
+ tvChannel.setText(item.getChannelName());
+ int channelIndex = item.getChannelIndex();
+ if (channelIndex == selectedChannelIndex && channelIndex != focusedChannelIndex) {
+ tvChannelNum.setTextColor(mContext.getResources().getColor(R.color.color_1890FF));
+ tvChannel.setTextColor(mContext.getResources().getColor(R.color.color_1890FF));
+ }
+ else{
+ tvChannelNum.setTextColor(Color.WHITE);
+ tvChannel.setTextColor(Color.WHITE);
+ }
+ }
+
+ public void setSelectedChannelIndex(int selectedChannelIndex) {
+ if (selectedChannelIndex == this.selectedChannelIndex) return;
+ int preSelectedChannelIndex = this.selectedChannelIndex;
+ this.selectedChannelIndex = selectedChannelIndex;
+ if (preSelectedChannelIndex != -1)
+ notifyItemChanged(preSelectedChannelIndex);
+ if (this.selectedChannelIndex != -1)
+ notifyItemChanged(this.selectedChannelIndex);
+ }
+
+ public void setFocusedChannelIndex(int focusedChannelIndex) {
+ int preFocusedChannelIndex = this.focusedChannelIndex;
+ this.focusedChannelIndex = focusedChannelIndex;
+ if (preFocusedChannelIndex != -1)
+ notifyItemChanged(preFocusedChannelIndex);
+ if (this.focusedChannelIndex != -1)
+ notifyItemChanged(this.focusedChannelIndex);
+ else if (this.selectedChannelIndex != -1)
+ notifyItemChanged(this.selectedChannelIndex);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingGroupAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingGroupAdapter.java
new file mode 100644
index 0000000000..134df48e5c
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingGroupAdapter.java
@@ -0,0 +1,59 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.graphics.Color;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.LiveSettingGroup;
+
+import java.util.ArrayList;
+
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveSettingGroupAdapter extends BaseQuickAdapter {
+ private int selectedGroupIndex = -1;
+ private int focusedGroupIndex = -1;
+
+ public LiveSettingGroupAdapter() {
+ super(R.layout.item_live_setting_group, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder holder, LiveSettingGroup group) {
+ TextView tvGroupName = holder.getView(R.id.tvSettingGroupName);
+ tvGroupName.setText(group.getGroupName());
+ int groupIndex = group.getGroupIndex();
+ if (groupIndex == selectedGroupIndex && groupIndex != focusedGroupIndex) {
+ tvGroupName.setTextColor(mContext.getResources().getColor(R.color.color_1890FF));
+ } else {
+ tvGroupName.setTextColor(Color.WHITE);
+ }
+ }
+
+ public void setSelectedGroupIndex(int selectedGroupIndex) {
+ int preSelectedGroupIndex = this.selectedGroupIndex;
+ this.selectedGroupIndex = selectedGroupIndex;
+ if (preSelectedGroupIndex != -1)
+ notifyItemChanged(preSelectedGroupIndex);
+ if (this.selectedGroupIndex != -1)
+ notifyItemChanged(this.selectedGroupIndex);
+ }
+
+ public int getSelectedGroupIndex() {
+ return selectedGroupIndex;
+ }
+
+ public void setFocusedGroupIndex(int focusedGroupIndex) {
+ this.focusedGroupIndex = focusedGroupIndex;
+ if (this.focusedGroupIndex != -1)
+ notifyItemChanged(this.focusedGroupIndex);
+ else if (this.selectedGroupIndex != -1)
+ notifyItemChanged(this.selectedGroupIndex);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingItemAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingItemAdapter.java
new file mode 100644
index 0000000000..8801c0d1a9
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/LiveSettingItemAdapter.java
@@ -0,0 +1,68 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.graphics.Color;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.LiveSettingItem;
+
+import java.util.ArrayList;
+
+
+/**
+ * @author pj567
+ * @date :2021/1/12
+ * @description:
+ */
+public class LiveSettingItemAdapter extends BaseQuickAdapter {
+ private int focusedItemIndex = -1;
+
+ public LiveSettingItemAdapter() {
+ super(R.layout.item_live_setting, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder holder, LiveSettingItem item) {
+ TextView tvItemName = holder.getView(R.id.tvSettingItemName);
+ tvItemName.setText(item.getItemName());
+ int itemIndex = item.getItemIndex();
+ if (item.isItemSelected() && itemIndex != focusedItemIndex) {
+ tvItemName.setTextColor(mContext.getResources().getColor(R.color.color_1890FF));
+ } else {
+ tvItemName.setTextColor(Color.WHITE);
+ }
+ }
+
+ public void selectItem(int selectedItemIndex, boolean select, boolean unselectPreItemIndex) {
+ if (unselectPreItemIndex) {
+ int preSelectedItemIndex = getSelectedItemIndex();
+ if (preSelectedItemIndex != -1) {
+ getData().get(preSelectedItemIndex).setItemSelected(false);
+ notifyItemChanged(preSelectedItemIndex);
+ }
+ }
+ if (selectedItemIndex != -1) {
+ getData().get(selectedItemIndex).setItemSelected(select);
+ notifyItemChanged(selectedItemIndex);
+ }
+ }
+
+ public void setFocusedItemIndex(int focusedItemIndex) {
+ int preFocusItemIndex = this.focusedItemIndex;
+ this.focusedItemIndex = focusedItemIndex;
+ if (preFocusItemIndex != -1)
+ notifyItemChanged(preFocusItemIndex);
+ if (this.focusedItemIndex != -1)
+ notifyItemChanged(this.focusedItemIndex);
+ }
+
+ public int getSelectedItemIndex() {
+ for (LiveSettingItem item : getData()) {
+ if (item.isItemSelected())
+ return item.getItemIndex();
+ }
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseDialogAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseAdapter.java
similarity index 75%
rename from app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseDialogAdapter.java
rename to app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseAdapter.java
index 521882f954..4d41ab213d 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseDialogAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/ParseAdapter.java
@@ -11,14 +11,9 @@
import java.util.ArrayList;
-/**
- * @author pj567
- * @date :2021/3/9
- * @description:
- */
-public class ParseDialogAdapter extends BaseQuickAdapter {
- public ParseDialogAdapter() {
- super(R.layout.item_parse_dialog_layout, new ArrayList<>());
+public class ParseAdapter extends BaseQuickAdapter {
+ public ParseAdapter() {
+ super(R.layout.item_play_parse, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/PinyinAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/PinyinAdapter.java
index 889ed1668d..aeac271d71 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/PinyinAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/PinyinAdapter.java
@@ -8,7 +8,7 @@
public class PinyinAdapter extends BaseQuickAdapter {
public PinyinAdapter() {
- super(R.layout.item_search_word_layout_1, new ArrayList<>());
+ super(R.layout.item_search_word_hot, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/QuickSearchAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/QuickSearchAdapter.java
new file mode 100644
index 0000000000..77dd75e3dc
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/QuickSearchAdapter.java
@@ -0,0 +1,49 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.api.ApiConfig;
+import com.github.tvbox.osc.bean.Movie;
+
+import java.util.ArrayList;
+
+/**
+ * @author pj567
+ * @date :2020/12/23
+ * @description:
+ */
+public class QuickSearchAdapter extends BaseQuickAdapter {
+ public QuickSearchAdapter() {
+ super(R.layout.item_quick_search_lite, new ArrayList<>());
+ }
+
+ @Override
+ protected void convert(BaseViewHolder helper, Movie.Video item) {
+ // lite
+ helper.setText(R.id.tvName, String.format("%s %s %s %s", ApiConfig.get().getSource(item.sourceKey).getName(), item.name, item.type == null ? "" : item.type, item.note == null ? "" : item.note));
+ // with preview
+ /*
+ helper.setText(R.id.tvName, item.name);
+ helper.setText(R.id.tvSite, ApiConfig.get().getSource(item.sourceKey).getName());
+ helper.setVisible(R.id.tvNote, item.note != null && !item.note.isEmpty());
+ if (item.note != null && !item.note.isEmpty()) {
+ helper.setText(R.id.tvNote, item.note);
+ }
+ ImageView ivThumb = helper.getView(R.id.ivThumb);
+ if (!TextUtils.isEmpty(item.pic)) {
+ Picasso.get()
+ .load(item.pic)
+ .transform(new RoundTransformation(MD5.string2MD5(item.pic + "position=" + helper.getLayoutPosition()))
+ .centerCorp(true)
+ .override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
+ .roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
+ .placeholder(R.drawable.error_loading)
+ .error(R.drawable.error_loading)
+ .into(ivThumb);
+ } else {
+ ivThumb.setImageResource(R.drawable.error_loading);
+ }
+ */
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchAdapter.java
index b771fbb64d..14b7e25dee 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchAdapter.java
@@ -1,25 +1,54 @@
package com.github.tvbox.osc.ui.adapter;
+import android.text.TextUtils;
+import android.widget.ImageView;
+
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.bean.Movie;
+import com.github.tvbox.osc.picasso.RoundTransformation;
+import com.github.tvbox.osc.util.HawkConfig;
+import com.github.tvbox.osc.util.MD5;
+import com.orhanobut.hawk.Hawk;
+import com.squareup.picasso.Picasso;
import java.util.ArrayList;
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
public class SearchAdapter extends BaseQuickAdapter {
public SearchAdapter() {
- super(R.layout.item_search_layout, new ArrayList<>());
+ super(Hawk.get(HawkConfig.SEARCH_VIEW, 0) == 0 ? R.layout.item_search_lite : R.layout.item_search, new ArrayList<>());
}
@Override
protected void convert(BaseViewHolder helper, Movie.Video item) {
- helper.setText(R.id.tvName, String.format("%s %s %s %s", ApiConfig.get().getSource(item.sourceKey).getName(), item.name, item.type == null ? "" : item.type, item.note == null ? "" : item.note));
+ // lite
+ if (Hawk.get(HawkConfig.SEARCH_VIEW, 0) == 0) {
+ helper.setText(R.id.tvName, String.format("%s %s %s %s", ApiConfig.get().getSource(item.sourceKey).getName(), item.name, item.type == null ? "" : item.type, item.note == null ? "" : item.note));
+ } else {// with preview
+ helper.setText(R.id.tvName, item.name);
+ helper.setText(R.id.tvSite, ApiConfig.get().getSource(item.sourceKey).getName());
+ helper.setVisible(R.id.tvNote, item.note != null && !item.note.isEmpty());
+ if (item.note != null && !item.note.isEmpty()) {
+ helper.setText(R.id.tvNote, item.note);
+ }
+ ImageView ivThumb = helper.getView(R.id.ivThumb);
+ if (!TextUtils.isEmpty(item.pic)) {
+ Picasso.get()
+ .load(item.pic)
+ .transform(new RoundTransformation(MD5.string2MD5(item.pic + "position=" + helper.getLayoutPosition()))
+ .centerCorp(true)
+ .override(AutoSizeUtils.mm2px(mContext, 300), AutoSizeUtils.mm2px(mContext, 400))
+ .roundRadius(AutoSizeUtils.mm2px(mContext, 10), RoundTransformation.RoundType.ALL))
+ .placeholder(R.drawable.img_loading_placeholder)
+ .error(R.drawable.img_loading_placeholder)
+ .into(ivThumb);
+ } else {
+ ivThumb.setImageResource(R.drawable.img_loading_placeholder);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchWordAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchWordAdapter.java
index 2ce35ab4e4..720e9a92d1 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchWordAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SearchWordAdapter.java
@@ -13,7 +13,7 @@
*/
public class SearchWordAdapter extends BaseQuickAdapter {
public SearchWordAdapter() {
- super(R.layout.item_search_word_layout, new ArrayList<>());
+ super(R.layout.item_search_word_split, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SelectDialogAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SelectDialogAdapter.java
new file mode 100644
index 0000000000..2701953fcf
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SelectDialogAdapter.java
@@ -0,0 +1,98 @@
+package com.github.tvbox.osc.ui.adapter;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.ListAdapter;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.github.tvbox.osc.R;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SelectDialogAdapter extends ListAdapter {
+
+ class SelectViewHolder extends RecyclerView.ViewHolder {
+
+ public SelectViewHolder(@NonNull @NotNull View itemView) {
+ super(itemView);
+ }
+ }
+
+ public interface SelectDialogInterface {
+ void click(T value, int pos);
+
+ String getDisplay(T val);
+ }
+
+
+ public static DiffUtil.ItemCallback stringDiff = new DiffUtil.ItemCallback() {
+
+ @Override
+ public boolean areItemsTheSame(@NonNull @NotNull String oldItem, @NonNull @NotNull String newItem) {
+ return oldItem.equals(newItem);
+ }
+
+ @Override
+ public boolean areContentsTheSame(@NonNull @NotNull String oldItem, @NonNull @NotNull String newItem) {
+ return oldItem.equals(newItem);
+ }
+ };
+
+
+ private ArrayList data = new ArrayList<>();
+
+ private int select = 0;
+
+ private SelectDialogInterface dialogInterface = null;
+
+ public SelectDialogAdapter(SelectDialogInterface dialogInterface, DiffUtil.ItemCallback diffCallback) {
+ super(diffCallback);
+ this.dialogInterface = dialogInterface;
+ }
+
+ public void setData(List newData, int defaultSelect) {
+ data.clear();
+ data.addAll(newData);
+ select = defaultSelect;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemCount() {
+ return data.size();
+ }
+
+
+ @Override
+ public SelectDialogAdapter.SelectViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
+ return new SelectDialogAdapter.SelectViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_dialog_select, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull @NotNull SelectDialogAdapter.SelectViewHolder holder, int position) {
+ T value = data.get(position);
+ String name = dialogInterface.getDisplay(value);
+ if (position == select)
+ name = "√ " + name;
+ ((TextView) holder.itemView.findViewById(R.id.tvName)).setText(name);
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (position == select)
+ return;
+ notifyItemChanged(select);
+ select = position;
+ notifyItemChanged(select);
+ dialogInterface.click(value, position);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesAdapter.java
index 12925cd98a..c7d0f95cb9 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesAdapter.java
@@ -17,7 +17,7 @@
*/
public class SeriesAdapter extends BaseQuickAdapter {
public SeriesAdapter() {
- super(R.layout.item_series_layout, new ArrayList<>());
+ super(R.layout.item_series, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesFlagAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesFlagAdapter.java
index 558cc55e64..d085400820 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesFlagAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SeriesFlagAdapter.java
@@ -17,7 +17,7 @@
*/
public class SeriesFlagAdapter extends BaseQuickAdapter {
public SeriesFlagAdapter() {
- super(R.layout.item_series_flag_layout, new ArrayList<>());
+ super(R.layout.item_series_flag, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingSortAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingMenuAdapter.java
similarity index 74%
rename from app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingSortAdapter.java
rename to app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingMenuAdapter.java
index 5be1adee3b..f28d83d23b 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingSortAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SettingMenuAdapter.java
@@ -11,9 +11,9 @@
* @date :2020/12/23
* @description:
*/
-public class SettingSortAdapter extends BaseQuickAdapter {
- public SettingSortAdapter() {
- super(R.layout.item_sort_setting_layout, new ArrayList<>());
+public class SettingMenuAdapter extends BaseQuickAdapter {
+ public SettingMenuAdapter() {
+ super(R.layout.item_setting_menu, new ArrayList<>());
}
@Override
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SortAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SortAdapter.java
index cf2f4954fe..10173bd10e 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SortAdapter.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SortAdapter.java
@@ -14,12 +14,11 @@
*/
public class SortAdapter extends BaseQuickAdapter {
public SortAdapter() {
- super(R.layout.item_home_sort_layout, new ArrayList<>());
+ super(R.layout.item_home_sort, new ArrayList<>());
}
@Override
protected void convert(BaseViewHolder helper, MovieSort.SortData item) {
helper.setText(R.id.tvTitle, item.name);
- helper.addOnClickListener(R.id.tvTitle);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceSettingAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceSettingAdapter.java
deleted file mode 100644
index fae4c5268c..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceSettingAdapter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.github.tvbox.osc.ui.adapter;
-
-import android.view.View;
-import android.widget.TextView;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.SourceBean;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class SourceSettingAdapter extends BaseQuickAdapter {
- public SourceSettingAdapter() {
- super(R.layout.item_source_setting_layout, new ArrayList<>());
- }
-
- @Override
- protected void convert(BaseViewHolder helper, SourceBean item) {
- TextView tvSourceAdd = helper.getView(R.id.tvSourceAdd);
- TextView tvSourceSpeed = helper.getView(R.id.tvSourceSpeed);
- TextView tvSource = helper.getView(R.id.tvSource);
- TextView tvSourceStatus = helper.getView(R.id.tvSourceStatus);
- if (item == SourceBean.speedTestBean) {
- tvSourceSpeed.setVisibility(View.VISIBLE);
- tvSource.setVisibility(View.GONE);
- tvSourceStatus.setVisibility(View.GONE);
- tvSourceAdd.setVisibility(View.GONE);
- return;
- }
- tvSourceSpeed.setVisibility(View.GONE);
- tvSourceAdd.setVisibility(View.GONE);
- tvSource.setVisibility(View.VISIBLE);
- tvSourceStatus.setVisibility(View.VISIBLE);
-// if (item.isHome()) {
-// tvSource.setTextColor(mContext.getResources().getColor(R.color.color_02F8E1));
-// } else {
-// tvSource.setTextColor(Color.WHITE);
-// }
- tvSource.setText(item.getName());
-
- if (item.isActive()) {
- tvSourceStatus.setTextColor(mContext.getResources().getColor(R.color.color_00FF0A));
- } else {
- tvSourceStatus.setTextColor(mContext.getResources().getColor(R.color.color_FF0057));
- }
-
- String status = (item.isActive() ? "已启用" + (item.isHome() ? " ☆首页源" : "") : "未启用");
- tvSourceStatus.setText(status);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceTidSortAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceTidSortAdapter.java
deleted file mode 100644
index 297ebf7314..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SourceTidSortAdapter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.github.tvbox.osc.ui.adapter;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.MovieSort;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2020/12/21
- * @description:
- */
-public class SourceTidSortAdapter extends BaseQuickAdapter {
- public SourceTidSortAdapter() {
- super(R.layout.item_source_sort_tid_layout, new ArrayList<>());
- }
-
- @Override
- protected void convert(BaseViewHolder helper, MovieSort.SortData item) {
- helper.setText(R.id.tvSortName, item.name);
- helper.setVisible(R.id.tvSortSelect, item.select);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SpeedTestAdapter.java b/app/src/main/java/com/github/tvbox/osc/ui/adapter/SpeedTestAdapter.java
deleted file mode 100644
index 8c06015bea..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/adapter/SpeedTestAdapter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.github.tvbox.osc.ui.adapter;
-
-import android.graphics.Color;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.SourceBeanSpeed;
-
-import java.util.ArrayList;
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class SpeedTestAdapter extends BaseQuickAdapter {
- public SpeedTestAdapter() {
- super(R.layout.item_speed_test_layout, new ArrayList<>());
- }
-
- @Override
- protected void convert(BaseViewHolder helper, SourceBeanSpeed item) {
- helper.setText(R.id.tvName, item.getBean().getName());
- int speed = item.getSpeed();
- int color = Color.WHITE;
- String speedText = "正在测速";
- if (speed == Integer.MAX_VALUE) {
- speedText = "连接失败";
- color = Color.RED;
- } else if (speed > 0) {
- speedText = speed + "ms";
- if (speed < 500) {
- color = Color.GREEN;
- } else {
- color = Color.RED;
- }
- }
- helper.setText(R.id.tvSpeed, speedText);
- helper.setTextColor(R.id.tvSpeed, color);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/AboutDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/AboutDialog.java
index ba26202984..df46f65e4c 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/AboutDialog.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/AboutDialog.java
@@ -1,59 +1,17 @@
package com.github.tvbox.osc.ui.dialog;
-import android.app.Dialog;
import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
import com.github.tvbox.osc.R;
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class AboutDialog {
- private View rootView;
- private Dialog mDialog;
+import org.jetbrains.annotations.NotNull;
- public AboutDialog() {
+public class AboutDialog extends BaseDialog {
- }
-
- public AboutDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_about, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- init(context);
- return this;
- }
-
- private void init(Context context) {
-
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
+ public AboutDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setContentView(R.layout.dialog_about);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiDialog.java
new file mode 100644
index 0000000000..2a00358dfc
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiDialog.java
@@ -0,0 +1,150 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.app.Activity;
+import android.content.Context;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.event.RefreshEvent;
+import com.github.tvbox.osc.server.ControlManager;
+import com.github.tvbox.osc.ui.adapter.ApiHistoryDialogAdapter;
+import com.github.tvbox.osc.ui.tv.QRCodeGen;
+import com.github.tvbox.osc.util.HawkConfig;
+import com.hjq.permissions.OnPermissionCallback;
+import com.hjq.permissions.Permission;
+import com.hjq.permissions.XXPermissions;
+import com.orhanobut.hawk.Hawk;
+
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
+/**
+ * 描述
+ *
+ * @author pj567
+ * @since 2020/12/27
+ */
+public class ApiDialog extends BaseDialog {
+ private ImageView ivQRCode;
+ private TextView tvAddress;
+ private EditText inputApi;
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void refresh(RefreshEvent event) {
+ if (event.type == RefreshEvent.TYPE_API_URL_CHANGE) {
+ inputApi.setText((String) event.obj);
+ }
+ }
+
+ public ApiDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setContentView(R.layout.dialog_api);
+ setCanceledOnTouchOutside(false);
+ ivQRCode = findViewById(R.id.ivQRCode);
+ tvAddress = findViewById(R.id.tvAddress);
+ inputApi = findViewById(R.id.input);
+ inputApi.setText(Hawk.get(HawkConfig.API_URL, ""));
+ findViewById(R.id.inputSubmit).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String newApi = inputApi.getText().toString().trim();
+ if (!newApi.isEmpty() && (newApi.startsWith("http") || newApi.startsWith("clan"))) {
+ ArrayList history = Hawk.get(HawkConfig.API_HISTORY, new ArrayList());
+ if (!history.contains(newApi))
+ history.add(0, newApi);
+ if (history.size() > 10)
+ history.remove(10);
+ Hawk.put(HawkConfig.API_HISTORY, history);
+ listener.onchange(newApi);
+ dismiss();
+ }
+ }
+ });
+ findViewById(R.id.apiHistory).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ArrayList history = Hawk.get(HawkConfig.API_HISTORY, new ArrayList());
+ if (history.isEmpty())
+ return;
+ String current = Hawk.get(HawkConfig.API_URL, "");
+ int idx = 0;
+ if (history.contains(current))
+ idx = history.indexOf(current);
+ ApiHistoryDialog dialog = new ApiHistoryDialog(getContext());
+ dialog.setTip("历史配置列表");
+ dialog.setAdapter(new ApiHistoryDialogAdapter.SelectDialogInterface() {
+ @Override
+ public void click(String value) {
+ inputApi.setText(value);
+ listener.onchange(value);
+ dialog.dismiss();
+ }
+
+ @Override
+ public void del(String value, ArrayList data) {
+ Hawk.put(HawkConfig.API_HISTORY, data);
+ }
+ }, history, idx);
+ dialog.show();
+ }
+ });
+ findViewById(R.id.storagePermission).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (XXPermissions.isGranted(getContext(), Permission.Group.STORAGE)) {
+ Toast.makeText(getContext(), "已获得存储权限", Toast.LENGTH_SHORT).show();
+ } else {
+ XXPermissions.with(getContext())
+ .permission(Permission.Group.STORAGE)
+ .request(new OnPermissionCallback() {
+ @Override
+ public void onGranted(List permissions, boolean all) {
+ if (all) {
+ Toast.makeText(getContext(), "已获得存储权限", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onDenied(List permissions, boolean never) {
+ if (never) {
+ Toast.makeText(getContext(), "获取存储权限失败,请在系统设置中开启", Toast.LENGTH_SHORT).show();
+ XXPermissions.startPermissionActivity((Activity) getContext(), permissions);
+ } else {
+ Toast.makeText(getContext(), "获取存储权限失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+ }
+ });
+ refreshQRCode();
+ }
+
+ private void refreshQRCode() {
+ String address = ControlManager.get().getAddress(false);
+ tvAddress.setText(String.format("手机/电脑扫描上方二维码或者直接浏览器访问地址\n%s", address));
+ ivQRCode.setImageBitmap(QRCodeGen.generateBitmap(address, AutoSizeUtils.mm2px(getContext(), 300), AutoSizeUtils.mm2px(getContext(), 300)));
+ }
+
+ public void setOnListener(OnListener listener) {
+ this.listener = listener;
+ }
+
+ OnListener listener = null;
+
+ public interface OnListener {
+ void onchange(String api);
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiHistoryDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiHistoryDialog.java
new file mode 100644
index 0000000000..4c2dd509ea
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ApiHistoryDialog.java
@@ -0,0 +1,45 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.ui.adapter.ApiHistoryDialogAdapter;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class ApiHistoryDialog extends BaseDialog {
+ public ApiHistoryDialog(@NonNull @NotNull Context context) {
+ super(context, R.style.CustomDialogStyleDim);
+ setContentView(R.layout.dialog_api_history);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ public void setTip(String tip) {
+ ((TextView) findViewById(R.id.title)).setText(tip);
+ }
+
+ public void setAdapter(ApiHistoryDialogAdapter.SelectDialogInterface sourceBeanSelectDialogInterface, List data, int select) {
+ ApiHistoryDialogAdapter adapter = new ApiHistoryDialogAdapter(sourceBeanSelectDialogInterface);
+ adapter.setData(data, select);
+ TvRecyclerView tvRecyclerView = ((TvRecyclerView) findViewById(R.id.list));
+ tvRecyclerView.setAdapter(adapter);
+ tvRecyclerView.setSelectedPosition(select);
+ tvRecyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ tvRecyclerView.scrollToPosition(select);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/BackupDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/BackupDialog.java
new file mode 100644
index 0000000000..97403369ee
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/BackupDialog.java
@@ -0,0 +1,192 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.base.App;
+import com.github.tvbox.osc.data.AppDataManager;
+import com.github.tvbox.osc.ui.adapter.BackupAdapter;
+import com.github.tvbox.osc.util.FileUtils;
+import com.hjq.permissions.OnPermissionCallback;
+import com.hjq.permissions.Permission;
+import com.hjq.permissions.XXPermissions;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+
+import org.jetbrains.annotations.NotNull;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+public class BackupDialog extends BaseDialog {
+
+ public BackupDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setContentView(R.layout.dialog_backup);
+ TvRecyclerView tvRecyclerView = ((TvRecyclerView) findViewById(R.id.list));
+ BackupAdapter adapter = new BackupAdapter();
+ tvRecyclerView.setAdapter(adapter);
+ adapter.setNewData(allBackup());
+ adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
+ @Override
+ public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
+ if (view.getId() == R.id.tvName) {
+ restore((String) adapter.getItem(position));
+ }
+ }
+ });
+ findViewById(R.id.backupNow).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ backup();
+ adapter.setNewData(allBackup());
+ }
+ });
+ findViewById(R.id.storagePermission).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (XXPermissions.isGranted(getContext(), Permission.Group.STORAGE)) {
+ Toast.makeText(getContext(), "已获得存储权限", Toast.LENGTH_SHORT).show();
+ } else {
+ XXPermissions.with(getContext())
+ .permission(Permission.Group.STORAGE)
+ .request(new OnPermissionCallback() {
+ @Override
+ public void onGranted(List permissions, boolean all) {
+ if (all) {
+ adapter.setNewData(allBackup());
+ Toast.makeText(getContext(), "已获得存储权限", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onDenied(List permissions, boolean never) {
+ if (never) {
+ Toast.makeText(getContext(), "获取存储权限失败,请在系统设置中开启", Toast.LENGTH_SHORT).show();
+ XXPermissions.startPermissionActivity((Activity) getContext(), permissions);
+ } else {
+ Toast.makeText(getContext(), "获取存储权限失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+
+ List allBackup() {
+ ArrayList result = new ArrayList<>();
+ try {
+ String root = Environment.getExternalStorageDirectory().getAbsolutePath();
+ File file = new File(root + "/tvbox_backup/");
+ File[] list = file.listFiles();
+ Arrays.sort(list, new Comparator() {
+ @Override
+ public int compare(File o1, File o2) {
+ if (o1.isDirectory() && o2.isFile()) return -1;
+ return o1.isFile() && o2.isDirectory() ? 1 : o2.getName().compareTo(o1.getName());
+ }
+ });
+ if (file.exists()) {
+ for (File f : list) {
+ if (result.size() > 10) {
+ FileUtils.recursiveDelete(f);
+ continue;
+ }
+ if (f.isDirectory()) {
+ result.add(f.getName());
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ void restore(String dir) {
+ try {
+ String root = Environment.getExternalStorageDirectory().getAbsolutePath();
+ File backup = new File(root + "/tvbox_backup/" + dir);
+ if (backup.exists()) {
+ File db = new File(backup, "sqlite");
+ if (AppDataManager.restore(db)) {
+ byte[] data = FileUtils.readSimple(new File(backup, "hawk"));
+ if (data != null) {
+ String hawkJson = new String(data, "UTF-8");
+ JSONObject jsonObject = new JSONObject(hawkJson);
+ Iterator it = jsonObject.keys();
+ SharedPreferences sharedPreferences = App.getInstance().getSharedPreferences("Hawk2", Context.MODE_PRIVATE);
+ while (it.hasNext()) {
+ String key = it.next();
+ String value = jsonObject.getString(key);
+ if (key.equals("cipher_key")) {
+ App.getInstance().getSharedPreferences("crypto.KEY_256", Context.MODE_PRIVATE).edit().putString(key, value).commit();
+ } else {
+ sharedPreferences.edit().putString(key, value).commit();
+ }
+ }
+ Toast.makeText(getContext(), "恢复成功,请重启应用!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getContext(), "Hawk恢复失败!", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(getContext(), "DB文件恢复失败!", Toast.LENGTH_SHORT).show();
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ void backup() {
+ try {
+ String root = Environment.getExternalStorageDirectory().getAbsolutePath();
+ File file = new File(root + "/tvbox_backup/");
+ if (!file.exists())
+ file.mkdirs();
+ Date now = new Date();
+ SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HHmmss");
+ File backup = new File(file, f.format(now));
+ backup.mkdirs();
+ File db = new File(backup, "sqlite");
+ if (AppDataManager.backup(db)) {
+ SharedPreferences sharedPreferences = App.getInstance().getSharedPreferences("Hawk2", Context.MODE_PRIVATE);
+ JSONObject jsonObject = new JSONObject();
+ for (String key : sharedPreferences.getAll().keySet()) {
+ jsonObject.put(key, sharedPreferences.getString(key, ""));
+ }
+ sharedPreferences = App.getInstance().getSharedPreferences("crypto.KEY_256", Context.MODE_PRIVATE);
+ for (String key : sharedPreferences.getAll().keySet()) {
+ jsonObject.put(key, sharedPreferences.getString(key, ""));
+ }
+ if (!FileUtils.writeSimple(jsonObject.toString().getBytes("UTF-8"), new File(backup, "hawk"))) {
+ backup.delete();
+ Toast.makeText(getContext(), "备份Hawk失败!", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getContext(), "备份成功!", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(getContext(), "DB文件不存在!", Toast.LENGTH_SHORT).show();
+ backup.delete();
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ Toast.makeText(getContext(), "备份失败!", Toast.LENGTH_SHORT).show();
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/BaseDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/BaseDialog.java
new file mode 100644
index 0000000000..f0c30ad554
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/BaseDialog.java
@@ -0,0 +1,42 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Build;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.annotation.NonNull;
+
+import com.github.tvbox.osc.R;
+
+public class BaseDialog extends Dialog {
+ public BaseDialog(@NonNull Context context) {
+ super(context, R.style.CustomDialogStyle);
+ }
+
+ public BaseDialog(Context context, int customDialogStyle) {
+ super(context, customDialogStyle);
+ }
+
+ @Override
+ public void show() {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+ super.show();
+ hideSysBar();
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+ }
+
+ private void hideSysBar() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ int uiOptions = getWindow().getDecorView().getSystemUiVisibility();
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
+ uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ getWindow().getDecorView().setSystemUiVisibility(uiOptions);
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeIJKCodeDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeIJKCodeDialog.java
deleted file mode 100644
index 9354dbe04d..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeIJKCodeDialog.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.annotation.IdRes;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.api.ApiConfig;
-import com.github.tvbox.osc.bean.IJKCode;
-import com.github.tvbox.osc.ui.adapter.IJKOptionAdapter;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
-import com.owen.tvrecyclerview.widget.TvRecyclerView;
-import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
-
-import java.util.List;
-
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class ChangeIJKCodeDialog {
- public interface Callback {
- void change();
- }
-
- private View rootView;
- private Dialog mDialog;
- private TvRecyclerView mGridView;
- private IJKOptionAdapter ijkOptionAdapter;
- private Callback callback;
-
- public ChangeIJKCodeDialog() {
-
- }
-
- public ChangeIJKCodeDialog build(Context context, Callback callback) {
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_change_ijk_code, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- this.callback = callback;
- init(context);
- return this;
- }
-
- private void init(Context context) {
- mGridView = findViewById(R.id.tvIJKCodecGrid);
- mGridView.setHasFixedSize(true);
- ijkOptionAdapter = new IJKOptionAdapter();
- mGridView.setAdapter(ijkOptionAdapter);
- mGridView.setLayoutManager(new V7LinearLayoutManager(context, 1, false));
- List codes = ApiConfig.get().getIjkCodes();
- // fix size
-// ViewGroup.LayoutParams layoutParams = mGridView.getLayoutParams();
-// int height = layoutParams.height;
-// layoutParams.height = height / 3 * codes.size();
- ijkOptionAdapter.setNewData(codes);
- for (int i = 0; i < codes.size(); i++) {
- if (codes.get(i).isSelected()) {
- mGridView.setSelection(i);
- break;
- }
- }
- ijkOptionAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
- @Override
- public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
- FastClickCheckUtil.check(view);
- for (int i = 0; i < codes.size(); i++) {
- if (codes.get(i).isSelected()) {
- ijkOptionAdapter.notifyItemChanged(i);
- codes.get(i).selected(false);
- break;
- }
- }
- codes.get(position).selected(true);
- ijkOptionAdapter.notifyItemChanged(position);
- callback.change();
- dismiss();
- }
- });
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangePlayDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangePlayDialog.java
deleted file mode 100644
index 11fbcbb97d..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangePlayDialog.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.IdRes;
-
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
-import com.github.tvbox.osc.util.HawkConfig;
-import com.orhanobut.hawk.Hawk;
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class ChangePlayDialog {
- private View rootView;
- private Dialog mDialog;
- private OnChangePlayListener playListener;
-
- public ChangePlayDialog() {
-
- }
-
- public ChangePlayDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_change_play, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- init(context);
- return this;
- }
-
- private void init(Context context) {
- TextView tvSystem = findViewById(R.id.tvSystem);
- TextView tvIjk = findViewById(R.id.tvIjk);
- TextView tvExo = findViewById(R.id.tvExo);
- int playType = Hawk.get(HawkConfig.PLAY_TYPE, 0);
- if (playType == 1) {
- tvIjk.requestFocus();
- tvIjk.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- } else if (playType == 2) {
- tvExo.requestFocus();
- tvExo.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- } else {
- tvSystem.requestFocus();
- tvSystem.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- }
- tvSystem.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- if (playType != 0 && playListener != null) {
- Hawk.put(HawkConfig.PLAY_TYPE, 0);
- playListener.onChange();
- }
- dismiss();
- }
- });
- tvIjk.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- if (playType != 1 && playListener != null) {
- Hawk.put(HawkConfig.PLAY_TYPE, 1);
- playListener.onChange();
- }
- dismiss();
- }
- });
- tvExo.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- if (playType != 2 && playListener != null) {
- Hawk.put(HawkConfig.PLAY_TYPE, 2);
- playListener.onChange();
- }
- dismiss();
- }
- });
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
-
- public ChangePlayDialog setOnChangePlayListener(OnChangePlayListener listener) {
- playListener = listener;
- return this;
- }
-
- public interface OnChangePlayListener {
- void onChange();
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeRenderDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeRenderDialog.java
deleted file mode 100644
index 7b5541ae18..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ChangeRenderDialog.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.IdRes;
-
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
-import com.github.tvbox.osc.util.HawkConfig;
-import com.orhanobut.hawk.Hawk;
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class ChangeRenderDialog {
- private View rootView;
- private Dialog mDialog;
- private OnChangeRenderListener renderListener;
-
- public ChangeRenderDialog() {
-
- }
-
- public ChangeRenderDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_change_render, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- init(context);
- return this;
- }
-
- private void init(Context context) {
- TextView tvTextureView = findViewById(R.id.tvTextureView);
- TextView tvSurfaceView = findViewById(R.id.tvSurfaceView);
- int renderType = Hawk.get(HawkConfig.PLAY_RENDER, 0);
- if (renderType == 0) {
- tvTextureView.requestFocus();
- tvTextureView.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- } else if (renderType == 1) {
- tvSurfaceView.requestFocus();
- tvSurfaceView.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- } else {
- tvTextureView.requestFocus();
- tvTextureView.setTextColor(context.getResources().getColor(R.color.color_058AF4));
- }
- tvTextureView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- if (renderType != 0 && renderListener != null) {
- Hawk.put(HawkConfig.PLAY_RENDER, 0);
- renderListener.onChange();
- }
- dismiss();
- }
- });
- tvSurfaceView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- if (renderType != 1 && renderListener != null) {
- Hawk.put(HawkConfig.PLAY_RENDER, 1);
- renderListener.onChange();
- }
- dismiss();
- }
- });
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
- public ChangeRenderDialog setOnChangePlayListener(OnChangeRenderListener listener) {
- renderListener = listener;
- return this;
- }
-
- public interface OnChangeRenderListener {
- void onChange();
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/FastParseDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/FastParseDialog.java
deleted file mode 100644
index be60d6d081..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/FastParseDialog.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.github.tvbox.osc.R;
-import com.lzy.okgo.OkGo;
-
-/**
- * 描述
- *
- * @author pj567
- * @since 2020/12/27
- */
-public class FastParseDialog {
- private View rootView;
- private Dialog mDialog;
-
- public FastParseDialog() {
-
- }
-
- public FastParseDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.fast_parse_dialog, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(false);
- mDialog.setContentView(rootView);
- mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- OkGo.getInstance().cancelTag("fast_parse");
- }
- });
- init(context);
- return this;
- }
-
- private void init(Context context) {
-
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public boolean isShowing() {
- return mDialog != null && mDialog.isShowing();
- }
-}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/GridFilterDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/GridFilterDialog.java
new file mode 100644
index 0000000000..7fcc7ba799
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/GridFilterDialog.java
@@ -0,0 +1,103 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.bean.MovieSort;
+import com.github.tvbox.osc.ui.adapter.GridFilterKVAdapter;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+
+public class GridFilterDialog extends BaseDialog {
+ private LinearLayout filterRoot;
+
+ public GridFilterDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setCanceledOnTouchOutside(false);
+ setCancelable(true);
+ setContentView(R.layout.dialog_grid_filter);
+ filterRoot = findViewById(R.id.filterRoot);
+ }
+
+ public interface Callback {
+ void change();
+ }
+
+ public void setOnDismiss(Callback callback) {
+ setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ if (selectChange) {
+ callback.change();
+ }
+ }
+ });
+ }
+
+ public void setData(MovieSort.SortData sortData) {
+ ArrayList filters = sortData.filters;
+ for (MovieSort.SortFilter filter : filters) {
+ View line = LayoutInflater.from(getContext()).inflate(R.layout.item_grid_filter, null);
+ ((TextView) line.findViewById(R.id.filterName)).setText(filter.name);
+ TvRecyclerView gridView = line.findViewById(R.id.mFilterKv);
+ gridView.setHasFixedSize(true);
+ gridView.setLayoutManager(new V7LinearLayoutManager(getContext(), 0, false));
+ GridFilterKVAdapter filterKVAdapter = new GridFilterKVAdapter();
+ gridView.setAdapter(filterKVAdapter);
+ String key = filter.key;
+ ArrayList values = new ArrayList<>(filter.values.keySet());
+ ArrayList keys = new ArrayList<>(filter.values.values());
+ filterKVAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+ View pre = null;
+
+ @Override
+ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+ if (sortData.filterSelect.get(key) == null || !sortData.filterSelect.get(key).equals(values.get(position))) {
+ sortData.filterSelect.put(key, keys.get(position));
+ selectChange = true;
+ if (pre != null) {
+ TextView val = pre.findViewById(R.id.filterValue);
+ val.getPaint().setFakeBoldText(false);
+ val.setTextColor(getContext().getResources().getColor(R.color.color_FFFFFF));
+ }
+ TextView val = view.findViewById(R.id.filterValue);
+ val.getPaint().setFakeBoldText(true);
+ val.setTextColor(getContext().getResources().getColor(R.color.color_02F8E1));
+ pre = view;
+ }
+ }
+ });
+ filterKVAdapter.setNewData(values);
+ filterRoot.addView(line);
+ }
+ }
+
+ private boolean selectChange = false;
+
+ public void show() {
+ selectChange = false;
+ super.show();
+ WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
+ layoutParams.gravity = Gravity.BOTTOM;
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ layoutParams.dimAmount = 0f;
+ getWindow().getDecorView().setPadding(0, 0, 0, 0);
+ getWindow().setAttributes(layoutParams);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/HistoryDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/HistoryDialog.java
deleted file mode 100644
index 7c9337629b..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/HistoryDialog.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.IdRes;
-
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.bean.VodInfo;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
-
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class HistoryDialog {
- private View rootView;
- private Dialog mDialog;
- private OnHistoryListener historyListener;
- private VodInfo vodInfo;
-
- public HistoryDialog build(Context context, VodInfo vodInfo) {
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_history, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- this.vodInfo = vodInfo;
- init(context);
- return this;
- }
-
- private void init(Context context) {
- TextView tvLook = findViewById(R.id.tvLook);
- TextView tvDelete = findViewById(R.id.tvDelete);
- tvLook.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- dismiss();
- if (historyListener != null) {
- historyListener.onLook(vodInfo);
- }
- }
- });
- tvDelete.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- FastClickCheckUtil.check(v);
- dismiss();
- if (historyListener != null) {
- historyListener.onDelete(vodInfo);
- }
- }
- });
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
-
- public HistoryDialog setOnHistoryListener(OnHistoryListener listener) {
- historyListener = listener;
- return this;
- }
-
- public interface OnHistoryListener {
- void onLook(VodInfo vodInfo);
-
- void onDelete(VodInfo vodInfo);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/LivePasswordDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/LivePasswordDialog.java
new file mode 100644
index 0000000000..ac4fd97ffc
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/LivePasswordDialog.java
@@ -0,0 +1,62 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.View;
+import android.widget.EditText;
+
+import androidx.annotation.NonNull;
+
+import com.github.tvbox.osc.R;
+
+import org.jetbrains.annotations.NotNull;
+
+
+
+/**
+ * 描述
+ *
+ * @author pj567
+ * @since 2020/12/27
+ */
+public class LivePasswordDialog extends BaseDialog {
+ private EditText inputPassword;
+
+ public LivePasswordDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setOwnerActivity((Activity) context);
+ setContentView(R.layout.dialog_live_password);
+ inputPassword = findViewById(R.id.input);
+ findViewById(R.id.inputSubmit).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String password = inputPassword.getText().toString().trim();
+ if (!password.isEmpty()) {
+ listener.onChange(password);
+ dismiss();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ listener.onCancel();
+ dismiss();
+ }
+
+ public void setOnListener(OnListener listener) {
+ this.listener = listener;
+ }
+
+ OnListener listener = null;
+
+ public interface OnListener {
+ void onChange(String password);
+ void onCancel();
+ }
+}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/LoadingDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/LoadingDialog.java
deleted file mode 100644
index 6aca38f9f5..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/LoadingDialog.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.github.tvbox.osc.R;
-
-/**
- * 描述
- *
- * @author pj567
- * @since 2020/12/27
- */
-public class LoadingDialog {
- private View rootView;
- private Dialog mDialog;
-
- public LoadingDialog() {
-
- }
-
- public LoadingDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.loading_dialog, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(false);
- mDialog.setContentView(rootView);
- init(context);
- return this;
- }
-
- private void init(Context context) {
-
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public boolean isShowing() {
- return mDialog != null && mDialog.isShowing();
- }
-}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ParseDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/ParseDialog.java
deleted file mode 100644
index 171c4ccf6a..0000000000
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/ParseDialog.java
+++ /dev/null
@@ -1,783 +0,0 @@
-package com.github.tvbox.osc.ui.dialog;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.Color;
-import android.net.http.SslError;
-import android.os.Build;
-import android.os.Handler;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.ConsoleMessage;
-import android.webkit.SslErrorHandler;
-import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebResourceRequest;
-import android.webkit.WebResourceResponse;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.annotation.IdRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.github.tvbox.osc.R;
-import com.github.tvbox.osc.api.ApiConfig;
-import com.github.tvbox.osc.bean.ParseBean;
-import com.github.tvbox.osc.ui.adapter.ParseDialogAdapter;
-import com.github.tvbox.osc.util.AdBlocker;
-import com.github.tvbox.osc.util.DefaultConfig;
-import com.github.tvbox.osc.util.FastClickCheckUtil;
-import com.github.tvbox.osc.util.HawkConfig;
-import com.github.tvbox.osc.util.LOG;
-import com.github.tvbox.osc.util.XWalkUtils;
-import com.lzy.okgo.OkGo;
-import com.lzy.okgo.callback.AbsCallback;
-import com.lzy.okgo.model.Response;
-import com.orhanobut.hawk.Hawk;
-import com.owen.tvrecyclerview.widget.TvRecyclerView;
-import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.xwalk.core.XWalkResourceClient;
-import org.xwalk.core.XWalkSettings;
-import org.xwalk.core.XWalkUIClient;
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkWebResourceRequest;
-import org.xwalk.core.XWalkWebResourceResponse;
-
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import me.jessyan.autosize.AutoSize;
-
-/**
- * @author pj567
- * @date :2021/1/6
- * @description:
- */
-public class ParseDialog {
- private FrameLayout rootView;
- private Dialog mDialog;
- private Context mContext;
- private TextView mParseTip;
-
- private static final String IPHONE_UA = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
- private static final String PC_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36";
- private static final String ANDROID_UA = "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Mobile Safari/537.36";
-
- private TvRecyclerView mGridView;
- private ParseDialogAdapter parseAdapter;
- private List parseBeans = new ArrayList<>();
- private Map loadedUrls = new HashMap<>();
- private Handler mHandler = new Handler();
- private boolean loadFound = false;
-
- private Runnable mParseTimeOut = new Runnable() {
- @Override
- public void run() {
- OkGo.getInstance().cancelTag("json_jx");
- Toast.makeText(mContext, "解析超时,请尝试切换解析重试!", Toast.LENGTH_SHORT).show();
- }
- };
-
- private Runnable mGridFocus = new Runnable() {
- @Override
- public void run() {
- mGridView.requestFocus();
- }
- };
-
- public ParseDialog build(Context context, BackPress backPress) {
- mContext = context;
- rootView = (FrameLayout) LayoutInflater.from(context).inflate(R.layout.dialog_parse, null);
- mParseTip = findViewById(R.id.mParse_tip);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
- @Override
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_UP
- && keyCode == KeyEvent.KEYCODE_BACK
- && event.getRepeatCount() == 0) {
- OkGo.getInstance().cancelTag("fast_parse");
- backPress.onBack();
- return true;
- }
- return false;
- }
- });
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
- mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- if (mX5WebView != null) {
- mX5WebView.stopLoading();
- mX5WebView.clearCache(true);
- mX5WebView.removeAllViews();
- mX5WebView.onDestroy();
- }
- if (mSysWebView != null) {
- mSysWebView.stopLoading();
- mSysWebView.clearCache(true);
- mSysWebView.removeAllViews();
- mSysWebView.destroy();
- }
- mHandler.removeCallbacks(mParseTimeOut);
- }
- });
- try {
- mDialog.getWindow().setLayout(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
- } catch (Throwable th) {
- th.printStackTrace();
- }
- return this;
- }
-
- public interface BackPress {
- void onBack();
- }
-
- public interface ParseCallback {
- void success(String playUrl, Map headers);
-
- void fail();
- }
-
- public void parse(String sourceKey, JSONObject info, ParseCallback callback) {
- try {
- boolean parse = info.optString("parse", "1").equals("1");
- boolean jx = info.optString("jx", "0").equals("1");
- String playUrl = info.optString("playUrl", "");
- String flag = info.optString("flag");
- String url = info.getString("url");
- HashMap headers = null;
- if (info.has("header")) {
- try {
- JSONObject hds = new JSONObject(info.getString("header"));
- Iterator keys = hds.keys();
- while (keys.hasNext()) {
- String key = keys.next();
- if (headers == null) {
- headers = new HashMap<>();
- }
- headers.put(key, hds.getString(key));
- }
- } catch (Throwable th) {
-
- }
- }
- if (parse || jx) {
- boolean userJxList = (playUrl.isEmpty() && ApiConfig.get().getVipParseFlags().contains(flag)) || jx;
- initParse(flag, userJxList, playUrl, url, callback);
- } else {
- callback.success(playUrl + url, headers);
- }
- } catch (Throwable th) {
- callback.fail();
- }
- }
-
- private XWalkView mX5WebView;
- private XWalkWebClient mX5WebClient;
- private WebView mSysWebView;
- private SysWebClient mSysWebClient;
-
- private void initParse(String flag, boolean userJx, String playUrl, String url, ParseCallback callback) {
- mParseTip.setText("资源解析中,请稍后");
- if (mSysWebView == null && mX5WebView == null) {
- boolean useSystemWebView = Hawk.get(HawkConfig.PARSE_WEBVIEW, true);
- if (!useSystemWebView) {
- XWalkUtils.tryUseXWalk(mContext, new XWalkUtils.XWalkState() {
- @Override
- public void success() {
- initWebView(false);
- initParseBean(flag, userJx, playUrl, url, callback);
- }
-
- @Override
- public void fail() {
- Toast.makeText(mContext, "XWalkView不兼容,已替换为系统自带WebView", Toast.LENGTH_LONG).show();
- initWebView(true);
- initParseBean(flag, userJx, playUrl, url, callback);
- }
-
- @Override
- public void ignore() {
- Toast.makeText(mContext, "XWalkView运行组件未下载,已替换为系统自带WebView", Toast.LENGTH_LONG).show();
- initWebView(true);
- initParseBean(flag, userJx, playUrl, url, callback);
- }
- });
- } else {
- initWebView(true);
- initParseBean(flag, userJx, playUrl, url, callback);
- }
- } else {
- initParseBean(flag, userJx, playUrl, url, callback);
- }
- }
-
- private void initWebView(boolean useSystemWebView) {
- if (useSystemWebView) {
- mSysWebView = new MyWebView(mContext);
- configWebViewSys(mSysWebView);
- } else {
- mX5WebView = new MyXWalkView(mContext);
- configWebViewX5(mX5WebView);
- }
- }
-
- class MyWebView extends WebView {
- public MyWebView(@NonNull Context context) {
- super(context);
- }
-
- @Override
- public void setOverScrollMode(int mode) {
- super.setOverScrollMode(mode);
- if (mContext instanceof Activity)
- AutoSize.autoConvertDensityOfGlobal((Activity) mContext);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return false;
- }
- }
-
- class MyXWalkView extends XWalkView {
- public MyXWalkView(Context context) {
- super(context);
- }
-
- @Override
- public void setOverScrollMode(int mode) {
- super.setOverScrollMode(mode);
- if (mContext instanceof Activity)
- AutoSize.autoConvertDensityOfGlobal((Activity) mContext);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return false;
- }
- }
-
- JSONObject jsonParse(String input, String json) throws JSONException {
- JSONObject jsonPlayData = new JSONObject(json);
- String url = jsonPlayData.getString("url");
- String msg = jsonPlayData.optString("msg", "");
- if (url.startsWith("//")) {
- url = "https:" + url;
- }
- if (!url.startsWith("http")) {
- return null;
- }
- JSONObject headers = new JSONObject();
- String ua = jsonPlayData.optString("user-agent", "");
- if (ua.trim().length() > 0) {
- headers.put("User-Agent", " " + ua);
- }
- String referer = jsonPlayData.optString("referer", "");
- if (referer.trim().length() > 0) {
- headers.put("Referer", " " + referer);
- }
- JSONObject taskResult = new JSONObject();
- taskResult.put("header", headers);
- taskResult.put("url", url);
- return taskResult;
- }
-
- private void doJsonJx(String jx, String url, ParseCallback callback) {
- OkGo.get(jx + url)
- .tag("json_jx")
- .execute(new AbsCallback() {
- @Override
- public String convertResponse(okhttp3.Response response) throws Throwable {
- if (response.body() != null) {
- return response.body().string();
- } else {
- throw new IllegalStateException("网络请求错误");
- }
- }
-
- @Override
- public void onSuccess(Response response) {
- String json = response.body();
- try {
- JSONObject rs = jsonParse(url, json);
- HashMap headers = null;
- if (rs.has("header")) {
- try {
- JSONObject hds = rs.getJSONObject("header");
- Iterator keys = hds.keys();
- while (keys.hasNext()) {
- String key = keys.next();
- if (headers == null) {
- headers = new HashMap<>();
- }
- headers.put(key, hds.getString(key));
- }
- } catch (Throwable th) {
-
- }
- }
- callback.success(rs.getString("url"), headers);
- } catch (JSONException e) {
- e.printStackTrace();
- callback.fail();
- }
- }
-
- @Override
- public void onError(Response response) {
- super.onError(response);
- callback.fail();
- }
- });
- }
-
- private void loadUrl(ParseBean pb, String flag, String url, ParseCallback callback) {
- if (pb == null || pb.getType() == 0) {
- if (mSysWebClient != null) {
- mSysWebClient.setCallback(callback);
- }
- if (mX5WebClient != null) {
- mX5WebClient.setCallback(callback);
- }
- if (mX5WebView != null) {
- mX5WebView.stopLoading();
- mX5WebView.clearCache(true);
- mX5WebView.loadUrl(url);
- }
- if (mSysWebView != null) {
- mSysWebView.stopLoading();
- mSysWebView.clearCache(true);
- mSysWebView.loadUrl(url);
- }
- } else if (pb.getType() == 1) { // json 解析
- doJsonJx(pb.getUrl(), url, callback);
- } else if (pb.getType() == 2) { // json 扩展
- LinkedHashMap jxs = new LinkedHashMap<>();
- for (ParseBean p : ApiConfig.get().getParseBeanList()) {
- if (p.getType() == 1) {
- jxs.put(p.getName(), p.mixUrl());
- }
- }
- new Thread(new Runnable() {
- @Override
- public void run() {
- JSONObject rs = ApiConfig.get().jsonExt(pb.getUrl(), jxs, url);
- if (rs == null || !rs.has("url")) {
- callback.fail();
- } else {
- HashMap headers = null;
- if (rs.has("header")) {
- try {
- JSONObject hds = rs.getJSONObject("header");
- Iterator keys = hds.keys();
- while (keys.hasNext()) {
- String key = keys.next();
- if (headers == null) {
- headers = new HashMap<>();
- }
- headers.put(key, hds.getString(key));
- }
- } catch (Throwable th) {
-
- }
- }
- boolean parseWV = rs.optInt("parse", 0) == 1;
- if (parseWV) {
- String wvUrl = DefaultConfig.checkReplaceProxy(rs.optString("url", ""));
- loadUrl(null, flag, wvUrl, callback);
- } else {
- callback.success(rs.optString("url", ""), headers);
- }
- }
- }
- }).start();
- } else if (pb.getType() == 3) { // json 聚合
- LinkedHashMap> jxs = new LinkedHashMap<>();
- String extendName = "";
- for (ParseBean p : ApiConfig.get().getParseBeanList()) {
- HashMap data = new HashMap();
- data.put("url", p.getUrl());
- if (p.getUrl().equals(pb.getUrl())) {
- extendName = p.getName();
- }
- data.put("type", p.getType() + "");
- data.put("ext", p.getExt());
- jxs.put(p.getName(), data);
- }
- String finalExtendName = extendName;
- new Thread(new Runnable() {
- @Override
- public void run() {
- JSONObject rs = ApiConfig.get().jsonExtMix(flag, pb.getUrl(), finalExtendName, jxs, url);
- if (rs == null || !rs.has("url")) {
- callback.fail();
- } else {
- HashMap headers = null;
- if (rs.has("header")) {
- try {
- JSONObject hds = rs.getJSONObject("header");
- Iterator keys = hds.keys();
- while (keys.hasNext()) {
- String key = keys.next();
- if (headers == null) {
- headers = new HashMap<>();
- }
- headers.put(key, hds.getString(key));
- }
- } catch (Throwable th) {
-
- }
- }
- callback.success(rs.optString("url", ""), headers);
- }
- }
- }).start();
- }
- mHandler.removeCallbacks(mParseTimeOut);
- mHandler.postDelayed(mGridFocus, 200);
- mHandler.postDelayed(mParseTimeOut, 30000);
- }
-
- private void initParseBean(String flag, boolean userJx, String playUrl, final String url, ParseCallback callback) {
- if (mGridView == null) {
- mGridView = findViewById(R.id.mGridView);
- parseAdapter = new ParseDialogAdapter();
- mGridView.setAdapter(parseAdapter);
- mGridView.setLayoutManager(new V7GridLayoutManager(mContext, 6));
- parseAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
- @Override
- public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
- FastClickCheckUtil.check(view);
- ParseBean parseBean = parseAdapter.getData().get(position);
- // 当前默认解析需要刷新
- int currentDefault = parseBeans.indexOf(ApiConfig.get().getDefaultParse());
- parseAdapter.notifyItemChanged(currentDefault);
- ApiConfig.get().setDefaultParse(parseBean);
- parseAdapter.notifyItemChanged(position);
- loadFound = false;
- loadUrl(parseBean, flag, url, callback);
- }
- });
- mGridView.setOnInBorderKeyEventListener(new TvRecyclerView.OnInBorderKeyEventListener() {
- @Override
- public boolean onInBorderKeyEvent(int direction, View focused) {
- return true;
- }
- });
- }
- int focusParseIdx = 0;
- String parseUrl = "";
- ParseBean parseBean = null;
- if (userJx) {
- parseBeans.addAll(ApiConfig.get().getParseBeanList());
- parseBean = ApiConfig.get().getDefaultParse();
- parseUrl = parseBean.getUrl();
- focusParseIdx = parseBeans.indexOf(parseBean);
- } else {
- parseUrl = playUrl;
- focusParseIdx = 0;
- }
- loadFound = false;
- parseAdapter.setNewData(parseBeans);
- mGridView.setSelection(focusParseIdx);
- if (parseBeans.size() > 0) {
- ParseBean finalParseBean = parseBean;
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- loadUrl(finalParseBean, flag, url, callback);
- }
- }, 3000);
- } else {
- loadUrl(null, flag, parseUrl + url, callback);
- }
- }
-
- private void configWebViewSys(WebView webView) {
- if (webView == null) {
- return;
- }
- ViewGroup.LayoutParams layoutParams = Hawk.get(HawkConfig.DEBUG_OPEN, false)
- ? new ViewGroup.LayoutParams(800, 400) :
- new ViewGroup.LayoutParams(1, 1);
- webView.setFocusable(false);
- webView.setFocusableInTouchMode(false);
- webView.clearFocus();
- webView.setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- rootView.addView(webView, layoutParams);
- /* 添加webView配置 */
- final WebSettings settings = webView.getSettings();
- settings.setNeedInitialFocus(false);
- settings.setAllowContentAccess(true);
- settings.setAllowFileAccess(true);
- settings.setAllowUniversalAccessFromFileURLs(true);
- settings.setAllowFileAccessFromFileURLs(true);
- settings.setDatabaseEnabled(true);
- settings.setDomStorageEnabled(true);
- settings.setJavaScriptEnabled(true);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- settings.setMediaPlaybackRequiresUserGesture(false);
- }
- if (Hawk.get(HawkConfig.DEBUG_OPEN, false)) {
- settings.setBlockNetworkImage(false);
- } else {
- settings.setBlockNetworkImage(true);
- }
- settings.setUseWideViewPort(true);
- settings.setDomStorageEnabled(true);
- settings.setJavaScriptCanOpenWindowsAutomatically(true);
- settings.setSupportMultipleWindows(false);
- settings.setLoadWithOverviewMode(true);
- settings.setBuiltInZoomControls(true);
- settings.setSupportZoom(false);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
- }
- settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
- /* 添加webView配置 */
- //设置编码
- settings.setDefaultTextEncodingName("utf-8");
- settings.setUserAgentString(webView.getSettings().getUserAgentString());
- settings.setUserAgentString(ANDROID_UA);
-
- webView.setWebChromeClient(new WebChromeClient() {
- @Override
- public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
- return false;
- }
- });
- mSysWebClient = new SysWebClient();
- webView.setWebViewClient(mSysWebClient);
- webView.setBackgroundColor(Color.BLACK);
- }
-
- private class SysWebClient extends WebViewClient {
- private ParseCallback callback;
-
- public void setCallback(ParseCallback callback) {
- this.callback = callback;
- }
-
- @Override
- public void onReceivedSslError(WebView webView, SslErrorHandler sslErrorHandler, SslError sslError) {
- sslErrorHandler.proceed();
- }
-
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
- return false;
- }
-
- @Nullable
- @Override
- public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
- // suppress favicon requests as we don't display them anywhere
- if (url.endsWith("/favicon.ico")) {
- return new WebResourceResponse("image/png", null, null);
- }
- LOG.i("shouldInterceptRequest url:" + url);
- boolean ad;
- if (!loadedUrls.containsKey(url)) {
- ad = AdBlocker.isAd(url);
- loadedUrls.put(url, ad);
- } else {
- ad = loadedUrls.get(url);
- }
-
- if (!ad && !loadFound) {
- if (DefaultConfig.isVideoFormat(url)) {
- loadFound = true;
- mHandler.removeCallbacks(mParseTimeOut);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- view.stopLoading();
- callback.success(url, null);
- }
- });
- }
- }
-
- return ad || loadFound ?
- AdBlocker.createEmptyResource() :
- super.shouldInterceptRequest(view, url);
- }
-
- @Override
- public void onLoadResource(WebView webView, String url) {
- super.onLoadResource(webView, url);
- }
- }
-
- private void configWebViewX5(XWalkView webView) {
- if (webView == null) {
- return;
- }
- ViewGroup.LayoutParams layoutParams = Hawk.get(HawkConfig.DEBUG_OPEN, false)
- ? new ViewGroup.LayoutParams(800, 400) :
- new ViewGroup.LayoutParams(1, 1);
- webView.setFocusable(false);
- webView.setFocusableInTouchMode(false);
- webView.clearFocus();
- webView.setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- rootView.addView(webView, layoutParams);
- /* 添加webView配置 */
- final XWalkSettings settings = webView.getSettings();
- settings.setAllowContentAccess(true);
- settings.setAllowFileAccess(true);
- settings.setAllowUniversalAccessFromFileURLs(true);
- settings.setAllowFileAccessFromFileURLs(true);
- settings.setDatabaseEnabled(true);
- settings.setDomStorageEnabled(true);
- settings.setJavaScriptEnabled(true);
-
- if (Hawk.get(HawkConfig.DEBUG_OPEN, false)) {
- settings.setBlockNetworkImage(false);
- } else {
- settings.setBlockNetworkImage(true);
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- settings.setMediaPlaybackRequiresUserGesture(false);
- }
- settings.setUseWideViewPort(true);
- settings.setDomStorageEnabled(true);
- settings.setJavaScriptCanOpenWindowsAutomatically(true);
- settings.setSupportMultipleWindows(false);
- settings.setLoadWithOverviewMode(true);
- settings.setBuiltInZoomControls(true);
- settings.setSupportZoom(false);
- settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
- settings.setUserAgentString(ANDROID_UA);
-
- webView.setBackgroundColor(Color.BLACK);
- webView.setUIClient(new XWalkUIClient(webView) {
- @Override
- public boolean onConsoleMessage(XWalkView view, String message, int lineNumber, String sourceId, ConsoleMessageType messageType) {
- return false;
- }
- });
- mX5WebClient = new XWalkWebClient(webView);
- webView.setResourceClient(mX5WebClient);
- }
-
- private class XWalkWebClient extends XWalkResourceClient {
- private ParseCallback callback;
-
- public void setCallback(ParseCallback callback) {
- this.callback = callback;
- }
-
- public XWalkWebClient(XWalkView view) {
- super(view);
- }
-
- @Override
- public void onDocumentLoadedInFrame(XWalkView view, long frameId) {
- super.onDocumentLoadedInFrame(view, frameId);
- }
-
- @Override
- public void onLoadStarted(XWalkView view, String url) {
- super.onLoadStarted(view, url);
- }
-
- @Override
- public void onLoadFinished(XWalkView view, String url) {
- super.onLoadFinished(view, url);
- }
-
- @Override
- public void onProgressChanged(XWalkView view, int progressInPercent) {
- super.onProgressChanged(view, progressInPercent);
- }
-
- @Override
- public XWalkWebResourceResponse shouldInterceptLoadRequest(XWalkView view, XWalkWebResourceRequest request) {
- String url = request.getUrl().toString();
- // suppress favicon requests as we don't display them anywhere
- if (url.endsWith("/favicon.ico")) {
- return createXWalkWebResourceResponse("image/png", null, null);
- }
- LOG.i("shouldInterceptLoadRequest url:" + url);
- boolean ad;
- if (!loadedUrls.containsKey(url)) {
- ad = AdBlocker.isAd(url);
- loadedUrls.put(url, ad);
- } else {
- ad = loadedUrls.get(url);
- }
- if (!ad && !loadFound) {
- if (DefaultConfig.isVideoFormat(url)) {
- loadFound = true;
- mHandler.removeCallbacks(mParseTimeOut);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- view.stopLoading();
- callback.success(url, null);
- }
- });
- }
- }
- return ad || loadFound ?
- createXWalkWebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes())) :
- super.shouldInterceptLoadRequest(view, request);
- }
-
- @Override
- public boolean shouldOverrideUrlLoading(XWalkView view, String s) {
- return false;
- }
-
- @Override
- public void onReceivedSslError(XWalkView view, ValueCallback callback, SslError error) {
- callback.onReceiveValue(true);
- }
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/QuickSearchDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/QuickSearchDialog.java
index f8868f27fa..4704086800 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/QuickSearchDialog.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/QuickSearchDialog.java
@@ -1,18 +1,16 @@
package com.github.tvbox.osc.ui.dialog;
-import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.view.LayoutInflater;
import android.view.View;
-import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.bean.Movie;
import com.github.tvbox.osc.event.RefreshEvent;
-import com.github.tvbox.osc.ui.adapter.SearchAdapter;
+import com.github.tvbox.osc.ui.adapter.QuickSearchAdapter;
import com.github.tvbox.osc.ui.adapter.SearchWordAdapter;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
@@ -20,34 +18,23 @@
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author pj567
- * @date :2020/12/23
- * @description:
- */
-public class QuickSearchDialog {
- private Context mContext;
- private View rootView;
- private Dialog mDialog;
+public class QuickSearchDialog extends BaseDialog {
private SearchWordAdapter searchWordAdapter;
- private SearchAdapter searchAdapter;
+ private QuickSearchAdapter searchAdapter;
private TvRecyclerView mGridView;
private TvRecyclerView mGridViewWord;
-
- public QuickSearchDialog build(Context context) {
- mContext = context;
- rootView = LayoutInflater.from(context).inflate(R.layout.dialog_quick_search, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setCancelable(true);
- mDialog.setContentView(rootView);
+ public QuickSearchDialog(@NonNull @NotNull Context context) {
+ super(context, R.style.CustomDialogStyleDim);
+ setCanceledOnTouchOutside(false);
+ setCancelable(true);
+ setContentView(R.layout.dialog_quick_search);
init(context);
- return this;
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -67,16 +54,19 @@ public void refresh(RefreshEvent event) {
private void init(Context context) {
EventBus.getDefault().register(this);
- mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
EventBus.getDefault().unregister(this);
}
});
mGridView = findViewById(R.id.mGridView);
- searchAdapter = new SearchAdapter();
+ searchAdapter = new QuickSearchAdapter();
mGridView.setHasFixedSize(true);
- mGridView.setLayoutManager(new V7LinearLayoutManager(context, 1, false));
+ // lite
+ mGridView.setLayoutManager(new V7LinearLayoutManager(getContext(), 1, false));
+ // with preview
+ // mGridView.setLayoutManager(new V7GridLayoutManager(getContext(), 3));
mGridView.setAdapter(searchAdapter);
searchAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
@@ -101,25 +91,4 @@ public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
});
searchWordAdapter.setNewData(new ArrayList<>());
}
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/RemoteDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/RemoteDialog.java
index e2366a03c4..af9a870c4e 100644
--- a/app/src/main/java/com/github/tvbox/osc/ui/dialog/RemoteDialog.java
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/RemoteDialog.java
@@ -1,56 +1,27 @@
package com.github.tvbox.osc.ui.dialog;
-import android.app.Dialog;
import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
import com.github.tvbox.osc.R;
import com.github.tvbox.osc.server.ControlManager;
-import com.github.tvbox.osc.server.RemoteServer;
import com.github.tvbox.osc.ui.tv.QRCodeGen;
-/**
- * 描述
- *
- * @author pj567
- * @since 2020/12/27
- */
-public class RemoteDialog {
- private View rootView;
- private Dialog mDialog;
- private Context mContext;
- private ImageView ivQRCode;
- private TextView tvAddress;
-
- public RemoteDialog() {
-
- }
+import org.jetbrains.annotations.NotNull;
- public RemoteDialog build(Context context) {
- rootView = LayoutInflater.from(context).inflate(R.layout.remote_dialog, null);
- mDialog = new Dialog(context, R.style.CustomDialogStyle);
- mDialog.setCanceledOnTouchOutside(false);
- mDialog.setContentView(rootView);
- mContext = context;
- init();
- return this;
- }
+import me.jessyan.autosize.utils.AutoSizeUtils;
- @SuppressWarnings("unchecked")
- private T findViewById(@IdRes int viewId) {
- View view = null;
- if (rootView != null) {
- view = rootView.findViewById(viewId);
- }
- return (T) view;
- }
+public class RemoteDialog extends BaseDialog {
+ private ImageView ivQRCode;
+ private TextView tvAddress;
- private void init() {
+ public RemoteDialog(@NonNull @NotNull Context context) {
+ super(context);
+ setContentView(R.layout.dialog_remote);
+ setCanceledOnTouchOutside(false);
ivQRCode = findViewById(R.id.ivQRCode);
tvAddress = findViewById(R.id.tvAddress);
refreshQRCode();
@@ -58,23 +29,7 @@ private void init() {
private void refreshQRCode() {
String address = ControlManager.get().getAddress(false);
- tvAddress.setText(String.format("手机/电脑扫描左边二维码或者直接浏览器访问地址\n%s", address));
- ivQRCode.setImageBitmap(QRCodeGen.generateBitmap(address, 200, 200));
- }
-
- public void dismiss() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- public void show() {
- if (mDialog != null && !mDialog.isShowing()) {
- mDialog.show();
- }
- }
-
- public boolean isShowing() {
- return mDialog != null && mDialog.isShowing();
+ tvAddress.setText(String.format("手机/电脑扫描上方二维码或者直接浏览器访问地址\n%s", address));
+ ivQRCode.setImageBitmap(QRCodeGen.generateBitmap(address, AutoSizeUtils.mm2px(getContext(), 240), AutoSizeUtils.mm2px(getContext(), 240)));
}
}
diff --git a/app/src/main/java/com/github/tvbox/osc/ui/dialog/SelectDialog.java b/app/src/main/java/com/github/tvbox/osc/ui/dialog/SelectDialog.java
new file mode 100644
index 0000000000..219051aceb
--- /dev/null
+++ b/app/src/main/java/com/github/tvbox/osc/ui/dialog/SelectDialog.java
@@ -0,0 +1,51 @@
+package com.github.tvbox.osc.ui.dialog;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.DiffUtil;
+
+import com.github.tvbox.osc.R;
+import com.github.tvbox.osc.ui.adapter.SelectDialogAdapter;
+import com.owen.tvrecyclerview.widget.TvRecyclerView;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class SelectDialog