修正exo点播异常;搜索分词修复;设置添加历史配置;支持读取用户自定义doh{"spider":"","doh":[{"name":"Google","url":"https://dns.google/dns-query","ips":["8.8.4.4","8.8.8.8"]}]}

pull/138/head
21561 10 months ago
parent c323f545e7
commit dbc878fa31
  1. 9
      app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java
  2. 60
      app/src/main/java/com/github/tvbox/osc/ui/activity/DetailActivity.java
  3. 75
      app/src/main/java/com/github/tvbox/osc/ui/activity/FastSearchActivity.java
  4. 7
      app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java
  5. 34
      app/src/main/java/com/github/tvbox/osc/ui/fragment/ModelSettingFragment.java
  6. 6
      app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java
  7. 1
      app/src/main/java/com/github/tvbox/osc/util/HawkConfig.java
  8. 125
      app/src/main/java/com/github/tvbox/osc/util/OkGoHelper.java
  9. 3
      app/src/main/res/layout/dialog_api.xml
  10. 59
      app/src/main/res/layout/fragment_model.xml

@ -21,6 +21,7 @@ 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.OkGoHelper;
import com.github.tvbox.osc.util.VideoParseRuler;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
@ -504,6 +505,14 @@ public class ApiConfig {
}
}
}
if (infoJson.has("doh")) {
String doh_json = infoJson.getAsJsonArray("doh").toString();
Hawk.put(HawkConfig.DOH_JSON,doh_json);
}else {
Hawk.put(HawkConfig.DOH_JSON,"");
}
OkGoHelper.setDnsList();
LOG.i("echo-api-config-----------load");
String defaultIJKADS="{\"ijk\":[{\"options\":[{\"name\":\"opensles\",\"category\":4,\"value\":\"0\"},{\"name\":\"framedrop\",\"category\":4,\"value\":\"1\"},{\"name\":\"soundtouch\",\"category\":4,\"value\":\"1\"},{\"name\":\"start-on-prepared\",\"category\":4,\"value\":\"1\"},{\"name\":\"http-detect-rangeupport\",\"category\":1,\"value\":\"0\"},{\"name\":\"fflags\",\"category\":1,\"value\":\"fastseek\"},{\"name\":\"skip_loop_filter\",\"category\":2,\"value\":\"48\"},{\"name\":\"reconnect\",\"category\":4,\"value\":\"1\"},{\"name\":\"enable-accurate-seek\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec-all-videos\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec-auto-rotate\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec-handle-resolution-change\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec-hevc\",\"category\":4,\"value\":\"0\"},{\"name\":\"max-buffer-size\",\"category\":4,\"value\":\"15728640\"}],\"group\":\"软解码\"},{\"options\":[{\"name\":\"opensles\",\"category\":4,\"value\":\"0\"},{\"name\":\"framedrop\",\"category\":4,\"value\":\"1\"},{\"name\":\"soundtouch\",\"category\":4,\"value\":\"1\"},{\"name\":\"start-on-prepared\",\"category\":4,\"value\":\"1\"},{\"name\":\"http-detect-rangeupport\",\"category\":1,\"value\":\"0\"},{\"name\":\"fflags\",\"category\":1,\"value\":\"fastseek\"},{\"name\":\"skip_loop_filter\",\"category\":2,\"value\":\"48\"},{\"name\":\"reconnect\",\"category\":4,\"value\":\"1\"},{\"name\":\"enable-accurate-seek\",\"category\":4,\"value\":\"0\"},{\"name\":\"mediacodec\",\"category\":4,\"value\":\"1\"},{\"name\":\"mediacodec-all-videos\",\"category\":4,\"value\":\"1\"},{\"name\":\"mediacodec-auto-rotate\",\"category\":4,\"value\":\"1\"},{\"name\":\"mediacodec-handle-resolution-change\",\"category\":4,\"value\":\"1\"},{\"name\":\"mediacodec-hevc\",\"category\":4,\"value\":\"1\"},{\"name\":\"max-buffer-size\",\"category\":4,\"value\":\"15728640\"}],\"group\":\"硬解码\"}],\"ads\":[\"mimg.0c1q0l.cn\",\"www.googletagmanager.com\",\"www.google-analytics.com\",\"mc.usihnbcq.cn\",\"mg.g1mm3d.cn\",\"mscs.svaeuzh.cn\",\"cnzz.hhttm.top\",\"tp.vinuxhome.com\",\"cnzz.mmstat.com\",\"www.baihuillq.com\",\"s23.cnzz.com\",\"z3.cnzz.com\",\"c.cnzz.com\",\"stj.v1vo.top\",\"z12.cnzz.com\",\"img.mosflower.cn\",\"tips.gamevvip.com\",\"ehwe.yhdtns.com\",\"xdn.cqqc3.com\",\"www.jixunkyy.cn\",\"sp.chemacid.cn\",\"hm.baidu.com\",\"s9.cnzz.com\",\"z6.cnzz.com\",\"um.cavuc.com\",\"mav.mavuz.com\",\"wofwk.aoidf3.com\",\"z5.cnzz.com\",\"xc.hubeijieshikj.cn\",\"tj.tianwenhu.com\",\"xg.gars57.cn\",\"k.jinxiuzhilv.com\",\"cdn.bootcss.com\",\"ppl.xunzhuo123.com\",\"xomk.jiangjunmh.top\",\"img.xunzhuo123.com\",\"z1.cnzz.com\",\"s13.cnzz.com\",\"xg.huataisangao.cn\",\"z7.cnzz.com\",\"xg.huataisangao.cn\",\"z2.cnzz.com\",\"s96.cnzz.com\",\"q11.cnzz.com\",\"thy.dacedsfa.cn\",\"xg.whsbpw.cn\",\"s19.cnzz.com\",\"z8.cnzz.com\",\"s4.cnzz.com\",\"f5w.as12df.top\",\"ae01.alicdn.com\",\"www.92424.cn\",\"k.wudejia.com\",\"vivovip.mmszxc.top\",\"qiu.xixiqiu.com\",\"cdnjs.hnfenxun.com\",\"cms.qdwght.com\"]}";
JsonObject defaultJson=new Gson().fromJson(defaultIJKADS, JsonObject.class);

