Add vod activity

pull/1/head
FongMi 4 years ago
parent a4fefc2b85
commit 59f792c752
  1. 1
      app/build.gradle
  2. 5
      app/src/main/AndroidManifest.xml
  3. 13
      app/src/main/java/com/fongmi/bear/ApiConfig.java
  4. 14
      app/src/main/java/com/fongmi/bear/bean/Result.java
  5. 19
      app/src/main/java/com/fongmi/bear/bean/Type.java
  6. 60
      app/src/main/java/com/fongmi/bear/model/SiteViewModel.java
  7. 18
      app/src/main/java/com/fongmi/bear/ui/activity/HomeActivity.java
  8. 1
      app/src/main/java/com/fongmi/bear/ui/activity/SplashActivity.java
  9. 81
      app/src/main/java/com/fongmi/bear/ui/activity/VodActivity.java
  10. 158
      app/src/main/java/com/fongmi/bear/ui/custom/ProgressLayout.java
  11. 72
      app/src/main/java/com/fongmi/bear/ui/fragment/VodFragment.java
  12. 4
      app/src/main/java/com/fongmi/bear/utils/Notify.java
  13. 3
      app/src/main/java/com/github/catvod/crawler/JarLoader.java
  14. 4
      app/src/main/java/com/github/catvod/crawler/SpiderDebug.java
  15. 8
      app/src/main/res/layout/activity_home.xml
  16. 21
      app/src/main/res/layout/activity_splash.xml
  17. 26
      app/src/main/res/layout/activity_vod.xml
  18. 14
      app/src/main/res/layout/fragment_vod.xml
  19. 0
      app/src/main/res/layout/view_progress.xml

