排卡最新升级

This commit is contained in:
2025-04-19 01:01:04 +08:00
parent ec8b2cab60
commit b5fb065208
19 changed files with 1279 additions and 487 deletions

View File

@@ -11,7 +11,7 @@ android {
minSdk 29 minSdk 29
targetSdk 34 targetSdk 34
versionCode 1 versionCode 1
versionName "1.6.1 b" versionName "1.6.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -44,6 +44,8 @@
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" tools:ignore="ProtectedPermissions"/> <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.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/> <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 <application
android:allowBackup="true" android:allowBackup="true"
@@ -78,9 +80,17 @@
</receiver> </receiver>
<service android:name=".ui.widget.MyWidgetService" /> <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 <meta-data
android:name="com.baidu.lbsapi.API_KEY" android:name="com.baidu.lbsapi.API_KEY"
android:value="lzzpL36kTbcmfQvhWDJOZwa3glQlYBbm"/> android:value="lzzpL36kTbcmfQvhWDJOZwa3glQlYBbm"/>
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.MainActivity"
android:exported="true" android:exported="true"
@@ -88,10 +98,25 @@
android:theme="@style/Theme.FindMaimaiUltra.NoActionBar"> android:theme="@style/Theme.FindMaimaiUltra.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </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>
<activity <activity
android:name=".ui.PageActivity" android:name=".ui.PageActivity"
android:exported="true" android:exported="true"
@@ -157,5 +182,4 @@
android:exported="false"> android:exported="false">
</service> </service>
</application> </application>
</manifest> </manifest>

View File

@@ -1,33 +1,55 @@
package org.astral.findmaimaiultra.ui; package org.astral.findmaimaiultra.ui;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; 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.Bundle;
import android.os.Environment;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.animation.Animation; import android.view.animation.Animation;
import android.view.animation.AnimationUtils; import android.view.animation.AnimationUtils;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
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.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.bottomsheet.BottomSheetBehavior;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.astral.findmaimaiultra.R; import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.adapter.PhotoAdapter; import org.astral.findmaimaiultra.adapter.PhotoAdapter;
import org.astral.findmaimaiultra.been.pixiv.jm.Album; 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 { public class JMActivity extends AppCompatActivity {
private FrameLayout overlay; private FrameLayout overlay;
private boolean isOverlayVisible = false; private boolean isOverlayVisible = false;
private BottomSheetBehavior<View> bottomSheetBehavior; private BottomSheetBehavior<View> bottomSheetBehavior;
private PhotoAdapter photoAdapter; private PhotoAdapter photoAdapter;
private static final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1;
private Album album;
@Override @Override
@SuppressLint("MissingInflatedId") @SuppressLint("MissingInflatedId")
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -36,18 +58,19 @@ public class JMActivity extends AppCompatActivity {
initRecyclerView(); initRecyclerView();
} }
@SuppressLint({"ClickableViewAccessibility", "SetTextI18n", "ResourceType"}) @SuppressLint({"ClickableViewAccessibility", "SetTextI18n", "ResourceType"})
private void initRecyclerView() { private void initRecyclerView() {
Intent intent = getIntent(); Intent intent = getIntent();
String res = intent.getStringExtra("album"); String res = intent.getStringExtra("album");
Album a = new Gson().fromJson(res, Album.class); Album a = new Gson().fromJson(res, Album.class);
album = a;
Toast.makeText(this,"加载中", Toast.LENGTH_SHORT).show(); Toast.makeText(this,"加载中", Toast.LENGTH_SHORT).show();
RecyclerView recyclerView = findViewById(R.id.recyclerView); RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setLayoutManager(new LinearLayoutManager(this));
photoAdapter = new PhotoAdapter(this, a.getImage_urls(), a.getNums(), a); photoAdapter = new PhotoAdapter(this, a.getImage_urls(), a.getNums(), a);
photoAdapter.clearLoad(); photoAdapter.clearLoad();
MaterialButton downloadButton = findViewById(R.id.download);
downloadButton.setOnClickListener(v -> downloadAllImages());
recyclerView.setAdapter(photoAdapter); recyclerView.setAdapter(photoAdapter);
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet)); bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
bottomSheetBehavior.setPeekHeight(dpToPx(80)); bottomSheetBehavior.setPeekHeight(dpToPx(80));
@@ -59,6 +82,67 @@ public class JMActivity extends AppCompatActivity {
+ " \n " + a.getTags().toString().replaceAll( "\"","") .replaceAll( "\\[","").replaceAll( "]","") + " \n " + a.getTags().toString().replaceAll( "\"","") .replaceAll( "\\[","").replaceAll( "]","")
+ " \n " + a.getAlbum_id().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) { public int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density); return (int) (dp * getResources().getDisplayMetrics().density);
} }
@@ -69,4 +153,54 @@ public class JMActivity extends AppCompatActivity {
photoAdapter.clearCache(); 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;
}
} }