@ -806,37 +806,35 @@ public class DetailActivity extends BaseActivity {
quickSearchData.clear();
quickSearchWord.addAll(SearchHelper.splitWords(searchTitle));
// 分词
OkGo.<String>get("http://api.pullword.com/get.php?source=" + URLEncoder.encode(searchTitle) + "&param1=0&param2=0&json=1")
.tag("fenci")
.execute(new AbsCallback<String>() {
@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<String> response) {
String json = response.body();
try {
for (JsonElement je : new Gson().fromJson(json, JsonArray.class)) {
quickSearchWord.add(je.getAsJsonObject().get("t").getAsString());
}
} catch (Throwable th) {
th.printStackTrace();
}
List<String> words = new ArrayList<>(new HashSet<>(quickSearchWord));
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, words));
}
@Override
public void onError(Response<String> response) {
super.onError(response);
}
});
// OkGo.<String>get("http://api.pullword.com/get.php?source=" + URLEncoder.encode(searchTitle) + "&param1=0&param2=0&json=1")
// .tag("fenci")
// .execute(new AbsCallback<String>() {
// @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<String> response) {
// String json = response.body();
// try {
// for (JsonElement je : new Gson().fromJson(json, JsonArray.class)) {
// quickSearchWord.add(je.getAsJsonObject().get("t").getAsString());
// }
// } catch (Throwable th) {
// th.printStackTrace();
// }
// List<String> words = new ArrayList<>(new HashSet<>(quickSearchWord));
// EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, words));
// }
//
// @Override
// public void onError(Response<String> response) {super.onError(response);}
// });
searchResult();
}

