Commit 80eade80 authored by fallenstardust's avatar fallenstardust
parents af4262ba 8b05da86
...@@ -4,6 +4,9 @@ import net.kk.xml.annotations.XmlElement; ...@@ -4,6 +4,9 @@ import net.kk.xml.annotations.XmlElement;
import java.util.List; import java.util.List;
/**
* 将服务器列表写入xml文件时利用的PO类
*/
@XmlElement("servers") @XmlElement("servers")
public class ServerList { public class ServerList {
@XmlElement("version") @XmlElement("version")
...@@ -20,7 +23,7 @@ public class ServerList { ...@@ -20,7 +23,7 @@ public class ServerList {
} }
public ServerList(int version, List<ServerInfo> serverInfoList) { public ServerList(int version, List<ServerInfo> serverInfoList) {
mServerInfoList = serverInfoList; this.mServerInfoList = serverInfoList;
this.vercode = version; this.vercode = version;
} }
......
package cn.garymb.ygomobile.bean.events; package cn.garymb.ygomobile.bean.events;
/**
* 用于EventBus的事件类型。
*/
public class CardInfoEvent { public class CardInfoEvent {
public int position; public int position;
public boolean toMain; public boolean toMain;
......
package cn.garymb.ygomobile.bean.events; package cn.garymb.ygomobile.bean.events;
/** /**
* 用于EventBus发布的时间类型。 * 用于EventBus的事件类型。
*/ */
public class ExCardEvent { public class ExCardEvent {
public enum EventType { public enum EventType {
......
package cn.garymb.ygomobile.bean.events; package cn.garymb.ygomobile.bean.events;
import cn.garymb.ygomobile.bean.ServerInfo; import cn.garymb.ygomobile.bean.ServerInfo;
/**
* 用于EventBus的事件类型。
*/
public class ServerInfoEvent { public class ServerInfoEvent {
public int position; public int position;
public ServerInfo serverInfo;//为了让接受event的HomeFragment能获取到当前server的端口号等信息,加入该属性 public ServerInfo serverInfo;//为了让接受event的HomeFragment能获取到当前server的端口号等信息,加入该属性
......
...@@ -6,7 +6,7 @@ import android.os.Parcelable; ...@@ -6,7 +6,7 @@ import android.os.Parcelable;
/* /*
This class contains two types of card information:ex-card information and updating log, which is marked This class contains two types of card information:ex-card information and updating log, which is marked
by "type 0" and "type 1", respectively. by "type 0" and "type 1", respectively.
本类包括两种卡牌信息,先行卡信息和更新日志(分别由·type 0和type 1表示)。 本类包括两种卡牌信息,先行卡信息和更新日志(分别由·type 0和type 1表示)。
*/ */
public class ExCard implements Parcelable { public class ExCard implements Parcelable {
private String name; private String name;
......
...@@ -9,6 +9,7 @@ import com.google.android.material.tabs.TabLayout; ...@@ -9,6 +9,7 @@ import com.google.android.material.tabs.TabLayout;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.activities.BaseActivity; import cn.garymb.ygomobile.ui.activities.BaseActivity;
import cn.garymb.ygomobile.utils.LogUtil; import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
public class ExCardActivity extends BaseActivity { public class ExCardActivity extends BaseActivity {
private static final String TAG = String.valueOf(ExCardActivity.class); private static final String TAG = String.valueOf(ExCardActivity.class);
...@@ -21,7 +22,7 @@ public class ExCardActivity extends BaseActivity { ...@@ -21,7 +22,7 @@ public class ExCardActivity extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ex_card); setContentView(R.layout.activity_ex_card);
viewPager = findViewById(R.id.viewPager); viewPager = findViewById(R.id.viewPager);
viewPager.setOffscreenPageLimit(2); viewPager.setOffscreenPageLimit(1);
tabLayout = findViewById(R.id.packagetablayout); tabLayout = findViewById(R.id.packagetablayout);
createTabFragment(); createTabFragment();
...@@ -47,4 +48,20 @@ public class ExCardActivity extends BaseActivity { ...@@ -47,4 +48,20 @@ public class ExCardActivity extends BaseActivity {
return true; return true;
} }
private int backCounter = 0;
//todo 当未下载完先行卡就退出页面时,会导致软件错误退出。未来通过监听返回事件,判断下载状态,若正在下载则阻拦返回键。
//若发生错误或已完成,则不阻拦返回。
@Override
public void onBackPressed() {
if (ExCardListFragment.downloadState == ExCardListFragment.DownloadState.DOWNLOAD_ING) {
if (backCounter < 1) {
backCounter++;
YGOUtil.showTextToast("下载中,建议不要退出页面,再次按返回键可以退出页面");
return;
}
}
super.onBackPressed();
}
} }
package cn.garymb.ygomobile.ex_card;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class ExCardData {
@SerializedName("id")
@Expose
private Long id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("desc")
@Expose
private String desc;
@SerializedName("overallString")
@Expose
private String overallString;
@SerializedName("picUrl")
@Expose
private String picUrl;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getOverallString() {
return overallString;
}
public void setOverallString(String overallString) {
this.overallString = overallString;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
}
\ No newline at end of file
package cn.garymb.ygomobile.ex_card; package cn.garymb.ygomobile.ex_card;
import static cn.garymb.ygomobile.Constants.URL_PRE_CARD;
import static cn.garymb.ygomobile.utils.StringUtils.mergeListDelimeter;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView; import android.widget.ImageView;
import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.RequestBuilder;
import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder; import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.jsoup.Jsoup; import java.io.IOException;
import org.jsoup.nodes.Document; import java.lang.reflect.Type;
import org.jsoup.nodes.Element; import java.util.List;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.loader.ImageLoader; import cn.garymb.ygomobile.loader.ImageLoader;
import cn.garymb.ygomobile.ui.plus.DialogPlus; import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit; import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil; import cn.garymb.ygomobile.utils.LogUtil;
import cn.garymb.ygomobile.utils.OkhttpUtil;
import cn.garymb.ygomobile.utils.glide.GlideCompat; import cn.garymb.ygomobile.utils.glide.GlideCompat;
import okhttp3.Response;
public class ExCardListAdapter extends BaseQuickAdapter<ExCard, BaseViewHolder> { public class ExCardListAdapter extends BaseQuickAdapter<ExCardData, BaseViewHolder> {
private static final String TAG = ExCardListAdapter.class.getSimpleName(); private static final String TAG = ExCardListAdapter.class.getSimpleName();
private ImageLoader imageLoader; private ImageLoader imageLoader;
...@@ -34,78 +38,84 @@ public class ExCardListAdapter extends BaseQuickAdapter<ExCard, BaseViewHolder> ...@@ -34,78 +38,84 @@ public class ExCardListAdapter extends BaseQuickAdapter<ExCard, BaseViewHolder>
public void loadData() { public void loadData() {
final DialogPlus dialog_read_ex = DialogPlus.show(getContext(), null, getContext().getString(R.string.fetch_ex_card)); final DialogPlus dialog_read_ex = DialogPlus.show(getContext(), null, getContext().getString(R.string.fetch_ex_card));
VUiKit.defer().when(() -> { VUiKit.defer().when(() -> {
//Connect to the website LogUtil.d(TAG, "start fetch");
Document document = Jsoup.connect(Constants.URL_YGO233_ADVANCE).get(); List<ExCardData> exCardDataList = null;
Element pre_card_content = document.getElementById("pre_release_cards"); try {
Element tbody = pre_card_content.getElementsByTag("tbody").get(0); Response response = OkhttpUtil.synchronousGet(URL_PRE_CARD, null, null);
Elements cards = tbody.getElementsByTag("tr"); String responseBodyString = response.body().string();
if (cards.size() > 5000) {//Considering the efficiency of html parse, if the size of Type listType = new TypeToken<List<ExCardData>>() {
// pre cards list is to large, return null directly. }.getType();
return null; Gson gson = new Gson();
}
ArrayList<ExCard> exCardList = new ArrayList<>(); // Convert JSON to Java object using Gson
for (Element card : cards) { exCardDataList = gson.fromJson(responseBodyString, listType);
Elements card_attributes = card.getElementsByTag("td");
String imageUrl = card_attributes.get(0).getElementsByTag("a").attr("href") + "!half";
String name = card_attributes.get(1).text(); } catch (IOException e) {
String description = card_attributes.get(2).text(); Log.e(TAG, "Error occured when fetching data from pre-card server");
ExCard exCard = new ExCard(name, imageUrl, description, 0); return null;
exCardList.add(exCard); }
} if (exCardDataList.isEmpty()) {
return null;
} else {
if (exCardList.isEmpty()) { return exCardDataList;
return null; }
} else {
return exCardList; })
} .fail((e) -> {
//关闭异常
if (dialog_read_ex.isShowing()) {
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
LogUtil.i(TAG, "webCrawler fail");
})
.done((exCardDataList) -> {
if (exCardDataList != null) {
LogUtil.i(TAG, "webCrawler done");
getData().clear();
addData(exCardDataList);
notifyDataSetChanged();
}
if (dialog_read_ex.isShowing()) {
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
});
}).fail((e) -> { }
//关闭异常
if (dialog_read_ex.isShowing()) {
try {
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
LogUtil.i(TAG, "webCrawler fail");
}).done(exCardList -> {
if (exCardList != null) {
LogUtil.i(TAG, "webCrawler done");
getData().clear(); private static Boolean isMonster(List<String> list) {
addData(exCardList); for (String data : list) {
notifyDataSetChanged(); if (data.equals("怪兽")) {
return true;
} }
if (dialog_read_ex.isShowing()) { }
try { return false;
dialog_read_ex.dismiss();
} catch (Exception ex) {
}
}
});
} }
@Override @Override
protected void convert(BaseViewHolder helper, ExCard item) { protected void convert(BaseViewHolder helper, ExCardData item) {
helper.setText(R.id.ex_card_name, item.getName()); helper.setText(R.id.ex_card_name, item.getName());
helper.setText(R.id.ex_card_description, item.getDescription()); helper.setText(R.id.ex_card_description, item.getDesc());
helper.setText(R.id.ex_card_overall,item.getOverallString());
if (item.isUpdatingLog()) {
helper.setGone(R.id.ex_card_image, true); ImageView imageview = helper.getView(R.id.ex_card_image);
} else { //the function cn.garymb.ygomobile.loader.ImageLoader.bindT(...)
helper.setGone(R.id.ex_card_image, false); //cn.garymb.ygomobile.loader.ImageLoader.setDefaults(...)
ImageView imageview = helper.getView(R.id.ex_card_image); //is a private function,so I copied the content of it to here
//the function cn.garymb.ygomobile.loader.ImageLoader.bindT(...) RequestBuilder<Drawable> resource = GlideCompat.with(imageview.getContext()).load(item.getPicUrl());
//cn.garymb.ygomobile.loader.ImageLoader.setDefaults(...) resource.placeholder(R.drawable.unknown);
//is a private function,so I copied the content of it to here resource.error(R.drawable.unknown);
RequestBuilder<Drawable> resource = GlideCompat.with(imageview.getContext()).load(item.getImageUrl()); resource.into(imageview);
resource.placeholder(R.drawable.unknown);
resource.error(R.drawable.unknown);
resource.into(imageview);
}
} }
} }
...@@ -12,6 +12,9 @@ import java.util.List; ...@@ -12,6 +12,9 @@ import java.util.List;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
/**
* 旧版本用于展示先行卡更新日志的页面,暂不使用。
*/
public class ExCardLogAdapter extends BaseExpandableListAdapter { public class ExCardLogAdapter extends BaseExpandableListAdapter {
public ExCardLogAdapter(Context context) { public ExCardLogAdapter(Context context) {
......
...@@ -26,6 +26,9 @@ import cn.garymb.ygomobile.ui.plus.DialogPlus; ...@@ -26,6 +26,9 @@ import cn.garymb.ygomobile.ui.plus.DialogPlus;
import cn.garymb.ygomobile.ui.plus.VUiKit; import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.LogUtil; import cn.garymb.ygomobile.utils.LogUtil;
/**
* 配合cn.garymb.ygomobile.ex_card.ExCardLogAdapter,实现展示先行卡更新日志的页面,暂不使用。
*/
public class ExCardLogFragment extends Fragment implements View.OnClickListener { public class ExCardLogFragment extends Fragment implements View.OnClickListener {
private static final String TAG = String.valueOf(ExCardLogFragment.class); private static final String TAG = String.valueOf(ExCardLogFragment.class);
private Context mContext; private Context mContext;
...@@ -92,7 +95,7 @@ public class ExCardLogFragment extends Fragment implements View.OnClickListener ...@@ -92,7 +95,7 @@ public class ExCardLogFragment extends Fragment implements View.OnClickListener
} }
}).fail((e) -> { }).fail((e) -> {
//ر쳣 //关闭异常
if (dialog_read_ex.isShowing()) { if (dialog_read_ex.isShowing()) {
try { try {
dialog_read_ex.dismiss(); dialog_read_ex.dismiss();
...@@ -111,7 +114,7 @@ public class ExCardLogFragment extends Fragment implements View.OnClickListener ...@@ -111,7 +114,7 @@ public class ExCardLogFragment extends Fragment implements View.OnClickListener
if (exCardLogList != null) { if (exCardLogList != null) {
LogUtil.i(TAG, "webCrawler parse html complete"); LogUtil.i(TAG, "webCrawler parse html complete");
} }
//ر쳣 //关闭异常
if (dialog_read_ex.isShowing()) { if (dialog_read_ex.isShowing()) {
try { try {
dialog_read_ex.dismiss(); dialog_read_ex.dismiss();
......
...@@ -29,15 +29,17 @@ public class ExPackageTabAdapter extends FragmentStatePagerAdapter { ...@@ -29,15 +29,17 @@ public class ExPackageTabAdapter extends FragmentStatePagerAdapter {
Fragment fragment = null; Fragment fragment = null;
if (position == 0) { if (position == 0) {
fragment = new ExCardListFragment(); fragment = new ExCardListFragment();
} else if (position == 1) {
fragment = new ExCardLogFragment();
} }
/* 目前只显示一个tab,未来可能添加其他tab */
// else if (position == 1) {
// fragment = new ExCardLogFragment();
// }
return fragment; return fragment;
} }
@Override @Override
public int getCount() { public int getCount() {
return 2; return 1;
} }
@Override @Override
...@@ -46,9 +48,10 @@ public class ExPackageTabAdapter extends FragmentStatePagerAdapter { ...@@ -46,9 +48,10 @@ public class ExPackageTabAdapter extends FragmentStatePagerAdapter {
if (position == 0) { if (position == 0) {
title = context.getString(R.string.ex_card_list_title); title = context.getString(R.string.ex_card_list_title);
} else if (position == 1) {
title = context.getString(R.string.ex_card_log_title);
} }
// else if (position == 1) {
// title = context.getString(R.string.ex_card_log_title);
// }
return title; return title;
} }
} }
...@@ -29,6 +29,7 @@ import ocgcore.enums.LimitType; ...@@ -29,6 +29,7 @@ import ocgcore.enums.LimitType;
* 包括LimitManager、CardManager、LimitList * 包括LimitManager、CardManager、LimitList
* LimitList负责判断禁止卡等 * LimitList负责判断禁止卡等
* field包括LimitManager、CardManager * field包括LimitManager、CardManager
* 未封装成单例,使用时要构造实例
*/ */
public class CardLoader implements ICardSearcher { public class CardLoader implements ICardSearcher {
private final LimitManager mLimitManager; private final LimitManager mLimitManager;
......
...@@ -307,7 +307,7 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene ...@@ -307,7 +307,7 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene
} }
/** /**
* 根据同服务器状态设置展示列表中每项的颜色(服务器不可用就设置为灰色) * 根据同服务器状态设置展示列表中每项的颜色(服务器不可用就设置为灰色)
*/ */
private void changeColor() { private void changeColor() {
/* 同步设置服务器列表的状态,在syncLoadData()里更新recyclerview的数据,在更新数据时convert()方法自动更改item的颜色 */ /* 同步设置服务器列表的状态,在syncLoadData()里更新recyclerview的数据,在更新数据时convert()方法自动更改item的颜色 */
...@@ -794,15 +794,10 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene ...@@ -794,15 +794,10 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene
// break; // break;
// } // }
if (ServerUtil.exCardState == ServerUtil.ExCardState.ERROR) { /* 查不到版本号也打开excard安卓原生activity */
WebActivity.open(getContext(), getString(R.string.action_download_expansions), Constants.URL_YGO233_ADVANCE); Intent exCardIntent = new Intent(getActivity(), ExCardActivity.class);
LogUtil.i(TAG, "cannot connect to ex card server, open webactivity"); startActivity(exCardIntent);
} else {
/* using Web crawler to extract the information of pre card */
LogUtil.i(TAG, "connect to ex card http server, open webactivity");
Intent exCardIntent = new Intent(getActivity(), ExCardActivity.class);
startActivity(exCardIntent);
}
break; break;
case R.id.action_help: { case R.id.action_help: {
final DialogPlus dialog = new DialogPlus(getContext()); final DialogPlus dialog = new DialogPlus(getContext());
......
...@@ -22,6 +22,7 @@ public class DownloadUtil { ...@@ -22,6 +22,7 @@ public class DownloadUtil {
private final OkHttpClient okHttpClient; private final OkHttpClient okHttpClient;
public static final int TYPE_DOWNLOAD_EXCEPTION = 1; public static final int TYPE_DOWNLOAD_EXCEPTION = 1;
public static final int TYPE_DOWNLOAD_ING = 2; public static final int TYPE_DOWNLOAD_ING = 2;
public static final int TYPE_DOWNLOAD_OK = 3;
//暂时关闭 //暂时关闭
private static final boolean ENABLE_CACHE = false; private static final boolean ENABLE_CACHE = false;
private static final Map<String, Call> cache = new HashMap<>(); private static final Map<String, Call> cache = new HashMap<>();
...@@ -83,8 +84,8 @@ public class DownloadUtil { ...@@ -83,8 +84,8 @@ public class DownloadUtil {
@Override @Override
public void onResponse(Call call, Response response) throws IOException { public void onResponse(Call call, Response response) throws IOException {
if(!response.isSuccessful()){ if (!response.isSuccessful()) {
listener.onDownloadFailed(new Exception("error:"+response.code())); listener.onDownloadFailed(new Exception("error:" + response.code()));
return; return;
} }
String contentLen = response.header("Content-Length"); String contentLen = response.header("Content-Length");
...@@ -104,10 +105,11 @@ public class DownloadUtil { ...@@ -104,10 +105,11 @@ public class DownloadUtil {
try { try {
is = response.body().byteStream(); is = response.body().byteStream();
long total = response.body().contentLength(); long total = response.body().contentLength();
if(contentLength > 0 && total != contentLength){ if (contentLength > 0 && total != contentLength) {
listener.onDownloadFailed(new Exception("file length[" + total + "] < " + contentLen)); listener.onDownloadFailed(new Exception("file length[" + total + "] < " + contentLen));
} else { } else {
out = new FileOutputStream(file); /* 入参为false时,向file覆盖写入 */
out = new FileOutputStream(file, false);
long sum = 0; long sum = 0;
while ((len = is.read(buf)) != -1) { while ((len = is.read(buf)) != -1) {
out.write(buf, 0, len); out.write(buf, 0, len);
...@@ -126,11 +128,11 @@ public class DownloadUtil { ...@@ -126,11 +128,11 @@ public class DownloadUtil {
IOUtils.close(is); IOUtils.close(is);
} }
if (saved) { if (saved) {
if (contentLength > 0 && file.length() < contentLength) { if (contentLength > 0 && file.length() < contentLength) {
listener.onDownloadFailed(new Exception("file length[" + file.length() + "] < " + contentLen)); listener.onDownloadFailed(new Exception("file length[" + file.length() + "] < " + contentLen));
} else { } else {
listener.onDownloadSuccess(file); listener.onDownloadSuccess(file);
} }
} }
if (ENABLE_CACHE) { if (ENABLE_CACHE) {
synchronized (cache) { synchronized (cache) {
......
...@@ -4,6 +4,7 @@ import android.text.TextUtils; ...@@ -4,6 +4,7 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -197,6 +198,25 @@ public class OkhttpUtil { ...@@ -197,6 +198,25 @@ public class OkhttpUtil {
client.newCall(request.build()).enqueue(callback); client.newCall(request.build()).enqueue(callback);
} }
public static Response synchronousGet(String address, Map<String, Object> map, String cookie) throws IOException {
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder httpBuilder = HttpUrl.parse(address).newBuilder();
if (map != null) {
for (Map.Entry<String, Object> param : map.entrySet()) {
httpBuilder.addQueryParameter(param.getKey(), param.getValue().toString());
}
}
Request.Builder request = new Request.Builder()
.url(httpBuilder.build());
Log.e("OkhttpUtil", "为" + httpBuilder.build());
if (!TextUtils.isEmpty(cookie)) {
request.addHeader("cookie", cookie);
}
return client.newCall(request.build()).execute();
}
public static void del(String address, Map<String, Object> map, String cookie, Callback callback) { public static void del(String address, Map<String, Object> map, String cookie, Callback callback) {
OkHttpClient client = new OkHttpClient(); OkHttpClient client = new OkHttpClient();
...@@ -292,10 +312,18 @@ public class OkhttpUtil { ...@@ -292,10 +312,18 @@ public class OkhttpUtil {
if (!TextUtils.isEmpty(cookie)) { if (!TextUtils.isEmpty(cookie)) {
request.addHeader("cookie", cookie); request.addHeader("cookie", cookie);
} }
Log.e("OkhttpUtil",json+" 状态 "+ request.build()); Log.e("OkhttpUtil", json + " 状态 " + request.build());
okHttpClient.newCall(request.build()).enqueue(callback); okHttpClient.newCall(request.build()).enqueue(callback);
} }
/**
* 将byte[]类型的十六进制数据(不进行解码)转为字符串格式。如,byte[]中存储的值为0xab78,则转换后的字符串的内容为“ab78”,
* byte[]中存储的值为0xb78,则转换后的字符串的内容为“0b78”
* 可用于将byte中的数据不做改变地打印到log中。
*
* @param buf
* @return
*/
public static String parseByte2HexStr(byte[] buf) { public static String parseByte2HexStr(byte[] buf) {
if (null == buf) { if (null == buf) {
return null; return null;
......
...@@ -4,7 +4,7 @@ import static cn.garymb.ygomobile.Constants.ASSET_SERVER_LIST; ...@@ -4,7 +4,7 @@ import static cn.garymb.ygomobile.Constants.ASSET_SERVER_LIST;
import static cn.garymb.ygomobile.Constants.URL_YGO233_DATAVER; import static cn.garymb.ygomobile.Constants.URL_YGO233_DATAVER;
import static cn.garymb.ygomobile.utils.StringUtils.isHost; import static cn.garymb.ygomobile.utils.StringUtils.isHost;
import static cn.garymb.ygomobile.utils.StringUtils.isNumeric; import static cn.garymb.ygomobile.utils.StringUtils.isNumeric;
import static cn.garymb.ygomobile.utils.StringUtils.isValidIP; import static cn.garymb.ygomobile.utils.WebParseUtil.isValidIP;
import android.content.Context; import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -76,8 +76,13 @@ public class ServerUtil { ...@@ -76,8 +76,13 @@ public class ServerUtil {
public void onResponse(Call call, Response response) throws IOException { public void onResponse(Call call, Response response) throws IOException {
failCounter = 0;//充值计数器 failCounter = 0;//充值计数器
String newVer = response.body().string(); String newVer = response.body().string();
/* 服务器有点怪,返回的版本号带个\n,要去掉 */
if (newVer.endsWith("\n")) {
newVer = newVer.substring(0, newVer.length() - 2);
}
serverExCardVersion = newVer; serverExCardVersion = newVer;
LogUtil.i(TAG, "ServerUtil fetch pre-card version:" + newVer); LogUtil.i(TAG, "ServerUtil fetch pre-card version:" + newVer);
if (!TextUtils.isEmpty(newVer)) { if (!TextUtils.isEmpty(newVer)) {
...@@ -164,6 +169,32 @@ public class ServerUtil { ...@@ -164,6 +169,32 @@ public class ServerUtil {
} }
} }
/**
* 读取xmlFile指定的本地文件server_list.xml和apk资源文件(assets)下的serverlist.xml,返回其中版本最新的
*
* @param context
* @param xmlFile 指定的本地文件server_list.xml
* @return
* @throws IOException
*/
private static ServerList mergeServerList(Context context, File xmlFile) throws IOException {
/* 读取apk中assets文件夹下的serverlist.xml文件 */
ServerList assetList = ServerListManager.readList(context.getAssets().open(ASSET_SERVER_LIST));
ServerList fileList = xmlFile.exists() ? ServerListManager.readList(new FileInputStream(xmlFile)) : null;
if (fileList == null) {
return assetList;
}
/* 如果apk下assets中的版本号更大,则返回assets下的server列表 */
if (fileList.getVercode() < assetList.getVercode()) {
xmlFile.delete();
return assetList;
}
return fileList;
}
/** /**
* 从资源文件serverlist.xml(或本地文件server_list.xml)解析服务器列表,并将新添加的服务器信息(name,addr,port)合并到服务器列表中。 * 从资源文件serverlist.xml(或本地文件server_list.xml)解析服务器列表,并将新添加的服务器信息(name,addr,port)合并到服务器列表中。
* *
...@@ -173,26 +204,21 @@ public class ServerUtil { ...@@ -173,26 +204,21 @@ public class ServerUtil {
* @param playerName * @param playerName
*/ */
public static void AddServer(Context context, String name, String Addr, int port, String playerName) { public static void AddServer(Context context, String name, String Addr, int port, String playerName) {
/* 读取本地文件server_list.xml */
File xmlFile = new File(context.getFilesDir(), Constants.SERVER_FILE);//读取文件路径下的server_list.xml File xmlFile = new File(context.getFilesDir(), Constants.SERVER_FILE);//读取文件路径下的server_list.xml
List<ServerInfo> serverInfos = new ArrayList<>();
ServerInfo mServerInfo = new ServerInfo();
mServerInfo.setName(name);
mServerInfo.setServerAddr(Addr);
mServerInfo.setPort(port);
mServerInfo.setPlayerName(playerName);
VUiKit.defer().when(() -> { VUiKit.defer().when(() -> {
/* 读取本地文件server_list.xml和资源文件(assets)下的serverlist.xml,返回其中版本最新的 */ return mergeServerList(context, xmlFile);
ServerList assetList = ServerListManager.readList(context.getAssets().open(ASSET_SERVER_LIST));//读取serverlist.xml文件
ServerList fileList = xmlFile.exists() ? ServerListManager.readList(new FileInputStream(xmlFile)) : null;
if (fileList == null) {
return assetList;
}
if (fileList.getVercode() < assetList.getVercode()) {
xmlFile.delete();
return assetList;
}
return fileList;
}).done((list) -> { }).done((list) -> {
List<ServerInfo> serverInfos = new ArrayList<>();
ServerInfo mServerInfo = new ServerInfo();
mServerInfo.setName(name);
mServerInfo.setServerAddr(Addr);
mServerInfo.setPort(port);
mServerInfo.setPlayerName(playerName);
boolean hasServer = false; boolean hasServer = false;
if (list != null) { if (list != null) {
serverInfos.clear(); serverInfos.clear();
...@@ -205,7 +231,7 @@ public class ServerUtil { ...@@ -205,7 +231,7 @@ public class ServerUtil {
hasServer = false; hasServer = false;
} }
} }
if (!hasServer && !serverInfos.contains(mServerInfo)) { if (!hasServer && !serverInfos.contains(mServerInfo)) {//todo serverInfos.contains(mServerInfo)好像没必要
serverInfos.add(mServerInfo); serverInfos.add(mServerInfo);
} }
} }
...@@ -229,9 +255,7 @@ public class ServerUtil { ...@@ -229,9 +255,7 @@ public class ServerUtil {
} }
public static boolean isPreServer(int port, String addr) { public static boolean isPreServer(int port, String addr) {
return (port == Constants.PORT_YGO233 && addr.equals(Constants.URL_YGO233_1)) || return (port == Constants.PORT_Mycard_Super_Pre_Server && addr.equals(Constants.URL_Mycard_Super_Pre_Server));
(port == Constants.PORT_YGO233 && addr.equals(Constants.URL_YGO233_2));
} }
} }
...@@ -51,8 +51,8 @@ public class SharedPreferenceUtil { ...@@ -51,8 +51,8 @@ public class SharedPreferenceUtil {
return getShareRecord().getInt("StartTimes", 0); return getShareRecord().getInt("StartTimes", 0);
} }
public static void setExpansionDataVer(String json) { public static void setExpansionDataVer(String dataVer) {
getShareRecord().edit().putString("ExpansionsDataVer", json).commit(); getShareRecord().edit().putString("ExpansionsDataVer", dataVer).commit();
} }
public static String getExpansionDataVer() { public static String getExpansionDataVer() {
......
...@@ -3,6 +3,7 @@ package cn.garymb.ygomobile.utils; ...@@ -3,6 +3,7 @@ package cn.garymb.ygomobile.utils;
import android.text.TextUtils; import android.text.TextUtils;
import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -82,28 +83,24 @@ public class StringUtils { ...@@ -82,28 +83,24 @@ public class StringUtils {
return isurl; return isurl;
} }
/** /**
* 检查字符串是否是IPv4 * 使用分隔符,将List<String>合为一个String
*/ */
public static boolean isValidIP(String s) { public static String mergeListDelimeter(List<String> list) {
if (TextUtils.isEmpty(s)) { if (list == null || list.isEmpty()) {
return false; return "";
} }
String[] arr = s.split("\\.");
if (arr.length != 4) { StringBuilder stringBuilder = new StringBuilder();
return false;
} for (int i = 0; i < list.size() - 1; i++) {
for (String value : arr) { stringBuilder.append(list.get(i));
try { stringBuilder.append("|");
int n = Integer.parseInt(value);
if (!(n >= 0 && n <= 255)) {
return false;
}
} catch (NumberFormatException e) {
return false;
}
} }
return true; stringBuilder.append(list.get(list.size() - 1));
return stringBuilder.toString();
} }
} }
...@@ -16,6 +16,7 @@ public class UnzipUtils { ...@@ -16,6 +16,7 @@ public class UnzipUtils {
public static final int ZIP_READY = 600; public static final int ZIP_READY = 600;
public static final int ZIP_UNZIP_OK = 601; public static final int ZIP_UNZIP_OK = 601;
public static final int ZIP_UNZIP_EXCEPTION = 602; public static final int ZIP_UNZIP_EXCEPTION = 602;
/** /**
* 解压缩一个文件 * 解压缩一个文件
* *
...@@ -82,7 +83,7 @@ public class UnzipUtils { ...@@ -82,7 +83,7 @@ public class UnzipUtils {
if (entry.isDirectory()) { if (entry.isDirectory()) {
continue; continue;
} }
if (entry.getName().contains(nameContains)) { if (entry.getName().contains(nameContains)) {//如果zip中包含.ypk格式的文件,则将其放到/storage/emulated/0/Android/data/cn.garymb.ygomobile.CN/files/ygocore目录下
InputStream is = zf.getInputStream(entry); InputStream is = zf.getInputStream(entry);
String str = folderPath + File.separator + entry.getName(); String str = folderPath + File.separator + entry.getName();
str = new String(str.getBytes("8859_1"), StandardCharsets.UTF_8); str = new String(str.getBytes("8859_1"), StandardCharsets.UTF_8);
......
package cn.garymb.ygomobile.utils;
import android.text.TextUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.ex_card.ExCard;
/**
* 用于解析html网页内容的工具类
*/
public class WebParseUtil {
/**
* 检查字符串是否是IPv4
*/
public static boolean isValidIP(String s) {
if (TextUtils.isEmpty(s)) {
return false;
}
String[] arr = s.split("\\.");
if (arr.length != 4) {
return false;
}
for (String value : arr) {
try {
int n = Integer.parseInt(value);
if (!(n >= 0 && n <= 255)) {
return false;
}
} catch (NumberFormatException e) {
return false;
}
}
return true;
}
public static List<ExCard> loadData() throws IOException {
//Connect to the website
Document document = Jsoup.connect(Constants.URL_YGO233_ADVANCE).get();
Element pre_card_content = document.getElementById("pre_release_cards");
Element tbody = pre_card_content.getElementsByTag("tbody").get(0);
Elements cards = tbody.getElementsByTag("tr");
if (cards.size() > 5000) {//Considering the efficiency of html parse, if the size of
// pre cards list is to large, return null directly.
return null;
}
ArrayList<ExCard> exCardList = new ArrayList<>();
for (Element card : cards) {
Elements card_attributes = card.getElementsByTag("td");
String imageUrl = card_attributes.get(0).getElementsByTag("a").attr("href") + "!half";
String name = card_attributes.get(1).text();
String description = card_attributes.get(2).text();
ExCard exCard = new ExCard(name, imageUrl, description, 0);
exCardList.add(exCard);
}
if (exCardList.isEmpty()) {
return null;
} else {
return exCardList;
}
}
}
...@@ -14,18 +14,29 @@ ...@@ -14,18 +14,29 @@
android:padding="5dp" android:padding="5dp"
android:scrollbars="vertical" /> android:scrollbars="vertical" />
<!-- 不知道为啥,android:focusableInTouchMode="true"就导致必须按两次linearylayout才触发点击事件
有帖子说:
一个View的点击事件在第一次点击时无效,第二次点击之后才会响应。
最后发现是因为焦点问题,第一次点击实际上是获取焦点,第二次点击才会响应点击事件。
只要在相关控件属性里面加了两个焦点相关的属性:
android:focusable="true"
android:focusableInTouchMode="false"
版权声明:本文为CSDN博主「qiqiname1989」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qiqiname1989/article/details/82177869-->
<LinearLayout <LinearLayout
android:id="@+id/btn_download_prerelease" android:id="@+id/layout_download_precard"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|right" android:layout_gravity="bottom|right"
android:layout_marginRight="20dp" android:layout_marginRight="30dp"
android:layout_marginBottom="70dp" android:layout_marginBottom="100dp"
android:clickable="true" android:clickable="true"
android:focusableInTouchMode="true" android:focusableInTouchMode="false"
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp"> android:padding="10dp">
<Button <Button
android:id="@+id/btn_download_precard"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:layout_gravity="center" android:layout_gravity="center"
...@@ -34,7 +45,7 @@ ...@@ -34,7 +45,7 @@
android:clickable="false" /> android:clickable="false" />
<TextView <TextView
android:id="@+id/text_download_prerelease" android:id="@+id/text_download_precard"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="30dp" android:layout_height="30dp"
android:background="@drawable/ic_radius_bg" android:background="@drawable/ic_radius_bg"
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sml="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:background="@drawable/list_item_bg" android:background="@drawable/list_item_bg"
android:orientation="horizontal"> android:orientation="horizontal"
android:paddingBottom="10dp">
<!-- set the layout_height in the linear layout to “wrap_content” <!-- set the layout_height in the linear layout to “wrap_content”
so it doesn’t only show one TextView per page.--> so it doesn’t only show one TextView per page.-->
...@@ -14,16 +13,16 @@ ...@@ -14,16 +13,16 @@
android:id="@+id/ex_card_image" android:id="@+id/ex_card_image"
android:layout_width="@dimen/card_width_middle" android:layout_width="@dimen/card_width_middle"
android:layout_height="@dimen/card_height_middle" android:layout_height="@dimen/card_height_middle"
android:padding="10dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingRight="2dp"
android:scaleType="fitXY" android:scaleType="fitXY"
tools:src="@drawable/unknown" /> tools:src="@drawable/unknown" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="10dp" android:orientation="vertical"
android:orientation="vertical"> android:padding="10dp">
<cn.garymb.ygomobile.ui.widget.AlwaysMarqueeTextView <cn.garymb.ygomobile.ui.widget.AlwaysMarqueeTextView
android:id="@+id/ex_card_name" android:id="@+id/ex_card_name"
...@@ -40,12 +39,19 @@ ...@@ -40,12 +39,19 @@
android:textSize="15sp" android:textSize="15sp"
tools:text="Card Name" /> tools:text="Card Name" />
<TextView
android:id="@+id/ex_card_overall"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView <TextView
android:id="@+id/ex_card_description" android:id="@+id/ex_card_description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
\ No newline at end of file
This diff is collapsed.
...@@ -269,6 +269,8 @@ ...@@ -269,6 +269,8 @@
<string name="Checking_Update">检查更新中,请稍候</string> <string name="Checking_Update">检查更新中,请稍候</string>
<string name="Found_Update">发现新版本,前往下载?</string> <string name="Found_Update">发现新版本,前往下载?</string>
<string name="Checking_Update_Failed">检查更新失败</string> <string name="Checking_Update_Failed">检查更新失败</string>
<string name="Download_Precard_Failed">先行卡下载失败</string>
<string name="Pre_Server_Name">萌卡超先行服</string>
<string name="Ask_to_Change_Other_Way">主线获取失败,尝试备选线路中...</string> <string name="Ask_to_Change_Other_Way">主线获取失败,尝试备选线路中...</string>
<string name="DuelAssistant">决斗助手启用中</string> <string name="DuelAssistant">决斗助手启用中</string>
<string name="masterrule">学习大师规则</string> <string name="masterrule">学习大师规则</string>
......
...@@ -266,6 +266,8 @@ ...@@ -266,6 +266,8 @@
<string name="Checking_Update">Now Checking Update</string> <string name="Checking_Update">Now Checking Update</string>
<string name="Found_Update">New upGrade is Founded, Download?</string> <string name="Found_Update">New upGrade is Founded, Download?</string>
<string name="Checking_Update_Failed">Checking Update Failed</string> <string name="Checking_Update_Failed">Checking Update Failed</string>
<string name="Download_Precard_Failed">Download pre-cards failed</string>
<string name="Pre_Server_Name">Mycard Super-pre Server</string>
<string name="Ask_to_Change_Other_Way">trying other way...</string> <string name="Ask_to_Change_Other_Way">trying other way...</string>
<string name="DuelAssistant">DuelAssiatant is On</string> <string name="DuelAssistant">DuelAssiatant is On</string>
<string name="masterrule">Master Rule</string> <string name="masterrule">Master Rule</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment