Add remark, reload config, home content

pull/1/head
FongMi 4 years ago
parent 03aed75826
commit ef065ac077
  1. 3
      app/build.gradle
  2. 64
      app/src/main/java/com/fongmi/bear/ApiConfig.java
  3. 8
      app/src/main/java/com/fongmi/bear/bean/Site.java
  4. 15
      app/src/main/java/com/fongmi/bear/bean/Vod.java
  5. 34
      app/src/main/java/com/fongmi/bear/model/SiteViewModel.java
  6. 31
      app/src/main/java/com/fongmi/bear/ui/activity/HomeActivity.java
  7. 20
      app/src/main/java/com/fongmi/bear/ui/activity/SettingActivity.java
  8. 2
      app/src/main/java/com/fongmi/bear/ui/activity/SplashActivity.java
  9. 2
      app/src/main/java/com/fongmi/bear/ui/adapter/VodAdapter.java
  10. 2
      app/src/main/java/com/fongmi/bear/utils/Utils.java
  11. 38
      app/src/main/java/com/github/catvod/crawler/JarLoader.java
  12. 1
      app/src/main/res/drawable/selector_item.xml
  13. 1
      app/src/main/res/drawable/selector_vod.xml
  14. 2
      app/src/main/res/drawable/shape_item_normal.xml
  15. 2
      app/src/main/res/drawable/shape_item_selected.xml
  16. 4
      app/src/main/res/drawable/shape_vod_name.xml
  17. 2
      app/src/main/res/drawable/shape_vod_normal.xml
  18. 17
      app/src/main/res/drawable/shape_vod_remark.xml
  19. 2
      app/src/main/res/drawable/shape_vod_selected.xml
  20. 9
      app/src/main/res/layout/activity_home.xml
  21. 11
      app/src/main/res/layout/adapter_vod.xml

