mirror of https://github.com/FongMi/TV.git
parent
6dc3f130d0
commit
b94665b48a
@ -0,0 +1,151 @@ |
||||
package com.fongmi.bear.bean; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class Config { |
||||
|
||||
@SerializedName("sites") |
||||
private List<Sites> sites; |
||||
@SerializedName("lives") |
||||
private List<Lives> lives; |
||||
@SerializedName("parses") |
||||
private List<Parses> parses; |
||||
@SerializedName("flags") |
||||
private List<String> flags; |
||||
@SerializedName("spider") |
||||
private String spider; |
||||
|
||||
public static Config objectFrom(String str) { |
||||
return new Gson().fromJson(str, Config.class); |
||||
} |
||||
|
||||
public List<Sites> getSites() { |
||||
return sites; |
||||
} |
||||
|
||||
public List<Lives> getLives() { |
||||
return lives; |
||||
} |
||||
|
||||
public List<Parses> getParses() { |
||||
return parses; |
||||
} |
||||
|
||||
public List<String> getFlags() { |
||||
return flags; |
||||
} |
||||
|
||||
public String getSpider() { |
||||
return spider; |
||||
} |
||||
|
||||
public static class Sites { |
||||
|
||||
@SerializedName("key") |
||||
private String key; |
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("type") |
||||
private Integer type; |
||||
@SerializedName("api") |
||||
private String api; |
||||
@SerializedName("searchable") |
||||
private Integer searchable; |
||||
@SerializedName("quickSearch") |
||||
private Integer quickSearch; |
||||
@SerializedName("filterable") |
||||
private Integer filterable; |
||||
@SerializedName("ext") |
||||
private String ext; |
||||
|
||||
public String getKey() { |
||||
return key; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public String getApi() { |
||||
return api; |
||||
} |
||||
|
||||
public Integer getSearchable() { |
||||
return searchable; |
||||
} |
||||
|
||||
public Integer getQuickSearch() { |
||||
return quickSearch; |
||||
} |
||||
|
||||
public Integer getFilterable() { |
||||
return filterable; |
||||
} |
||||
|
||||
public String getExt() { |
||||
return ext; |
||||
} |
||||
} |
||||
|
||||
public static class Lives { |
||||
|
||||
@SerializedName("group") |
||||
private String group; |
||||
@SerializedName("channels") |
||||
private List<Channels> channels; |
||||
|
||||
|
||||
public String getGroup() { |
||||
return group; |
||||
} |
||||
|
||||
public List<Channels> getChannels() { |
||||
return channels; |
||||
} |
||||
|
||||
public static class Channels { |
||||
|
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("urls") |
||||
private List<String> urls; |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public List<String> getUrls() { |
||||
return urls; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static class Parses { |
||||
|
||||
@SerializedName("name") |
||||
private String name; |
||||
@SerializedName("type") |
||||
private Integer type; |
||||
@SerializedName("url") |
||||
private String url; |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public Integer getType() { |
||||
return type; |
||||
} |
||||
|
||||
public String getUrl() { |
||||
return url; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
package com.fongmi.bear.net; |
||||
|
||||
public abstract class Callback { |
||||
|
||||
public void onResponse(String result) { |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
package com.fongmi.bear.net; |
||||
|
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import okhttp3.OkHttpClient; |
||||
|
||||
public class OKHttp { |
||||
|
||||
private final OkHttpClient client; |
||||
|
||||
private static class Loader { |
||||
static volatile OKHttp INSTANCE = new OKHttp(); |
||||
} |
||||
|
||||
public static OKHttp get() { |
||||
return Loader.INSTANCE; |
||||
} |
||||
|
||||
public OKHttp() { |
||||
client = getBuilder().build(); |
||||
} |
||||
|
||||
private OkHttpClient.Builder getBuilder() { |
||||
return new OkHttpClient.Builder().readTimeout(15, TimeUnit.SECONDS).writeTimeout(15, TimeUnit.SECONDS).connectTimeout(15, TimeUnit.SECONDS).retryOnConnectionFailure(true).sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert); |
||||
} |
||||
|
||||
public OkHttpClient client() { |
||||
return client; |
||||
} |
||||
} |
||||
@ -0,0 +1,112 @@ |
||||
package com.fongmi.bear.net; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.InetAddress; |
||||
import java.net.Socket; |
||||
import java.security.GeneralSecurityException; |
||||
import java.security.cert.X509Certificate; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
|
||||
import javax.net.ssl.SSLContext; |
||||
import javax.net.ssl.SSLSocket; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
import javax.net.ssl.X509TrustManager; |
||||
|
||||
public class SSLSocketFactoryCompat extends SSLSocketFactory { |
||||
|
||||
public static final X509TrustManager trustAllCert = new X509TrustManager() { |
||||
|
||||
@Override |
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) { |
||||
} |
||||
|
||||
@Override |
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) { |
||||
} |
||||
|
||||
@Override |
||||
public X509Certificate[] getAcceptedIssuers() { |
||||
return new X509Certificate[]{}; |
||||
} |
||||
}; |
||||
|
||||
static String[] protocols = null; |
||||
static String[] cipherSuites = null; |
||||
|
||||
static { |
||||
try { |
||||
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); |
||||
if (socket != null) { |
||||
List<String> protocols = new LinkedList<>(); |
||||
for (String protocol : socket.getSupportedProtocols()) if (!protocol.toUpperCase().contains("SSL")) protocols.add(protocol); |
||||
SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]); |
||||
} |
||||
} catch (IOException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
private final SSLSocketFactory defaultFactory; |
||||
|
||||
public SSLSocketFactoryCompat(X509TrustManager tm) { |
||||
try { |
||||
SSLContext sslContext = SSLContext.getInstance("TLS"); |
||||
sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null); |
||||
defaultFactory = sslContext.getSocketFactory(); |
||||
} catch (GeneralSecurityException e) { |
||||
throw new AssertionError(); // The system has no TLS. Just give up.
|
||||
} |
||||
} |
||||
|
||||
private void upgradeTLS(SSLSocket ssl) { |
||||
if (protocols != null) { |
||||
ssl.setEnabledProtocols(protocols); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String[] getDefaultCipherSuites() { |
||||
return cipherSuites; |
||||
} |
||||
|
||||
@Override |
||||
public String[] getSupportedCipherSuites() { |
||||
return cipherSuites; |
||||
} |
||||
|
||||
@Override |
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { |
||||
Socket ssl = defaultFactory.createSocket(s, host, port, autoClose); |
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); |
||||
return ssl; |
||||
} |
||||
|
||||
@Override |
||||
public Socket createSocket(String host, int port) throws IOException { |
||||
Socket ssl = defaultFactory.createSocket(host, port); |
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); |
||||
return ssl; |
||||
} |
||||
|
||||
@Override |
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { |
||||
Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort); |
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); |
||||
return ssl; |
||||
} |
||||
|
||||
@Override |
||||
public Socket createSocket(InetAddress host, int port) throws IOException { |
||||
Socket ssl = defaultFactory.createSocket(host, port); |
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); |
||||
return ssl; |
||||
} |
||||
|
||||
@Override |
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { |
||||
Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort); |
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl); |
||||
return ssl; |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@ |
||||
package com.fongmi.bear.net; |
||||
|
||||
import android.os.Handler; |
||||
import android.os.Looper; |
||||
|
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
|
||||
import okhttp3.Request; |
||||
import okhttp3.Response; |
||||
|
||||
public class Task { |
||||
|
||||
private final ExecutorService executor; |
||||
private final Callback callback; |
||||
private final Handler handler; |
||||
|
||||
public static Task create(Callback callback) { |
||||
return new Task(callback); |
||||
} |
||||
|
||||
public Task(Callback callback) { |
||||
this.executor = Executors.newSingleThreadExecutor(); |
||||
this.handler = new Handler(Looper.getMainLooper()); |
||||
this.callback = callback; |
||||
} |
||||
|
||||
public void run(String url) { |
||||
executor.submit(() -> doInBackground(url)); |
||||
} |
||||
|
||||
private void doInBackground(String url) { |
||||
try { |
||||
Response res = OKHttp.get().client().newCall(new Request.Builder().url(url).build()).execute(); |
||||
onPostExecute(res.body().string()); |
||||
} catch (Exception e) { |
||||
onPostExecute(""); |
||||
} |
||||
} |
||||
|
||||
private void onPostExecute(String result) { |
||||
handler.post(() -> { |
||||
if (callback != null) callback.onResponse(result); |
||||
}); |
||||
} |
||||
} |
||||
@ -1,15 +1,33 @@ |
||||
package com.fongmi.bear.ui; |
||||
|
||||
import android.app.Activity; |
||||
import android.content.Intent; |
||||
|
||||
import androidx.viewbinding.ViewBinding; |
||||
|
||||
import com.fongmi.bear.App; |
||||
import com.fongmi.bear.databinding.ActivityHomeBinding; |
||||
|
||||
public class HomeActivity extends BaseActivity { |
||||
|
||||
private ActivityHomeBinding binding; |
||||
|
||||
public static void newInstance(Activity activity) { |
||||
activity.startActivity(new Intent(activity, HomeActivity.class)); |
||||
activity.finish(); |
||||
} |
||||
|
||||
@Override |
||||
protected ViewBinding getBinding() { |
||||
return binding = ActivityHomeBinding.inflate(getLayoutInflater()); |
||||
} |
||||
|
||||
@Override |
||||
protected void initView() { |
||||
if (App.get().getConfig() == null) { |
||||
SettingActivity.newInstance(this); |
||||
} else { |
||||
|
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
package com.fongmi.bear.ui; |
||||
|
||||
import android.app.Activity; |
||||
import android.content.Intent; |
||||
import android.widget.Toast; |
||||
|
||||
import androidx.viewbinding.ViewBinding; |
||||
|
||||
import com.fongmi.bear.databinding.ActivitySettingBinding; |
||||
import com.fongmi.bear.utils.Prefers; |
||||
|
||||
public class SettingActivity extends BaseActivity { |
||||
|
||||
private ActivitySettingBinding binding; |
||||
|
||||
public static void newInstance(Activity activity) { |
||||
activity.startActivity(new Intent(activity, SettingActivity.class)); |
||||
} |
||||
|
||||
@Override |
||||
protected ViewBinding getBinding() { |
||||
return binding = ActivitySettingBinding.inflate(getLayoutInflater()); |
||||
} |
||||
|
||||
@Override |
||||
protected void initView() { |
||||
binding.url.setText(Prefers.getString("url")); |
||||
} |
||||
|
||||
@Override |
||||
protected void initEvent() { |
||||
binding.config.setOnClickListener(view -> Toast.makeText(SettingActivity.this, "config", Toast.LENGTH_SHORT).show()); |
||||
} |
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
<?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_focused="true" /> |
||||
<item android:drawable="@drawable/shape_item_normal" /> |
||||
</selector> |
||||
@ -0,0 +1,15 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
|
||||
<solid android:color="@color/trans_20" /> |
||||
|
||||
<corners android:radius="4dp" /> |
||||
|
||||
<padding |
||||
android:bottom="8dp" |
||||
android:left="12dp" |
||||
android:right="12dp" |
||||
android:top="8dp" /> |
||||
|
||||
</shape> |
||||
@ -0,0 +1,19 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:shape="rectangle"> |
||||
|
||||
<solid android:color="@color/trans_25" /> |
||||
|
||||
<corners android:radius="4dp" /> |
||||
|
||||
<padding |
||||
android:bottom="8dp" |
||||
android:left="12dp" |
||||
android:right="12dp" |
||||
android:top="8dp" /> |
||||
|
||||
<stroke |
||||
android:width="1dp" |
||||
android:color="@color/white" /> |
||||
|
||||
</shape> |
||||
@ -0,0 +1,60 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout 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" |
||||
android:background="@drawable/wallpaper_1" |
||||
android:orientation="vertical" |
||||
android:padding="16dp"> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="horizontal"> |
||||
|
||||
<LinearLayout |
||||
android:id="@+id/config" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="8dp" |
||||
android:layout_weight="1" |
||||
android:background="@drawable/selector_item" |
||||
android:focusable="true" |
||||
android:focusableInTouchMode="true" |
||||
android:orientation="horizontal"> |
||||
|
||||
<TextView |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginEnd="16dp" |
||||
android:text="@string/setting_url" |
||||
android:textColor="@color/white" |
||||
android:textSize="18sp" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/url" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_weight="1" |
||||
android:gravity="end" |
||||
android:singleLine="true" |
||||
android:textColor="@color/white" |
||||
android:textSize="18sp" |
||||
tools:ignore="NestedWeights" |
||||
tools:text="https://" /> |
||||
|
||||
</LinearLayout> |
||||
|
||||
<TextView |
||||
android:id="@+id/history" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:background="@drawable/selector_item" |
||||
android:focusable="true" |
||||
android:focusableInTouchMode="true" |
||||
android:text="@string/setting_history" |
||||
android:textColor="@color/white" |
||||
android:textSize="18sp" /> |
||||
|
||||
</LinearLayout> |
||||
</LinearLayout> |
||||
@ -1,5 +1,7 @@ |
||||
<resources> |
||||
|
||||
<string name="app_name">熊爱影视</string> |
||||
|
||||
<string name="setting_url">配置接口</string> |
||||
<string name="setting_history">历史配置</string> |
||||
|
||||
</resources> |
||||
@ -1,5 +1,7 @@ |
||||
<resources> |
||||
|
||||
<string name="app_name">熊愛影視</string> |
||||
<string name="setting_url">配置接口</string> |
||||
<string name="setting_history">歷史配置</string> |
||||
|
||||
</resources> |
||||
@ -1,5 +1,7 @@ |
||||
<resources> |
||||
|
||||
<string name="app_name">BearTV</string> |
||||
<string name="setting_url">Configure</string> |
||||
<string name="setting_history">History</string> |
||||
|
||||
</resources> |
||||
Loading…
Reference in new issue