@ -28,12 +28,7 @@ import com.github.tvbox.osc.util.FastClickCheckUtil;
import com.github.tvbox.osc.util.SearchHelper;
import com.github.tvbox.osc.util.js.JSEngine;
import com.github.tvbox.osc.viewmodel.SourceViewModel;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.Response;
import com.owen.tvrecyclerview.widget.TvRecyclerView;
import com.owen.tvrecyclerview.widget.V7GridLayoutManager;
import com.owen.tvrecyclerview.widget.V7LinearLayoutManager;
@ -42,7 +37,6 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -277,40 +271,43 @@ public class FastSearchActivity extends BaseActivity {
private void fenci() {
if (!quickSearchWord.isEmpty()) return; // 如果经有分词了,不再进行二次分词
quickSearchWord.addAll(SearchHelper.splitWords(searchTitle));
List<String> words = new ArrayList<>(new HashSet<>(quickSearchWord));
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, words));
// 分词
OkGo.<String>get("http://api.pullword.com/get.php?source=" + URLEncoder.encode(searchTitle) + "&param1=0&param2=0&json=1")
.tag("fenci")
.execute(new AbsCallback<String>() {
@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<String> response) {
String json = response.body();
quickSearchWord.clear();
try {
for (JsonElement je : new Gson().fromJson(json, JsonArray.class)) {
quickSearchWord.add(je.getAsJsonObject().get("t").getAsString());
}
} catch (Throwable th) {
th.printStackTrace();
}
quickSearchWord.addAll(SearchHelper.splitWords(searchTitle));
List<String> words = new ArrayList<>(new HashSet<>(quickSearchWord));
EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, words));
}
@Override
public void onError(Response<String> response) {
super.onError(response);
}
});
// OkGo.<String>get("http://api.pullword.com/get.php?source=" + URLEncoder.encode(searchTitle) + "&param1=0&param2=0&json=1")
// .tag("fenci")
// .execute(new AbsCallback<String>() {
// @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<String> response) {
// String json = response.body();
// quickSearchWord.clear();
// try {
// for (JsonElement je : new Gson().fromJson(json, JsonArray.class)) {
// quickSearchWord.add(je.getAsJsonObject().get("t").getAsString());
// }
// } catch (Throwable th) {
// th.printStackTrace();
// }
// quickSearchWord.addAll(SearchHelper.splitWords(searchTitle));
// List<String> words = new ArrayList<>(new HashSet<>(quickSearchWord));
// EventBus.getDefault().post(new RefreshEvent(RefreshEvent.TYPE_QUICK_SEARCH_WORD, words));
// }
//
// @Override
// public void onError(Response<String> response) {
// super.onError(response);
// }
// });
}
private void initData() {

@ -218,7 +218,11 @@ public class PlayActivity extends BaseActivity {
if(replay){
play(true);
}else {
playUrl(webPlayUrl,webHeaderMap);
if(webPlayUrl!=null && !webPlayUrl.isEmpty()) {
playUrl(webPlayUrl,webHeaderMap);
}else {
play(false);
}
}
}
@ -509,6 +513,7 @@ public class PlayActivity extends BaseActivity {
try {
String url_encode;
url_encode=URLEncoder.encode(url,"UTF-8");
LOG.i("echo-BOM-------");
url = ControlManager.get().getAddress(true) + "proxy?go=bom&url="+ url_encode;
}catch (UnsupportedEncodingException e) {

@ -20,9 +20,11 @@ import com.github.tvbox.osc.event.RefreshEvent;
import com.github.tvbox.osc.player.thirdparty.RemoteTVBox;
import com.github.tvbox.osc.ui.activity.HomeActivity;
import com.github.tvbox.osc.ui.activity.SettingActivity;
import com.github.tvbox.osc.ui.adapter.ApiHistoryDialogAdapter;
import com.github.tvbox.osc.ui.adapter.SelectDialogAdapter;
import com.github.tvbox.osc.ui.dialog.AboutDialog;
import com.github.tvbox.osc.ui.dialog.ApiDialog;
import com.github.tvbox.osc.ui.dialog.ApiHistoryDialog;
import com.github.tvbox.osc.ui.dialog.BackupDialog;
import com.github.tvbox.osc.ui.dialog.SearchRemoteTvDialog;
import com.github.tvbox.osc.ui.dialog.SelectDialog;
@ -251,8 +253,8 @@ public class ModelSettingFragment extends BaseLazyFragment {
public void click(String value, int pos) {
tvDns.setText(OkGoHelper.dnsHttpsList.get(pos));
Hawk.put(HawkConfig.DOH_URL, pos);
String url = OkGoHelper.getDohUrl(pos);
OkGoHelper.dnsOverHttps.setUrl(url.isEmpty() ? null : HttpUrl.get(url));
// String url = OkGoHelper.getDohUrl(pos);
// OkGoHelper.dnsOverHttps.setUrl(url.isEmpty() ? null : HttpUrl.get(url));
IjkMediaPlayer.toggleDotPort(pos > 0);
}
@ -298,6 +300,34 @@ public class ModelSettingFragment extends BaseLazyFragment {
}
});
findViewById(R.id.llApiHistory).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<String> history = Hawk.get(HawkConfig.API_HISTORY, new ArrayList<String>());
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(mActivity);
dialog.setTip("历史配置列表");
dialog.setAdapter(new ApiHistoryDialogAdapter.SelectDialogInterface() {
@Override
public void click(String value) {
Hawk.put(HawkConfig.API_URL, value);
tvApi.setText(value);
dialog.dismiss();
}
@Override
public void del(String value, ArrayList<String> data) {
Hawk.put(HawkConfig.API_HISTORY, data);
}
}, history, idx);
dialog.show();
}
});
findViewById(R.id.llMediaCodec).setOnClickListener(new View.OnClickListener() {

@ -237,7 +237,11 @@ public class PlayFragment extends BaseLazyFragment {
if(replay){
play(true);
}else {
playUrl(webPlayUrl,webHeaderMap);
if(webPlayUrl!=null && !webPlayUrl.isEmpty()) {
playUrl(webPlayUrl,webHeaderMap);
}else {
play(false);
}
}
}

@ -40,5 +40,6 @@ public class HawkConfig {
public static final String REMOTE_TVBOX = "remote_tvbox_host";
public static final String IJK_CACHE_PLAY = "ijk_cache_play";
public static final String PLAYER_IS_LIVE = "player_is_live";
public static final String DOH_JSON = "doh_json";
public static boolean hotVodDelete;
}

@ -8,6 +8,9 @@ import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.base.App;
import com.github.tvbox.osc.picasso.MyOkhttpDownLoader;
import com.github.tvbox.osc.util.SSL.SSLSocketFactoryCompat;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.https.HttpsUtils;
import com.lzy.okgo.interceptor.HttpLoggingInterceptor;
@ -20,6 +23,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -44,8 +48,14 @@ import xyz.doikki.videoplayer.exo.ExoMediaSourceHelper;
public class OkGoHelper {
public static final long DEFAULT_MILLISECONDS = 8000; //默认的超时时间
public static final long DEFAULT_MILLISECONDS = 6500; //默认的超时时间
// 示例 JSON 字符串
private static final String dnsConfigJson = "["
+ "{\"name\": \"腾讯\", \"url\": \"https://doh.pub/dns-query\"},"
+ "{\"name\": \"阿里\", \"url\": \"https://dns.alidns.com/dns-query\"},"
+ "{\"name\": \"360\", \"url\": \"https://doh.360.cn/dns-query\"}"
+ "]";
static OkHttpClient ItvClient = null;
static void initExoOkHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
@ -85,35 +95,66 @@ public class OkGoHelper {
public static boolean is_doh = false;
public static Map<String, String> myHosts = null;
public static String getDohUrl(int type) {
switch (type) {
case 1: {
return "https://doh.pub/dns-query";
}
case 2: {
return "https://dns.alidns.com/dns-query";
}
case 3: {
return "https://doh.360.cn/dns-query";
}
case 4: {
return "https://dns.adguard.com/dns-query";
}
case 5: {
return "https://dns.quad9.net/dns-query";
}
String json=Hawk.get(HawkConfig.DOH_JSON,"");
if(json.isEmpty())json=dnsConfigJson;
JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray();
if (type >= 1 && type < dnsHttpsList.size()) {
JsonObject dnsConfig = jsonArray.get(type - 1).getAsJsonObject();
return dnsConfig.get("url").getAsString(); // 获取对应的 URL
}
return "";
}
static void initDnsOverHttps() {
public static void setDnsList() {
dnsHttpsList.clear();
String json=Hawk.get(HawkConfig.DOH_JSON,"");
if(json.isEmpty())json=dnsConfigJson;
JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray();
dnsHttpsList.add("关闭");
dnsHttpsList.add("腾讯");
dnsHttpsList.add("阿里");
dnsHttpsList.add("360");
dnsHttpsList.add("AdGuard");
dnsHttpsList.add("Quad9");
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject dnsConfig = jsonArray.get(i).getAsJsonObject();
String name = dnsConfig.has("name") ? dnsConfig.get("name").getAsString() : "Unknown Name";
dnsHttpsList.add(name);
}
if(Hawk.get(HawkConfig.DOH_URL, 0)+1>dnsHttpsList.size())Hawk.put(HawkConfig.DOH_URL, 0);
}
private static List<InetAddress> DohIps(JsonArray ips) {
List<InetAddress> inetAddresses = new ArrayList<>();
if (ips != null) {
for (int j = 0; j < ips.size(); j++) {
try {
InetAddress inetAddress = InetAddress.getByName(ips.get(j).getAsString());
inetAddresses.add(inetAddress); // 添加到 List 中
} catch (Exception e) {
e.printStackTrace(); // 处理无效的 IP 字符串
}
}
}
return inetAddresses;
}
static void initDnsOverHttps() {
Integer dohSelector=Hawk.get(HawkConfig.DOH_URL, 0);
JsonArray ips=null;
try {
dnsHttpsList.add("关闭");
String json=Hawk.get(HawkConfig.DOH_JSON,"");
if(json.isEmpty())json=dnsConfigJson;
JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray();
if(dohSelector+1>jsonArray.size())Hawk.put(HawkConfig.DOH_URL, 0);
for (int i = 0; i < jsonArray.size(); i++) {
JsonObject dnsConfig = jsonArray.get(i).getAsJsonObject();
String name = dnsConfig.has("name") ? dnsConfig.get("name").getAsString() : "Unknown Name";
dnsHttpsList.add(name);
if(dohSelector==i)ips = dnsConfig.has("ips") ? dnsConfig.getAsJsonArray("ips") : null;
}
} catch (Exception e) {
e.printStackTrace();
}
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkExoPlayer");
if (Hawk.get(HawkConfig.DEBUG_OPEN, false)) {
@ -133,10 +174,20 @@ public class OkGoHelper {
OkHttpClient dohClient = builder.build();
String dohUrl = getDohUrl(Hawk.get(HawkConfig.DOH_URL, 0));
if (!dohUrl.isEmpty()) is_doh = true;
dnsOverHttps = new DnsOverHttps.Builder()
.client(dohClient)
.url(dohUrl.isEmpty() ? null : HttpUrl.get(dohUrl))
.build();
// dnsOverHttps = new DnsOverHttps.Builder()
// .client(dohClient)
// .url(dohUrl.isEmpty() ? null : HttpUrl.get(dohUrl))
// .build();
DnsOverHttps.Builder dnsBuilder = new DnsOverHttps.Builder();
dnsBuilder.client(dohClient);
dnsBuilder.url(dohUrl.isEmpty() ? null : HttpUrl.get(dohUrl));
if (is_doh && ips!=null){
List<InetAddress> IPS=DohIps(ips);
dnsOverHttps = dnsBuilder.bootstrapDnsHosts(IPS).build();
}else {
dnsOverHttps = dnsBuilder.build();
}
}
// 自定义 DNS 解析器
@ -150,15 +201,13 @@ public class OkGoHelper {
myHosts = ApiConfig.get().getMyHost(); //确保只获取一次减少消耗
if(!myHosts.isEmpty())mapHosts(myHosts);
}
// 判断输入是否为 IP 地址
if (isValidIpAddress(hostname)) {
return Collections.singletonList(InetAddress.getByName(hostname));
} else if (!map.isEmpty() && map.containsKey(hostname)) {
}
if (map!=null && map.containsKey(hostname)) {
return Objects.requireNonNull(map.get(hostname));
} else {
// return (is_doh?dnsOverHttps:Dns.SYSTEM).lookup(hostname);
return (dnsOverHttps).lookup(hostname);
}
return dnsOverHttps.lookup(hostname);
}
public synchronized void mapHosts(Map<String,String> hosts) {
@ -174,6 +223,7 @@ public class OkGoHelper {
try {
// 获取所有与主机名关联的 IP 地址
InetAddress[] allAddresses = InetAddress.getAllByName(host);
if(excludeIps.isEmpty())return Arrays.asList(allAddresses);
// 创建一个列表用于存储有效的 IP 地址
List<InetAddress> validAddresses = new ArrayList<>();
Set<String> excludeIpsSet = new HashSet<>();
@ -193,18 +243,13 @@ public class OkGoHelper {
//简单判断减少开销
private boolean isValidIpAddress(String str) {
// 处理 IPv4 地址的判断
if (str.indexOf('.') > 0) return isValidIPv4(str);
// 处理 IPv6 地址的判断
if (str.indexOf(':') > 0) return true;
return false;
return str.indexOf(':') > 0;
}
private boolean isValidIPv4(String str) {
String[] parts = str.split("\\.");
// IPv4 地址必须有 4 个部分
if (parts.length != 4) return false;
// 检查每一部分是否是 0-255 的数字
for (String part : parts) {
try {
Integer.parseInt(part);

@ -45,7 +45,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/vs_10"
android:orientation="horizontal">
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:id="@+id/apiHistory"

@ -109,11 +109,19 @@
android:textSize="@dimen/ts_30" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/vs_60"
android:layout_marginBottom="@dimen/vs_10"
android:focusable="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llApi"
android:layout_width="match_parent"
android:layout_height="@dimen/vs_60"
android:layout_marginBottom="@dimen/vs_10"
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/vs_5"
android:layout_marginRight="@dimen/vs_5"
android:layout_weight="3.08"
android:background="@drawable/shape_setting_model_focus"
android:focusable="true"
android:gravity="center_vertical"
@ -151,6 +159,49 @@
android:textColor="@android:color/white"
android:textSize="@dimen/ts_30" />
</LinearLayout>
<LinearLayout
android:id="@+id/llApiHistory"
android:layout_width="@dimen/vs_0"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/vs_5"
android:layout_marginLeft="@dimen/vs_5"
android:layout_weight="1"
android:background="@drawable/shape_setting_model_focus"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="@dimen/vs_20"
android:paddingRight="@dimen/vs_20">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="配置历史"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@+id/tvMediaCodec1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/vs_10"
android:layout_marginLeft="@dimen/vs_10"
android:text=">"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_30" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
@ -1009,7 +1060,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="数据备份还原"
android:text="数据备份"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_24" />

Loading…
Cancel
Save