@ -35,12 +35,13 @@ android {
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.room:room-runtime:2.4.2'
implementation 'com.github.bumptech.glide:glide:4.13.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'com.google.android.exoplayer:exoplayer:2.18.0'
implementation 'com.google.android.exoplayer:extension-rtmp:2.17.1'
implementation 'com.google.android.exoplayer:extension-rtmp:2.18.0'
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'org.jsoup:jsoup:1.14.3'
implementation 'com.orhanobut:logger:2.2.0'

@ -1,5 +1,8 @@
package com.fongmi.bear;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import com.fongmi.bear.bean.Live;
@ -15,9 +18,14 @@ import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Request;
@ -25,13 +33,14 @@ import okhttp3.Response;
public class ApiConfig {
private List<Site> sites;
private List<Parse> parses;
private List<Live> channels;
private Parse defaultParse;
private JarLoader jarLoader;
private final JarLoader jarLoader;
private final List<Parse> parses;
private final List<Live> lives;
private final List<Site> sites;
private final Handler handler;
private String spider;
private Site home;
private Parse parse;
private Site site;
private static class Loader {
static volatile ApiConfig INSTANCE = new ApiConfig();
@ -42,10 +51,19 @@ public class ApiConfig {
}
public ApiConfig() {
this.site = new Site();
this.sites = new ArrayList<>();
this.parses = new ArrayList<>();
this.channels = new ArrayList<>();
this.lives = new ArrayList<>();
this.jarLoader = new JarLoader();
this.handler = new Handler(Looper.getMainLooper());
}
private void clear() {
this.sites.clear();
this.parses.clear();
this.lives.clear();
this.site = new Site();
}
public void loadConfig(Callback callback) {
@ -53,17 +71,18 @@ public class ApiConfig {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
try {
clear();
parseJson(response.body().string());
loadJar();
callback.success();
handler.post(callback::success);
} catch (Exception e) {
callback.error("解析配置失敗");
handler.post(() -> callback.error("解析配置失敗"));
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
callback.error("無法取得配置");
handler.post(() -> callback.error("取得配置失敗"));
}
});
}
@ -84,7 +103,9 @@ public class ApiConfig {
site.setExt(Json.safeString(obj, "ext", ""));
sites.add(site);
}
if (sites.size() > 0) home = sites.get(0);
if (sites.size() > 0) {
site = sites.get(0);
}
}
private void loadJar() throws IOException {
@ -97,7 +118,24 @@ public class ApiConfig {
return jarLoader.getSpider(site.getApi(), site.getExt());
}
public Site getHome() {
return home;
public Object[] proxyLocal(Map<?, ?> param) {
return jarLoader.proxyInvoke(param);
}
public JSONObject jsonExt(String key, LinkedHashMap<String, String> jxs, String url) {
return jarLoader.jsonExt(key, jxs, url);
}
public JSONObject jsonExtMix(String flag, String key, String name, LinkedHashMap<String, HashMap<String, String>> jxs, String url) {
return jarLoader.jsonExtMix(flag, key, name, jxs, url);
}
public Site getSite(String key) {
for (Site item : sites) if (item.getKey().equals(key)) return item;
return new Site();
}
public Site getSite() {
return site;
}
}

@ -15,15 +15,15 @@ public class Site {
@SerializedName("name")
private String name;
@SerializedName("type")
private Integer type;
private int type;
@SerializedName("api")
private String api;
@SerializedName("searchable")
private Integer searchable;
private int searchable;
@SerializedName("quickSearch")
private Integer quickSearch;
private int quickSearch;
@SerializedName("filterable")
private Integer filterable;
private int filterable;
@SerializedName("ext")
private String ext;

@ -1,5 +1,8 @@
package com.fongmi.bear.bean;
import android.text.TextUtils;
import android.view.View;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -19,18 +22,22 @@ public class Vod {
}
public String getVodId() {
return vodId;
return TextUtils.isEmpty(vodId) ? "" : vodId;
}
public String getVodName() {
return vodName;
return TextUtils.isEmpty(vodName) ? "" : vodName;
}
public String getVodPic() {
return vodPic;
return TextUtils.isEmpty(vodPic) ? "" : vodPic;
}
public String getVodRemarks() {
return vodRemarks;
return TextUtils.isEmpty(vodRemarks) ? "" : vodRemarks;
}
public int getRemarkVisible() {
return getVodRemarks().isEmpty() ? View.GONE : View.VISIBLE;
}
}

@ -0,0 +1,34 @@
package com.fongmi.bear.model;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import com.fongmi.bear.ApiConfig;
import com.fongmi.bear.bean.Result;
import com.fongmi.bear.bean.Site;
import com.github.catvod.crawler.Spider;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SiteViewModel extends ViewModel {
public static final ExecutorService service = Executors.newFixedThreadPool(5);
public MutableLiveData<Result> result;
public SiteViewModel() {
this.result = new MutableLiveData<>();
}
public void homeContent(String key) {
Site site = ApiConfig.get().getSite(key);
int type = site.getType();
if (type == 3) {
service.execute(() -> {
Spider spider = ApiConfig.get().getCSP(site);
result.postValue(Result.objectFrom(spider.homeContent(false)));
});
}
}
}

@ -3,20 +3,25 @@ package com.fongmi.bear.ui.activity;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.viewbinding.ViewBinding;
import com.fongmi.bear.ApiConfig;
import com.fongmi.bear.R;
import com.fongmi.bear.bean.Func;
import com.fongmi.bear.databinding.ActivityHomeBinding;
import com.fongmi.bear.model.SiteViewModel;
import com.fongmi.bear.ui.adapter.FuncAdapter;
import com.fongmi.bear.ui.adapter.VodAdapter;
import com.fongmi.bear.ui.custom.SpaceItemDecoration;
import com.fongmi.bear.utils.Prefers;
public class HomeActivity extends BaseActivity {
private ActivityHomeBinding binding;
private SiteViewModel siteViewModel;
private FuncAdapter funcAdapter;
private VodAdapter vodAdapter;
@ -32,9 +37,9 @@ public class HomeActivity extends BaseActivity {
@Override
protected void initView() {
if (Prefers.getUrl().isEmpty()) SettingActivity.start(this);
//else if (ApiConfig.get().getConfig() == null) Notify.show(R.string.error_config);
setRecyclerView();
setViewModel();
homeContent();
}
@Override
@ -43,15 +48,22 @@ public class HomeActivity extends BaseActivity {
}
private void setRecyclerView() {
binding.func.setHasFixedSize(true);
binding.func.setLayoutManager(new GridLayoutManager(this, 5));
binding.func.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
binding.func.setAdapter(funcAdapter = new FuncAdapter());
binding.update.setHasFixedSize(true);
binding.update.setLayoutManager(new GridLayoutManager(this, 5));
binding.update.addItemDecoration(new SpaceItemDecoration(5, 12, false, 0));
binding.update.setAdapter(vodAdapter = new VodAdapter());
}
private void setViewModel() {
siteViewModel = new ViewModelProvider(this).get(SiteViewModel.class);
siteViewModel.result.observe(this, result -> vodAdapter.addAll(result.getList()));
}
private void homeContent() {
siteViewModel.homeContent(ApiConfig.get().getSite().getKey());
}
private void onFuncClick(Func item) {
switch (item.getResId()) {
case R.string.home_setting:
@ -59,4 +71,11 @@ public class HomeActivity extends BaseActivity {
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) return;
homeContent();
}
}

@ -7,8 +7,10 @@ import android.view.View;
import androidx.viewbinding.ViewBinding;
import com.fongmi.bear.ApiConfig;
import com.fongmi.bear.databinding.ActivitySettingBinding;
import com.fongmi.bear.databinding.DialogConfigBinding;
import com.fongmi.bear.net.Callback;
import com.fongmi.bear.utils.Notify;
import com.fongmi.bear.utils.Prefers;
@ -17,7 +19,7 @@ public class SettingActivity extends BaseActivity {
private ActivitySettingBinding binding;
public static void start(Activity activity) {
activity.startActivity(new Intent(activity, SettingActivity.class));
activity.startActivityForResult(new Intent(activity, SettingActivity.class), 1000);
}
@Override
@ -42,6 +44,22 @@ public class SettingActivity extends BaseActivity {
Notify.show(this, bindingDialog.getRoot(), (dialogInterface, i) -> {
Prefers.put("url", bindingDialog.url.getText().toString().trim());
binding.url.setText(Prefers.getUrl());
reloadConfig();
});
}
//TODO SHOW PROGRESS
private void reloadConfig() {
ApiConfig.get().loadConfig(new Callback() {
@Override
public void success() {
setResult(RESULT_OK);
}
@Override
public void error(String msg) {
Notify.show(msg);
}
});
}
}

@ -10,6 +10,7 @@ import androidx.viewbinding.ViewBinding;
import com.fongmi.bear.ApiConfig;
import com.fongmi.bear.databinding.ActivitySplashBinding;
import com.fongmi.bear.net.Callback;
import com.fongmi.bear.utils.Notify;
@SuppressLint("CustomSplashScreen")
public class SplashActivity extends BaseActivity {
@ -48,6 +49,7 @@ public class SplashActivity extends BaseActivity {
@Override
public void error(String msg) {
HomeActivity.start(getActivity());
Notify.show(msg);
}
});
}

@ -68,6 +68,8 @@ public class VodAdapter extends RecyclerView.Adapter<VodAdapter.VodHolder> {
public void onBindViewHolder(@NonNull VodAdapter.VodHolder holder, int position) {
Vod item = items.get(position);
holder.binding.name.setText(item.getVodName());
holder.binding.remark.setText(item.getVodRemarks());
holder.binding.remark.setVisibility(item.getRemarkVisible());
Utils.loadImage(item.getVodPic(), holder.binding.image);
}
}

@ -63,7 +63,7 @@ public class Utils {
}
public static void loadImage(String url, ImageView view) {
Glide.with(App.get()).load(url).transform(new CenterCrop(), new RoundedCorners(ResUtil.dp2px(10))).into(view);
Glide.with(App.get()).load(url).transform(new CenterCrop(), new RoundedCorners(ResUtil.dp2px(8))).into(view);
}
public static void hideSystemUI(Activity activity) {

@ -6,8 +6,12 @@ import com.fongmi.bear.App;
import com.fongmi.bear.utils.FileUtil;
import com.orhanobut.logger.Logger;
import org.json.JSONObject;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -77,16 +81,44 @@ public class JarLoader {
spiders.put(clsKey, spider);
return spider;
} catch (Exception e) {
e.printStackTrace();
return new SpiderNull();
}
}
public JSONObject jsonExt(String key, LinkedHashMap<String, String> jxs, String url) {
try {
String clsKey = "Json" + key;
String hotClass = "com.github.catvod.parser." + clsKey;
Class<?> jsonParserCls = classLoader.loadClass(hotClass);
Method mth = jsonParserCls.getMethod("parse", LinkedHashMap.class, String.class);
return (JSONObject) mth.invoke(null, jxs, url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public JSONObject jsonExtMix(String flag, String key, String name, LinkedHashMap<String, HashMap<String, String>> jxs, String url) {
try {
String clsKey = "Mix" + key;
String hotClass = "com.github.catvod.parser." + clsKey;
Class<?> jsonParserCls = classLoader.loadClass(hotClass);
Method mth = jsonParserCls.getMethod("parse", LinkedHashMap.class, String.class, String.class, String.class);
return (JSONObject) mth.invoke(null, jxs, name, flag, url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Object[] proxyInvoke(Map params) {
try {
if (proxyFun != null) return (Object[]) proxyFun.invoke(null, params);
} catch (Exception ignored) {
else return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
}

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_item_selected" android:state_selected="true" />
<item android:drawable="@drawable/shape_item_selected" android:state_focused="true" />
<item android:drawable="@drawable/shape_item_normal" />
</selector>

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_vod_selected" android:state_selected="true" />
<item android:drawable="@drawable/shape_vod_selected" android:state_focused="true" />
<item android:drawable="@drawable/shape_vod_normal" />
</selector>

@ -4,7 +4,7 @@
<solid android:color="@color/black_20" />
<corners android:radius="5dp" />
<corners android:radius="4dp" />
<padding
android:bottom="8dp"

@ -4,7 +4,7 @@
<solid android:color="@color/black_25" />
<corners android:radius="5dp" />
<corners android:radius="4dp" />
<padding
android:bottom="8dp"

@ -5,7 +5,7 @@
<solid android:color="@color/black_60" />
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp" />
</shape>

@ -2,6 +2,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
<corners android:radius="8dp" />
</shape>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#CC177535" />
<corners
android:bottomRightRadius="4dp"
android:topRightRadius="4dp" />
<padding
android:bottom="4dp"
android:left="4dp"
android:right="4dp"
android:top="4dp" />
</shape>

@ -2,7 +2,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
<corners android:radius="8dp" />
<stroke
android:width="1dp"

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -21,13 +20,7 @@
android:id="@+id/func"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
tools:itemCount="5"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:listitem="@layout/adapter_func"
tools:orientation="vertical"
tools:scrollbars="vertical"
tools:spanCount="5" />
android:layout_marginTop="16dp" />
<TextView
android:layout_width="wrap_content"

@ -14,6 +14,17 @@
android:scaleType="center"
tools:src="@drawable/ic_vod" />
<TextView
android:id="@+id/remark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/name"
android:background="@drawable/shape_vod_remark"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="14sp"
tools:text="1080p" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"

Loading…
Cancel
Save