排卡最新升级
This commit is contained in:
@@ -11,7 +11,7 @@ android {
|
||||
minSdk 29
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.6.1 b"
|
||||
versionName "1.6.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" tools:ignore="ProtectedPermissions"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/>
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
@@ -78,9 +80,17 @@
|
||||
</receiver>
|
||||
<service android:name=".ui.widget.MyWidgetService" />
|
||||
|
||||
<receiver android:name=".ui.NfcBroadcastReceiver" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<meta-data
|
||||
android:name="com.baidu.lbsapi.API_KEY"
|
||||
android:value="lzzpL36kTbcmfQvhWDJOZwa3glQlYBbm"/>
|
||||
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:exported="true"
|
||||
@@ -88,10 +98,25 @@
|
||||
android:theme="@style/Theme.FindMaimaiUltra.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data
|
||||
android:scheme="org.astral.findmaimaiultra"
|
||||
android:host="data" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.TAG_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.nfc.action.TECH_DISCOVERED"
|
||||
android:resource="@xml/nfc_filter" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.PageActivity"
|
||||
android:exported="true"
|
||||
@@ -157,5 +182,4 @@
|
||||
android:exported="false">
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,33 +1,55 @@
|
||||
package org.astral.findmaimaiultra.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.gson.Gson;
|
||||
import org.astral.findmaimaiultra.R;
|
||||
import org.astral.findmaimaiultra.adapter.PhotoAdapter;
|
||||
import org.astral.findmaimaiultra.been.pixiv.jm.Album;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
|
||||
public class JMActivity extends AppCompatActivity {
|
||||
private FrameLayout overlay;
|
||||
private boolean isOverlayVisible = false;
|
||||
private BottomSheetBehavior<View> bottomSheetBehavior;
|
||||
private PhotoAdapter photoAdapter;
|
||||
private static final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1;
|
||||
private Album album;
|
||||
@Override
|
||||
@SuppressLint("MissingInflatedId")
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -36,18 +58,19 @@ public class JMActivity extends AppCompatActivity {
|
||||
|
||||
initRecyclerView();
|
||||
}
|
||||
|
||||
@SuppressLint({"ClickableViewAccessibility", "SetTextI18n", "ResourceType"})
|
||||
private void initRecyclerView() {
|
||||
Intent intent = getIntent();
|
||||
String res = intent.getStringExtra("album");
|
||||
Album a = new Gson().fromJson(res, Album.class);
|
||||
album = a;
|
||||
Toast.makeText(this,"加载中", Toast.LENGTH_SHORT).show();
|
||||
RecyclerView recyclerView = findViewById(R.id.recyclerView);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
photoAdapter = new PhotoAdapter(this, a.getImage_urls(), a.getNums(), a);
|
||||
photoAdapter.clearLoad();
|
||||
|
||||
MaterialButton downloadButton = findViewById(R.id.download);
|
||||
downloadButton.setOnClickListener(v -> downloadAllImages());
|
||||
recyclerView.setAdapter(photoAdapter);
|
||||
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
|
||||
bottomSheetBehavior.setPeekHeight(dpToPx(80));
|
||||
@@ -59,6 +82,67 @@ public class JMActivity extends AppCompatActivity {
|
||||
+ " \n " + a.getTags().toString().replaceAll( "\"","") .replaceAll( "\\[","").replaceAll( "]","")
|
||||
+ " \n " + a.getAlbum_id().replaceAll( "\"","").replaceAll( "\\[","").replaceAll( "]",""));
|
||||
}
|
||||
|
||||
private void downloadAllImages() {
|
||||
String folderName = album.getName();
|
||||
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + File.separator + "findmaimaiultra"), folderName);
|
||||
int totalImages = photoAdapter.getItemCount();
|
||||
int[] downloadedCount = {0}; // 使用数组来保存下载计数,以便在匿名内部类中修改
|
||||
|
||||
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "Download started", Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.show();
|
||||
for (int i = 0; i < album.getImage_urls().size(); i++) {
|
||||
String imageUrl = album.getImage_urls().get(i);
|
||||
int num = album.getNums().get(i);
|
||||
String FileName = "image_" + album.getAlbum_id() + "_" + i + ".jpg";
|
||||
File file = new File(folder, FileName);
|
||||
if (!folder.exists()) {
|
||||
if (!folder.mkdirs()) {
|
||||
Toast.makeText(this, "Failed to create folder", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(imageUrl)
|
||||
.into(new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
Bitmap decodedBitmap = decodeImage(resource, num);
|
||||
downloadedCount[0]++;
|
||||
updateSnackBar(snackbar, downloadedCount[0], totalImages);
|
||||
saveBitmapToFile(decodedBitmap, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
super.onLoadFailed(errorDrawable);
|
||||
downloadedCount[0]++;
|
||||
updateSnackBar(snackbar, downloadedCount[0], totalImages);
|
||||
}
|
||||
});
|
||||
}
|
||||
snackbar.setText("下载完成!保存在/Download/FindMaimaiUltra/本子名称 目录");
|
||||
snackbar.setDuration(Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction("OK", v -> snackbar.dismiss());
|
||||
Snackbar.make(findViewById(android.R.id.content), "下载完成!保存在/Download/FindMaimaiUltra/本子名称 目录", Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction("OK", v -> {
|
||||
// 处理 Snackbar 按钮点击事件
|
||||
})
|
||||
.show();
|
||||
}
|
||||
private void updateSnackBar(Snackbar snackbar, int current, int total) {
|
||||
String message = "Downloaded " + current + "/" + total + " images";
|
||||
snackbar.setText(message);
|
||||
if (current == total) {
|
||||
snackbar.dismiss();
|
||||
}
|
||||
}
|
||||
public int dpToPx(int dp) {
|
||||
return (int) (dp * getResources().getDisplayMetrics().density);
|
||||
}
|
||||
@@ -69,4 +153,54 @@ public class JMActivity extends AppCompatActivity {
|
||||
photoAdapter.clearCache();
|
||||
}
|
||||
}
|
||||
private void saveBitmapToFile(Bitmap bitmap, File file) {
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, "Failed to save image", Toast.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private Bitmap decodeImage(Bitmap imgSrc, int num) {
|
||||
if (num == 0) {
|
||||
return imgSrc;
|
||||
}
|
||||
|
||||
int w = imgSrc.getWidth();
|
||||
int h = imgSrc.getHeight();
|
||||
|
||||
// 创建新的解密图片
|
||||
Bitmap imgDecode = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(imgDecode);
|
||||
|
||||
int over = h % num;
|
||||
for (int i = 0; i < num; i++) {
|
||||
int move = h / num;
|
||||
int ySrc = h - (move * (i + 1)) - over;
|
||||
int yDst = move * i;
|
||||
|
||||
if (i == 0) {
|
||||
move += over;
|
||||
} else {
|
||||
yDst += over;
|
||||
}
|
||||
|
||||
Rect srcRect = new Rect(0, ySrc, w, ySrc + move);
|
||||
Rect dstRect = new Rect(0, yDst, w, yDst + move);
|
||||
|
||||
canvas.drawBitmap(imgSrc, srcRect, dstRect, null);
|
||||
}
|
||||
|
||||
return imgDecode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.google.gson.Gson;
|
||||
import okhttp3.*;
|
||||
import org.astral.findmaimaiultra.R;
|
||||
import org.astral.findmaimaiultra.been.faker.RegionData;
|
||||
import org.astral.findmaimaiultra.been.faker.UserData;
|
||||
import org.astral.findmaimaiultra.been.faker.UserRegion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
@@ -158,6 +160,7 @@ public class LinkQQBot extends AppCompatActivity {
|
||||
Toast.makeText(LinkQQBot.this, "设置已保存,您的UsrId已写入硬盘!", Toast.LENGTH_SHORT).show();
|
||||
try {
|
||||
getUserRegionData(responseData);
|
||||
getUserData(responseData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -168,6 +171,34 @@ public class LinkQQBot extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
}
|
||||
private void getUserData(String userId) throws Exception {
|
||||
String url = "http://mai.godserver.cn:11451/api/qq/userData?qq=" + userId ;
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String json = response.body().string();
|
||||
UserData userData = new Gson().fromJson(json, UserData.class);
|
||||
SharedPreferences.Editor editor = sp.edit();
|
||||
editor.putString("paikaname", userData.getUserName());
|
||||
editor.putInt("iconId",userData.getIconId());
|
||||
editor.putString("rating", userData.getPlayerRating() + "");
|
||||
editor.apply();
|
||||
Log.d("TAG", "onResponse: " + userData.getUserName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
Log.d("TAG", "onFailure: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getUserRegionData(String userId) throws Exception {
|
||||
String url = "http://mai.godserver.cn:11451/api/qq/region2?qq=" + userId ;
|
||||
|
||||
@@ -2,12 +2,17 @@ package org.astral.findmaimaiultra.ui;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.*;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
@@ -36,6 +41,11 @@ import org.astral.findmaimaiultra.ui.home.HomeFragment;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
@@ -44,15 +54,26 @@ public class MainActivity extends AppCompatActivity implements ImagePickerListen
|
||||
private AppBarConfiguration mAppBarConfiguration;
|
||||
private ActivityMainBinding binding;
|
||||
private SharedPreferences settingProperties;
|
||||
private NfcAdapter nfcAdapter;
|
||||
private PendingIntent pendingIntent;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
|
||||
if (nfcAdapter == null) {
|
||||
Toast.makeText(this, "NFC is not available on this device", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_IMMUTABLE);
|
||||
handleNfcIntent(getIntent());
|
||||
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
settingProperties = getSharedPreferences("setting", Context.MODE_PRIVATE);
|
||||
|
||||
setSupportActionBar(binding.appBarMain.toolbar);
|
||||
DrawerLayout drawer = binding.drawerLayout;
|
||||
NavigationView navigationView = binding.navView;
|
||||
@@ -67,6 +88,122 @@ public class MainActivity extends AppCompatActivity implements ImagePickerListen
|
||||
NavigationUI.setupWithNavController(navigationView, navController);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (nfcAdapter != null) {
|
||||
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (nfcAdapter != null) {
|
||||
nfcAdapter.disableForegroundDispatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
Log.d("111111111", "onNewIntent: " + intent.getAction());
|
||||
handleNfcIntent(intent);
|
||||
super.onNewIntent(intent);
|
||||
}
|
||||
|
||||
private void handleNfcIntent(Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
|
||||
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
|
||||
if (rawMsgs != null) {
|
||||
NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
|
||||
for (int i = 0; i < rawMsgs.length; i++) {
|
||||
msgs[i] = (NdefMessage) rawMsgs[i];
|
||||
}
|
||||
// Process the messages
|
||||
List<String> nfcData = processNdefMessages(msgs);
|
||||
for (String data : nfcData) {
|
||||
if(data.contains("paika")) {
|
||||
Intent intent2 = new Intent(this, PaikaActivity.class);
|
||||
intent2.putExtra("data", data);
|
||||
startActivity(intent2);
|
||||
}
|
||||
// 在这里处理NFC数据
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> processNdefMessages(NdefMessage[] msgs) {
|
||||
List<String> nfcData = new ArrayList<>();
|
||||
if (msgs == null || msgs.length == 0) return nfcData;
|
||||
|
||||
for (NdefMessage msg : msgs) {
|
||||
NdefRecord[] records = msg.getRecords();
|
||||
for (NdefRecord record : records) {
|
||||
String recordData = parseNdefRecord(record);
|
||||
if (recordData != null) {
|
||||
nfcData.add(recordData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nfcData;
|
||||
}
|
||||
|
||||
private String parseNdefRecord(NdefRecord record) {
|
||||
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_URI)) {
|
||||
return parseUri(record);
|
||||
} else if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
|
||||
return parseText(record);
|
||||
} else {
|
||||
// 处理其他类型的记录
|
||||
return new String(record.getPayload(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private String parseUri(NdefRecord record) {
|
||||
byte[] uriField = record.getPayload();
|
||||
String prefix = ((char) (uriField[0] & 0x0F)) + "";
|
||||
byte[] fullUri = new byte[uriField.length - 1];
|
||||
System.arraycopy(uriField, 1, fullUri, 0, uriField.length - 1);
|
||||
return prefix + new String(fullUri, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private String parseText(NdefRecord record) {
|
||||
byte[] payload = record.getPayload();
|
||||
if (payload.length < 2) {
|
||||
Log.w("NfcBroadcastReceiver", "Invalid payload length for text record");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 第一个字节的高4位表示字符编码(0表示UTF-8,1表示UTF-16)
|
||||
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
|
||||
int languageCodeLength = payload[0] & 0077;
|
||||
|
||||
if (languageCodeLength > payload.length - 1) {
|
||||
Log.w("NfcBroadcastReceiver", "Invalid language code length");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 解析语言代码(通常不需要,除非你有特殊需求)
|
||||
String languageCode = new String(payload, 1, languageCodeLength, StandardCharsets.US_ASCII);
|
||||
|
||||
// 解析文本数据
|
||||
int textStartIndex = 1 + languageCodeLength;
|
||||
int textLength = payload.length - textStartIndex;
|
||||
|
||||
if (textLength <= 0) {
|
||||
Log.w("NfcBroadcastReceiver", "No text data found");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new String(payload, textStartIndex, textLength, Charset.forName(textEncoding));
|
||||
} catch (Exception e) {
|
||||
Log.w("NfcBroadcastReceiver", "Unsupported charset: " + textEncoding, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
@@ -93,6 +230,7 @@ public class MainActivity extends AppCompatActivity implements ImagePickerListen
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updatePlace() {
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.astral.findmaimaiultra.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.TextView;
|
||||
import org.astral.findmaimaiultra.R;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NfcActivity extends Activity {
|
||||
private TextView textView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_nfc);
|
||||
textView = findViewById(R.id.textView);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
|
||||
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
|
||||
if (rawMsgs != null) {
|
||||
NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
|
||||
for (int i = 0; i < rawMsgs.length; i++) {
|
||||
msgs[i] = (NdefMessage) rawMsgs[i];
|
||||
}
|
||||
// Process the messages
|
||||
processNdefMessages(msgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNdefMessages(NdefMessage[] msgs) {
|
||||
if (msgs == null || msgs.length == 0) return;
|
||||
|
||||
for (NdefMessage msg : msgs) {
|
||||
NdefRecord[] records = msg.getRecords();
|
||||
for (NdefRecord record : records) {
|
||||
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_URI)) {
|
||||
String uri = parseUri(record);
|
||||
textView.setText(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String parseUri(NdefRecord record) {
|
||||
byte[] uriField = record.getPayload();
|
||||
String prefix = ((char) (uriField[0] & 0x0F)) + "";
|
||||
byte[] fullUri = new byte[uriField.length - 1];
|
||||
System.arraycopy(uriField, 1, fullUri, 0, uriField.length - 1);
|
||||
return prefix + new String(fullUri, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.astral.findmaimaiultra.ui;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NfcBroadcastReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
|
||||
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
|
||||
if (rawMsgs != null) {
|
||||
NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
|
||||
for (int i = 0; i < rawMsgs.length; i++) {
|
||||
msgs[i] = (NdefMessage) rawMsgs[i];
|
||||
}
|
||||
// Process the messages
|
||||
processNdefMessages(context, msgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNdefMessages(Context context, NdefMessage[] msgs) {
|
||||
if (msgs == null || msgs.length == 0) return;
|
||||
|
||||
for (NdefMessage msg : msgs) {
|
||||
NdefRecord[] records = msg.getRecords();
|
||||
for (NdefRecord record : records) {
|
||||
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_URI)) {
|
||||
String uri = parseUri(record);
|
||||
Log.d("NfcBroadcastReceiver", "URI: " + uri);
|
||||
// 你可以在这里启动MainActivity或者执行其他操作
|
||||
Intent mainIntent = new Intent(context, MainActivity.class);
|
||||
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(mainIntent);
|
||||
} else if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
|
||||
String text = parseText(record);
|
||||
Log.d("NfcBroadcastReceiver", "Text: " + text);
|
||||
// 你可以在这里启动MainActivity或者执行其他操作
|
||||
Intent mainIntent = new Intent(context, MainActivity.class);
|
||||
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mainIntent.putExtra("nfc_text", text);
|
||||
context.startActivity(mainIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String parseUri(NdefRecord record) {
|
||||
byte[] uriField = record.getPayload();
|
||||
String prefix = ((char) (uriField[0] & 0x0F)) + "";
|
||||
byte[] fullUri = new byte[uriField.length - 1];
|
||||
System.arraycopy(uriField, 1, fullUri, 0, uriField.length - 1);
|
||||
return prefix + new String(fullUri, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private String parseText(NdefRecord record) {
|
||||
byte[] payload = record.getPayload();
|
||||
if (payload.length < 2) {
|
||||
Log.w("NfcBroadcastReceiver", "Invalid payload length for text record");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 第一个字节的高4位表示字符编码(0表示UTF-8,1表示UTF-16)
|
||||
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
|
||||
int languageCodeLength = payload[0] & 0077;
|
||||
|
||||
if (languageCodeLength > payload.length - 1) {
|
||||
Log.w("NfcBroadcastReceiver", "Invalid language code length");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 解析语言代码(通常不需要,除非你有特殊需求)
|
||||
String languageCode = new String(payload, 1, languageCodeLength, StandardCharsets.US_ASCII);
|
||||
|
||||
// 解析文本数据
|
||||
int textStartIndex = 1 + languageCodeLength;
|
||||
int textLength = payload.length - textStartIndex;
|
||||
|
||||
if (textLength <= 0) {
|
||||
Log.w("NfcBroadcastReceiver", "No text data found");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new String(payload, textStartIndex, textLength, Charset.forName(textEncoding));
|
||||
} catch (Exception e) {
|
||||
Log.w("NfcBroadcastReceiver", "Unsupported charset: " + textEncoding, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,429 +2,547 @@ package org.astral.findmaimaiultra.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.*;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.dialog.MaterialDialogs;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import okhttp3.*;
|
||||
import org.astral.findmaimaiultra.R;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class PaikaActivity extends AppCompatActivity {
|
||||
private MaterialButton enter;
|
||||
private TextInputEditText partyName;
|
||||
private Context context;
|
||||
private OkHttpClient client;
|
||||
private String party;
|
||||
private TextView partyHouse;
|
||||
private TableLayout tableLayout;
|
||||
private SharedPreferences sharedPreferences;
|
||||
private TextInputEditText name;
|
||||
private String paikaname;
|
||||
private MaterialButton add;
|
||||
private MaterialButton play;
|
||||
private MaterialButton leave;
|
||||
private MaterialButton card;
|
||||
private Handler handler;
|
||||
private String cardStyle;
|
||||
private String old = "";
|
||||
private String use_party;
|
||||
private String use_name;
|
||||
private int iconId;
|
||||
private int iconResId = iconId;
|
||||
private int status;
|
||||
private Toolbar toolbar;
|
||||
private List<String> players = new ArrayList<>();
|
||||
private Handler handler = new Handler();
|
||||
private ImageView player1Avatar;
|
||||
private ImageView player2Avatar;
|
||||
private TextView player1Name;
|
||||
private TextView player2Name;
|
||||
private boolean isPlaying = false;
|
||||
@SuppressLint("MissingInflatedId")
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
setContentView(R.layout.activity_paika);
|
||||
enter = findViewById(R.id.enter);
|
||||
partyName = findViewById(R.id.party);
|
||||
context = getApplicationContext();
|
||||
client = new OkHttpClient();
|
||||
add = findViewById(R.id.add);
|
||||
leave = findViewById(R.id.leave);
|
||||
play = findViewById(R.id.play);
|
||||
tableLayout = findViewById(R.id.tableLayout);
|
||||
sharedPreferences = getSharedPreferences("setting", MODE_PRIVATE);
|
||||
name = findViewById(R.id.name);
|
||||
partyHouse= findViewById(R.id.partyHouse);
|
||||
card = findViewById(R.id.card);
|
||||
handler = new Handler();
|
||||
if(sharedPreferences.getString("paikaname", null) != null) {
|
||||
name.setText(sharedPreferences.getString("paikaname", null));
|
||||
paikaname = sharedPreferences.getString("paikaname", null);
|
||||
}
|
||||
enter.setOnClickListener(v -> {
|
||||
enterParty();
|
||||
});
|
||||
cardStyle = sharedPreferences.getString("cardStyle", "maimai PiNK.png");
|
||||
if (!cardStyle.contains(".")){
|
||||
cardStyle = cardStyle + ".png";
|
||||
}
|
||||
card.setText(cardStyle.split("\\.")[0]);
|
||||
add.setOnClickListener(v -> {
|
||||
paikaname = name.getText().toString();
|
||||
if(paikaname.equals("")) {
|
||||
Toast.makeText(context, "请输入昵称", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
updateCard();
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), "{\"party\":\"" + party + "\",\"name\":\"" + paikaname + "\"}");
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party + "&people=" + paikaname)
|
||||
.post(requestBody)
|
||||
.build();
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("paikaname", paikaname);
|
||||
editor.apply();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
joinParty();
|
||||
}
|
||||
sharedPreferences = getSharedPreferences("setting", Context.MODE_PRIVATE);
|
||||
handler.postDelayed(refreshTask, 3000);
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
leave.setOnClickListener(v->{
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party + "&people=" + paikaname)
|
||||
.delete()
|
||||
.build();
|
||||
play.setVisibility(View.GONE);
|
||||
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
joinParty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
play.setOnClickListener(v->{
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), "{\"party\":\"" + party + "\",\"people\":\"" + paikaname + "\"}");
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/partyPlay?party=" + party)
|
||||
.post(requestBody)
|
||||
.build();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
joinParty();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
}
|
||||
});
|
||||
});
|
||||
card.setOnClickListener(v -> {
|
||||
Toast.makeText(context, "目前样式:" + cardStyle, Toast.LENGTH_SHORT).show();
|
||||
|
||||
// 创建 AlertDialog
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("请选择卡牌样式");
|
||||
|
||||
// 加载自定义布局
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_card_style, null);
|
||||
LinearLayout layout = dialogView.findViewById(R.id.layout_buttons); // 假设 LinearLayout 的 id 是 layout_buttons
|
||||
|
||||
// 添加选项
|
||||
String[] styles = {
|
||||
"maimai でらっくす FESTiVAL PLUS",
|
||||
"maimai でらっくす UNiVERSE PLUS",
|
||||
"maimai でらっくす PLUS",
|
||||
"maimai でらっくす FESTiVAL",
|
||||
"maimai でらっくす UNiVERSE",
|
||||
"maimai でらっくす BUDDiES",
|
||||
"maimai でらっくす",
|
||||
"maimai MURASAKi",
|
||||
"maimai PiNK",
|
||||
"maimai ORANGE",
|
||||
"maimai GreeN",
|
||||
"maimai MiLK"
|
||||
};
|
||||
|
||||
// 创建 AlertDialog 对象
|
||||
AlertDialog dialog = builder.create();
|
||||
|
||||
for (String style : styles) {
|
||||
MaterialButton button = new MaterialButton(this);
|
||||
button.setText(style);
|
||||
button.setPadding(16, 16, 16, 16);
|
||||
button.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
|
||||
button.setTextColor(getResources().getColor(R.color.white));
|
||||
button.setOnClickListener(view -> {
|
||||
cardStyle = style + ".png";
|
||||
updateCard();
|
||||
Toast.makeText(context, "已选择样式: " + cardStyle, Toast.LENGTH_SHORT).show();
|
||||
use_name = sharedPreferences.getString("paikaname", "");
|
||||
iconId = sharedPreferences.getInt("iconId", 0);
|
||||
iconResId = iconId;
|
||||
player1Avatar = findViewById(R.id.player1Avatar);
|
||||
player2Avatar = findViewById(R.id.player2Avatar);
|
||||
player1Name = findViewById(R.id.player1Name);
|
||||
player2Name = findViewById(R.id.player2Name);
|
||||
if (use_name.equals("")) {
|
||||
//询问并做个名字
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle("请输入昵称");
|
||||
TextInputEditText textInputEditText = new TextInputEditText(this);
|
||||
builder.setView(textInputEditText);
|
||||
builder.setPositiveButton("确定", (dialog, which) -> {
|
||||
use_name = textInputEditText.getText().toString();
|
||||
dialog.dismiss();
|
||||
});
|
||||
layout.addView(button);
|
||||
builder.setNegativeButton("取消", null);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
// 设置 AlertDialog 的内容视图
|
||||
dialog.setView(dialogView);
|
||||
status = sharedPreferences.getInt("paikastatus", 0);
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
|
||||
// 显示 AlertDialog
|
||||
dialog.show();
|
||||
});
|
||||
Intent intent = getIntent();
|
||||
if (intent.getStringExtra("data") != null) {
|
||||
String data = intent.getStringExtra("data");
|
||||
Log.d("123456", data);
|
||||
|
||||
}
|
||||
private void updateCard() {
|
||||
RequestBody emptyRequestBody = RequestBody.create("", MediaType.parse("text/plain"));
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/player?party=" + party + "&people=" + paikaname + "&card=" + cardStyle)
|
||||
.post(emptyRequestBody)
|
||||
.build();
|
||||
card.setText(cardStyle.split("\\.")[0]);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("cardStyle", cardStyle);
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
Log.d("TAG", "Response: " + response.body().string());
|
||||
}
|
||||
use_party = data.split("paika")[1];
|
||||
Log.d("partySetting", use_party);
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private void enterParty() {
|
||||
LinearLayout joinParty = findViewById(R.id.joinParty);
|
||||
joinParty.setVisibility(LinearLayout.VISIBLE);
|
||||
LinearLayout enterParty = findViewById(R.id.enterParty);
|
||||
enterParty.setVisibility(LinearLayout.GONE);
|
||||
TextInputEditText partyName = findViewById(R.id.party);
|
||||
party = partyName.getText().toString();
|
||||
if (!name.getText().toString().isEmpty()) {
|
||||
paikaname = name.getText().toString();
|
||||
}
|
||||
handler = new Handler();
|
||||
Runnable runnable = new Runnable() {
|
||||
if (sharedPreferences.getString("use_party", "").equals(use_party)) {
|
||||
getData();
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
joinParty();
|
||||
handler.postDelayed(this, 5000);
|
||||
if (players != null && !players.isEmpty()) {
|
||||
// 如果 players 不为空,执行 doUPlay()
|
||||
doUPlay();
|
||||
} else {
|
||||
// 如果 players 为空,继续延迟 1 秒后检查
|
||||
handler.postDelayed(this, 1000);
|
||||
}
|
||||
};
|
||||
handler.post(runnable);
|
||||
}
|
||||
private void joinParty() {
|
||||
getShangJiPeople();
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party)
|
||||
.build();
|
||||
Log.d("MainLaunch", "onResponse: " + request);
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String responseData = null;
|
||||
try {
|
||||
responseData = response.body().string();
|
||||
if(old.equals(responseData)) {
|
||||
return;
|
||||
}, 1000); // 延迟 1 秒
|
||||
|
||||
}else {
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}else
|
||||
if(!sharedPreferences.getString("use_party", "").equals("")) {
|
||||
use_party = sharedPreferences.getString("use_party", "");
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle("重新进入房间");
|
||||
builder.setMessage("重新进入房间号?");
|
||||
TextInputEditText textInputEditText = new TextInputEditText(this);
|
||||
builder.setView(textInputEditText);
|
||||
textInputEditText.setText(use_party);
|
||||
builder.setPositiveButton("确定", (dialog, which) -> {
|
||||
use_party = textInputEditText.getText().toString();
|
||||
|
||||
if (status == 0) {
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name);
|
||||
}else {
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name + " 正在队列");
|
||||
}
|
||||
String finalResponseData = responseData;
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("paikaname", paikaname);
|
||||
editor.commit();
|
||||
runOnUiThread(() -> {
|
||||
List<String> list = new Gson().fromJson(finalResponseData, new TypeToken<List<String>>() {
|
||||
}.getType());
|
||||
tableLayout.removeAllViews();
|
||||
|
||||
// 表头行
|
||||
TableRow headerRow = new TableRow(context);
|
||||
addTextViewToRow(headerRow, "排卡顺序", 2);
|
||||
addTextViewToRow(headerRow, "昵称", 5);
|
||||
addTextViewToRow(headerRow, "辅助操作此玩家", 4);
|
||||
tableLayout.addView(headerRow);
|
||||
|
||||
// 数据行
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
String name = list.get(i);
|
||||
if (i == 0) {
|
||||
play.setVisibility(name.equals(paikaname) ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
TableRow row = new TableRow(context);
|
||||
|
||||
// 排卡顺序
|
||||
addTextViewToRow(row, (i + 1) + "", 1);
|
||||
|
||||
// 昵称(图片 + 文字)
|
||||
LinearLayout nameLayout = new LinearLayout(context);
|
||||
nameLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
TableRow.LayoutParams layoutParams = new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 5);
|
||||
nameLayout.setLayoutParams(layoutParams);
|
||||
|
||||
// 图片
|
||||
ImageView imageView = new ImageView(context);
|
||||
updateUserCard( imageView,name);
|
||||
nameLayout.addView(imageView);
|
||||
|
||||
// 文字
|
||||
TextView textView = new TextView(context);
|
||||
textView.setText(name);
|
||||
textView.setTextSize(14);
|
||||
textView.setPadding(30, 20, 0, 0);
|
||||
//设置颜色colorPrimary
|
||||
//设计成斜式
|
||||
textView.setTypeface(Typeface.create("serif-italic", Typeface.NORMAL));
|
||||
textView.setTextColor(getResources().getColor(R.color.colorSecondary));
|
||||
nameLayout.addView(textView);
|
||||
|
||||
row.addView(nameLayout);
|
||||
|
||||
// 辅助操作按钮
|
||||
addButtonToRow(row, "插队", 1, name);
|
||||
addButtonToRow(row, "上机", 1, name);
|
||||
addButtonToRow(row, "离开", 1, name);
|
||||
|
||||
tableLayout.addView(row);
|
||||
}
|
||||
editor.putString("use_party", use_party);
|
||||
editor.apply();
|
||||
getData();
|
||||
});
|
||||
old = finalResponseData;
|
||||
}
|
||||
}
|
||||
builder.setNegativeButton("取消", null);
|
||||
builder.show();
|
||||
}else if (status == 0 && intent.getStringExtra("data") == null) {
|
||||
//询问加入房价
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle("进入房间");
|
||||
builder.setMessage("进入房间号?");
|
||||
TextInputEditText textInputEditText = new TextInputEditText(this);
|
||||
builder.setView(textInputEditText);
|
||||
builder.setPositiveButton("确定", (dialog, which) -> {
|
||||
use_party = textInputEditText.getText().toString();
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name);
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
Log.e("MainLaunch", "onFailure: ", e);
|
||||
}
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putString("use_party", use_party);
|
||||
editor.apply();
|
||||
getData();
|
||||
});
|
||||
builder.setNegativeButton("取消", null);
|
||||
builder.show();
|
||||
}
|
||||
private void updateUserCard(ImageView imageView,String people) {
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/player?people=" + people + "&party=" + party)
|
||||
.build();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
if(response.isSuccessful()) {
|
||||
String responseData = response.body().string();
|
||||
runOnUiThread(()->{
|
||||
Glide.with(context)
|
||||
.load("http://cdn.godserver.cn/resource/static/mai/pic/" + responseData) // 图片URL
|
||||
.placeholder(R.drawable.placeholder) // 占位图
|
||||
.into(imageView);
|
||||
});
|
||||
Log.d("123456", status + "");
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name);
|
||||
if (status == 1) {
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name + " 正在队列");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
Toast.makeText(context, "卡牌展示失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
// 辅助方法:添加 TextView 到 TableRow 并设置权重
|
||||
private void addTextViewToRow(TableRow row, String text, int weight) {
|
||||
TextView textView = new TextView(context);
|
||||
textView.setText(text);
|
||||
textView.setTextColor(ContextCompat.getColor(context, R.color.textcolorPrimary));
|
||||
TableRow.LayoutParams params = new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, weight);
|
||||
textView.setLayoutParams(params);
|
||||
row.addView(textView);
|
||||
}
|
||||
|
||||
// 辅助方法:添加 Button 到 TableRow 并设置权重
|
||||
private void addButtonToRow(TableRow row, String text, int weight,String username) {
|
||||
Button button = new Button(context);
|
||||
button.setText(text);
|
||||
if(text.equals("插队")) {
|
||||
addButton(button,"change",paikaname,username);
|
||||
}else if(text.equals("上机")) {
|
||||
addButton(button,"play",paikaname,username);
|
||||
}else if(text.equals("离开")) {
|
||||
addButton(button,"leave",paikaname,username);
|
||||
}
|
||||
TableRow.LayoutParams params = new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, weight);
|
||||
button.setLayoutParams(params);
|
||||
row.addView(button);
|
||||
}
|
||||
private void addButton(Button button,String data1,String data0,String data) {
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.white));
|
||||
// 添加测试数据到 TableLayout
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Request request = null;
|
||||
if(data1.equals("change")) {
|
||||
RequestBody body = RequestBody.create(data1, MediaType.get("application/json; charset=utf-8"));
|
||||
request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party + "&people=" + data0 + "&changeToPeople=" + data)
|
||||
.put(body)
|
||||
.build();
|
||||
}else if(data1.equals("play")) {
|
||||
RequestBody body = RequestBody.create(data1, MediaType.get("application/json; charset=utf-8"));
|
||||
request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/partyPlay?party=" + party + "&people=" + data)
|
||||
.delete(body)
|
||||
.build();
|
||||
}else if(data1.equals("leave")) {
|
||||
RequestBody body = RequestBody.create(data1, MediaType.get("application/json; charset=utf-8"));
|
||||
request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party + "&people=" + data)
|
||||
.delete(body)
|
||||
.build();
|
||||
doFab(view);
|
||||
}
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
Log.d("TAG", "onResponse: " + response.body().string());
|
||||
runOnUiThread(()->{
|
||||
Toast.makeText(PaikaActivity.this, "操作成功", Toast.LENGTH_SHORT);
|
||||
});
|
||||
joinParty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
private void doUPlay() {
|
||||
// 使用 MaterialAlertDialogBuilder 创建弹窗
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
View dialogView = inflater.inflate(R.layout.dialog_uplay, null);
|
||||
dialogView.setMinimumWidth(600);
|
||||
dialogView.setMinimumHeight(1000);
|
||||
builder.setView(dialogView);
|
||||
|
||||
// 获取按钮并设置点击事件
|
||||
MaterialButton btnPlay = dialogView.findViewById(R.id.btnPlay);
|
||||
AtomicInteger num = new AtomicInteger();
|
||||
|
||||
for (int i = 0; i < players.size();i ++) {
|
||||
if(players.get(i).equals(use_name + "()" + iconId)) {
|
||||
Log.d("UPlayDialog", "num:" + i);
|
||||
num.set(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 创建并显示弹窗
|
||||
AlertDialog dialog = builder.create();
|
||||
btnPlay.setOnClickListener(v -> {
|
||||
// 处理“上机”按钮点击事件
|
||||
num.set(-1);
|
||||
|
||||
for (int i = 0; i < players.size();i ++) {
|
||||
if(players.get(i).equals(use_name + "()" + iconId)) {
|
||||
Log.d("UPlayDialog", "num:" + i);
|
||||
num.set(i);
|
||||
Log.d("UPlayDialog", use_name + "()" + iconId);
|
||||
Log.d("UPlayDialog", players.get(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num.get() == 2 || num.get() == 3) {
|
||||
Log.d("UPlayDialog", "上机 clicked");
|
||||
play();
|
||||
} else if (num.get() == 1 || num.get() ==0) {
|
||||
Snackbar.make(v, "正在上机!", Snackbar.LENGTH_SHORT)
|
||||
.setAction("确定", null)
|
||||
.show();
|
||||
} else if (players.isEmpty()) {
|
||||
Snackbar.make(v, "还在加载队列", Snackbar.LENGTH_SHORT)
|
||||
.setAction("确定", null)
|
||||
.show(); } else {
|
||||
Snackbar.make(v, "还在排队!如特殊情况请点击顺位头像请求换位", Snackbar.LENGTH_SHORT)
|
||||
.setAction("确定", null)
|
||||
.show();
|
||||
}
|
||||
dialog.dismiss();
|
||||
// 可以在这里添加更多的逻辑
|
||||
});
|
||||
|
||||
if (num.get() ==0 | num.get() == 1) {
|
||||
Snackbar.make(findViewById(R.id.back), "正在上机!", Snackbar.LENGTH_SHORT)
|
||||
.setAction("确定", null)
|
||||
.show();
|
||||
}else {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// 设置弹窗为全屏大小
|
||||
if (dialog.getWindow() != null) {
|
||||
dialog.getWindow().setLayout(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void doFab(View view) {
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
||||
View dialogView = LayoutInflater.from(this).inflate(R.layout.paika_dialog, null);
|
||||
|
||||
MaterialButton addButton = dialogView.findViewById(R.id.addButton);
|
||||
addButton.setOnClickListener(v -> {
|
||||
status = 1;
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name + " 正在队列");
|
||||
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putInt("paikastatus", status);
|
||||
editor.putString("use_party", use_party);
|
||||
editor.commit();
|
||||
|
||||
join();
|
||||
});
|
||||
MaterialButton leaveButton = dialogView.findViewById(R.id.leaveButton);
|
||||
leaveButton.setOnClickListener(v -> {
|
||||
status = 0;
|
||||
toolbar.setTitle(use_party + " 房间 " + use_name);
|
||||
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putInt("paikastatus", status);
|
||||
editor.commit();
|
||||
|
||||
remove();
|
||||
});
|
||||
MaterialButton leaveRoomButton = dialogView.findViewById(R.id.leaveRoomButton);
|
||||
leaveRoomButton.setOnClickListener(v -> {
|
||||
status = 0;
|
||||
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putInt("paikastatus", status);
|
||||
editor.putString("use_party", "");
|
||||
editor.commit();
|
||||
|
||||
remove();
|
||||
Intent intent = new Intent(PaikaActivity.this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
builder.setView(dialogView);
|
||||
builder.show();
|
||||
|
||||
}
|
||||
});
|
||||
private Runnable refreshTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!use_party.isEmpty()) {
|
||||
getData(); // 调用刷新方法
|
||||
}
|
||||
});
|
||||
handler.postDelayed(this, 3000); // 每隔 2 秒执行一次
|
||||
}
|
||||
public void getShangJiPeople() {
|
||||
};
|
||||
private void getData() {
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/partyPlay?party=" + party)
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party)
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
String data = response.body().string();
|
||||
runOnUiThread(()->{
|
||||
partyHouse.setText("房间号"+ party+" "+data + "正在上机");
|
||||
});
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String res = response.body().string();
|
||||
players = new Gson().fromJson(res, new TypeToken<List<String>>() {
|
||||
}.getType());
|
||||
addDataToTableLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
Log.d("123456", "getData");
|
||||
}
|
||||
private void join() {
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party + "&people=" + use_name + "()" + iconId)
|
||||
.post(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
Snackbar.make(findViewById(R.id.back), "加入成功", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
getData();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
Log.d("123456", "getData"); }
|
||||
private void remove() {
|
||||
Log.d("123456", "remove");
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party + "&people=" + use_name + "()" + iconId)
|
||||
.delete(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
Snackbar.make(findViewById(R.id.back), "退出成功", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
getData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private void play() {
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/partyPlay?party=" + use_party )
|
||||
.post(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
Snackbar.make(findViewById(R.id.back), "上机成功!", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private void unplay() {
|
||||
}
|
||||
private void addDataToTableLayout() {
|
||||
Context context = this;
|
||||
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TableLayout tableLayout = findViewById(R.id.tableLayout);
|
||||
//清空
|
||||
tableLayout.removeAllViews();
|
||||
try {
|
||||
Glide.with(context)
|
||||
.load("https://assets2.lxns.net/maimai/icon/" + Integer.parseInt(players.get(0).split("\\(\\)")[1]) +".png")
|
||||
.into(player1Avatar);
|
||||
Glide.with(context)
|
||||
.load("https://assets2.lxns.net/maimai/icon/" + Integer.parseInt(players.get(1).split("\\(\\)")[1]) +".png")
|
||||
.into(player2Avatar);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
player1Name.setText(players.get(0).split("\\(\\)")[0]);
|
||||
player2Name.setText(players.get(1).split("\\(\\)")[0]);
|
||||
|
||||
for (int i = 2; i < players.size(); i++) {
|
||||
String name = players.get(i).split("\\(\\)")[0];
|
||||
int iconId = Integer.parseInt(players.get(i).split("\\(\\)")[1]);
|
||||
TableRow tableRow = (TableRow) LayoutInflater.from(context).inflate(R.layout.table_row_item, tableLayout, false);
|
||||
int finalI = i;
|
||||
ImageView userAvatar = tableRow.findViewById(R.id.userAvatar);
|
||||
try {
|
||||
Glide.with(context)
|
||||
.load("https://assets2.lxns.net/maimai/icon/" + iconId +".png")
|
||||
.into(userAvatar);
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
TextView username = tableRow.findViewById(R.id.username);
|
||||
username.setText(name);
|
||||
tableLayout.addView(tableRow);
|
||||
|
||||
tableRow.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
|
||||
builder.setTitle("操作");
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.paika_item_dialog, null);
|
||||
builder.setView(view);
|
||||
MaterialButton change = view.findViewById(R.id.change);
|
||||
change.setText("插队");
|
||||
MaterialButton removeButton = view.findViewById(R.id.removeButton);
|
||||
removeButton.setText("移除");
|
||||
MaterialButton fuzhushangji = view.findViewById(R.id.fuzhushangji);
|
||||
fuzhushangji.setText("辅助上机");
|
||||
|
||||
change.setOnClickListener(v2->{
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party + "&people=" + use_name + "()" + iconResId + "&changeToPeople=" + players.get(finalI))
|
||||
.put(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
Log.d("123456", "http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party + "&people=" + use_name + "()" + iconResId + "&changeToPeople=" + players.get(finalI));
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
getData();
|
||||
Log.d("123456", "onResponse: " + response.body().string());
|
||||
Snackbar.make(findViewById(R.id.back), "换位成功", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
removeButton.setOnClickListener(v2->{
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + use_party + "&people=" +players.get(finalI))
|
||||
.delete(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
getData();
|
||||
Snackbar.make(findViewById(R.id.back), "移除成功", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
fuzhushangji.setOnClickListener(v2->{
|
||||
if (finalI == 2 ) {
|
||||
Request request = new Request.Builder()
|
||||
.url("http://mai.godserver.cn:11451/api/mai/v1/partyPlay?party=" + use_party )
|
||||
.post(RequestBody.create("", MediaType.parse("application/json")))
|
||||
.build();
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
getData();
|
||||
Snackbar.make(findViewById(R.id.back), "辅助上机成功", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
Log.d("123456", "onFailure: " + e);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
Snackbar.make(findViewById(R.id.back), "辅助上机失败,位置不满足要求", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
builder.show();
|
||||
}
|
||||
});
|
||||
// 添加分割线
|
||||
if (finalI < players.size() - 1) {
|
||||
View separator = new View(context);
|
||||
separator.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
1
|
||||
));
|
||||
separator.setBackgroundColor(ContextCompat.getColor(context, R.color.dividerColor));
|
||||
tableLayout.addView(separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// 用户类
|
||||
private static class User {
|
||||
private String name;
|
||||
private int avatar;
|
||||
|
||||
public User(String name, int avatar) {
|
||||
this.name = name;
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ public class HomeFragment extends Fragment {
|
||||
|
||||
}
|
||||
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -218,19 +218,25 @@ public class PixivFragment extends Fragment {
|
||||
.build();
|
||||
if (query.matches("\\d+")) {
|
||||
request = new Request.Builder()
|
||||
.url("jm.godserver.cn:35621/album/" + query + "/")
|
||||
.url("http://jm.godserver.cn:35621/album/" + query + "/")
|
||||
.build();
|
||||
type = 1;
|
||||
}
|
||||
snackbar = Snackbar.make(requireView(), "加载中", Snackbar.LENGTH_SHORT);
|
||||
snackbar = Snackbar.make(requireView(), "加载中", Snackbar.LENGTH_INDEFINITE);
|
||||
//snackbar长时间显示
|
||||
|
||||
snackbar.show();
|
||||
int finalType = type;
|
||||
Snackbar finalSnackbar = snackbar;
|
||||
Log.d("TAG", "fetchDataJM: " + type);
|
||||
Log.d("TAG", "fetchDataJM: " + query);
|
||||
Log.d("URL", "fetchDataJM: " + request.url());
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
|
||||
String json = response.body().string();
|
||||
if (response.isSuccessful()) {
|
||||
finalSnackbar.dismiss();
|
||||
if(finalType == 0) {
|
||||
System.out.println(json);
|
||||
Gson gson = new Gson();
|
||||
@@ -255,7 +261,13 @@ public class PixivFragment extends Fragment {
|
||||
// 隐藏 Snackbar
|
||||
finalSnackbar.dismiss();
|
||||
});
|
||||
}else if (finalType == 1) {
|
||||
}else {
|
||||
handler.post(() -> {
|
||||
path2.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
path2.setVisibility(View.VISIBLE);
|
||||
});
|
||||
Log.d("fetchDataJM", "onResponse: " + json);
|
||||
Album albumItem = new Gson().fromJson(json, Album.class);
|
||||
openJMProject(albumItem);
|
||||
}
|
||||
@@ -264,13 +276,25 @@ public class PixivFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
|
||||
handler.post(() -> {
|
||||
// 处理失败情况
|
||||
Toast.makeText(requireContext(), "超时", Toast.LENGTH_SHORT).show();
|
||||
finalSnackbar.dismiss();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fetchData(String word, int page, Snackbar snackbar) {
|
||||
if (word.matches("\\d+")) {
|
||||
IllustData illustData = new IllustData();
|
||||
illustData.setId(word);
|
||||
illustData.setTitle(word);
|
||||
illustData.setUrl(word);
|
||||
|
||||
openIllustData(illustData);
|
||||
return;
|
||||
}
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
//设置超时时间60s
|
||||
client.newBuilder().connectTimeout(60, TimeUnit.SECONDS);
|
||||
@@ -427,6 +451,8 @@ public class PixivFragment extends Fragment {
|
||||
user.setText(photoResponse.getBody().getUserName());
|
||||
TextView des = view.findViewById(R.id.des);
|
||||
des.setText(photoResponse.getBody().getDescription());
|
||||
builder.setTitle(photoResponse.getBody().getIllustTitle());
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
14
app/src/main/res/layout/activity_nfc.xml
Normal file
14
app/src/main/res/layout/activity_nfc.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="Waiting for NFC tag..."
|
||||
android:textSize="18sp"/>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -2,124 +2,139 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/colorOnPrimary"
|
||||
android:fillViewport="true">
|
||||
android:fillViewport="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:titleTextColor="@color/white"
|
||||
app:subtitleTextColor="@color/white"
|
||||
android:tooltipText="@string/app_name"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
|
||||
|
||||
<!-- 水平布局包含两个卡片 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<!-- 第一个卡片 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/enterParty">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/party"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="PartyName" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="进入或创建房间"
|
||||
android:id="@+id/enter"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<!-- 输入框,占据剩余空间 -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="输入您的昵称(方便别人识别)" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:text="Default"
|
||||
android:id="@+id/card"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
android:id="@+id/joinParty">
|
||||
<TextView
|
||||
<ImageView
|
||||
android:id="@+id/player1Avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/partyHouse"
|
||||
android:textSize="16sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_launcher"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player1Name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Player 1"
|
||||
android:textColor="@color/textcolorPrimary"
|
||||
android:layout_height="wrap_content"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:textSize="16sp"
|
||||
android:paddingStart="8dp"/>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- 第二个卡片 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="排卡"
|
||||
android:textColor="@color/white"
|
||||
android:id="@+id/add"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/player2Avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/red"
|
||||
android:text="退勤"
|
||||
android:id="@+id/leave"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
android:src="@drawable/ic_launcher"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player2Name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="gone"
|
||||
android:text="上机"
|
||||
android:id="@+id/play"/>
|
||||
android:text="Player 2"
|
||||
android:textColor="@color/textcolorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:paddingStart="8dp"/>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- ScrollView 包含边框 -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="@color/colorOnPrimary">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:stretchColumns="*">
|
||||
<!-- 这里可以添加排序列表的行 -->
|
||||
</TableLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@color/colorSecondary"
|
||||
android:contentDescription="123"
|
||||
android:src="@drawable/id_add"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
|
||||
</LinearLayout>
|
||||
22
app/src/main/res/layout/dialog_uplay.xml
Normal file
22
app/src/main/res/layout/dialog_uplay.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="600dp"
|
||||
android:layout_height="1000dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/colorOnPrimary"
|
||||
android:layout_margin="0dp"
|
||||
android:padding="0dp"> <!-- 移除内边距 -->
|
||||
|
||||
<!-- 上机按钮 -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnPlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="600dp"
|
||||
android:text="上机"
|
||||
android:textColor="@color/white"
|
||||
app:backgroundTint="@color/VlineBaseGreen"
|
||||
android:gravity="center"
|
||||
android:layout_margin="0dp"
|
||||
android:textSize="18sp"/>
|
||||
</LinearLayout>
|
||||
@@ -44,6 +44,10 @@
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp"
|
||||
android:textColor="@color/colorSecondaryVariant"
|
||||
android:id="@+id/dec"/>
|
||||
<com.google.android.material.button.MaterialButton android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="下载全部本子"
|
||||
android:id="@+id/download"/>
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
|
||||
50
app/src/main/res/layout/paika_dialog.xml
Normal file
50
app/src/main/res/layout/paika_dialog.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialogTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="操作选择"
|
||||
android:textSize="20sp"
|
||||
android:textColor="@color/textcolorPrimary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialogMessage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="请选择一个操作"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/textcolorPrimary"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/addButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="排卡"
|
||||
android:textColor="@color/white"
|
||||
app:backgroundTint="@color/VlineBaseGreen"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/leaveButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="退勤"
|
||||
android:textColor="@color/white"
|
||||
app:backgroundTint="@color/red"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/leaveRoomButton"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="退出房间"
|
||||
android:textColor="@color/white"
|
||||
app:backgroundTint="@color/colorPrimary"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
</LinearLayout>
|
||||
19
app/src/main/res/layout/paika_item_dialog.xml
Normal file
19
app/src/main/res/layout/paika_item_dialog.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||
android:padding="16dp"
|
||||
|
||||
android:layout_height="match_parent" android:orientation="vertical">
|
||||
<com.google.android.material.button.MaterialButton android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/change"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
<com.google.android.material.button.MaterialButton android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/removeButton"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
<com.google.android.material.button.MaterialButton android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/fuzhushangji"
|
||||
tools:ignore="MissingConstraints"/>
|
||||
</LinearLayout>
|
||||
25
app/src/main/res/layout/table_row_item.xml
Normal file
25
app/src/main/res/layout/table_row_item.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/userAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_launcher"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Username"
|
||||
android:textColor="@color/textcolorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:paddingStart="16dp"/>
|
||||
</TableRow>
|
||||
@@ -29,4 +29,7 @@
|
||||
<color name="border_color">#000000</color> <!-- 黑色 -->
|
||||
|
||||
<color name="red">#F44336</color>
|
||||
<color name="red2">#FF9189</color>
|
||||
|
||||
<color name="dividerColor">#7D7D7D</color>
|
||||
</resources>
|
||||
5
app/src/main/res/xml/nfc_filter.xml
Normal file
5
app/src/main/res/xml/nfc_filter.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<nfc>
|
||||
<tech-list>
|
||||
<tech>android.nfc.tech.Ndef</tech>
|
||||
</tech-list>
|
||||
</nfc>
|
||||
Reference in New Issue
Block a user