Commit 649bce0a authored by feihuaduo's avatar feihuaduo

修复多行时卡组码识别的问题

修复主页识别卡组码无法识别卡组名的问题
决斗助手模块化
升级到gradle 7.3
parent fafaae57
...@@ -10,7 +10,7 @@ buildscript { ...@@ -10,7 +10,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.2.0' classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.android.tools.build:gradle-experimental:0.11.1' classpath 'com.android.tools.build:gradle-experimental:0.11.1'
//classpath 'me.tatarka:gradle-retrolambda:3.2.5' //classpath 'me.tatarka:gradle-retrolambda:3.2.5'
} }
......
...@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME ...@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
...@@ -129,4 +129,6 @@ dependencies { ...@@ -129,4 +129,6 @@ dependencies {
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.2.0' implementation 'com.ashokvarma.android:bottom-navigation-bar:2.2.0'
//圆形头像 //圆形头像
implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'de.hdodenhof:circleimageview:2.2.0'
//决斗助手
implementation 'com.github.feihuaduo:YGODuelAssistantLib:1.0'
} }
...@@ -218,16 +218,6 @@ public interface Constants { ...@@ -218,16 +218,6 @@ public interface Constants {
String QUERY_YDK = "ydk"; String QUERY_YDK = "ydk";
String QUERY_NAME = "name"; String QUERY_NAME = "name";
String QUERY_MAIN = "m";
String QUERY_DECK = "d";
String QUERY_EXTRA = "e";
String QUERY_SIDE = "s";
String QUERY_VERSION = "v";
String QUERY_MAIN_ALL = "main";
String QUERY_EXTRA_ALL = "extra";
String QUERY_SIDE_ALL = "side";
String QUERY_YGO_TYPE = "ygotype";
String ARG_DECK = "deck";
String PATH_ROOM = "/room"; String PATH_ROOM = "/room";
String QUERY_HOST = "host"; String QUERY_HOST = "host";
String QUERY_PORT = "port"; String QUERY_PORT = "port";
...@@ -245,48 +235,7 @@ public interface Constants { ...@@ -245,48 +235,7 @@ public interface Constants {
String DEF_ENCODING = "utf-8"; String DEF_ENCODING = "utf-8";
String[] NUM_40_LIST = {
"0"
, "1"
, "2"
, "3"
, "4"
, "5"
, "6"
, "7"
, "8"
, "9"
, "a"
, "b"
, "c"
, "d"
, "e"
, "f"
, "g"
, "h"
, "i"
, "j"
, "k"
, "l"
, "m"
, "n"
, "o"
, "p"
, "q"
, "r"
, "s"
, "t"
, "u"
, "v"
, "w"
, "x"
, "y"
, "z"
, "A"
, "B"
, "C"
, "D"
};
/*23333先行密码与正式密码对照数组 /*23333先行密码与正式密码对照数组
*来源网站:https://ygocdb.com/api/v0/idChangelogArray.jsonp *来源网站:https://ygocdb.com/api/v0/idChangelogArray.jsonp
*/ */
......
...@@ -19,10 +19,11 @@ import android.util.Log; ...@@ -19,10 +19,11 @@ import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import com.ourygo.assistant.util.YGODAUtil; import com.ourygo.lib.duelassistant.util.YGODAUtil;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import cn.garymb.ygodata.YGOGameOptions; import cn.garymb.ygodata.YGOGameOptions;
...@@ -246,13 +247,19 @@ public class GameUriManager { ...@@ -246,13 +247,19 @@ public class GameUriManager {
if (!TextUtils.isEmpty(name)) { if (!TextUtils.isEmpty(name)) {
doOpenPath(name); doOpenPath(name);
} else { } else {
Deck deckInfo = new Deck(uri); YGODAUtil.deDeckListener(uri, (uri1, mainList, exList, sideList, isCompleteDeck, exception) -> {
File file = deckInfo.saveTemp(AppsSettings.get().getDeckDir()); if (!TextUtils.isEmpty(exception)){
if (!deckInfo.isCompleteDeck()) { YGOUtil.show("卡组解析失败,原因为:"+exception);
YGOUtil.show("当前卡组缺少完整信息,将只显示已有卡片"); return;
} }
startSetting.putExtra(Intent.EXTRA_TEXT, file.getAbsolutePath()); Deck deckInfo = new Deck(uri,mainList,exList,sideList);
activity.startActivity(startSetting); File file = deckInfo.saveTemp(AppsSettings.get().getDeckDir());
if (!deckInfo.isCompleteDeck()) {
YGOUtil.show("当前卡组缺少完整信息,将只显示已有卡片");
}
startSetting.putExtra(Intent.EXTRA_TEXT, file.getAbsolutePath());
activity.startActivity(startSetting);
});
} }
} else if (Constants.URI_ROOM.equals(host)) { } else if (Constants.URI_ROOM.equals(host)) {
YGODAUtil.deRoomListener(uri, (host1, port, password, exception) -> { YGODAUtil.deRoomListener(uri, (host1, port, password, exception) -> {
......
package cn.garymb.ygomobile.bean; package cn.garymb.ygomobile.bean;
import static cn.garymb.ygomobile.Constants.ARG_DECK;
import static cn.garymb.ygomobile.Constants.NUM_40_LIST;
import static cn.garymb.ygomobile.Constants.QUERY_DECK;
import static cn.garymb.ygomobile.Constants.QUERY_EXTRA_ALL;
import static cn.garymb.ygomobile.Constants.QUERY_MAIN_ALL;
import static cn.garymb.ygomobile.Constants.QUERY_SIDE_ALL;
import static cn.garymb.ygomobile.Constants.QUERY_VERSION;
import static cn.garymb.ygomobile.Constants.QUERY_YDK;
import static cn.garymb.ygomobile.Constants.QUERY_YGO_TYPE;
import static cn.garymb.ygomobile.Constants.YDK_FILE_EX; import static cn.garymb.ygomobile.Constants.YDK_FILE_EX;
import android.net.Uri; import android.net.Uri;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import com.ourygo.lib.duelassistant.util.YGODAUtil;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import cn.garymb.ygomobile.App;
import cn.garymb.ygomobile.Constants; import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.cards.deck.DeckUtils; import cn.garymb.ygomobile.ui.cards.deck.DeckUtils;
import cn.garymb.ygomobile.utils.FileLogUtil;
import cn.garymb.ygomobile.utils.YGOUtil;
public class Deck implements Parcelable { public class Deck implements Parcelable {
public static final Creator<Deck> CREATOR = new Creator<Deck>() { public static final Creator<Deck> CREATOR = new Creator<Deck>() {
...@@ -41,10 +33,7 @@ public class Deck implements Parcelable { ...@@ -41,10 +33,7 @@ public class Deck implements Parcelable {
return new Deck[size]; return new Deck[size];
} }
}; };
private static final int YGO_DECK_PROTOCOL_0 = 0;
private static final int YGO_DECK_PROTOCOL_1 = 1;
private static final String CARD_DIVIDE_ID = "_";
private static final String CARD_DIVIDE_NUM = "*";
private ArrayList<Integer> allList; private ArrayList<Integer> allList;
private final ArrayList<Integer> mainlist; private final ArrayList<Integer> mainlist;
...@@ -60,162 +49,19 @@ public class Deck implements Parcelable { ...@@ -60,162 +49,19 @@ public class Deck implements Parcelable {
allList = new ArrayList<>(); allList = new ArrayList<>();
} }
public Deck(String name, Uri uri) { public Deck(String name, List<Integer> mainList, List<Integer> exList, List<Integer> sideList) {
this(name); this(name);
int version = YGO_DECK_PROTOCOL_0; this.mainlist.addAll(mainList);
this.extraList.addAll(exList);
try { this.sideList.addAll(sideList);
String ygoType = uri.getQueryParameter(QUERY_YGO_TYPE);
if (ygoType.equals(ARG_DECK)) {
version = Integer.parseInt(uri.getQueryParameter(QUERY_VERSION));
}
} catch (Exception exception) {
version = YGO_DECK_PROTOCOL_0;
}
String main = null, extra = null, side = null;
List<String> mList = new ArrayList<>();
List<String> eList = new ArrayList<>();
List<String> sList = new ArrayList<>();
String[] mains, extras, sides;
switch (version) {
case YGO_DECK_PROTOCOL_0:
main = uri.getQueryParameter(QUERY_MAIN_ALL);
extra = uri.getQueryParameter(QUERY_EXTRA_ALL);
side = uri.getQueryParameter(QUERY_SIDE_ALL);
mains = main.split(CARD_DIVIDE_ID);
mList.addAll(Arrays.asList(mains));
extras = extra.split(CARD_DIVIDE_ID);
eList.addAll(Arrays.asList(extras));
sides = side.split(CARD_DIVIDE_ID);
sList.addAll(Arrays.asList(sides));
for (String m : mList) {
int[] idNum = toIdAndNum(m, version);
if (idNum[0] > 0) {
for (int i = 0; i < idNum[1]; i++) {
mainlist.add(idNum[0]);
}
}
}
for (String m : eList) {
int[] idNum = toIdAndNum(m, version);
if (idNum[0] > 0) {
for (int i = 0; i < idNum[1]; i++) {
extraList.add(idNum[0]);
}
}
}
for (String m : sList) {
int[] idNum = toIdAndNum(m, version);
if (idNum[0] > 0) {
for (int i = 0; i < idNum[1]; i++) {
sideList.add(idNum[0]);
}
}
}
break;
case YGO_DECK_PROTOCOL_1:
String deck = uri.getQueryParameter(QUERY_DECK);
deck = deck.replace("-", "+");
deck = deck.replace("_", "/");
byte[] bytes = Base64.decode(deck, Base64.NO_WRAP);
Log.e("Deck", deck.length() + "字符位数" + bytes.length);
String[] bits = new String[bytes.length * 8];
for (int i = 0; i < bytes.length; i++) {
String b = Integer.toBinaryString(bytes[i]);
b = YGOUtil.toNumLength(b, 8);
if (b.length() > 8)
b = b.substring(b.length() - 8);
if (i < 8)
Log.e("Deck", b + " byte:" + bytes[i]);
for (int x = 0; x < 8; x++)
bits[i * 8 + x] = b.substring(x, x + 1);
}
bits = YGOUtil.toNumLength(bits, 16);
int mNum = Integer.valueOf(YGOUtil.getArrayString(bits, 0, 8), 2);
int eNum = Integer.valueOf(YGOUtil.getArrayString(bits, 8, 12), 2);
int sNum = Integer.valueOf(YGOUtil.getArrayString(bits, 12, 16), 2);
try {
FileLogUtil.write("种类数量" + mNum + " " + eNum + " " + sNum + " ");
FileLogUtil.write("m:" + YGOUtil.getArrayString(bits, 0, 8));
FileLogUtil.write("s:" + YGOUtil.getArrayString(bits, 8, 12));
FileLogUtil.write("e:" + YGOUtil.getArrayString(bits, 12, 16));
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Deck", "种类数量" + mNum + " " + eNum + " " + sNum + " ");
Log.e("Deck", "m:" + YGOUtil.getArrayString(bits, 0, 8));
Log.e("Deck", "e:" + YGOUtil.getArrayString(bits, 8, 12));
Log.e("Deck", "s:" + YGOUtil.getArrayString(bits, 12, 16));
if (bits.length < (16 + (mNum * 29))) {
mNum = (bits.length - 16) / 29;
isCompleteDeck = false;
}
for (int i = 0; i < mNum; i++) {
int cStart = 16 + (i * 29);
int cardNum = Integer.valueOf(YGOUtil.getArrayString(bits, cStart, cStart + 2), 2);
int cardId = Integer.valueOf(YGOUtil.getArrayString(bits, cStart + 2, cStart + 29), 2);
for (int x = 0; x < cardNum; x++) {
mainlist.add(cardId);
}
}
if (!isCompleteDeck)
return;
if (bits.length < (16 + mNum * 29 + (eNum * 29))) {
eNum = (bits.length - 16 - (mNum * 29)) / 29;
isCompleteDeck = false;
}
for (int i = 0; i < eNum; i++) {
int cStart = 16 + mNum * 29 + (i * 29);
int cardNum = Integer.valueOf(YGOUtil.getArrayString(bits, cStart, cStart + 2), 2);
Log.e("DeckSetting", eNum + " 当前 " + i + " " + cStart);
int cardId = Integer.valueOf(YGOUtil.getArrayString(bits, cStart + 2, cStart + 29), 2);
for (int x = 0; x < cardNum; x++) {
extraList.add(cardId);
}
}
if (!isCompleteDeck)
return;
if (bits.length < (16 + mNum * 29 + (eNum * 29) + (sNum * 29))) {
sNum = (bits.length - 16 - (mNum * 29) - (eNum * 29)) / 29;
isCompleteDeck = false;
}
for (int i = 0; i < sNum; i++) {
int cStart = 16 + mNum * 29 + eNum * 29 + (i * 29);
int cardNum = Integer.valueOf(YGOUtil.getArrayString(bits, cStart, cStart + 2), 2);
int cardId = Integer.valueOf(YGOUtil.getArrayString(bits, cStart + 2, cStart + 29), 2);
for (int x = 0; x < cardNum; x++) {
sideList.add(cardId);
}
}
break;
}
} }
public Deck(Uri uri) { public Deck(Uri uri, List<Integer> mainList, List<Integer> exList, List<Integer> sideList) {
this(uri.getQueryParameter(QUERY_YDK), uri); this(TextUtils.isEmpty(uri.getQueryParameter(Constants.QUERY_NAME))
? App.get().getString(R.string.rename_deck) + System.currentTimeMillis()
: uri.getQueryParameter(Constants.QUERY_NAME), mainList, exList, sideList);
} }
public Deck(String name) { public Deck(String name) {
this(); this();
this.name = name; this.name = name;
...@@ -232,224 +78,19 @@ public class Deck implements Parcelable { ...@@ -232,224 +78,19 @@ public class Deck implements Parcelable {
in.readList(this.sideList, Integer.class.getClassLoader()); in.readList(this.sideList, Integer.class.getClassLoader());
} }
private int[] toIdAndNum(String m, int protocol) { public Uri toUri() {
//元素0为卡密,元素1为卡片数量 Map<String,String> map=new HashMap<>();
int[] idNum; map.put(Constants.QUERY_NAME, name);
return YGODAUtil.toUri(mainlist,extraList,sideList,map);
switch (protocol) {
case YGO_DECK_PROTOCOL_0:
idNum = toIdAndNum0(m);
break;
default:
idNum = toIdAndNum0(m);
break;
}
return idNum;
}
public boolean isCompleteDeck() {
return isCompleteDeck;
}
private int[] toIdAndNum0(String m) {
//元素0为卡密,元素1为卡片数量
int[] idNum = {0, 1};
if (m.contains(CARD_DIVIDE_NUM)) {
try {
idNum[1] = Integer.parseInt(m.substring(m.length() - 1));
} catch (Exception e) {
}
idNum[0] = toId(m.substring(0, m.length() - 2), YGO_DECK_PROTOCOL_0);
} else {
idNum[0] = toId(m, YGO_DECK_PROTOCOL_0);
}
return idNum;
}
public Uri toAppUri() {
return toUri(Constants.SCHEME_APP);
}
public Uri toHttpUri() {
return toUri(Constants.SCHEME_HTTP);
}
public Uri toUri(String host) {
Uri.Builder uri = Uri.parse(host + "://")
.buildUpon()
.authority(Constants.URI_HOST);
//.path(Constants.PATH_DECK);
if (!TextUtils.isEmpty(name)) {
uri.appendQueryParameter(Constants.QUERY_NAME, name);
}
uri.appendQueryParameter(QUERY_YGO_TYPE, ARG_DECK);
uri.appendQueryParameter(Constants.QUERY_VERSION, "1");
// if (mainlist.size() != 0)
// deck+=toString(mainlist);
// if (extraList.size() != 0)
// deck+=toString(extraList);
// if (sideList.size() != 0)
// deck+=toString(sideList);
int mNum = getTypeNum(mainlist);
int eNum = getTypeNum(extraList);
int sNum = getTypeNum(sideList);
String deck = toBit(mainlist, extraList, sideList, mNum, eNum, sNum);
String m = Integer.toBinaryString(mNum);
String e = Integer.toBinaryString(eNum);
String s = Integer.toBinaryString(sNum);
m = YGOUtil.toNumLength(m, 8);
e = YGOUtil.toNumLength(e, 4);
s = YGOUtil.toNumLength(s, 4);
Log.e("Deck", "分享数量" + mNum + " " + eNum + " " + sNum);
deck = m + e + s + deck;
byte[] bytes = YGOUtil.toBytes(deck);
String message = Base64.encodeToString(bytes, Base64.NO_WRAP);
Log.e("Deck", message.length() + " 转换时位数 " + bytes.length);
message = message.replace("+", "-");
message = message.replace("/", "_");
message = message.replace("=", "");
Log.e("Deck", "转换后数据" + message);
for (int i = 0; i < 8; i++) {
}
uri.appendQueryParameter(QUERY_DECK, message);
return uri.build();
}
private String toBit(ArrayList<Integer> mainlist, ArrayList<Integer> extraList, ArrayList<Integer> sideList, int mNum, int eNum, int sNum) {
String mains = tobyte(mainlist, mNum);
String extras = tobyte(extraList, eNum);
String sides = tobyte(sideList, sNum);
String message = mains + extras + sides;
return message;
}
public int getTypeNum(List<Integer> list) {
int num = 0;
for (int i = 0; i < list.size(); i++) {
Integer id = list.get(i);
if (id > 0) {
num++;
//如果是最后一张就不用对比下张卡
if (i != list.size() - 1) {
int id1 = list.get(i + 1);
//如果下张是同名卡
if (id1 == id) {
//如果是倒数第二张就不用对比下下张卡
if (i != list.size() - 2) {
id1 = list.get(i + 2);
//如果下下张是同名卡
if (id1 == id) {
i++;
}
}
i++;
}
}
}
}
return num;
}
private String tobyte(List<Integer> ids, int typeNum) {
String bytes = "";
for (int i = 0; i < ids.size(); i++) {
Integer id = ids.get(i);
if (id > 0) {
//转换为29位二进制码
String idB = toB(id);
//如果是最后一张就不用对比下张卡
if (i != ids.size() - 1) {
int id1 = ids.get(i + 1);
//同名卡张数
int tNum = 1;
//如果下张是同名卡
if (id1 == id) {
tNum++;
//如果是倒数第二张就不用对比下下张卡
if (i != ids.size() - 2) {
id1 = ids.get(i + 2);
//如果下下张是同名卡
if (id1 == id) {
tNum++;
i++;
}
}
i++;
}
tNum = Math.min(3, tNum);
switch (tNum) {
case 1:
idB = "01" + idB;
break;
case 2:
idB = "10" + idB;
break;
case 3:
idB = "11" + idB;
break;
}
} else {
idB = "01" + idB;
}
bytes += idB;
}
}
return bytes;
}
private String toB(int id) {
return YGOUtil.toNumLength(Integer.toBinaryString(id), 27);
}
//压缩卡密,目前直接转换为40进制
private String compressedId(int id) {
StringBuilder compressedId1 = new StringBuilder();
while (id > 40) {
compressedId1.insert(0, NUM_40_LIST[id % 40]);
id /= 40;
}
compressedId1.insert(0, NUM_40_LIST[id]);
if (compressedId1.length() < 5)
for (int i = compressedId1.length(); i < 5; i++)
compressedId1.insert(0, "0");
return compressedId1.toString();
} }
public void setCompleteDeck(boolean completeDeck) {
private int getCardIdUnCompressedId(String compressedNum) { isCompleteDeck = completeDeck;
for (int i = 0; i < NUM_40_LIST.length; i++) {
if (compressedNum.equals(NUM_40_LIST[i]))
return i;
}
return 0;
} }
//解析卡密,目前直接16进制转换为10进制 public boolean isCompleteDeck() {
private int unId(String id) { return isCompleteDeck;
int num = 0;
id = id.trim();
String[] sList = new String[id.length()];
for (int i = 0; i < id.length(); i++) {
sList[i] = id.charAt(i) + "";
}
for (int i = sList.length - 1; i >= 0; i--)
num += (getCardIdUnCompressedId(sList[i]) * Math.pow(40, sList.length - 1 - i));
// Log.e("DeckUU",(getCardIdUnCompressedId(sList[0]) * Math.pow(40, sList.length-1)+" "+sList.length+" num"+num));
return num;
} }
public String getName() { public String getName() {
return name; return name;
} }
...@@ -482,22 +123,7 @@ public class Deck implements Parcelable { ...@@ -482,22 +123,7 @@ public class Deck implements Parcelable {
return file; return file;
} }
private int toId(String str, int version) {
if (TextUtils.isEmpty(str)) return 0;
try {
switch (version) {
case YGO_DECK_PROTOCOL_0:
return Integer.parseInt(str);
case YGO_DECK_PROTOCOL_1:
//如果需要返回40进制码:
return unId(str);
default:
return Integer.parseInt(str);
}
} catch (Exception e) {
return 0;
}
}
public List<Integer> getSideList() { public List<Integer> getSideList() {
return sideList; return sideList;
......
...@@ -28,7 +28,7 @@ import com.app.hubert.guide.NewbieGuide; ...@@ -28,7 +28,7 @@ import com.app.hubert.guide.NewbieGuide;
import com.app.hubert.guide.model.GuidePage; import com.app.hubert.guide.model.GuidePage;
import com.app.hubert.guide.model.HighLight; import com.app.hubert.guide.model.HighLight;
import com.app.hubert.guide.model.HighlightOptions; import com.app.hubert.guide.model.HighlightOptions;
import com.ourygo.assistant.util.DuelAssistantManagement; import com.ourygo.lib.duelassistant.util.DuelAssistantManagement;
import java.util.List; import java.util.List;
......
...@@ -55,7 +55,7 @@ import com.feihua.dialogutils.util.DialogUtils; ...@@ -55,7 +55,7 @@ import com.feihua.dialogutils.util.DialogUtils;
import com.nightonke.boommenu.BoomButtons.BoomButton; import com.nightonke.boommenu.BoomButtons.BoomButton;
import com.nightonke.boommenu.BoomButtons.TextOutsideCircleButton; import com.nightonke.boommenu.BoomButtons.TextOutsideCircleButton;
import com.nightonke.boommenu.BoomMenuButton; import com.nightonke.boommenu.BoomMenuButton;
import com.ourygo.assistant.util.DuelAssistantManagement; import com.ourygo.lib.duelassistant.util.DuelAssistantManagement;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
...@@ -920,7 +920,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte ...@@ -920,7 +920,7 @@ public class DeckManagerFragment extends BaseFragemnt implements RecyclerViewIte
Button bt_image_share = viewDialog.findViewById(R.id.bt_image_share); Button bt_image_share = viewDialog.findViewById(R.id.bt_image_share);
Button bt_code_share = viewDialog.findViewById(R.id.bt_code_share); Button bt_code_share = viewDialog.findViewById(R.id.bt_code_share);
TextView tv_code = viewDialog.findViewById(R.id.et_code); TextView tv_code = viewDialog.findViewById(R.id.et_code);
tv_code.setText(deck.toAppUri().toString()); tv_code.setText(deck.toUri().toString());
ImageUtil.show(getContext(), savePath, iv_image, System.currentTimeMillis() + ""); ImageUtil.show(getContext(), savePath, iv_image, System.currentTimeMillis() + "");
bt_code_share.setOnClickListener(v -> { bt_code_share.setOnClickListener(v -> {
......
...@@ -33,9 +33,10 @@ import androidx.cardview.widget.CardView; ...@@ -33,9 +33,10 @@ import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.ourygo.assistant.base.listener.OnDuelAssistantListener;
import com.ourygo.assistant.util.DuelAssistantManagement; import com.ourygo.lib.duelassistant.listener.OnDuelAssistantListener;
import com.ourygo.assistant.util.Util; import com.ourygo.lib.duelassistant.util.DuelAssistantManagement;
import com.ourygo.lib.duelassistant.util.Util;
import com.stx.xhb.androidx.XBanner; import com.stx.xhb.androidx.XBanner;
import com.tubb.smrv.SwipeMenuRecyclerView; import com.tubb.smrv.SwipeMenuRecyclerView;
...@@ -66,7 +67,6 @@ import cn.garymb.ygomobile.ui.activities.WebActivity; ...@@ -66,7 +67,6 @@ import cn.garymb.ygomobile.ui.activities.WebActivity;
import cn.garymb.ygomobile.ui.adapters.ServerListAdapter; import cn.garymb.ygomobile.ui.adapters.ServerListAdapter;
import cn.garymb.ygomobile.ui.adapters.SimpleListAdapter; import cn.garymb.ygomobile.ui.adapters.SimpleListAdapter;
import cn.garymb.ygomobile.ui.cards.CardDetailRandom; import cn.garymb.ygomobile.ui.cards.CardDetailRandom;
import cn.garymb.ygomobile.ui.cards.deck.DeckUtils;
import cn.garymb.ygomobile.ui.mycard.McNews; import cn.garymb.ygomobile.ui.mycard.McNews;
import cn.garymb.ygomobile.ui.mycard.MyCard; import cn.garymb.ygomobile.ui.mycard.MyCard;
import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil; import cn.garymb.ygomobile.ui.mycard.mcchat.util.ImageUtil;
...@@ -511,7 +511,7 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene ...@@ -511,7 +511,7 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene
} }
@Override @Override
public void onCardSearch(String key, int id) { public void onCardQuery(String key, int id) {
/* /*
if (id == ID_HOMEFRAGMENT) { if (id == ID_HOMEFRAGMENT) {
Intent intent = new Intent(this, CardSearchFragment.class); Intent intent = new Intent(this, CardSearchFragment.class);
...@@ -521,11 +521,15 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene ...@@ -521,11 +521,15 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene
} }
@Override @Override
public void onSaveDeck(String message, boolean isUrl, int id) { public void onSaveDeck(Uri uri, List<Integer> mainList, List<Integer> exList, List<Integer> sideList, boolean isCompleteDeck, String exception, int id) {
saveDeck(message, isUrl); saveDeck(uri,mainList,exList,sideList,isCompleteDeck,exception);
} }
public void saveDeck(String deckMessage, boolean isUrl) { public void saveDeck(Uri uri, List<Integer> mainList, List<Integer> exList, List<Integer> sideList, boolean isCompleteDeck, String exception) {
if (!TextUtils.isEmpty(exception)){
YGOUtil.show("卡组解析失败,原因为:"+exception);
return;
}
DialogPlus dialog = new DialogPlus(getContext()); DialogPlus dialog = new DialogPlus(getContext());
dialog.setTitle(R.string.question); dialog.setTitle(R.string.question);
dialog.setMessage(R.string.find_deck_text); dialog.setMessage(R.string.find_deck_text);
...@@ -538,33 +542,23 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene ...@@ -538,33 +542,23 @@ public class HomeFragment extends BaseFragemnt implements OnDuelAssistantListene
}); });
dialog.setRightButtonListener((dlg, s) -> { dialog.setRightButtonListener((dlg, s) -> {
dialog.dismiss(); dialog.dismiss();
Deck deckInfo;
//如果是卡组url //如果是卡组url
if (isUrl) { if (uri != null) {
Deck deckInfo = new Deck(getString(R.string.rename_deck) + System.currentTimeMillis(), Uri.parse(deckMessage)); deckInfo = new Deck(uri, mainList, exList, sideList);
File file = deckInfo.saveTemp(AppsSettings.get().getDeckDir());
if (!deckInfo.isCompleteDeck()) {
YGOUtil.show("当前卡组缺少完整信息,将只显示已有卡片");
}
if (!file.getAbsolutePath().isEmpty()) {
mBundle.putString("setDeck", file.getAbsolutePath());
activity.fragment_deck_cards.setArguments(mBundle);
}
activity.switchFragment(activity.fragment_deck_cards, 2, true);
} else { } else {
//如果是卡组文本 deckInfo = new Deck(getString(R.string.rename_deck) + System.currentTimeMillis(), mainList, exList, sideList);
try { }
//以当前时间戳作为卡组名保存卡组 deckInfo.setCompleteDeck(isCompleteDeck);
File file = DeckUtils.save(getString(R.string.rename_deck) + System.currentTimeMillis(), deckMessage); File file = deckInfo.saveTemp(AppsSettings.get().getDeckDir());
if (!file.getAbsolutePath().isEmpty()) { if (!deckInfo.isCompleteDeck()) {
mBundle.putString("setDeck", file.getAbsolutePath()); YGOUtil.show("当前卡组缺少完整信息,将只显示已有卡片");
activity.fragment_deck_cards.setArguments(mBundle); }
} if (!file.getAbsolutePath().isEmpty()) {
activity.switchFragment(activity.fragment_deck_cards, 2, true); mBundle.putString("setDeck", file.getAbsolutePath());
} catch (IOException e) { activity.fragment_deck_cards.setArguments(mBundle);
e.printStackTrace();
Toast.makeText(getContext(), getString(R.string.save_failed_bcos) + e, Toast.LENGTH_SHORT).show();
}
} }
activity.switchFragment(activity.fragment_deck_cards, 2, true);
}); });
} }
......
...@@ -2,9 +2,6 @@ package cn.garymb.ygomobile.ui.mycard; ...@@ -2,9 +2,6 @@ package cn.garymb.ygomobile.ui.mycard;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static cn.garymb.ygomobile.Constants.ARG_DECK;
import static cn.garymb.ygomobile.Constants.QUERY_YGO_TYPE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
......
...@@ -26,7 +26,7 @@ import android.widget.Toast; ...@@ -26,7 +26,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.ourygo.assistant.util.Util; import com.ourygo.lib.duelassistant.util.Util;
import com.tencent.smtt.sdk.ValueCallback; import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebChromeClient; import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings; import com.tencent.smtt.sdk.WebSettings;
......
...@@ -14,7 +14,8 @@ import androidx.annotation.Nullable; ...@@ -14,7 +14,8 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.ourygo.assistant.util.Util;
import com.ourygo.lib.duelassistant.util.Util;
import cn.garymb.ygomobile.base.BaseFragemnt; import cn.garymb.ygomobile.base.BaseFragemnt;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
......
...@@ -18,7 +18,7 @@ import com.bumptech.glide.request.RequestOptions; ...@@ -18,7 +18,7 @@ import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey; import com.bumptech.glide.signature.ObjectKey;
import com.ourygo.assistant.util.Util; import com.ourygo.lib.duelassistant.util.Util;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.utils.PaletteUtil; import cn.garymb.ygomobile.utils.PaletteUtil;
......
...@@ -96,7 +96,7 @@ public class YGODialogUtil { ...@@ -96,7 +96,7 @@ public class YGODialogUtil {
public ViewHolder(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) { public ViewHolder(Context context, String selectDeckPath, OnDeckMenuListener onDeckMenuListener) {
DialogUtils du = DialogUtils.getdx(context); DialogUtils du = DialogUtils.getdx(context);
View viewDialog = du.dialogBottomSheet(R.layout.dialog_deck_select, false); View viewDialog = du.dialogBottomSheet(R.layout.dialog_deck_select, true);
RecyclerView rv_type, rv_deck; RecyclerView rv_type, rv_deck;
rv_deck = viewDialog.findViewById(R.id.rv_deck); rv_deck = viewDialog.findViewById(R.id.rv_deck);
...@@ -380,7 +380,7 @@ public class YGODialogUtil { ...@@ -380,7 +380,7 @@ public class YGODialogUtil {
deckAdp.notifyDataSetChanged(); deckAdp.notifyDataSetChanged();
} }
})); }));
itemTouchHelper.attachToRecyclerView(rv_type); // itemTouchHelper.attachToRecyclerView(rv_type);
} }
private String[] getStringType(List<DeckType> deckTypeList) { private String[] getStringType(List<DeckType> deckTypeList) {
......
...@@ -15,8 +15,8 @@ import androidx.core.content.ContextCompat; ...@@ -15,8 +15,8 @@ import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.ourygo.assistant.util.PermissionUtil; import com.ourygo.lib.duelassistant.util.PermissionUtil;
import com.ourygo.assistant.util.Util; import com.ourygo.lib.duelassistant.util.Util;
import cn.garymb.ygomobile.App; import cn.garymb.ygomobile.App;
import cn.garymb.ygomobile.lite.R; import cn.garymb.ygomobile.lite.R;
...@@ -37,51 +37,6 @@ public class YGOUtil { ...@@ -37,51 +37,6 @@ public class YGOUtil {
return App.get().getResources().getString(stringId); return App.get().getResources().getString(stringId);
} }
public static byte[] toBytes(String bits) {
int y = bits.length() % 8;
Log.e("Deck",bits.length()+"之前余数"+y);
if (y != 0)
bits = toNumLengthLast(bits, bits.length()+8 - y);
Log.e("Deck",bits.length()+"余数"+y);
byte[] bytes=new byte[bits.length()/8];
for (int i=0;i<bits.length()/8;i++) {
bytes[i] = (byte) Integer.valueOf(bits.substring(i * 8, i * 8 + 8), 2).intValue();
if (i<8){
Log.e("Deck",bits.substring(i*8,i*8+8)+" 字节 "+bytes[i] );
}
}
Log.e("Deck","二进制"+bits );
return bytes;
}
public static String toNumLength(String message, int num) {
while (message.length() < num) {
message = "0" + message;
}
return message;
}
public static String toNumLengthLast(String message, int num) {
while (message.length() < num) {
message +="0";
}
return message;
}
public static String[] toNumLength(String[] nums, int num) {
if (nums.length < num) {
String[] bms = nums;
nums = new String[num];
for (int i = 0; i < num - bms.length; i++)
nums[i] = "0";
for (int i = 0; i < bms.length; i++)
nums[i + num - bms.length] = bms[i];
}
return nums;
}
/** /**
* 根据卡密获取高清图下载地址 * 根据卡密获取高清图下载地址
* *
...@@ -92,15 +47,6 @@ public class YGOUtil { ...@@ -92,15 +47,6 @@ public class YGOUtil {
return "https://cdn02.moecube.com:444/ygomobile-images/" + code + ".png"; return "https://cdn02.moecube.com:444/ygomobile-images/" + code + ".png";
} }
public static String getArrayString(String[] bytes, int start, int end) {
String message = "";
for (int i = start; i < end; i++) {
message += bytes[i];
}
return message;
}
//关闭输入法 //关闭输入法
public static void closeKeyboard(Activity activity) { public static void closeKeyboard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
......
package com.ourygo.assistant.base.listener;
public interface OnClipChangedListener {
void onClipChanged(String clipMessge,boolean isCheck,int id);
}
package com.ourygo.assistant.base.listener;
/**
* Create By feihua On 2021/9/29
*/
public interface OnDeRoomListener {
void onDeRoom(String host,int port,String password,String exception);
}
package com.ourygo.assistant.base.listener;
public interface OnDuelAssistantListener {
void onJoinRoom(String host,int port,String password,int id);
void onCardSearch(String key,int id);
void onSaveDeck(String message,boolean isUrl,int id);
boolean isListenerEffective();
}
\ No newline at end of file
package com.ourygo.assistant.service;
import static cn.garymb.ygomobile.Constants.ASSET_SERVER_LIST;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import com.ourygo.assistant.base.listener.OnDuelAssistantListener;
import com.ourygo.assistant.util.ClipManagement;
import com.ourygo.assistant.util.DuelAssistantManagement;
import com.ourygo.assistant.util.PermissionUtil;
import com.ourygo.assistant.util.Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import cn.garymb.ygomobile.AppsSettings;
import cn.garymb.ygomobile.Constants;
import cn.garymb.ygomobile.bean.Deck;
import cn.garymb.ygomobile.bean.ServerInfo;
import cn.garymb.ygomobile.bean.ServerList;
import cn.garymb.ygomobile.lite.R;
import cn.garymb.ygomobile.ui.adapters.ServerListAdapter;
import cn.garymb.ygomobile.ui.cards.CardSearchFragment;
import cn.garymb.ygomobile.ui.cards.DeckManagerFragment;
import cn.garymb.ygomobile.ui.cards.deck.DeckUtils;
import cn.garymb.ygomobile.ui.home.MainActivity;
import cn.garymb.ygomobile.ui.home.ServerListManager;
import cn.garymb.ygomobile.ui.plus.VUiKit;
import cn.garymb.ygomobile.utils.YGOUtil;
public class DuelAssistantService extends Service implements OnDuelAssistantListener {
private static final String TAG = "DuelAssistantService";
private static final String CHANNEL_ID = "YGOMobile";
private static final String CHANNEL_NAME = "Duel_Assistant";
private static final String DUEL_ASSISTANT_SERVICE_ACTION = "YGOMOBILE:ACTION_DUEL_ASSISTANT_SERVICE";
private static final String CMD_NAME = "CMD";
private static final String CMD_START_GAME = "CMD : START GAME";
private static final String CMD_STOP_SERVICE = "CMD : STOP SERVICE";
//卡组url前缀
private static final String DECK_URL_PREFIX = Constants.SCHEME_APP + "://" + Constants.URI_HOST;
//悬浮窗显示的时间
private static final int TIME_DIS_WINDOW = 3000;
public static String DeckText = "";
//悬浮窗布局View
private View mFloatLayout;
private TextView tv_message;
private Button bt_join, bt_close;
//是否可以移除悬浮窗上面的视图
private boolean isDis = false;
private WindowManager.LayoutParams wmParams;
private WindowManager mWindowManager;
private OnDuelAssistantListener onDuelAssistantListener;
private DuelAssistantManagement duelAssistantManagement;
//决斗跳转
@Override
public IBinder onBind(Intent p1) {
// TODO: Implement this method
return null;
}
@Override
public void onCreate() {
// TODO: Implement this method
super.onCreate();
//开启服务
startForeground();
//初始化加房布局
createFloatView();
duelAssistantManagement = DuelAssistantManagement.getInstance();
duelAssistantManagement.addDuelAssistantListener(this);
}
@Override
public void onDestroy() {
super.onDestroy();
duelAssistantManagement.removeDuelAssistantListener(this);
//关闭悬浮窗时的声明
stopForeground(true);
}
private void startForeground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (PermissionUtil.isNotificationListenerEnabled(this)) {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_view_duel_assistant);
Intent intent = new Intent(this, this.getClass());
intent.setAction(DUEL_ASSISTANT_SERVICE_ACTION);
PendingIntent pendingIntent;
intent.putExtra(CMD_NAME, CMD_START_GAME);
pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.notification_view_duel_assistant, pendingIntent);
intent.putExtra(CMD_NAME, CMD_STOP_SERVICE);
pendingIntent = PendingIntent.getService(this, 2, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.buttonStopService, pendingIntent);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT);
channel.setSound(null, null);
channel.enableLights(false);
channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null)
manager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_icon);
builder.setCustomContentView(remoteViews);
startForeground(1, builder.build());
} else {
//如果没有通知权限则关闭服务
stopForeground(true);
stopService(new Intent(DuelAssistantService.this, DuelAssistantService.class));
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null)
return super.onStartCommand(intent, flags, startId);
String action = intent.getAction();
Log.d(TAG, "rev action:" + action);
if (DUEL_ASSISTANT_SERVICE_ACTION.equals(action)) {
String cmd = intent.getStringExtra(CMD_NAME);
Log.d(TAG, "rev cmd:" + cmd);
if (null == cmd) {
Log.e(TAG, "cmd null");
} else {
switch (cmd) {
case CMD_STOP_SERVICE:
stopSelf();
break;
case CMD_START_GAME:
Intent intent2 = new Intent(DuelAssistantService.this, MainActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent2);
break;
default:
Log.e(TAG, "unknown cmd:" + cmd);
break;
}
collapseStatusBar();
}
}
return super.onStartCommand(intent, flags, startId);
}
private void collapseStatusBar() {
try {
@SuppressLint("WrongConstant") Object statusBarManager = getSystemService("statusbar");
if (null == statusBarManager) {
return;
}
Class<?> clazz = statusBarManager.getClass();
Method methodCollapse;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
methodCollapse = clazz.getMethod("collapse");
} else {
methodCollapse = clazz.getMethod("collapsePanels");
}
methodCollapse.invoke(statusBarManager);
} catch (Exception e) {
e.printStackTrace();
}
}
private void saveDeck(String deckMessage, boolean isUrl) {
tv_message.setText(R.string.find_deck_text);
bt_close.setText(R.string.search_close);
bt_join.setText(R.string.save_n_open);
disJoinDialog();
showJoinDialog();
new Handler().postDelayed(() -> {
if (isDis) {
isDis = false;
mWindowManager.removeView(mFloatLayout);
}
}, TIME_DIS_WINDOW);
bt_close.setOnClickListener(v -> disJoinDialog());
bt_join.setOnClickListener(v -> {
disJoinDialog();
Intent startSetting = new Intent(getBaseContext(), MainActivity.class);
//如果是卡组url
if (isUrl) {
Deck deckInfo = new Deck(getString(R.string.rename_deck) + System.currentTimeMillis(), Uri.parse(deckMessage));
File file = deckInfo.saveTemp(AppsSettings.get().getDeckDir());
if (!deckInfo.isCompleteDeck()){
YGOUtil.show("当前卡组缺少完整信息,将只显示已有卡片");
}
startSetting.putExtra("flag", 2);
startSetting.putExtra(Intent.EXTRA_TEXT, file.getAbsolutePath());
} else {
//如果是卡组文本
try {
//以当前时间戳作为卡组名保存卡组
File file = DeckUtils.save(getString(R.string.rename_deck) + System.currentTimeMillis(), deckMessage);
startSetting.putExtra("flag", 2);
startSetting.putExtra(Intent.EXTRA_TEXT, file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(DuelAssistantService.this, getString(R.string.save_failed_bcos) + e, Toast.LENGTH_SHORT).show();
}
}
});
}
private void joinRoom(String host, int port, String password) {
String message;
if (!TextUtils.isEmpty(host))
message = getString(R.string.quick_join)
+ "\nIP:" + host
+ "\n端口:" + port
+ "\n密码:" + password;
else
message = getString(R.string.quick_join) + "\"" + password + "\"";
tv_message.setText(message);
bt_join.setText(R.string.join);
bt_close.setText(R.string.search_close);
disJoinDialog();
showJoinDialog();
new Handler().postDelayed(() -> {
if (isDis) {
isDis = false;
mWindowManager.removeView(mFloatLayout);
}
}, TIME_DIS_WINDOW);
bt_close.setOnClickListener(p1 -> disJoinDialog());
bt_join.setOnClickListener(p1 -> {
if (isDis) {
isDis = false;
mWindowManager.removeView(mFloatLayout);
}
ServerListAdapter mServerListAdapter = new ServerListAdapter(DuelAssistantService.this);
ServerListManager mServerListManager = new ServerListManager(DuelAssistantService.this, mServerListAdapter);
mServerListManager.syncLoadData();
File xmlFile = new File(getFilesDir(), Constants.SERVER_FILE);
VUiKit.defer().when(() -> {
ServerList assetList = ServerListManager.readList(DuelAssistantService.this.getAssets().open(ASSET_SERVER_LIST));
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) -> {
if (list != null) {
String host1=host;
int port1=port;
ServerInfo serverInfo = list.getServerInfoList().get(0);
if (TextUtils.isEmpty(host1)){
host1=serverInfo.getServerAddr();
port1=serverInfo.getPort();
}
Util.duelIntent(DuelAssistantService.this, host1, port1, serverInfo.getPlayerName(), password);
}
});
});
}
private void disJoinDialog() {
if (isDis) {
isDis = false;
mWindowManager.removeView(mFloatLayout);
}
}
private void showJoinDialog() {
if (!isDis) {
mWindowManager.addView(mFloatLayout, wmParams);
isDis = true;
}
}
private void createFloatView() {
wmParams = new WindowManager.LayoutParams();
//获取的是WindowManagerImpl.CompatModeWrapper
mWindowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);
//设置window type
wmParams.type = android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
//设置背景透明
wmParams.format = PixelFormat.TRANSLUCENT;
//设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
//实现悬浮窗到状态栏
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//安卓7.0要求
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
//安卓8.0要求
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
//调整悬浮窗显示的停靠位置为左侧置顶
wmParams.gravity = Gravity.START | Gravity.TOP;
// 以屏幕左上角为原点,设置x、y初始值,相对于gravity
wmParams.x = 0;
wmParams.y = 0;
//设置悬浮窗口长宽数据
wmParams.width = WindowManager.LayoutParams.MATCH_PARENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
//获取浮动窗口视图所在布局
mFloatLayout = LayoutInflater.from(this).inflate(R.layout.duel_assistant_service, null);
//添加mFloatLayout
bt_join = mFloatLayout.findViewById(R.id.bt_join);
tv_message = mFloatLayout.findViewById(R.id.tv_message);
bt_close = mFloatLayout.findViewById(R.id.bt_close);
}
@Override
public void onJoinRoom(String host, int port, String password, int id) {
if (id == ClipManagement.ID_CLIP_LISTENER) {
//如果有悬浮窗权限再显示
if (PermissionUtil.isServicePermission(this)) {
joinRoom(host, port, password);
}
}
}
@Override
public void onCardSearch(String key, int id) {
if (id == ClipManagement.ID_CLIP_LISTENER) {
Intent intent = new Intent(DuelAssistantService.this, CardSearchFragment.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(CardSearchFragment.SEARCH_MESSAGE, key);
startActivity(intent);
}
}
@Override
public void onSaveDeck(String message, boolean isUrl, int id) {
if (id == ClipManagement.ID_CLIP_LISTENER) {
saveDeck(message, isUrl);
}
}
@Override
public boolean isListenerEffective() {
return Util.isContextExisted(this);
}
}
package com.ourygo.assistant.util;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.text.TextUtils;
import com.ourygo.assistant.base.listener.OnClipChangedListener;
import java.io.IOException;
import cn.garymb.ygomobile.utils.FileLogUtil;
public class ClipManagement implements ClipboardManager.OnPrimaryClipChangedListener {
public static final int ID_CLIP_LISTENER = -1;
private static final ClipManagement ourInstance = new ClipManagement();
private ClipboardManager clipboardManager;
private OnClipChangedListener onClipChangedListener;
private ClipManagement() {
}
public static ClipManagement getInstance() {
return ourInstance;
}
public void setOnClipChangedListener(OnClipChangedListener onClipChangedListener) {
this.onClipChangedListener = onClipChangedListener;
}
public void startClipboardListener(Context context) {
if (clipboardManager == null)
clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboardManager == null)
return;
clipboardManager.addPrimaryClipChangedListener(this);
}
public void removeClipboardListener() {
if (clipboardManager == null)
return;
clipboardManager.removePrimaryClipChangedListener(this);
}
//获取剪贴板内容
public String getClipMessage() {
ClipData clipData = clipboardManager.getPrimaryClip();
if (clipData == null) {
try {
FileLogUtil.writeAndTime("剪贴板为空");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
CharSequence charSequence = clipData.getItemAt(0).getText();
if (charSequence != null)
return charSequence.toString();
return null;
}
public void clear() {
removeClipboardListener();
onClipChangedListener = null;
}
@Override
public void onPrimaryClipChanged() {
final String clipMessage = getClipMessage();
//如果复制的内容为空则不执行下面的代码
if (TextUtils.isEmpty(clipMessage)) {
return;
}
// if (onClipChangedListener != null)
// onClipChangedListener.onClipChanged(clipMessage, false, ID_CLIP_LISTENER);
}
public void onPrimaryClipChanged(boolean isCheck, int id) {
final String clipMessage = getClipMessage();
//如果复制的内容为空则不执行下面的代码
if (TextUtils.isEmpty(clipMessage)) {
return;
}
if (onClipChangedListener != null)
onClipChangedListener.onClipChanged(clipMessage, isCheck, id);
}
}
package com.ourygo.assistant.util;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import com.ourygo.assistant.base.listener.OnClipChangedListener;
import com.ourygo.assistant.base.listener.OnDuelAssistantListener;
import java.util.ArrayList;
import java.util.List;
public class DuelAssistantManagement implements OnClipChangedListener {
private static final DuelAssistantManagement ourInstance = new DuelAssistantManagement();
private Context context;
private List<OnDuelAssistantListener> onDuelAssistantListenerList;
private ClipManagement clipManagement;
//卡查内容
private String cardSearchMessage = "";
private String lastMessage = "";
private DuelAssistantManagement() {
onDuelAssistantListenerList = new ArrayList<>();
}
public static DuelAssistantManagement getInstance() {
return ourInstance;
}
public void init(Context context) {
this.context = context;
//初始化剪贴板监听
initClipListener();
}
public void addDuelAssistantListener(OnDuelAssistantListener onDuelAssistantListener) {
if (!onDuelAssistantListenerList.contains(onDuelAssistantListener))
onDuelAssistantListenerList.add(onDuelAssistantListener);
}
public void removeDuelAssistantListener(OnDuelAssistantListener onDuelAssistantListener) {
onDuelAssistantListenerList.remove(onDuelAssistantListener);
}
public List<OnDuelAssistantListener> getOnDuelAssistantListenerList() {
return onDuelAssistantListenerList;
}
private void initClipListener() {
clipManagement = ClipManagement.getInstance();
clipManagement.startClipboardListener(context);
clipManagement.setOnClipChangedListener(this);
}
public void clear() {
context = null;
lastMessage = "";
cardSearchMessage = "";
onDuelAssistantListenerList.clear();
}
public String getCardSearchMessage() {
return cardSearchMessage;
}
public boolean deckCheck(String message, int id) {
//如果复制的内容是多行作为卡组去判断
if (message.contains("\n")) {
for (String s : Record.DeckTextKey) {
//只要包含其中一个关键字就视为卡组
if (message.contains(s)) {
onSaveDeck(message, false, id);
return true;
}
}
}
//如果是卡组url
int deckStart = message.indexOf(Record.DECK_URL_PREFIX);
if (deckStart != -1) {
onSaveDeck(message.substring(deckStart + Record.DECK_URL_PREFIX.length()), true, id);
return true;
} else if (message.contains("?" + Record.ARG_YGO_TYPE + "=" + Record.ARG_DECK) || message.contains("&" + Record.ARG_YGO_TYPE + "=" + Record.ARG_DECK)) {
String m1 = "?" + Record.ARG_YGO_TYPE + "=" + Record.ARG_DECK;
String m2 = "&" + Record.ARG_YGO_TYPE + "=" + Record.ARG_DECK;
int s1 = message.indexOf(m1);
if (s1 == -1)
s1 = message.indexOf(m2);
int start = message.lastIndexOf(Record.DECK_URL_PREFIX, s1);
if (start == -1)
start = message.lastIndexOf(Record.HTTP_URL_PREFIX, s1);
if (start == -1)
start = message.lastIndexOf(Record.HTTPS_URL_PREFIX, s1);
if (start != -1)
onSaveDeck(message.substring(start + Record.DECK_URL_PREFIX.length()), true, id);
return true;
}
return false;
}
public boolean roomCheck(String message, int id) {
if (message.contains("?" + Record.ARG_YGO_TYPE + "=" + Record.ARG_ROOM) || message.contains("&" + Record.ARG_YGO_TYPE + "=" + Record.ARG_ROOM)) {
String m1 = "?" + Record.ARG_YGO_TYPE + "=" + Record.ARG_ROOM;
String m2 = "&" + Record.ARG_YGO_TYPE + "=" + Record.ARG_ROOM;
int s1 = message.indexOf(m1);
if (s1 == -1)
s1 = message.indexOf(m2);
int start = message.lastIndexOf(Record.ROOM_URL_PREFIX, s1);
if (start == -1)
start = message.lastIndexOf(Record.HTTP_URL_PREFIX, s1);
if (start == -1)
start = message.lastIndexOf(Record.HTTPS_URL_PREFIX, s1);
onJoinRoom(message.substring(start + Record.DECK_URL_PREFIX.length()), id);
return true;
}
int start = -1;
int end = -1;
String passwordPrefixKey = null;
for (String s : Record.PASSWORD_PREFIX) {
start = message.indexOf(s);
passwordPrefixKey = s;
if (start != -1) {
break;
}
}
if (start != -1) {
//如果密码含有空格,则以空格结尾
end = message.indexOf(" ", start);
//如果不含有空格则取片尾所有
if (end == -1) {
end = message.length();
} else {
//如果只有密码前缀而没有密码内容则不跳转
if (end - start == passwordPrefixKey.length())
return false;
}
onJoinRoom(null, 0, message.substring(start, end), id);
return true;
}
return false;
}
public boolean cardSearchCheck(String message, int id) {
for (String s : Record.CARD_SEARCH_KEY) {
int cardSearchStart = message.indexOf(s);
if (cardSearchStart != -1) {
//卡查内容
cardSearchMessage = message.substring(cardSearchStart + s.length(), message.length());
//如果复制的文本里带?号后面没有内容则不跳转
if (TextUtils.isEmpty(cardSearchMessage)) {
return false;
}
//如果卡查内容包含“=”并且复制的内容包含“.”不卡查(链接判断)
if (cardSearchMessage.contains("=") || message.contains(".")) {
return false;
}
onCardSearch(cardSearchMessage, id);
return true;
}
}
return false;
}
private void onJoinRoom(String roomUrl, int id) {
YGODAUtil.deRoomListener(Uri.parse(roomUrl), (host, port, password, exception) -> {
if (TextUtils.isEmpty(exception)) {
onJoinRoom(host, port, password, id);
}
});
}
private void onJoinRoom(String host, int port, String password, int id) {
int i = 0;
while (i < onDuelAssistantListenerList.size()) {
OnDuelAssistantListener onDuelAssistantListener = onDuelAssistantListenerList.get(i);
if (onDuelAssistantListener.isListenerEffective()) {
onDuelAssistantListener.onJoinRoom(host, port, password, id);
i++;
} else {
onDuelAssistantListenerList.remove(i);
}
}
}
private void onCardSearch(String key, int id) {
int i = 0;
while (i < onDuelAssistantListenerList.size()) {
OnDuelAssistantListener onDuelAssistantListener = onDuelAssistantListenerList.get(i);
if (onDuelAssistantListener.isListenerEffective()) {
onDuelAssistantListener.onCardSearch(key, id);
i++;
} else {
onDuelAssistantListenerList.remove(i);
}
}
}
public void onSaveDeck(String message, boolean isUrl, int id) {
int i = 0;
while (i < onDuelAssistantListenerList.size()) {
OnDuelAssistantListener onDuelAssistantListener = onDuelAssistantListenerList.get(i);
if (onDuelAssistantListener.isListenerEffective()) {
onDuelAssistantListener.onSaveDeck(message, isUrl, id);
i++;
} else {
onDuelAssistantListenerList.remove(i);
}
}
}
@Override
public void onClipChanged(String clipMessage, boolean isCheck, int id) {
if (isCheck)
if (clipMessage.equals(lastMessage))
return;
if (deckCheck(clipMessage, id)) {
lastMessage = clipMessage;
} else if (roomCheck(clipMessage, id)) {
lastMessage = clipMessage;
}
// else if (cardSearchCheck(clipMessage, id))
// lastMessage = clipMessage;
}
public void setLastMessage(String lastMessage) {
this.lastMessage = lastMessage;
}
public void checkClip(int id) {
clipManagement.onPrimaryClipChanged(true, id);
}
}
package com.ourygo.assistant.util;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import androidx.core.app.NotificationManagerCompat;
public class PermissionUtil {
//判断应用是否开启了通知权限
public static boolean isNotificationListenerEnabled(Context context) {
return NotificationManagerCompat.from(context).areNotificationsEnabled();
}
//判断是否有悬浮窗权限
public static boolean isServicePermission(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(context))
return false;
}
return true;
}
}
package com.ourygo.assistant.util;
public class Record {
//卡查关键字
public static final String[] CARD_SEARCH_KEY = new String[]{"?", "?"};
public static final int YGO_ROOM_PROTOCOL_1=1;
//加房关键字
public static final String[] PASSWORD_PREFIX = {
"M,", "m,",
"T,","t,",
"PR,", "pr,",
"AI,", "ai,",
"LF2,", "lf2,",
"M#", "m#",
"T#", "t#",
"PR#", "pr#",
"NS#", "ns#",
"S#", "s#",
"AI#", "ai#",
"LF2#", "lf2#",
"R#", "r#"
};
public static final String ROOM_PREFIX="room:{";
public static final String ROOM_END="}";
//卡组复制
public static final String[] DeckTextKey = new String[]{"#main"};
//卡组url前缀
public static final String DECK_URL_PREFIX = "ygo://deck";
public static final String ROOM_URL_PREFIX = "room://deck";
public static final String HTTP_URL_PREFIX = "http://";
public static final String HTTPS_URL_PREFIX = "https://";
public static final String ARG_PORT = "po";
public static final String ARG_HOST = "h";
public static final String ARG_PASSWORD = "pw";
public static final String ARG_PORT_ALL = "port";
public static final String ARG_HOST_ALL = "host";
public static final String ARG_PASSWORD_ALL = "password";
public static final String ARG_YGO_TYPE="ygotype";
public static final String ARG_DECK="deck";
public static final String ARG_ROOM="room";
}
package com.ourygo.assistant.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* Create By feihua On 2021/9/29
*/
public class UrlUtil {
/**
* URLEncoder编码
*/
public static String enURL(String paramString) {
if (paramString == null || paramString.equals("")) {
return "";
}
try {
String str = new String(paramString.getBytes(), "UTF-8");
str = URLEncoder.encode(str, "UTF-8");
return str;
} catch (Exception localException) {
}
return "";
}
/**
* URLDecoder解码
*/
public static String deURL(String paramString) {
if (paramString == null || paramString.equals("")) {
return "";
}
try {
String url = new String(paramString.getBytes(), "UTF-8");
url = URLDecoder.decode(url, "UTF-8");
return url;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
}
package com.ourygo.assistant.util;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import com.ourygo.assistant.service.DuelAssistantService;
import java.util.List;
public class Util {
public static boolean startDuelService(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (PermissionUtil.isNotificationListenerEnabled(context))
context.startForegroundService(new Intent(context, DuelAssistantService.class));
else
return false;
} else {
context.startService(new Intent(context, DuelAssistantService.class));
}
}
return true;
}
public static Intent getNotificationPermissionInitent(Context context){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
intent.setData(uri);
return intent;
}
public static Intent getServicePermissionIntent(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+context.getPackageName()));
}
return null;
}
public static void duelIntent(Context context, String ip, int port, String name, String password) {
Intent intent1 = new Intent("ygomobile.intent.action.GAME");
intent1.putExtra("host", ip);
intent1.putExtra("port", port);
intent1.putExtra("user", name);
intent1.putExtra("room", password);
//intent1.setPackage("cn.garymb.ygomobile");
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
public static boolean isServiceExisted(Context context, String className) {
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityManager
.getRunningServices(Integer.MAX_VALUE);
if (!(serviceList.size() > 0)) {
return false;
}
for (int i = 0; i < serviceList.size(); i++) {
ActivityManager.RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if (serviceName.getClassName().equals(className)) {
return true;
}
}
return false;
}
public static boolean isContextExisted(Context context) {
if (context != null) {
if (context instanceof Activity) {
if (!((Activity)context).isFinishing()) {
return true;
}
} else if (context instanceof Service) {
if (isServiceExisted(context, context.getClass().getName())) {
return true;
}
} else if (context instanceof Application) {
return true;
}
}
return false;
}
}
package com.ourygo.assistant.util;
import static cn.garymb.ygomobile.Constants.QUERY_VERSION;
import static cn.garymb.ygomobile.Constants.QUERY_YGO_TYPE;
import android.net.Uri;
import com.ourygo.assistant.base.listener.OnDeRoomListener;
/**
* Create By feihua On 2021/9/29
*/
public class YGODAUtil {
public static void deRoomListener(Uri uri, OnDeRoomListener onDeRoomListener){
String host = "", password = "";
int port = 0;
int version = Record.YGO_ROOM_PROTOCOL_1;
try {
String ygoType = uri.getQueryParameter(QUERY_YGO_TYPE);
if (ygoType.equals(Record.ARG_ROOM)) {
version = Integer.parseInt(uri.getQueryParameter(QUERY_VERSION));
}
} catch (Exception exception) {
onDeRoomListener.onDeRoom(null,-1,null,"非加房协议");
}
switch (version) {
case Record.YGO_ROOM_PROTOCOL_1:
try {
host = UrlUtil.deURL(uri.getQueryParameter(Record.ARG_HOST));
} catch (Exception ignored) {
}
try {
port = Integer.parseInt(UrlUtil.deURL(uri.getQueryParameter(Record.ARG_PORT)));
} catch (Exception ignored) {
}
try {
password = UrlUtil.deURL(uri.getQueryParameter(Record.ARG_PASSWORD));
} catch (Exception ignored) {
}
break;
}
onDeRoomListener.onDeRoom(host,port,password,null);
}
}
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