View File

@@ -22,7 +22,9 @@ import com.google.gson.Gson;
import okhttp3.*; import okhttp3.*;
import org.astral.findmaimaiultra.R; import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.been.faker.RegionData; import org.astral.findmaimaiultra.been.faker.RegionData;
import org.astral.findmaimaiultra.been.faker.UserData;
import org.astral.findmaimaiultra.been.faker.UserRegion; import org.astral.findmaimaiultra.been.faker.UserRegion;
import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@@ -158,6 +160,7 @@ public class LinkQQBot extends AppCompatActivity {
Toast.makeText(LinkQQBot.this, "设置已保存,您的UsrId已写入硬盘!", Toast.LENGTH_SHORT).show(); Toast.makeText(LinkQQBot.this, "设置已保存,您的UsrId已写入硬盘!", Toast.LENGTH_SHORT).show();
try { try {
getUserRegionData(responseData); getUserRegionData(responseData);
getUserData(responseData);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(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 { private void getUserRegionData(String userId) throws Exception {
String url = "http://mai.godserver.cn:11451/api/qq/region2?qq=" + userId ; String url = "http://mai.godserver.cn:11451/api/qq/region2?qq=" + userId ;

View File

@@ -2,12 +2,17 @@ package org.astral.findmaimaiultra.ui;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.*; import android.content.*;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@@ -36,6 +41,11 @@ import org.astral.findmaimaiultra.ui.home.HomeFragment;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; 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; import static android.app.Activity.RESULT_OK;
@@ -44,15 +54,26 @@ public class MainActivity extends AppCompatActivity implements ImagePickerListen
private AppBarConfiguration mAppBarConfiguration; private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding; private ActivityMainBinding binding;
private SharedPreferences settingProperties; private SharedPreferences settingProperties;
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(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()); binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
settingProperties = getSharedPreferences("setting", Context.MODE_PRIVATE); settingProperties = getSharedPreferences("setting", Context.MODE_PRIVATE);
setSupportActionBar(binding.appBarMain.toolbar); setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout; DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView; NavigationView navigationView = binding.navView;
@@ -67,6 +88,122 @@ public class MainActivity extends AppCompatActivity implements ImagePickerListen
NavigationUI.setupWithNavController(navigationView, navController); 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-81表示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 @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present. // 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; return false;
} }
private void updatePlace() { private void updatePlace() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this); MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
LinearLayout layout = new LinearLayout(this); LinearLayout layout = new LinearLayout(this);

View File

@@ -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);
}
}

View File

@@ -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-81表示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;
}
}
}

View File