@ -38,7 +38,6 @@ dependencies {
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.androidprogresslayout:library:2.0.2@aar'
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'

@ -59,6 +59,11 @@
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.VodActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:screenOrientation="sensorLandscape" />
<activity
android:name=".ui.activity.SettingActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"

@ -38,7 +38,6 @@ public class ApiConfig {
private final List<Live> lives;
private final List<Site> sites;
private final Handler handler;
private String spider;
private Parse parse;
private Site home;
@ -75,8 +74,10 @@ public class ApiConfig {
public void onResponse(@NonNull Call call, @NonNull Response response) {
try {
clear();
parseJson(response.body().string());
loadJar();
JsonObject object = new Gson().fromJson(response.body().string(), JsonObject.class);
String spider = Json.safeString(object, "spider", "");
parseJson(object);
loadJar(spider);
handler.post(callback::success);
} catch (Exception e) {
handler.post(() -> callback.error("配置解析失敗"));
@ -90,9 +91,7 @@ public class ApiConfig {
});
}
private void parseJson(String json) {
JsonObject object = new Gson().fromJson(json, JsonObject.class);
spider = Json.safeString(object, "spider", "");
private void parseJson(JsonObject object) {
for (JsonElement opt : object.get("sites").getAsJsonArray()) {
JsonObject obj = (JsonObject) opt;
Site site = new Site();
@ -112,7 +111,7 @@ public class ApiConfig {
}
}
private void loadJar() throws IOException {
private void loadJar(String spider) throws IOException {
Request request = new Request.Builder().url(spider).build();
Response response = OKHttp.get().client().newCall(request).execute();
jarLoader.load(response.body().bytes());

@ -1,5 +1,7 @@
package com.fongmi.bear.bean;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
@ -8,6 +10,8 @@ import java.util.List;
public class Result {
@SerializedName("class")
private List<Type> types;
@SerializedName("list")
private List<Vod> list;
@ -16,7 +20,17 @@ public class Result {
return result == null ? new Result() : result;
}
public List<Type> getTypes() {
return types;
}
public List<Vod> getList() {
return list == null ? Collections.emptyList() : list;
}
@NonNull
@Override
public String toString() {
return new Gson().toJson(this);
}
}

@ -0,0 +1,19 @@
package com.fongmi.bear.bean;
import com.google.gson.annotations.SerializedName;
public class Type {
@SerializedName("type_id")
private String typeId;
@SerializedName("type_name")
private String typeName;
public String getTypeId() {
return typeId;
}
public String getTypeName() {
return typeName;
}
}

@ -11,38 +11,64 @@ import com.fongmi.bear.bean.Site;
import com.github.catvod.crawler.Spider;
import com.github.catvod.crawler.SpiderDebug;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class SiteViewModel extends ViewModel {
public ExecutorService mService;
public MutableLiveData<Result> mResult;
public ExecutorService mService;
public SiteViewModel() {
this.mService = Executors.newFixedThreadPool(5);
this.mService = Executors.newFixedThreadPool(2);
this.mResult = new MutableLiveData<>();
}
public void homeContent(String key) {
if (TextUtils.isEmpty(key)) {
public MutableLiveData<Result> getResult() {
return mResult;
}
public void homeContent() {
Site home = ApiConfig.get().getHome();
if (TextUtils.isEmpty(home.getKey())) {
mResult.postValue(new Result());
return;
}
Site site = ApiConfig.get().getSite(key);
if (site.getType() == 3) {
mService.submit(() -> {
Spider spider = ApiConfig.get().getCSP(site);
} else {
postResult(() -> {
Spider spider = ApiConfig.get().getCSP(home);
String homeContent = spider.homeContent(false);
SpiderDebug.log(homeContent);
SpiderDebug.json(homeContent);
Result result = Result.objectFrom(homeContent);
if (result.getList().isEmpty()) {
String homeVideoContent = spider.homeVideoContent();
SpiderDebug.log(homeVideoContent);
result = Result.objectFrom(homeVideoContent);
}
mResult.postValue(result);
if (result.getList().size() > 0) return result;
String homeVideoContent = spider.homeVideoContent();
SpiderDebug.json(homeVideoContent);
return Result.objectFrom(homeVideoContent);
});
}
}
public void categoryContent(String tid, String page, boolean filter, HashMap<String, String> extend) {
Site home = ApiConfig.get().getHome();
postResult(() -> {
Spider spider = ApiConfig.get().getCSP(home);
String categoryContent = spider.categoryContent(tid, page, filter, extend);
SpiderDebug.json(categoryContent);
return Result.objectFrom(categoryContent);
});
}
private void postResult(Callable<Result> callable) {
mService.execute(() -> {
try {
Future<Result> future = mService.submit(callable);
Result result = future.get(10, TimeUnit.SECONDS);
mResult.postValue(result);
} catch (Exception e) {
mResult.postValue(new Result());
}
});
}
}

@ -9,9 +9,9 @@ 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.bean.Result;
import com.fongmi.bear.databinding.ActivityHomeBinding;
import com.fongmi.bear.model.SiteViewModel;
import com.fongmi.bear.ui.adapter.FuncAdapter;
@ -39,7 +39,7 @@ public class HomeActivity extends BaseActivity {
protected void initView() {
setRecyclerView();
setViewModel();
homeContent();
getContent();
}
@Override
@ -61,17 +61,21 @@ public class HomeActivity extends BaseActivity {
mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class);
mSiteViewModel.mResult.observe(this, result -> {
mVodAdapter.addAll(result.getList());
mBinding.recommendLayout.showContent();
mBinding.progress.showContent();
});
}
private void homeContent() {
mBinding.recommendLayout.showProgress();
mSiteViewModel.homeContent(ApiConfig.get().getHome().getKey());
private void getContent() {
mBinding.progress.showProgress();
mSiteViewModel.homeContent();
}
private void onFuncClick(Func item) {
switch (item.getResId()) {
case R.string.home_vod:
Result result = mSiteViewModel.getResult().getValue();
if (result != null) VodActivity.start(this, result);
break;
case R.string.home_setting:
SettingActivity.start(this);
break;
@ -82,6 +86,6 @@ public class HomeActivity extends BaseActivity {
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) return;
homeContent();
getContent();
}
}

@ -32,7 +32,6 @@ public class SplashActivity extends BaseActivity {
@Override
public void onAnimationEnd(Animator animation) {
mBinding.title.setVisibility(View.GONE);
mBinding.progress.animate().alpha(1).setDuration(500).start();
mBinding.info.animate().alpha(1).setDuration(500).start();
loadConfig();
}

@ -0,0 +1,81 @@
package com.fongmi.bear.ui.activity;
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewbinding.ViewBinding;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.fongmi.bear.bean.Result;
import com.fongmi.bear.bean.Type;
import com.fongmi.bear.databinding.ActivityVodBinding;
import com.fongmi.bear.ui.fragment.VodFragment;
import com.google.android.material.tabs.TabLayout;
public class VodActivity extends BaseActivity {
private ActivityVodBinding mBinding;
private Result mResult;
private String getResult() {
return getIntent().getStringExtra("result");
}
public static void start(Activity activity, Result result) {
Intent intent = new Intent(activity, VodActivity.class);
intent.putExtra("result", result.toString());
activity.startActivity(intent);
}
@Override
protected ViewBinding getBinding() {
return mBinding = ActivityVodBinding.inflate(getLayoutInflater());
}
@Override
protected void initView() {
mResult = Result.objectFrom(getResult());
for (Type type : mResult.getTypes()) mBinding.tab.addTab(mBinding.tab.newTab().setText(type.getTypeName()));
mBinding.pager.setAdapter(new PageAdapter(this));
mBinding.pager.setOffscreenPageLimit(mResult.getTypes().size());
}
@Override
protected void initEvent() {
mBinding.tab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
mBinding.pager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class PageAdapter extends FragmentStateAdapter {
public PageAdapter(@NonNull FragmentActivity activity) {
super(activity);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return VodFragment.newInstance(mResult.getTypes().get(position).getTypeId());
}
@Override
public int getItemCount() {
return mResult.getTypes().size();
}
}
}

@ -0,0 +1,158 @@
package com.fongmi.bear.ui.custom;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.fongmi.bear.databinding.ViewProgressBinding;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ProgressLayout extends RelativeLayout {
private static final String TAG_PROGRESS = "ProgressLayout.TAG_PROGRESS";
private static final String TAG_ERROR = "ProgressLayout.TAG_ERROR";
public enum State {
CONTENT, PROGRESS, ERROR
}
private View mProgressView;
private TextView mErrorTextView;
private List<View> mContentViews = new ArrayList<View>();
private ProgressLayout.State mState = ProgressLayout.State.CONTENT;
public ProgressLayout(Context context) {
super(context);
}
public ProgressLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ProgressLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mProgressView = ViewProgressBinding.inflate(LayoutInflater.from(getContext())).getRoot();
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(CENTER_IN_PARENT);
mProgressView.setTag(TAG_PROGRESS);
addView(mProgressView, layoutParams);
mErrorTextView = new TextView(getContext());
mErrorTextView.setTag(TAG_ERROR);
layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(CENTER_IN_PARENT);
addView(mErrorTextView, layoutParams);
mProgressView.setVisibility(GONE);
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
if (child.getTag() == null || (!child.getTag().equals(TAG_PROGRESS) && !child.getTag().equals(TAG_ERROR))) {
mContentViews.add(child);
}
}
public void showProgress() {
switchState(ProgressLayout.State.PROGRESS, null, Collections.<Integer>emptyList());
}
public void showProgress(List<Integer> skipIds) {
switchState(ProgressLayout.State.PROGRESS, null, skipIds);
}
public void showErrorText() {
switchState(ProgressLayout.State.ERROR, null, Collections.<Integer>emptyList());
}
public void showErrorText(List<Integer> skipIds) {
switchState(ProgressLayout.State.ERROR, null, skipIds);
}
public void showErrorText(String error) {
switchState(ProgressLayout.State.ERROR, error, Collections.<Integer>emptyList());
}
public void showErrorText(String error, List<Integer> skipIds) {
switchState(ProgressLayout.State.ERROR, error, skipIds);
}
public void showContent() {
switchState(ProgressLayout.State.CONTENT, null, Collections.<Integer>emptyList());
}
public void showContent(List<Integer> skipIds) {
switchState(ProgressLayout.State.CONTENT, null, skipIds);
}
public void switchState(ProgressLayout.State state) {
switchState(state, null, Collections.<Integer>emptyList());
}
public void switchState(ProgressLayout.State state, String errorText) {
switchState(state, errorText, Collections.<Integer>emptyList());
}
public void switchState(ProgressLayout.State state, List<Integer> skipIds) {
switchState(state, null, skipIds);
}
public void switchState(ProgressLayout.State state, String errorText, List<Integer> skipIds) {
mState = state;
switch (state) {
case CONTENT:
mErrorTextView.setVisibility(View.GONE);
mProgressView.setVisibility(View.GONE);
setContentVisibility(true, skipIds);
break;
case PROGRESS:
mErrorTextView.setVisibility(View.GONE);
mProgressView.setVisibility(View.VISIBLE);
setContentVisibility(false, skipIds);
break;
case ERROR:
mErrorTextView.setText(errorText);
mErrorTextView.setVisibility(View.VISIBLE);
mProgressView.setVisibility(View.GONE);
setContentVisibility(false, skipIds);
break;
}
}
public ProgressLayout.State getState() {
return mState;
}
public boolean isProgress() {
return mState == ProgressLayout.State.PROGRESS;
}
public boolean isContent() {
return mState == ProgressLayout.State.CONTENT;
}
public boolean isError() {
return mState == ProgressLayout.State.ERROR;
}
private void setContentVisibility(boolean visible, List<Integer> skipIds) {
for (View v : mContentViews) {
if (!skipIds.contains(v.getId())) {
v.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
}
}

@ -0,0 +1,72 @@
package com.fongmi.bear.ui.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import com.fongmi.bear.databinding.FragmentVodBinding;
import com.fongmi.bear.model.SiteViewModel;
import com.fongmi.bear.ui.adapter.VodAdapter;
import com.fongmi.bear.ui.custom.SpaceItemDecoration;
import java.util.HashMap;
public class VodFragment extends Fragment {
private FragmentVodBinding mBinding;
private SiteViewModel mSiteViewModel;
private VodAdapter mVodAdapter;
private String getTypeId() {
return getArguments().getString("typeId");
}
public static VodFragment newInstance(String typeId) {
Bundle args = new Bundle();
args.putString("typeId", typeId);
VodFragment fragment = new VodFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mBinding = FragmentVodBinding.inflate(inflater, container, false);
return mBinding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
setRecyclerView();
setViewModel();
getContent();
}
private void setRecyclerView() {
mBinding.recycler.setHasFixedSize(true);
mBinding.recycler.setLayoutManager(new GridLayoutManager(getContext(), 5));
mBinding.recycler.addItemDecoration(new SpaceItemDecoration(5, 12, false, 0));
mBinding.recycler.setAdapter(mVodAdapter = new VodAdapter());
}
private void setViewModel() {
mSiteViewModel = new ViewModelProvider(this).get(SiteViewModel.class);
mSiteViewModel.mResult.observe(getViewLifecycleOwner(), result -> {
mVodAdapter.addAll(result.getList());
mBinding.progress.showContent();
});
}
private void getContent() {
mBinding.progress.showProgress();
mSiteViewModel.categoryContent(getTypeId(), "1", true, new HashMap<>());
}
}

@ -13,7 +13,7 @@ import androidx.appcompat.app.AlertDialog;
import com.fongmi.bear.App;
import com.fongmi.bear.R;
import com.fongmi.bear.databinding.DialogProgressBinding;
import com.fongmi.bear.databinding.ViewProgressBinding;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class Notify {
@ -54,7 +54,7 @@ public class Notify {
}
public static void progress(Context context) {
DialogProgressBinding binding = DialogProgressBinding.inflate(LayoutInflater.from(context));
ViewProgressBinding binding = ViewProgressBinding.inflate(LayoutInflater.from(context));
get().mProgress = new MaterialAlertDialogBuilder(context).setView(binding.getRoot()).create();
get().mProgress.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
get().mProgress.show();

@ -4,7 +4,6 @@ import android.content.Context;
import com.fongmi.bear.App;
import com.fongmi.bear.utils.FileUtil;
import com.orhanobut.logger.Logger;
import org.json.JSONObject;
@ -51,7 +50,7 @@ public class JarLoader {
if (classInit != null) {
Method method = classInit.getMethod("init", Context.class);
method.invoke(classInit, App.get());
Logger.d("自定義爬蟲代碼加載成功!");
SpiderDebug.log("自定義爬蟲代碼加載成功!");
try {
Class<?> proxy = classLoader.loadClass("com.github.catvod.spider.Proxy");
proxyFun = proxy.getMethod("proxy", Map.class);

@ -13,4 +13,8 @@ public class SpiderDebug {
public static void log(String msg) {
Logger.t(TAG).d(msg);
}
public static void json(String msg) {
Logger.t(TAG).json(msg);
}
}

@ -6,7 +6,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
@ -48,8 +48,8 @@
android:textColor="@color/white"
android:textSize="24sp" />
<com.github.androidprogresslayout.ProgressLayout
android:id="@+id/recommendLayout"
<com.fongmi.bear.ui.custom.ProgressLayout
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp">
@ -60,6 +60,6 @@
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</com.github.androidprogresslayout.ProgressLayout>
</com.fongmi.bear.ui.custom.ProgressLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

@ -20,31 +20,24 @@
tools:alpha="1" />
<LinearLayout
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical">
android:alpha="0"
android:gravity="center"
android:orientation="vertical"
tools:alpha="1">
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:alpha="0"
android:indeterminateTint="@color/white"
tools:alpha="1" />
<include layout="@layout/view_progress" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="12dp"
android:alpha="0"
android:text="@string/splash_info"
android:textColor="@color/white"
android:textSize="18sp"
tools:alpha="1" />
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:nestedScrollingEnabled="false" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<com.fongmi.bear.ui.custom.ProgressLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</com.fongmi.bear.ui.custom.ProgressLayout>
Loading…
Cancel
Save