@@ -2,429 +2,547 @@ package org.astral.findmaimaiultra.ui;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.*; import android.widget.*;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.google.android.material.button.MaterialButton; 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.android.material.textfield.TextInputEditText;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import okhttp3.*; import okhttp3.*;
import org.astral.findmaimaiultra.R; import org.astral.findmaimaiultra.R;
import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class PaikaActivity extends AppCompatActivity { 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 SharedPreferences sharedPreferences;
private TextInputEditText name; private String use_party;
private String paikaname; private String use_name;
private MaterialButton add; private int iconId;
private MaterialButton play; private int iconResId = iconId;
private MaterialButton leave; private int status;
private MaterialButton card; private Toolbar toolbar;
private Handler handler; private List<String> players = new ArrayList<>();
private String cardStyle; private Handler handler = new Handler();
private String old = ""; private ImageView player1Avatar;
private ImageView player2Avatar;
private TextView player1Name;
private TextView player2Name;
private boolean isPlaying = false;
@SuppressLint("MissingInflatedId") @SuppressLint("MissingInflatedId")
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
setContentView(R.layout.activity_paika); setContentView(R.layout.activity_paika);
enter = findViewById(R.id.enter); sharedPreferences = getSharedPreferences("setting", Context.MODE_PRIVATE);
partyName = findViewById(R.id.party); handler.postDelayed(refreshTask, 3000);
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();
}
@Override use_name = sharedPreferences.getString("paikaname", "");
public void onFailure(@NonNull Call call, @NonNull IOException e) { 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);
leave.setOnClickListener(v->{ if (use_name.equals("")) {
Request request = new Request.Builder() //询问并做个名字
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party + "&people=" + paikaname) MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
.delete() builder.setTitle("请输入昵称");
.build(); TextInputEditText textInputEditText = new TextInputEditText(this);
play.setVisibility(View.GONE); builder.setView(textInputEditText);
builder.setPositiveButton("确定", (dialog, which) -> {
client.newCall(request).enqueue(new Callback() { use_name = textInputEditText.getText().toString();
@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();
dialog.dismiss(); dialog.dismiss();
}); });
layout.addView(button); builder.setNegativeButton("取消", null);
builder.show();
} }
// 设置 AlertDialog 的内容视图 status = sharedPreferences.getInt("paikastatus", 0);
dialog.setView(dialogView); toolbar = findViewById(R.id.toolbar);
// 显示 AlertDialog Intent intent = getIntent();
dialog.show(); if (intent.getStringExtra("data") != null) {
}); String data = intent.getStringExtra("data");
Log.d("123456", data);
} use_party = data.split("paika")[1];
private void updateCard() { Log.d("partySetting", use_party);
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());
}
@Override if (sharedPreferences.getString("use_party", "").equals(use_party)) {
public void onFailure(@NonNull Call call, @NonNull IOException e) { getData();
handler.postDelayed(new Runnable() {
}
});
}
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() {
@Override @Override
public void run() { public void run() {
joinParty(); if (players != null && !players.isEmpty()) {
handler.postDelayed(this, 5000); // 如果 players 不为空,执行 doUPlay()
doUPlay();
} else {
// 如果 players 为空,继续延迟 1 秒后检查
handler.postDelayed(this, 1000);
} }
};
handler.post(runnable);
} }
private void joinParty() { }, 1000); // 延迟 1 秒
getShangJiPeople();
Request request = new Request.Builder() }else {
.url("http://mai.godserver.cn:11451/api/mai/v1/party?party=" + party) toolbar.setTitle(use_party + " 房间 " + use_name);
.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;
} }
} catch (IOException e) { }else
throw new RuntimeException(e); 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(); SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("paikaname", paikaname); editor.putString("use_party", use_party);
editor.commit(); editor.apply();
runOnUiThread(() -> { getData();
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);
}
}); });
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 SharedPreferences.Editor editor = sharedPreferences.edit();
public void onFailure(@NonNull Call call, @NonNull IOException e) { editor.putString("use_party", use_party);
Log.e("MainLaunch", "onFailure: ", e); editor.apply();
} getData();
}); });
builder.setNegativeButton("取消", null);
builder.show();
} }
private void updateUserCard(ImageView imageView,String people) { Log.d("123456", status + "");
Request request = new Request.Builder() toolbar.setTitle(use_party + " 房间 " + use_name);
.url("http://mai.godserver.cn:11451/api/mai/v1/player?people=" + people + "&party=" + party) if (status == 1) {
.build(); toolbar.setTitle(use_party + " 房间 " + use_name + " 正在队列");
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);
});
} }
} toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.white));
// 添加测试数据到 TableLayout
@Override FloatingActionButton fab = findViewById(R.id.fab);
public void onFailure(@NonNull Call call, @NonNull IOException e) { fab.setOnClickListener(new View.OnClickListener() {
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() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Request request = null; doFab(view);
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();
} }
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 private void doUPlay() {
public void onFailure(@NonNull Call call, @NonNull IOException e) { // 使用 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() 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(); .build();
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() { client.newCall(request).enqueue(new Callback() {
@Override @Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string(); if (response.isSuccessful()) {
runOnUiThread(()->{ String res = response.body().string();
partyHouse.setText("房间号"+ party+" "+data + "正在上机"); players = new Gson().fromJson(res, new TypeToken<List<String>>() {
}); }.getType());
addDataToTableLayout();
}
} }
@Override @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;
}
}
} }

View File

@@ -98,6 +98,7 @@ public class HomeFragment extends Fragment {
} }
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
} }
@Override @Override

View File

@@ -218,19 +218,25 @@ public class PixivFragment extends Fragment {
.build(); .build();
if (query.matches("\\d+")) { if (query.matches("\\d+")) {
request = new Request.Builder() request = new Request.Builder()
.url("jm.godserver.cn:35621/album/" + query + "/") .url("http://jm.godserver.cn:35621/album/" + query + "/")
.build(); .build();
type = 1; type = 1;
} }
snackbar = Snackbar.make(requireView(), "加载中", Snackbar.LENGTH_SHORT); snackbar = Snackbar.make(requireView(), "加载中", Snackbar.LENGTH_INDEFINITE);
//snackbar长时间显示
snackbar.show(); snackbar.show();
int finalType = type; int finalType = type;
Snackbar finalSnackbar = snackbar; 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() { client.newCall(request).enqueue(new Callback() {
@Override @Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String json = response.body().string(); String json = response.body().string();
if (response.isSuccessful()) { if (response.isSuccessful()) {
finalSnackbar.dismiss();
if(finalType == 0) { if(finalType == 0) {
System.out.println(json); System.out.println(json);
Gson gson = new Gson(); Gson gson = new Gson();
@@ -255,7 +261,13 @@ public class PixivFragment extends Fragment {
// 隐藏 Snackbar // 隐藏 Snackbar
finalSnackbar.dismiss(); 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); Album albumItem = new Gson().fromJson(json, Album.class);
openJMProject(albumItem); openJMProject(albumItem);
} }
@@ -264,13 +276,25 @@ public class PixivFragment extends Fragment {
@Override @Override
public void onFailure(@NotNull Call call, @NotNull IOException e) { 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) { 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(); OkHttpClient client = new OkHttpClient();
//设置超时时间60s //设置超时时间60s
client.newBuilder().connectTimeout(60, TimeUnit.SECONDS); client.newBuilder().connectTimeout(60, TimeUnit.SECONDS);
@@ -427,6 +451,8 @@ public class PixivFragment extends Fragment {
user.setText(photoResponse.getBody().getUserName()); user.setText(photoResponse.getBody().getUserName());
TextView des = view.findViewById(R.id.des); TextView des = view.findViewById(R.id.des);
des.setText(photoResponse.getBody().getDescription()); des.setText(photoResponse.getBody().getDescription());
builder.setTitle(photoResponse.getBody().getIllustTitle());
}); });
} }
} }

View 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>

View File

@@ -2,124 +2,139 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" 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: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 <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="16dp"> 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 <ImageView
android:layout_width="0dp" android:id="@+id/player1Avatar"
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
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:id="@+id/partyHouse" android:layout_height="wrap_content"
android:textSize="16sp" 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:textColor="@color/textcolorPrimary"
android:layout_height="wrap_content"/> android:textSize="16sp"
<com.google.android.material.button.MaterialButton 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="排卡" android:orientation="horizontal"
android:textColor="@color/white" android:gravity="center_vertical"
android:id="@+id/add"/> android:padding="16dp">
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent" <ImageView
android:id="@+id/player2Avatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/red" android:src="@drawable/ic_launcher"
android:text="退勤" android:adjustViewBounds="true"
android:id="@+id/leave"/> android:maxWidth="48dp"
<com.google.android.material.button.MaterialButton android:maxHeight="48dp"/>
android:layout_width="match_parent"
<TextView
android:id="@+id/player2Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/white" android:text="Player 2"
android:visibility="gone" android:textColor="@color/textcolorPrimary"
android:text="上机" android:textSize="16sp"
android:id="@+id/play"/> 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 <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent">
<TableLayout <TableLayout
android:id="@+id/tableLayout" android:id="@+id/tableLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:stretchColumns="*"> android:stretchColumns="*">
<!-- 这里可以添加排序列表的行 -->
</TableLayout> </TableLayout>
</ScrollView> </ScrollView>
</LinearLayout> </com.google.android.material.card.MaterialCardView>
</LinearLayout> <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> </LinearLayout>

View 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>

View File

@@ -44,6 +44,10 @@
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp"
android:textColor="@color/colorSecondaryVariant" android:textColor="@color/colorSecondaryVariant"
android:id="@+id/dec"/> 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> </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View 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>

View 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>

View 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>

View File

@@ -29,4 +29,7 @@
<color name="border_color">#000000</color> <!-- 黑色 --> <color name="border_color">#000000</color> <!-- 黑色 -->
<color name="red">#F44336</color> <color name="red">#F44336</color>
<color name="red2">#FF9189</color>
<color name="dividerColor">#7D7D7D</color>
</resources> </resources>

View File

@@ -0,0 +1,5 @@
<nfc>
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</nfc>