This commit is contained in:
2025-03-24 21:43:54 +08:00
commit 8443a94b73
168 changed files with 16532 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
package org.astral.findmaimaiultra;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("org.astral.findmaimaiultra", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- 允许获取精确位置,精准定位必选 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 后台获取位置信息,若需后台定位则必选 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- 用于申请调用A-GPS模块,卫星定位加速 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="35"
tools:ignore="ScopedStorage"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="35"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<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"/>
<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
tools:targetApi="34"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:persistent="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:icon="@drawable/ic_launcher"
android:roundIcon="@drawable/ic_launcher"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:enableOnBackInvokedCallback="true"
android:theme="@style/Theme.FindMaimaiUltra">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.FindMaimaiUltra.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".ui.PageActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.FindMaimaiUltra.NoActionBar">
</activity>
<activity
android:name=".ui.LinkQQBot"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.FindMaimaiUltra.NoActionBar">
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,152 @@
package org.astral.findmaimaiultra.adapter;
import android.annotation.SuppressLint;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.been.Place;
import java.util.List;
public class PlaceAdapter extends RecyclerView.Adapter<PlaceAdapter.PlaceViewHolder> {
private List<Place> placeList;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(Place place);
}
public PlaceAdapter(List<Place> placeList, OnItemClickListener listener) {
this.placeList = placeList;
this.listener = listener;
}
@NonNull
@Override
public PlaceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_place, parent, false);
return new PlaceViewHolder(itemView);
}
@SuppressLint({"SetTextI18n", "UseCompatLoadingForDrawables"})
@Override
public void onBindViewHolder(@NonNull PlaceViewHolder holder, int position) {
Place place = placeList.get(position);
if (place.getIsUse()==0) {
holder.nameTextView.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.red));
}
if (place.getName().contains("收藏")) {
holder.nameTextView.setText(place.getName() + "");
} else {
holder.nameTextView.setText(place.getName());
}
holder.provinceTextView.setText(place.getProvince());
holder.cityTextView.setText(place.getCity());
holder.areaTextView.setText(place.getArea());
holder.addressTextView.setText(place.getAddress());
double rating = (double) ((place.getNum() + place.getNumJ()) * (place.getGood() + 1)) / (place.getGood() + place.getBad() + 1);
Log.i("rating", rating + "");
if (rating >= 3) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_sssp));
} else if (rating < 3 && rating >= 2) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_sss));
} else if (rating < 2 && rating >= 1) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_ss));
} else if (rating < 1 && rating >= 0.5) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_s));
} else if (rating < 0.5 && rating >= 0) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_s));
} else {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.rank_a));
}
Log.i("rating", rating + "|" + place.getName());
// 控制竖线的位置
controlVerticalLines(holder, place);
// 设置点击监听器
holder.itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onItemClick(place);
}
});
}
private void controlVerticalLines(PlaceViewHolder holder, Place place) {
ConstraintLayout horizontalLinesContainer = holder.itemView.findViewById(R.id.horizontalLinesContainer);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(horizontalLinesContainer);
double rating = (double) ((place.getNum() + place.getNumJ()) * (place.getGood() + 5)) / (place.getBad() + 5);
// 根据 rating 计算竖线的位置百分比
float bias1 = (float) (rating / 3.0); // 示例百分比,假设 rating 最大为 3
float bias2 = (float) (2 * rating / 3.0); // 示例百分比,假设 rating 最大为 3
float bias3 = 1.0f; // 第三条竖线始终在最右边
// 确保 bias 不超过 1.0
bias1 = Math.min(bias1, 1.0f);
bias2 = Math.min(bias2, 1.0f);
// 设置 Guideline 的位置
constraintSet.setGuidelinePercent(R.id.guideline1, bias1);
constraintSet.setGuidelinePercent(R.id.guideline2, bias2);
constraintSet.setGuidelinePercent(R.id.guideline3, bias3);
if (rating >= 3) {
// 显示所有竖线
constraintSet.setVisibility(R.id.verticalLine1, View.VISIBLE);
constraintSet.setVisibility(R.id.verticalLine2, View.VISIBLE);
constraintSet.setVisibility(R.id.verticalLine3, View.VISIBLE);
} else if (rating < 3 && rating >= 2) {
// 显示前两条竖线
constraintSet.setVisibility(R.id.verticalLine1, View.VISIBLE);
constraintSet.setVisibility(R.id.verticalLine2, View.VISIBLE);
constraintSet.setVisibility(R.id.verticalLine3, View.GONE);
} else if (rating < 2 && rating >= 1) {
// 显示第一条竖线
constraintSet.setVisibility(R.id.verticalLine1, View.VISIBLE);
constraintSet.setVisibility(R.id.verticalLine2, View.GONE);
constraintSet.setVisibility(R.id.verticalLine3, View.GONE);
} else {
// 不显示竖线
constraintSet.setVisibility(R.id.verticalLine1, View.GONE);
constraintSet.setVisibility(R.id.verticalLine2, View.GONE);
constraintSet.setVisibility(R.id.verticalLine3, View.GONE);
}
constraintSet.applyTo(horizontalLinesContainer);
}
@Override
public int getItemCount() {
return placeList.size();
}
static class PlaceViewHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
TextView provinceTextView;
TextView cityTextView;
TextView areaTextView;
TextView addressTextView;
ImageView imageView;
PlaceViewHolder(@NonNull View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.nameTextView);
provinceTextView = itemView.findViewById(R.id.provinceTextView);
cityTextView = itemView.findViewById(R.id.cityTextView);
areaTextView = itemView.findViewById(R.id.areaTextView);
addressTextView = itemView.findViewById(R.id.addressTextView);
imageView = itemView.findViewById(R.id.photoId);
}
}
}

View File

@@ -0,0 +1,63 @@
package org.astral.findmaimaiultra.adapter;
import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.astral.findmaimaiultra.been.PlaceContent;
import java.util.List;
public class ReviewAdapter extends RecyclerView.Adapter<ReviewAdapter.ViewHolder> {
private List<PlaceContent> reviews;
public ReviewAdapter(List<PlaceContent> reviews) {
this.reviews = reviews;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
return new ViewHolder(view);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
PlaceContent review = reviews.get(position);
if(review.isUsed()) {
holder.textViewUser.setText(review.getUser_name());
holder.textViewContent.setText(review.getUser_content());
}
}
@Override
public int getItemCount() {
return reviews.size();
}
public void addReview(PlaceContent review) {
reviews.add(review);
notifyItemInserted(reviews.size() - 1);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView textViewUser;
TextView textViewContent;
public ViewHolder(@NonNull View itemView) {
super(itemView);
textViewUser = itemView.findViewById(android.R.id.text1);
textViewContent = itemView.findViewById(android.R.id.text2);
textViewUser.setTextSize(18);
textViewContent.setTextSize(14);
}
}
}

View File

@@ -0,0 +1,50 @@
package org.astral.findmaimaiultra.been;
public class AiLog {
private long id;
private String x;
private String y;
private String androidId;
private String message;
private String time;
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
public String getAndroidId() {
return androidId;
}
public void setAndroidId(String androidId) {
this.androidId = androidId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}

View File

@@ -0,0 +1,22 @@
package org.astral.findmaimaiultra.been;
public class AiUserMessage {
private String Time;
private String Message;
public String getTime() {
return Time;
}
public void setTime(String time) {
Time = time;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
}

View File

@@ -0,0 +1,51 @@
package org.astral.findmaimaiultra.been;
import java.util.List;
public class AmapReverseGeocodeResponse {
private String status;
private String info;
private Regeocode regeocode;
public String getStatus() {
return status;
}
public Regeocode getRegeocode() {
return regeocode;
}
public static class Regeocode {
private String formatted_address;
private AddressComponent addressComponent;
public String getFormattedAddress() {
return formatted_address;
}
public AddressComponent getAddressComponent() {
return addressComponent;
}
}
public static class AddressComponent {
private String province;
private List<String> city;
public String getProvince() {
return province;
}
public List<String> getCity() {
return city;
}
public void setProvince(String province) {
this.province = province;
}
public void setCity(List<String> city) {
this.city = city;
}
}
}

View File

@@ -0,0 +1,138 @@
package org.astral.findmaimaiultra.been;
import com.google.gson.annotations.SerializedName;
public class Chart {
@SerializedName("achievements")
private double achievements;
@SerializedName("ds")
private double ds;
@SerializedName("dxScore")
private int dxScore;
@SerializedName("fc")
private String fc;
@SerializedName("fs")
private String fs;
@SerializedName("level")
private String level;
@SerializedName("level_index")
private int level_index;
@SerializedName("level_label")
private String levelLabel;
@SerializedName("ra")
private int ra;
@SerializedName("rate")
private String rate;
@SerializedName("song_id")
private int songId;
@SerializedName("title")
private String title;
@SerializedName("type")
private String type;
public double getAchievements() {
return achievements;
}
public void setAchievements(double achievements) {
this.achievements = achievements;
}
public double getDs() {
return ds;
}
public void setDs(double ds) {
this.ds = ds;
}
public int getDxScore() {
return dxScore;
}
public void setDxScore(int dxScore) {
this.dxScore = dxScore;
}
public String getFc() {
return fc;
}
public void setFc(String fc) {
this.fc = fc;
}
public String getFs() {
return fs;
}
public void setFs(String fs) {
this.fs = fs;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public int getLevel_index() {
return level_index;
}
public void setLevel_index(int level_index) {
this.level_index = level_index;
}
public String getLevelLabel() {
return levelLabel;
}
public void setLevelLabel(String levelLabel) {
this.levelLabel = levelLabel;
}
public int getRa() {
return ra;
}
public void setRa(int ra) {
this.ra = ra;
}
public String getRate() {
return rate;
}
public void setRate(String rate) {
this.rate = rate;
}
public int getSongId() {
return songId;
}
public void setSongId(int songId) {
this.songId = songId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
// Getters and Setters
}

View File

@@ -0,0 +1,88 @@
package org.astral.findmaimaiultra.been;
import java.io.Serializable;
public class ChartPlay implements Serializable {
private String songName;
private String length;
private String difficulty;
private String chartZipUrl;
private int likes;
private int downloads;
private String author;
private int id;
private boolean isUsed;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isUsed() {
return isUsed;
}
public void setUsed(boolean used) {
isUsed = used;
}
// Getters and Setters
public String getSongName() {
return songName;
}
public void setSongName(String songName) {
this.songName = songName;
}
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
public String getDifficulty() {
return difficulty;
}
public void setDifficulty(String difficulty) {
this.difficulty = difficulty;
}
public String getChartZipUrl() {
return chartZipUrl;
}
public void setChartZipUrl(String chartZipUrl) {
this.chartZipUrl = chartZipUrl;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
public int getDownloads() {
return downloads;
}
public void setDownloads(int downloads) {
this.downloads = downloads;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}

View File

@@ -0,0 +1,28 @@
package org.astral.findmaimaiultra.been;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Charts {
@SerializedName("dx")
private List<Chart> dx;
@SerializedName("sd")
private List<Chart> sd;
// Getters and Setters
public List<Chart> getDx() {
return dx;
}
public void setDx(List<Chart> dx) {
this.dx = dx;
}
public List<Chart> getSd() {
return sd;
}
public void setSd(List<Chart> sd) {
this.sd = sd;
}
}

View File

@@ -0,0 +1,57 @@
package org.astral.findmaimaiultra.been;
public class ChatMessage {
private String message;
private String time;
private boolean isUser;
private boolean isThinking;
public ChatMessage(String message, boolean isUser) {
this.message = message;
this.isUser = isUser;
this.isThinking = false;
}
public ChatMessage(String message, boolean isUser,String time) {
this.message = message;
this.isUser = isUser;
this.isThinking = false;
this.time = time;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public void setUser(boolean user) {
isUser = user;
}
public void setThinking(boolean thinking) {
isThinking = thinking;
}
public ChatMessage(String message, boolean isUser, boolean isThinking) {
this.message = message;
this.isUser = isUser;
this.isThinking = isThinking;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isUser() {
return isUser;
}
public boolean isThinking() {
return isThinking;
}
}

View File

@@ -0,0 +1,61 @@
package org.astral.findmaimaiultra.been;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class CompassView extends View {
private Paint paint;
private float direction = 0.0f;
public CompassView(Context context) {
super(context);
init();
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
}
public void setDirection(float direction) {
this.direction = direction;
invalidate(); // 重新绘制
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int center = Math.min(width, height) / 2;
// 绘制指南针中心
canvas.drawCircle(width / 2, height / 2, center, paint);
// 绘制指针
float angle = (direction + 180) * (float) Math.PI / 180;
float x = (float) (width / 2 + center * 0.8 * Math.cos(angle));
float y = (float) (height / 2 + center * 0.8 * Math.sin(angle));
paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
canvas.drawLine(width / 2, height / 2, x, y, paint);
}
}

View File

@@ -0,0 +1,71 @@
package org.astral.findmaimaiultra.been;
import org.astral.findmaimaiultra.been.lx.Notes;
public class Difficulty {
private String type;
private int difficulty;
private String level;
private double level_value;
private String note_designer;
private int version;
private Notes notes;
// Getters and Setters
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getDifficulty() {
return difficulty;
}
public void setDifficulty(int difficulty) {
this.difficulty = difficulty;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public double getLevel_value() {
return level_value;
}
public void setLevel_value(double level_value) {
this.level_value = level_value;
}
public String getNote_designer() {
return note_designer;
}
public void setNote_designer(String note_designer) {
this.note_designer = note_designer;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Notes getNotes() {
return notes;
}
public void setNotes(Notes notes) {
this.notes = notes;
}
}

View File

@@ -0,0 +1,82 @@
package org.astral.findmaimaiultra.been;
public class DistanceCalculator {
// 地球椭球参数WGS-84
private static final double a = 6378137.0; // 长半轴
private static final double b = 6356752.314245; // 短半轴
private static final double f = 1 / 298.257223563; // 扁率
// 计算两点之间的距离
public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
// 将角度转换为弧度
lat1 = Math.toRadians(lat1);
lon1 = Math.toRadians(lon1);
lat2 = Math.toRadians(lat2);
lon2 = Math.toRadians(lon2);
// 计算纬度差和经度差
double L = lon2 - lon1;
double U1 = Math.atan((1 - f) * Math.tan(lat1));
double U2 = Math.atan((1 - f) * Math.tan(lat2));
double sinU1 = Math.sin(U1);
double cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2);
double cosU2 = Math.cos(U2);
double lambda = L;
double lambdaP = 2 * Math.PI;
double iterLimit = 20;
double cosSqAlpha = 0;
double sinSigma = 0;
double cosSigma = 0;
double cos2SigmaM = 0;
double sigma = 0;
while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0) {
double sinLambda = Math.sin(lambda);
double cosLambda = Math.cos(lambda);
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +
(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
if (sinSigma == 0) {
return 0; // 两点重合
}
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
double sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
if (Double.isNaN(cos2SigmaM)) {
cos2SigmaM = 0; // 两点位于赤道上
}
double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
lambdaP = lambda;
lambda = L + (1 - C) * f * sinAlpha *
(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
}
if (iterLimit == 0) {
return 0; // 迭代次数超过限制
}
double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
double s = b * A * (sigma - deltaSigma);
return s / 1000; // 返回距离(单位:公里)
}
public static void main(String[] args) {
double lat1 = 39.9042; // 北京
double lon1 = 116.4074;
double lat2 = 31.2304; // 上海
double lon2 = 121.4737;
double distance = calculateDistance(lat1, lon1, lat2, lon2);
System.out.println("Distance between Beijing and Shanghai: " + distance + " km");
}
}

View File

@@ -0,0 +1,125 @@
package org.astral.findmaimaiultra.been;
import android.os.Parcel;
import android.os.Parcelable;
public class Geocode implements Parcelable {
private String formatted_address;
private String country;
private String province;
private String citycode;
private String city;
private String district;
private String location;
private String level;
public Geocode() {}
// 必须实现的构造函数用于从Parcel中读取数据
protected Geocode(Parcel in) {
formatted_address = in.readString();
country = in.readString();
province = in.readString();
citycode = in.readString();
city = in.readString();
district = in.readString();
location = in.readString();
level = in.readString();
}
// 必须实现的方法用于将对象写入Parcel
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(formatted_address);
dest.writeString(country);
dest.writeString(province);
dest.writeString(citycode);
dest.writeString(city);
dest.writeString(district);
dest.writeString(location);
dest.writeString(level);
}
// 必须实现的方法返回一个CREATOR对象
@Override
public int describeContents() {
return 0;
}
public static final Creator<Geocode> CREATOR = new Creator<Geocode>() {
@Override
public Geocode createFromParcel(Parcel in) {
return new Geocode(in);
}
@Override
public Geocode[] newArray(int size) {
return new Geocode[size];
}
};
// Getter and Setter methods
public void setFormatted_address(String formatted_address) {
this.formatted_address = formatted_address;
}
public String getFormatted_address() {
return formatted_address;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return country;
}
public void setProvince(String province) {
this.province = province;
}
public String getProvince() {
return province;
}
public void setCitycode(String citycode) {
this.citycode = citycode;
}
public String getCitycode() {
return citycode;
}
public void setCity(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setDistrict(String district) {
this.district = district;
}
public String getDistrict() {
return district;
}
public void setLocation(String location) {
this.location = location;
}
public String getLocation() {
return location;
}
public void setLevel(String level) {
this.level = level;
}
public String getLevel() {
return level;
}
}

View File

@@ -0,0 +1,31 @@
package org.astral.findmaimaiultra.been;
public class GpsData {
private double x;
private double y;
private String key;
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,80 @@
package org.astral.findmaimaiultra.been;
public class Market {
private int id;
private String marketName;
private double distance;
private int parentId;
private double x;
private double y;
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMarketName() {
return marketName;
}
public void setMarketName(String marketName) {
this.marketName = marketName;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
@Override
public String toString() {
return "{" +
"\"id\":" + id +
", \"marketName\":\"" + marketName + '\"' +
", \"distance=\":" + distance +
", \"parentId\":" + parentId +
", \"x\":" + x +
", \"y\":" + y +
", \"type\":" + type +
'}';
}
}

View File

@@ -0,0 +1,28 @@
package org.astral.findmaimaiultra.been;
// Message.java
public class Message {
private String role;
private String content;
public Message(String role, String content) {
this.role = role;
this.content = content;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@@ -0,0 +1,214 @@
package org.astral.findmaimaiultra.been;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class Place implements Parcelable {
private int id;
private String name;
private String province;
private String city;
private String area;
private String address;
private int isUse;
private double x;
private double y;
private int count;
private int good;
private int bad;
public int num;
public int numJ;
private String meituan_link;
private String douyin_link;
public String getMeituan_link() {
return meituan_link;
}
public void setMeituan_link(String meituan_link) {
this.meituan_link = meituan_link;
}
public String getDouyin_link() {
return douyin_link;
}
public void setDouyin_link(String douyin_link) {
this.douyin_link = douyin_link;
}
public int getNumJ() {
return numJ;
}
public void setNumJ(int numJ) {
this.numJ = numJ;
}
public Place(int id, String name, String province, String city, String area, String address, int isUse, double x, double y, int count, int good, int bad) {
this.id = id;
this.name = name;
this.province = province;
this.city = city;
this.area = area;
this.address = address;
this.isUse = isUse;
this.x = x;
this.y = y;
this.count = count;
this.good = good;
this.bad = bad;
}
protected Place(Parcel in) {
id = in.readInt();
name = in.readString();
province = in.readString();
city = in.readString();
area = in.readString();
address = in.readString();
isUse = in.readInt();
x = in.readDouble();
y = in.readDouble();
count = in.readInt();
good = in.readInt();
bad = in.readInt();
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public static final Creator<Place> CREATOR = new Creator<Place>() {
@Override
public Place createFromParcel(Parcel in) {
return new Place(in);
}
@Override
public Place[] newArray(int size) {
return new Place[size];
}
};
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getIsUse() {
return isUse;
}
public void setIsUse(int isUse) {
this.isUse = isUse;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getGood() {
return good;
}
public void setGood(int good) {
this.good = good;
}
public int getBad() {
return bad;
}
public void setBad(int bad) {
this.bad = bad;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeString(province);
dest.writeString(city);
dest.writeString(area);
dest.writeString(address);
dest.writeInt(isUse);
dest.writeDouble(x);
dest.writeDouble(y);
dest.writeInt(count);
dest.writeInt(good);
dest.writeInt(bad);
}
}

View File

@@ -0,0 +1,49 @@
package org.astral.findmaimaiultra.been;
public class PlaceContent {
private int id;
private String user_name;
private String user_content;
private int place_id;
private boolean used;
public boolean isUsed() {
return used;
}
public void setUsed(boolean used) {
this.used = used;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_content() {
return user_content;
}
public void setUser_content(String user_content) {
this.user_content = user_content;
}
public int getPlace_id() {
return place_id;
}
public void setPlace_id(int place_id) {
this.place_id = place_id;
}
}

View File

@@ -0,0 +1,79 @@
package org.astral.findmaimaiultra.been;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class PlayerData {
@SerializedName("additional_rating")
private int additionalRating;
@SerializedName("charts")
private Charts charts;
@SerializedName("nickname")
private String nickname;
@SerializedName("plate")
private String plate;
@SerializedName("rating")
private int rating;
@SerializedName("user_general_data")
private Object userGeneralData;
@SerializedName("username")
private String username;
// Getters and Setters
public int getAdditionalRating() {
return additionalRating;
}
public void setAdditionalRating(int additionalRating) {
this.additionalRating = additionalRating;
}
public Charts getCharts() {
return charts;
}
public void setCharts(Charts charts) {
this.charts = charts;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPlate() {
return plate;
}
public void setPlate(String plate) {
this.plate = plate;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public Object getUserGeneralData() {
return userGeneralData;
}
public void setUserGeneralData(Object userGeneralData) {
this.userGeneralData = userGeneralData;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@@ -0,0 +1,50 @@
package org.astral.findmaimaiultra.been;
import com.google.gson.annotations.SerializedName;
public class Release {
@SerializedName("tag_name")
private String tagName;
@SerializedName("name")
private String name;
@SerializedName("body")
private String body;
@SerializedName("html_url")
private String htmlUrl;
// Getters and setters
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getHtmlUrl() {
return htmlUrl;
}
public void setHtmlUrl(String htmlUrl) {
this.htmlUrl = htmlUrl;
}
}

View File

@@ -0,0 +1,30 @@
package org.astral.findmaimaiultra.been;
// RequestData.java
import java.util.List;
public class RequestData {
private String model;
private List<Message> messages;
public RequestData(String model, List<Message> messages) {
this.model = model;
this.messages = messages;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
}

View File

@@ -0,0 +1,41 @@
package org.astral.findmaimaiultra.been;
// ResponseData.java
public class ResponseData {
private String model;
private String created_at;
private String response;
private boolean done;
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
}

View File

@@ -0,0 +1,79 @@
package org.astral.findmaimaiultra.been.faker;
public class MusicRating {
private int musicId;
private String musicName;
private int level;
private double level_info;
private int romVersion;
private int achievement;
private int rating;
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMusicName() {
return musicName;
}
public void setMusicName(String musicName) {
this.musicName = musicName;
}
public double getLevel_info() {
return level_info;
}
public void setLevel_info(double level_info) {
this.level_info = level_info;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
// Getters and Setters
public int getMusicId() {
return musicId;
}
public void setMusicId(int musicId) {
this.musicId = musicId;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getRomVersion() {
return romVersion;
}
public void setRomVersion(int romVersion) {
this.romVersion = romVersion;
}
public int getAchievement() {
return achievement;
}
public void setAchievement(int achievement) {
this.achievement = achievement;
}
}

View File

@@ -0,0 +1,40 @@
package org.astral.findmaimaiultra.been.faker;
public class QRCodeMessage {
private int errorID;
private String key;
private String timestamp;
private int userID;
public int getErrorID() {
return errorID;
}
public void setErrorID(int errorID) {
this.errorID = errorID;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
}

View File

@@ -0,0 +1,33 @@
package org.astral.findmaimaiultra.been.faker;
import java.util.List;
public class RegionData {
private int userId;
private int length;
private List<UserRegion> userRegionList;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public List<UserRegion> getUserRegionList() {
return userRegionList;
}
public void setUserRegionList(List<UserRegion> userRegionList) {
this.userRegionList = userRegionList;
}
}

View File

@@ -0,0 +1,157 @@
package org.astral.findmaimaiultra.been.faker;
public class Udemae {
private int maxLoseNum;
private int npcTotalWinNum;
private int npcTotalLoseNum;
private int npcMaxWinNum;
private int npcMaxLoseNum;
private int npcWinNum;
private int npcLoseNum;
private int rate;
private int classValue;
private int maxRate;
private int maxClassValue;
private int totalWinNum;
private int totalLoseNum;
private int maxWinNum;
private int MaxLoseNum;
private int winNum;
private int loseNum;
private int NpcTotalWinNum;
private int NpcTotalLoseNum;
private int NpcMaxWinNum;
private int NpcMaxLoseNum;
private int NpcWinNum;
private int NpcLoseNum;
// Getters and Setters
public int getMaxLoseNum() {
return maxLoseNum;
}
public void setMaxLoseNum(int maxLoseNum) {
this.maxLoseNum = maxLoseNum;
}
public int getWinNum() {
return winNum;
}
public void setWinNum(int winNum) {
this.winNum = winNum;
}
public int getLoseNum() {
return loseNum;
}
public void setLoseNum(int loseNum) {
this.loseNum = loseNum;
}
public int getNpcTotalWinNum() {
return npcTotalWinNum;
}
public void setNpcTotalWinNum(int npcTotalWinNum) {
this.npcTotalWinNum = npcTotalWinNum;
}
public int getNpcTotalLoseNum() {
return npcTotalLoseNum;
}
public void setNpcTotalLoseNum(int npcTotalLoseNum) {
this.npcTotalLoseNum = npcTotalLoseNum;
}
public int getNpcMaxWinNum() {
return npcMaxWinNum;
}
public void setNpcMaxWinNum(int npcMaxWinNum) {
this.npcMaxWinNum = npcMaxWinNum;
}
public int getNpcMaxLoseNum() {
return npcMaxLoseNum;
}
public void setNpcMaxLoseNum(int npcMaxLoseNum) {
this.npcMaxLoseNum = npcMaxLoseNum;
}
public int getNpcWinNum() {
return npcWinNum;
}
public void setNpcWinNum(int npcWinNum) {
this.npcWinNum = npcWinNum;
}
public int getNpcLoseNum() {
return npcLoseNum;
}
public void setNpcLoseNum(int npcLoseNum) {
this.npcLoseNum = npcLoseNum;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
public int getClassValue() {
return classValue;
}
public void setClassValue(int classValue) {
this.classValue = classValue;
}
public int getMaxRate() {
return maxRate;
}
public void setMaxRate(int maxRate) {
this.maxRate = maxRate;
}
public int getMaxClassValue() {
return maxClassValue;
}
public void setMaxClassValue(int maxClassValue) {
this.maxClassValue = maxClassValue;
}
public int getTotalWinNum() {
return totalWinNum;
}
public void setTotalWinNum(int totalWinNum) {
this.totalWinNum = totalWinNum;
}
public int getTotalLoseNum() {
return totalLoseNum;
}
public void setTotalLoseNum(int totalLoseNum) {
this.totalLoseNum = totalLoseNum;
}
public int getMaxWinNum() {
return maxWinNum;
}
public void setMaxWinNum(int maxWinNum) {
this.maxWinNum = maxWinNum;
}
}

View File

@@ -0,0 +1,177 @@
package org.astral.findmaimaiultra.been.faker;
import java.util.Date;
public class UserData {
private int userId;
private String userName;
private boolean isLogin;
private String lastGameId;
private String lastRomVersion;
private String lastDataVersion;
private String lastLoginDate;
private String lastPlayDate;
private int playerRating;
private int nameplateId;
private int iconId;
private int trophyId;
private int isNetMember;
private boolean isInherit;
private int totalAwake;
private int dispRate;
private String dailyBonusDate;
private String headPhoneVolume;
private int banState;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public boolean isLogin() {
return isLogin;
}
public void setLogin(boolean login) {
isLogin = login;
}
public String getLastGameId() {
return lastGameId;
}
public void setLastGameId(String lastGameId) {
this.lastGameId = lastGameId;
}
public String getLastRomVersion() {
return lastRomVersion;
}
public void setLastRomVersion(String lastRomVersion) {
this.lastRomVersion = lastRomVersion;
}
public String getLastDataVersion() {
return lastDataVersion;
}
public void setLastDataVersion(String lastDataVersion) {
this.lastDataVersion = lastDataVersion;
}
public String getLastLoginDate() {
return lastLoginDate;
}
public void setLastLoginDate(String lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
public String getLastPlayDate() {
return lastPlayDate;
}
public void setLastPlayDate(String lastPlayDate) {
this.lastPlayDate = lastPlayDate;
}
public int getPlayerRating() {
return playerRating;
}
public void setPlayerRating(int playerRating) {
this.playerRating = playerRating;
}
public int getNameplateId() {
return nameplateId;
}
public void setNameplateId(int nameplateId) {
this.nameplateId = nameplateId;
}
public int getIconId() {
return iconId;
}
public void setIconId(int iconId) {
this.iconId = iconId;
}
public int getTrophyId() {
return trophyId;
}
public void setTrophyId(int trophyId) {
this.trophyId = trophyId;
}
public int getIsNetMember() {
return isNetMember;
}
public void setIsNetMember(int isNetMember) {
this.isNetMember = isNetMember;
}
public boolean isInherit() {
return isInherit;
}
public void setInherit(boolean inherit) {
isInherit = inherit;
}
public int getTotalAwake() {
return totalAwake;
}
public void setTotalAwake(int totalAwake) {
this.totalAwake = totalAwake;
}
public int getDispRate() {
return dispRate;
}
public void setDispRate(int dispRate) {
this.dispRate = dispRate;
}
public String getDailyBonusDate() {
return dailyBonusDate;
}
public void setDailyBonusDate(String dailyBonusDate) {
this.dailyBonusDate = dailyBonusDate;
}
public String getHeadPhoneVolume() {
return headPhoneVolume;
}
public void setHeadPhoneVolume(String headPhoneVolume) {
this.headPhoneVolume = headPhoneVolume;
}
public int getBanState() {
return banState;
}
public void setBanState(int banState) {
this.banState = banState;
}
}

View File

@@ -0,0 +1,90 @@
package org.astral.findmaimaiultra.been.faker;
import java.util.List;
public class UserDataDetails {
private String accessCode;
private String userName;
private String friendCode;
private Integer isNetMember;
private Integer playerRating;
private Integer playerOldRating;
private Integer playerNewRating;
private Integer highestRating;
private Integer gradeRating;
private Integer musicRating;
private Integer gradeRank;
private Integer courseRank;
private Integer classRank;
private Integer nameplateId;
private Integer frameId;
private Integer iconId;
private Integer trophyId;
private Integer plateId;
private Integer titleId;
private Integer partnerId;
private List<Integer> charaSlot;
private List<Integer> charaLockSlot;
private Long contentBit;
private Integer selectMapId;
private Integer playCount;
private Integer currentPlayCount;
private Integer playVsCount;
private Integer playSyncCount;
private Integer winCount;
private Integer helpCount;
private Integer comboCount;
private Long totalDeluxscore;
private Long totalBasicDeluxscore;
private Long totalAdvancedDeluxscore;
private Long totalExpertDeluxscore;
private Long totalMasterDeluxscore;
private Long totalReMasterDeluxscore;
private Integer totalSync;
private Integer totalBasicSync;
private Integer totalAdvancedSync;
private Integer totalExpertSync;
private Integer totalMasterSync;
private Integer totalReMasterSync;
private Long totalAchievement;
private Long totalBasicAchievement;
private Long totalAdvancedAchievement;
private Long totalExpertAchievement;
private Long totalMasterAchievement;
private Long totalReMasterAchievement;
private String eventWatchedDate;
private String lastGameId;
private String lastRomVersion;
private String lastDataVersion;
private String lastLoginDate;
private String lastPlayDate;
private String lastPairLoginDate;
private String lastTrialPlayDate;
private Integer lastPlayCredit;
private Integer lastPlayMode;
private Integer lastPlaceId;
private String lastPlaceName;
private Integer lastAllNetId;
private Integer lastRegionId;
private String lastRegionName;
private String lastClientId;
private String lastCountryCode;
private Integer lastSelectEMoney;
private Integer lastSelectTicket;
private Integer lastSelectCourse;
private Integer lastCountCourse;
private String firstGameId;
private String firstRomVersion;
private String firstDataVersion;
private String firstPlayDate;
private String compatibleCmVersion;
private Integer totalAwake;
private String dailyBonusDate;
private String dailyCourseBonusDate;
private Integer mapStock;
private Integer renameCredit;
private Integer cmLastEmoneyCredit;
private Integer cmLastEmoneyBrand;
private String dateTime;
}

View File

@@ -0,0 +1,61 @@
package org.astral.findmaimaiultra.been.faker;
import java.util.List;
public class UserRating {
private int rating;
private List<MusicRating> ratingList;
private List<MusicRating> newRatingList;
private List<MusicRating> nextRatingList;
private List<MusicRating> nextNewRatingList;
private Udemae udemae;
// Getters and Setters
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public List<MusicRating> getRatingList() {
return ratingList;
}
public void setRatingList(List<MusicRating> ratingList) {
this.ratingList = ratingList;
}
public List<MusicRating> getNewRatingList() {
return newRatingList;
}
public void setNewRatingList(List<MusicRating> newRatingList) {
this.newRatingList = newRatingList;
}
public List<MusicRating> getNextRatingList() {
return nextRatingList;
}
public void setNextRatingList(List<MusicRating> nextRatingList) {
this.nextRatingList = nextRatingList;
}
public List<MusicRating> getNextNewRatingList() {
return nextNewRatingList;
}
public void setNextNewRatingList(List<MusicRating> nextNewRatingList) {
this.nextNewRatingList = nextNewRatingList;
}
public Udemae getUdemae() {
return udemae;
}
public void setUdemae(Udemae udemae) {
this.udemae = udemae;
}
}

View File

@@ -0,0 +1,40 @@
package org.astral.findmaimaiultra.been.faker;
public class UserRegion {
private int regionId;
private int playCount;
private String province;
private String created;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public int getRegionId() {
return regionId;
}
public void setRegionId(int regionId) {
this.regionId = regionId;
}
public int getPlayCount() {
return playCount;
}
public void setPlayCount(int playCount) {
this.playCount = playCount;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
}

View File

@@ -0,0 +1,25 @@
package org.astral.findmaimaiultra.been.faker;
import java.util.List;
public class UserScore {
private long userId;
private UserRating userRating;
// Getters and Setters
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public UserRating getUserRating() {
return userRating;
}
public void setUserRating(UserRating userRating) {
this.userRating = userRating;
}
}

View File

@@ -0,0 +1,68 @@
package org.astral.findmaimaiultra.been.lx;
public class Difficulty {
private String type;
private int difficulty;
private String level;
private double level_value;
private String note_designer;
private int version;
private Notes notes;
// Getters and Setters
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getDifficulty() {
return difficulty;
}
public void setDifficulty(int difficulty) {
this.difficulty = difficulty;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public double getLevel_value() {
return level_value;
}
public void setLevel_value(double level_value) {
this.level_value = level_value;
}
public String getNote_designer() {
return note_designer;
}
public void setNote_designer(String note_designer) {
this.note_designer = note_designer;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public Notes getNotes() {
return notes;
}
public void setNotes(Notes notes) {
this.notes = notes;
}
}

View File

@@ -0,0 +1,117 @@
package org.astral.findmaimaiultra.been.lx;
public class Lx_chart {
private int id;
private String song_name;
private String level;
private int level_index;
private double achievements;
private String fc;
private String fs;
private int dx_score;
private double dx_rating;
private String rate;
private String type;
private String upload_time;
// 无参构造函数
public Lx_chart() {}
// 全参构造函数
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSong_name() {
return song_name;
}
public void setSong_name(String song_name) {
this.song_name = song_name;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public int getLevel_index() {
return level_index;
}
public void setLevel_index(int level_index) {
this.level_index = level_index;
}
public double getAchievements() {
return achievements;
}
public void setAchievements(double achievements) {
this.achievements = achievements;
}
public String getFc() {
return fc;
}
public void setFc(String fc) {
this.fc = fc;
}
public String getFs() {
return fs;
}
public void setFs(String fs) {
this.fs = fs;
}
public int getDx_score() {
return dx_score;
}
public void setDx_score(int dx_score) {
this.dx_score = dx_score;
}
public double getDx_rating() {
return dx_rating;
}
public void setDx_rating(double dx_rating) {
this.dx_rating = dx_rating;
}
public String getRate() {
return rate;
}
public void setRate(String rate) {
this.rate = rate;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUpload_time() {
return upload_time;
}
public void setUpload_time(String upload_time) {
this.upload_time = upload_time;
}
}

View File

@@ -0,0 +1,62 @@
package org.astral.findmaimaiultra.been.lx;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Lx_data {
@SerializedName("standard_total")
private int standardTotal;
@SerializedName("dx_total")
private int dxTotal;
@SerializedName("standard")
private List<Lx_chart> standard;
@SerializedName("dx")
private List<Lx_chart> dx;
@Override
public String toString() {
return "Lx_data{" +
"standardTotal=" + standardTotal +
", dxTotal=" + dxTotal +
", standard=" + standard +
", dx=" + dx +
'}';
}
// Getters and Setters
public int getStandardTotal() {
return standardTotal;
}
public void setStandardTotal(int standardTotal) {
this.standardTotal = standardTotal;
}
public int getDxTotal() {
return dxTotal;
}
public void setDxTotal(int dxTotal) {
this.dxTotal = dxTotal;
}
public List<Lx_chart> getStandard() {
return standard;
}
public void setStandard(List<Lx_chart> standard) {
this.standard = standard;
}
public List<Lx_chart> getDx() {
return dx;
}
public void setDx(List<Lx_chart> dx) {
this.dx = dx;
}
}

View File

@@ -0,0 +1,38 @@
package org.astral.findmaimaiultra.been.lx;
import com.google.gson.annotations.SerializedName;
public class Lx_data_scores {
@SerializedName("success")
private boolean success;
@SerializedName("code")
private int code;
@SerializedName("data")
private Lx_chart[] data;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Lx_chart[] getData() {
return data;
}
public void setData(Lx_chart[] data) {
this.data = data;
}
}

View File

@@ -0,0 +1,203 @@
package org.astral.findmaimaiultra.been.lx;
import com.google.gson.annotations.SerializedName;
public class Lx_playerInfo {
@SerializedName("success")
private boolean success;
@SerializedName("code")
private int code;
@SerializedName("data")
private Data data;
// Getters and Setters
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public static class Data {
@SerializedName("name")
private String name;
@SerializedName("rating")
private int rating;
@SerializedName("friend_code")
private long friendCode;
@SerializedName("trophy")
private Trophy trophy;
@SerializedName("course_rank")
private int courseRank;
@SerializedName("class_rank")
private int classRank;
@SerializedName("star")
private int star;
@SerializedName("icon")
private Icon icon;
@SerializedName("upload_time")
private String uploadTime;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public long getFriendCode() {
return friendCode;
}
public void setFriendCode(long friendCode) {
this.friendCode = friendCode;
}
public Trophy getTrophy() {
return trophy;
}
public void setTrophy(Trophy trophy) {
this.trophy = trophy;
}
public int getCourseRank() {
return courseRank;
}
public void setCourseRank(int courseRank) {
this.courseRank = courseRank;
}
public int getClassRank() {
return classRank;
}
public void setClassRank(int classRank) {
this.classRank = classRank;
}
public int getStar() {
return star;
}
public void setStar(int star) {
this.star = star;
}
public Icon getIcon() {
return icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
public String getUploadTime() {
return uploadTime;
}
public void setUploadTime(String uploadTime) {
this.uploadTime = uploadTime;
}
}
public static class Trophy {
@SerializedName("id")
private int id;
@SerializedName("name")
private String name;
@SerializedName("color")
private String color;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public static class Icon {
@SerializedName("id")
private int id;
@SerializedName("name")
private String name;
@SerializedName("genre")
private String genre;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
}
}

View File

@@ -0,0 +1,39 @@
package org.astral.findmaimaiultra.been.lx;
import com.google.gson.annotations.SerializedName;
public class Lx_res {
@SerializedName("success")
private boolean success;
@SerializedName("code")
private int code;
@SerializedName("data")
private Lx_data data;
// Getters and Setters
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Lx_data getData() {
return data;
}
public void setData(Lx_data data) {
this.data = data;
}
}

View File

@@ -0,0 +1,59 @@
package org.astral.findmaimaiultra.been.lx;
public class Notes {
private int total;
private int tap;
private int hold;
private int slide;
private int touch;
private int break_;
// Getters and Setters
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getTap() {
return tap;
}
public void setTap(int tap) {
this.tap = tap;
}
public int getHold() {
return hold;
}
public void setHold(int hold) {
this.hold = hold;
}
public int getSlide() {
return slide;
}
public void setSlide(int slide) {
this.slide = slide;
}
public int getTouch() {
return touch;
}
public void setTouch(int touch) {
this.touch = touch;
}
public int getBreak_() {
return break_;
}
public void setBreak_(int break_) {
this.break_ = break_;
}
}

View File

@@ -0,0 +1,80 @@
package org.astral.findmaimaiultra.been.lx;
import java.util.Map;
public class Song {
private int id;
private String title;
private String artist;
private String genre;
private int bpm;
private int version;
private String rights;
private Map<String, Difficulty[]> difficulties;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public int getBpm() {
return bpm;
}
public void setBpm(int bpm) {
this.bpm = bpm;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getRights() {
return rights;
}
public void setRights(String rights) {
this.rights = rights;
}
public Map<String, Difficulty[]> getDifficulties() {
return difficulties;
}
public void setDifficulties(Map<String, Difficulty[]> difficulties) {
this.difficulties = difficulties;
}
}

View File

@@ -0,0 +1,136 @@
package org.astral.findmaimaiultra.map2d;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;
import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.been.Place;
import java.util.ArrayList;
public class BasicMapActivity extends AppCompatActivity {
private MapView mapView;
private BaiduMap baiduMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SDKInitializer.setAgreePrivacy(getApplicationContext(),true);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.maimaimap);
Intent intent = getIntent();
double x = Double.parseDouble(intent.getStringExtra("x"));
double y = Double.parseDouble(intent.getStringExtra("y"));
Log.d("BasicMapActivity", "x: " + x + ", y: " + y);
mapView = findViewById(R.id.bmapView);
mapView.onCreate(this,savedInstanceState);
baiduMap = mapView.getMap();
// 设置地图中心点
LatLng latLng = new LatLng(y, x); // 北京市经纬度
baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLngZoom(latLng, 13)); // 缩放级别调整为
// 添加独特样式的标记
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo); // 自定义图标资源
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 200, 130, true); // 缩放到 100x100 像素
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromBitmap(scaledBitmap);
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title("舞萌痴位置")
.icon(descriptor); // 使用自定义图标
baiduMap.addOverlay(markerOptions);
ArrayList<Place> placeList = intent.getParcelableArrayListExtra("place_list_key");
for (Place place : placeList) {
addMarker(new LatLng(place.getY(), place.getX()), place.getName(), place.getAddress());
}
// 设置标记点击监听器
baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
showMarkerInfoDialog(marker);
return true; // 返回 true 表示已处理点击事件
}
});
}
// 在 addMarker 方法中设置 snippet
private void addMarker(LatLng latLng, String title, String snippet) {
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable.sd);
MarkerOptions markerOptions = new MarkerOptions();
Bundle bundle = new Bundle();
bundle.putString("snippet", snippet);
bundle.putString("title", title);
markerOptions.position(latLng)
.title(title)
.extraInfo(bundle)
.icon(descriptor);
baiduMap.addOverlay(markerOptions);
}
// 在 showMarkerInfoDialog 方法中获取 snippet
private void showMarkerInfoDialog(Marker marker) {
View dialogView = LayoutInflater.from(this).inflate(R.layout.marker_info_dialog, null);
TextView titleTextView = dialogView.findViewById(R.id.titleTextView);
TextView snippetTextView = dialogView.findViewById(R.id.snippetTextView);
Bundle extraInfo = marker.getExtraInfo();
titleTextView.setText(extraInfo.getString("title"));
// 获取 snippet
snippetTextView.setText(extraInfo.getString("snippet"));
new AlertDialog.Builder(this)
.setView(dialogView)
.setPositiveButton("导航", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialogInterface, int i) {
double lx = marker.getPosition().latitude;
double ly = marker.getPosition().longitude;
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("baidumap://map/direction?origin=latlng:" + lx + "," + ly + "|name:我的位置&destination=name:" + marker.getTitle() + "&mode=driving&src=yourCompanyName|yourAppName"));
BasicMapActivity.this.startActivity(intent);
}
})
.setNegativeButton("关闭", null)
.show();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}

View File

@@ -0,0 +1,44 @@
package org.astral.findmaimaiultra.message;
public class ApiResponse {
private int status;
private String message;
private long timestamp;
public ApiResponse() {
}
public ApiResponse(int status, String message) {
this.status = status;
this.message = message;
this.timestamp = System.currentTimeMillis();
}
public ApiResponse(String uid) {
this.status = 200;
this.message = uid;
this.timestamp = System.currentTimeMillis();
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}

View File

@@ -0,0 +1,11 @@
package org.astral.findmaimaiultra.service;
import org.astral.findmaimaiultra.been.Release;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface GitHubApiService {
@GET("repos/{owner}/{repo}/releases/latest")
Call<Release> getLatestRelease(@Path("owner") String owner, @Path("repo") String repo);
}

View File

@@ -0,0 +1,252 @@
// HackGetUserId.java
package org.astral.findmaimaiultra.ui;
import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
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.UserRegion;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class LinkQQBot extends AppCompatActivity {
private static Context context;
private static final int REQUEST_IMAGE_PICK = 1;
private TextInputEditText userId;
private OkHttpClient client;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hack_get_user_id);
context = this;
sp = getSharedPreferences("setting", MODE_PRIVATE);
userId = findViewById(R.id.userId);
userId.setOnClickListener(v -> {
Toast.makeText(this, "不可更改", Toast.LENGTH_SHORT).show();
});
userId.setText(sp.getString("userId", ""));
if(sp.contains("userId")) {
TextInputLayout userBox = findViewById(R.id.userBox);
userBox.setVisibility(View.VISIBLE);
}
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
TextInputEditText key = findViewById(R.id.key);
TextInputEditText safecode = findViewById(R.id.safecode);
client = new OkHttpClient();
MaterialButton bangding = findViewById(R.id.bangding);
bangding.setOnClickListener(v -> {
if (key.getText().toString().equals("")) {
Toast.makeText(this, "请输入基于QQ机器人获取的Key", Toast.LENGTH_SHORT).show();
return;
}
if (safecode.getText().toString().equals("")) {
Toast.makeText(this, "请输入您的安全码", Toast.LENGTH_SHORT).show();
return;
}
try {
sendApiRequest(key.getText().toString(), safecode.getText().toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
MaterialButton getTicket = findViewById(R.id.getTicket);
getTicket.setOnClickListener(v -> {
try {
getTicket(userId.getText().toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
// 如果已经保存了userId则直接获取数据
if (!userId.getText().toString().equals("")) {
try {
getUserRegionData(userId.getText().toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private void getTicket(String uid) throws Exception {
String url = "http://mai.godserver.cn:11451/api/qq/wmcfajuan?qq=" + uid + "&num=6";
Log.d("TAG", "getTicket: " + url);
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if (response.isSuccessful()) {
runOnUiThread(() ->{
try {
Toast.makeText(LinkQQBot.this, response.body().string(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
});
}
private void sendApiRequest(String key,String safecode) throws Exception {
String url = "http://mai.godserver.cn:11451/api/qq/safeCoding?result=" + key + "&safecode=" + safecode;
Request request = new Request.Builder()
.url(url)
.build();
Log.d("TAG", "sendApiRequest: " + url);
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(LinkQQBot.this, "Request failed", Toast.LENGTH_SHORT).show());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
final String responseData = response.body().string();
runOnUiThread(() -> {
Toast.makeText(LinkQQBot.this, "Response: " + responseData, Toast.LENGTH_LONG).show();
Log.d("TAG", "Response: " + responseData);
userId.setText(responseData);
SharedPreferences.Editor editor = sp.edit();
editor.putString("userId", responseData);
editor.apply();
Toast.makeText(LinkQQBot.this, "设置已保存,您的UsrId已写入硬盘!", Toast.LENGTH_SHORT).show();
try {
getUserRegionData(responseData);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} else {
runOnUiThread(() -> Toast.makeText(LinkQQBot.this, "Request not successful", Toast.LENGTH_SHORT).show());
}
}
});
}
private void getUserRegionData(String userId) throws Exception {
String url = "http://mai.godserver.cn:11451/api/qq/region2?qq=" + userId ;
Request request = new Request.Builder()
.url(url)
.build();
Log.d("url",url);
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(LinkQQBot.this, "Request failed", Toast.LENGTH_SHORT).show());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
final String responseData = response.body().string();
runOnUiThread(() -> {
Log.d("TAG", "Response: " + responseData);
Gson gson = new Gson();
RegionData regionData = gson.fromJson(responseData, RegionData.class);
sortUserRegions(regionData.getUserRegionList());
});
} else {
runOnUiThread(() -> Toast.makeText(LinkQQBot.this, "Request not successful", Toast.LENGTH_SHORT).show());
}
}
});
}
private void sortUserRegions(List<UserRegion> userRegions) {
Collections.sort(userRegions, new Comparator<UserRegion>() {
@Override
public int compare(UserRegion o1, UserRegion o2) {
return Integer.compare(o2.getPlayCount(), o1.getPlayCount());
}
});
// 处理排序后的数据,例如显示在表格中
displaySortedUserRegions(userRegions);
}
private void displaySortedUserRegions(List<UserRegion> userRegions) {
// 假设你有一个TableLayout来显示数据
TableLayout tableLayout = findViewById(R.id.tableLayout);
tableLayout.removeAllViews();
// 添加表头
TableRow headerRow = new TableRow(this);
TextView headerRegionId = new TextView(this);
headerRegionId.setText("地区 ID");
TextView headerPlayCount = new TextView(this);
headerPlayCount.setText("PC次数");
TextView headerProvince = new TextView(this);
headerProvince.setText("省份");
TextView headerCreated = new TextView(this);
headerCreated.setText("版本初次日期");
headerCreated.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
headerRegionId.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
headerPlayCount.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
headerProvince.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
headerRow.addView(headerRegionId);
headerRow.addView(headerPlayCount);
headerRow.addView(headerProvince);
headerRow.addView(headerCreated);
tableLayout.addView(headerRow);
// 添加数据行
for (UserRegion userRegion : userRegions) {
TableRow row = new TableRow(this);
TextView textViewRegionId = new TextView(this);
textViewRegionId.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
textViewRegionId.setText(String.valueOf(userRegion.getRegionId()));
TextView textViewPlayCount = new TextView(this);
textViewPlayCount.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
textViewPlayCount.setText(String.valueOf(userRegion.getPlayCount()));
TextView textViewProvince = new TextView(this);
textViewProvince.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
textViewProvince.setText(userRegion.getProvince());
TextView textViewCreated = new TextView(this);
textViewCreated.setText(userRegion.getCreated());
textViewCreated.setTextColor(ContextCompat.getColor(LinkQQBot.context, R.color.primary));
row.addView(textViewRegionId);
row.addView(textViewPlayCount);
row.addView(textViewProvince);
row.addView(textViewCreated);
tableLayout.addView(row);
}
}
}

View File

@@ -0,0 +1,63 @@
package org.astral.findmaimaiultra.ui;
import android.os.Bundle;
import android.view.View;
import android.view.Menu;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
package org.astral.findmaimaiultra.ui.gallery;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;
import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.been.Place;
import org.astral.findmaimaiultra.databinding.FragmentGalleryBinding;
import org.astral.findmaimaiultra.map2d.BasicMapActivity;
import org.astral.findmaimaiultra.utill.SharedViewModel;
import java.util.ArrayList;
import java.util.Objects;
public class GalleryFragment extends Fragment {
private FragmentGalleryBinding binding;
private MapView mapView;
private BaiduMap baiduMap;
private SharedViewModel sharedViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
GalleryViewModel galleryViewModel =
new ViewModelProvider(this).get(GalleryViewModel.class);
SDKInitializer.setAgreePrivacy(requireContext().getApplicationContext(),true);
SDKInitializer.initialize(requireContext().getApplicationContext());
binding = FragmentGalleryBinding.inflate(inflater, container, false);
View root = binding.getRoot();
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
double x = Double.parseDouble(Objects.requireNonNull(sharedViewModel.getSharedMap().getValue().get("x")));
double y = Double.parseDouble(Objects.requireNonNull(sharedViewModel.getSharedMap().getValue().get("y")));
mapView = binding.bmapView;
mapView.onCreate(getContext(),savedInstanceState);
baiduMap = mapView.getMap();
// 设置地图中心点
LatLng latLng = new LatLng(y, x); // 北京市经纬度
baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLngZoom(latLng, 13)); // 缩放级别调整为
// 添加独特样式的标记
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo); // 自定义图标资源
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 200, 130, true); // 缩放到 100x100 像素
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromBitmap(scaledBitmap);
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.title("舞萌痴位置")
.icon(descriptor); // 使用自定义图标
baiduMap.addOverlay(markerOptions);
ArrayList<Place> placeList = Objects.requireNonNull(sharedViewModel.getPlacelist().getValue());
for (Place place : placeList) {
addMarker(new LatLng(place.getY(), place.getX()), place.getName(), place.getAddress());
}
// 设置标记点击监听器
baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
showMarkerInfoDialog(marker);
return true; // 返回 true 表示已处理点击事件
}
});
return root;
}
private void addMarker(LatLng latLng, String title, String snippet) {
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable.sd);
MarkerOptions markerOptions = new MarkerOptions();
Bundle bundle = new Bundle();
bundle.putString("snippet", snippet);
bundle.putString("title", title);
markerOptions.position(latLng)
.title(title)
.extraInfo(bundle)
.icon(descriptor);
baiduMap.addOverlay(markerOptions);
}
// 在 showMarkerInfoDialog 方法中获取 snippet
private void showMarkerInfoDialog(Marker marker) {
View dialogView = LayoutInflater.from(getContext()).inflate(R.layout.marker_info_dialog, null);
TextView titleTextView = dialogView.findViewById(R.id.titleTextView);
TextView snippetTextView = dialogView.findViewById(R.id.snippetTextView);
Bundle extraInfo = marker.getExtraInfo();
try {
titleTextView.setText(extraInfo.getString("title"));
// 获取 snippet
snippetTextView.setText(extraInfo.getString("snippet"));
new AlertDialog.Builder(getContext())
.setView(dialogView)
.setPositiveButton("导航", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialogInterface, int i) {
double lx = marker.getPosition().latitude;
double ly = marker.getPosition().longitude;
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("baidumap://map/direction?origin=latlng:" + lx + "," + ly + "|name:我的位置&destination=name:" + marker.getTitle() + "&mode=driving&src=yourCompanyName|yourAppName"));
getContext().startActivity(intent);
}
})
.setNegativeButton("关闭", null)
.show();
}catch (Exception e) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getContext(), "乌蒙痴位置", Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,19 @@
package org.astral.findmaimaiultra.ui.gallery;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class GalleryViewModel extends ViewModel {
private final MutableLiveData<String> mText;
public GalleryViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is gallery fragment");
}
public LiveData<String> getText() {
return mText;
}
}

View File

@@ -0,0 +1,567 @@
package org.astral.findmaimaiultra.ui.home;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.*;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.navigation.NavigationView;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import okhttp3.*;
import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.adapter.PlaceAdapter;
import org.astral.findmaimaiultra.been.*;
import org.astral.findmaimaiultra.databinding.FragmentHomeBinding;
import org.astral.findmaimaiultra.ui.MainActivity;
import org.astral.findmaimaiultra.ui.PageActivity;
import org.astral.findmaimaiultra.utill.AddressParser;
import org.astral.findmaimaiultra.utill.SharedViewModel;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.util.*;
public class HomeFragment extends Fragment {
private RecyclerView recyclerView;
private Handler handler = new Handler(Looper.getMainLooper());
private LocationManager locationManager;
private String tot;
private String x;
private String y;
private PlaceAdapter adapter;
public static List<Market> marketList = new ArrayList<>();
private Context context;
public static String province;
public static String city;
public static List<Place> a = new ArrayList<>();
public static List<Place> b = new ArrayList<>();
private BroadcastReceiver locationReceiver;
public static List<TextView> textViews = new ArrayList<>();
private boolean flag = true;
private double tagXY[] = new double[2];
private String tagplace;
private boolean isFlag = true;
private SharedPreferences shoucang;
private SharedPreferences settingProperties;
private FragmentHomeBinding binding;
private SharedViewModel sharedViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取 SharedPreferences 实例
context = getContext();
if (context != null) {
shoucang = context.getSharedPreferences("shoucang_prefs", Context.MODE_PRIVATE);
settingProperties = context.getSharedPreferences("setting_prefs", Context.MODE_PRIVATE);
}
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot();
recyclerView = binding.recyclerView;
// 初始化 RecyclerView
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
// 初始化数据
List<Place> placeList = new ArrayList<>();
recyclerView.setAdapter(adapter);
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0x123);
// 示例:读取 SharedPreferences 中的数据
if (shoucang != null) {
String savedData = shoucang.getString("key_name", "default_value");
// 使用 savedData
}
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
// 示例:写入 SharedPreferences 数据
private void saveDataToSharedPreferences(String key, String value) {
if (shoucang != null) {
SharedPreferences.Editor editor = shoucang.edit();
editor.putString(key, value);
editor.apply(); // 或者 editor.commit();
}
}
private void showNetworkErrorToast(String text) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show());
}
}
@SuppressLint("StaticFieldLeak")
private void sendGetRequest() {
OkHttpClient client = new OkHttpClient();
String web = "http://mai.godserver.cn:11451/api/mai/v1/search?prompt1=" + city.split("")[0] + "&status=市";
if (!isFlag) {
web = "http://mai.godserver.cn:11451/api/mai/v1/search?data_place=" + tagplace;
}
Request request = new Request.Builder()
.url(web)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("OkHttp", "Error: " + e.getMessage());
showNetworkErrorToast("网络错误");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
if (!result.equals("BedWeb")) {
List<Place> places = parseJsonToPlaceList(result);
if (places != null) {
updateUI(places);
}
} else {
showNetworkErrorToast("网络错误(服务器维护)");
}
} else {
showNetworkErrorToast( "致命错误,服务器未启动");
}
}
});
}
private void updateUI(List<Place> places) {
a.clear();
b.clear();
for (Place p : places) {
try {
if (p.getName().equals("个人位置")) {
x = String.valueOf(p.getX());
y = String.valueOf(p.getY());
tot = p.getAddress();
city = p.getCity();
province = p.getProvince();
}
if (p.getIsUse() == 1) {
b.add(p);
}
} catch (Exception e) {
e.printStackTrace();
}
}
a.clear();
TreeMap<Double, Place> treeMap = new TreeMap<>();
for (Place p : b) {
double distance = DistanceCalculator.calculateDistance(Double.parseDouble(x), Double.parseDouble(y), p.getX(), p.getY());
if (shoucang.contains(p.getId() + "")) {
p.setName(p.getName() + " 收藏" + " 距离您" + String.format(Locale.CHINA, "%.2f", distance) + "km");
treeMap.put(distance - 1000, p);
} else {
p.setName(p.getName() + " 距离您" + String.format(Locale.CHINA, "%.2f", distance) + "km");
treeMap.put(distance, p);
}
if (p.getNumJ() > 0) {
p.setName(p.getName() + "\uD83D\uDCB3");
}
}
for (Double key : treeMap.keySet()) {
a.add(treeMap.get(key));
}
boolean flag2 = true;
if (flag2) {
adapter = new PlaceAdapter(a, new PlaceAdapter.OnItemClickListener() {
@Override
public void onItemClick(Place place) {
Intent intent = new Intent(context, PageActivity.class);
intent.putExtra("id", place.getId());
intent.putExtra("name", place.getName());
intent.putExtra("address", place.getAddress());
intent.putExtra("province", place.getProvince());
intent.putExtra("city", place.getCity());
intent.putExtra("area", place.getArea());
intent.putExtra("x", place.getX());
intent.putExtra("y", place.getY());
intent.putExtra("count", place.getCount());
intent.putExtra("bad", place.getBad());
intent.putExtra("good", place.getGood());
intent.putExtra("num", place.getNum());
intent.putExtra("numJ", place.getNumJ());
intent.putExtra("meituan", place.getMeituan_link());
intent.putExtra("douyin", place.getDouyin_link());
startActivity(intent);
}
});
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.setAdapter(adapter);
// 设置 Toolbar 标题
String navHomeLabel = getString(R.string.menu_home);
Toolbar toolbar = ((MainActivity) requireActivity()).findViewById(R.id.toolbar);
toolbar.setTitle("FindMaimaiDX - " + a.size() + " 店铺" + "\n" + tot);
// 更新 SharedViewModel 中的 Map
sharedViewModel.addToMap("places", new Gson().toJson(a));
// 通知适配器数据已更改
adapter.notifyDataSetChanged();
}
});
// 设置Toolbar
for (Place p : a) {
if (p.getX() == 0.0) {
// Log.i(p.getId() + "", p.getName() + "没有坐标");
}
}
}
}
private List<Place> parseJsonToPlaceList(String jsonString) {
Gson gson = new Gson();
Type placeListType = new TypeToken<List<Place>>() {
}.getType();
if(jsonString.equals("BedWeb")) {
Toast.makeText(context, "网络错误(服务器维护?)", Toast.LENGTH_SHORT);
return null;
}
return gson.fromJson(jsonString, placeListType);
}
@SuppressLint("MissingPermission")
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0x123 && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 创建 LocationManager 对象
locationManager = (LocationManager) requireActivity().getSystemService(Context.LOCATION_SERVICE);
// 获取最新的定位信息
Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocation != null) {
// 调用高德地图 API 进行逆地理编码
reverseGeocode(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude());
} else {
Log.d("Location", "无法获取最新定位信息");
setDefaultLocation(); // 设置默认位置
}
}
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 12000, 16f, new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
Log.d("Location", "onLocationChanged");
if (flag) {
Toast.makeText(context, "定位成功", Toast.LENGTH_SHORT).show();
// 调用高德地图 API 进行逆地理编码
reverseGeocode(location.getLatitude(), location.getLongitude());
}
}
@Override
public void onProviderDisabled(@NonNull String provider) {
Toast.makeText(requireActivity().getApplicationContext(), "关闭定位", Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
Log.d("Location", "GPS定位失败");
setDefaultLocation(); // 设置默认位置
}
}
// 调用高德地图 API 进行逆地理编码
private void reverseGeocode(double latitude, double longitude) {
new Thread(() -> {
try {
// 构建请求 URL
x = String.valueOf(longitude);
y = String.valueOf(latitude);
String url = "https://restapi.amap.com/v3/geocode/regeo?key=234cad2e2f0706e54c92591647a363c3&location=" + longitude + "," + latitude;
Log.d("Location", url);
// 发起网络请求
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String responseData = response.body().string();
// 使用 Gson 解析 JSON
Gson gson = new Gson();
Log.d("Location", responseData);
AmapReverseGeocodeResponse geocodeResponse = gson.fromJson(responseData, AmapReverseGeocodeResponse.class);
if (geocodeResponse.getStatus().equals("1")) { // 状态码 "1" 表示成功
AmapReverseGeocodeResponse.Regeocode regeocode = geocodeResponse.getRegeocode();
AmapReverseGeocodeResponse.AddressComponent addressComponent = regeocode.getAddressComponent();
// 解析地址信息
String address = regeocode.getFormattedAddress();
String province = addressComponent.getProvince();
String city;
try {
city = addressComponent.getCity().get(0).replace("", "");
} catch (Exception e) {
city = addressComponent.getProvince().replace("", "");
}
// 更新 UI
String finalCity = city;
getActivity().runOnUiThread(() -> {
tot = address;
HomeFragment.province = province;
HomeFragment.city = finalCity;
sharedViewModel.addToMap("tot", tot);
sharedViewModel.addToMap("x", x);
sharedViewModel.addToMap("y", y);
extracted();
});
} else {
Log.d("Location", "高德地图 API 调用失败,尝试使用 Android 自带 Geocoder");
fallbackToGeocoder(latitude, longitude); // 调用备用方案
}
} else {
Log.d("Location", "高德地图 API 调用失败,尝试使用 Android 自带 Geocoder");
fallbackToGeocoder(latitude, longitude); // 调用备用方案
}
} catch (Exception e) {
e.printStackTrace();
Log.d("Location", "高德地图 API 调用失败,尝试使用 Android 自带 Geocoder");
fallbackToGeocoder(latitude, longitude); // 调用备用方案
}
}).start();
}
// 备用方案:使用 Android 自带的 Geocoder 进行逆地理编码
private void fallbackToGeocoder(double latitude, double longitude) {
try {
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
List<android.location.Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses != null && !addresses.isEmpty()) {
Address address = addresses.get(0);
String detail = address.getAddressLine(0);
String province = address.getAdminArea();
String city = address.getLocality();
// 更新 UI
requireActivity().runOnUiThread(() -> {
tot = detail;
this.province = province;
this.city = city;
extracted();
});
} else {
Log.d("Location", "Android 自带 Geocoder 获取地址失败");
setDefaultLocation(); // 设置默认位置
}
} catch (IOException e) {
e.printStackTrace();
Log.d("Location", "Android 自带 Geocoder 获取地址失败");
setDefaultLocation(); // 设置默认位置
}
}
// 设置默认位置
private void setDefaultLocation() {
x = String.valueOf(116.3912757);
y = String.valueOf(39.906217);
}
//手动刷新定位
private void extracted() {
//tot = tot.split("\"")[1];
Log.i("TAG", "x=" + x + ";y=" + y);
//tot = "天津市东丽区民航大学";
if(!isFlag) {
}else {
try {
AddressParser.parseAddress(tot);
} catch (Exception e) {
Toast.makeText(context, "错误", Toast.LENGTH_SHORT);
}
}
sendGetRequest();
recyclerView.setLayoutManager(new LinearLayoutManager(context));
}
public static List<Geocode> parseJsonToGeocodeList(String jsonString) {
Gson gson = new Gson();
JsonArray jsonArray = gson.fromJson(jsonString, JsonArray.class);
List<Geocode> Geocodes = new ArrayList<>();
for (JsonElement jsonElement : jsonArray) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
Geocode geocode = new Geocode();
// 获取 marketName
String formatted_address = jsonObject.get("formatted_address").getAsString();
geocode.setFormatted_address(formatted_address);
geocode.setProvince(jsonObject.get("province").getAsString());
geocode.setCity(jsonObject.get("city").getAsString());
geocode.setDistrict(jsonObject.get("district").getAsString());
geocode.setCountry(jsonObject.get("country").getAsString());
geocode.setLevel(jsonObject.get("level").getAsString());
geocode.setCitycode(jsonObject.get("citycode").getAsString());
// 获取 x, y
String location = jsonObject.get("location").getAsString();
String[] coordinates = location.split(",");
geocode.setLocation(location);
Geocodes.add(geocode);
}
return Geocodes;
}
private String getAppVersionName() {
try {
PackageInfo packageInfo = requireActivity().getPackageManager().getPackageInfo(requireActivity().getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* 打开QQ
* @param context
*/
public static void gotoQQ(Context context) {
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(new ComponentName("com.tencent.mobileqq", "com.tencent.mobileqq.activity.SplashActivity"));
if (!(context instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "未安装QQ", Toast.LENGTH_SHORT).show();
}
}
private void addPlace(Place place) {
String url = "http://mai.godserver.cn:11451/api/mai/v1/place";
String body = new Gson().toJson(place,Place.class);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
Request request = new Request.Builder()
.url(url)
.put(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Toast.makeText(context, "添加失败", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
@SuppressLint("NotifyDataSetChanged")
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
final String responseData = response.body().string();
requireActivity().runOnUiThread(() -> {
Toast.makeText(context, "添加成功", Toast.LENGTH_SHORT).show();
});
}else {
Toast.makeText(context, "添加失败", Toast.LENGTH_SHORT).show();
}
}
});
}
private void showNavigationOptions() {
final CharSequence[] items = {"Google Maps", "高德地图", "百度地图(暂时不可用)"};
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("选择导航应用")
.setItems(items, (dialog, item) -> {
switch (item) {
case 0:
startGoogleMaps();
break;
case 1:
startAmap();
break;
case 2:
startBaiduMaps();
break;
}
})
.show();
}
private void startGoogleMaps() {
String uri = "google.navigation:q=" + tagXY[0] + "," + tagXY[1];
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);
}
private void startAmap() {
// 高德地图
Intent intent = new Intent("android.intent.action.VIEW", android.net.Uri.parse("androidamap://route?sourceApplication=appName&slat=&slon=&sname=我的位置&dlat=" + tagXY[1] +"&dlon="+ tagXY[0]+"&dname=" +tagplace + "&dev=0&t=2"));
this.startActivity(intent);
}
private void startBaiduMaps() {
Toast.makeText(PageActivity.context, "111", Toast.LENGTH_SHORT).show();
String uri = "baidumap://map/direction?destination=latlng:" + tagXY[0] + "," + tagXY[1] +"&mode=driving&src=appName";
Intent intent = new Intent("com.baidu.tieba", android.net.Uri.parse(uri));
startActivity(intent);
}
private static List<Market> parseJsonToPlaceList2(String jsonString) {
Gson gson = new Gson();
Type placeListType = new TypeToken<List<Market>>() {
}.getType();
return gson.fromJson(jsonString, placeListType);
}
}

View File

@@ -0,0 +1,19 @@
package org.astral.findmaimaiultra.ui.home;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class HomeViewModel extends ViewModel {
private final MutableLiveData<String> mText;
public HomeViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is home fragment");
}
public LiveData<String> getText() {
return mText;
}
}

View File

@@ -0,0 +1,335 @@
package org.astral.findmaimaiultra.ui.slideshow;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.*;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.radiobutton.MaterialRadioButton;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.android.material.textfield.TextInputEditText;
import com.yalantis.ucrop.UCrop;
import org.astral.findmaimaiultra.been.Release;
import org.astral.findmaimaiultra.databinding.FragmentSlideshowBinding;
import org.astral.findmaimaiultra.service.GitHubApiService;
import org.astral.findmaimaiultra.ui.LinkQQBot;
import org.astral.findmaimaiultra.utill.GitHubApiClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Objects;
import static android.app.Activity.RESULT_OK;
public class SlideshowFragment extends Fragment {
private SharedPreferences settingProperties;
private static final int PICK_IMAGE_REQUEST = 1;
private static final int REQUEST_CODE_PERMISSIONS = 1001;
private TextInputEditText shuiyuEditText;
private TextInputEditText luoxueEditText;
private TextInputEditText userId;
private String x;
private String y;
private FragmentSlideshowBinding binding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settingProperties = requireActivity().getSharedPreferences("setting", Context.MODE_PRIVATE);
}
private void show(String text) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show());
}
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
SlideshowViewModel slideshowViewModel =
new ViewModelProvider(this).get(SlideshowViewModel.class);
binding = FragmentSlideshowBinding.inflate(inflater, container, false);
View root = binding.getRoot();
SwitchMaterial switchMaterial = binding.switchBeta1;
switchMaterial.setChecked(settingProperties.getBoolean("setting_autobeta1", false));
switchMaterial.setOnCheckedChangeListener((buttonView, isChecked) -> {
SharedPreferences.Editor editor = settingProperties.edit();
if (isChecked) {
show( "已开启实验性功能,可能并不起作用");
editor.putBoolean("setting_autobeta1", true);
} else {
editor.putBoolean("setting_autobeta1", false);
}
editor.apply();
});
shuiyuEditText = binding.shuiyu;
luoxueEditText = binding.luoxue;
userId = binding.qqbot;
MaterialButton openQQBot = binding.openQQbot;
openQQBot.setOnClickListener(v -> {
try {
Intent intent = new Intent(getContext(), LinkQQBot.class);
startActivity(intent);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
loadSettings();
MaterialButton saveButton = binding.saveSettingsButton;
saveButton.setOnClickListener(v -> {
saveSettings(switchMaterial.isChecked(), shuiyuEditText.getText().toString(), luoxueEditText.getText().toString(), userId.getText().toString());
});
MaterialButton changeButton = binding.changePhoto;
changeButton.setOnClickListener(v -> openFileChooser());
TextView uuid = binding.uuid;
@SuppressLint("HardwareIds") String androidId = Settings.Secure.getString(getContext().getContentResolver(), Settings.Secure.ANDROID_ID);
uuid.setText("Android ID:" + androidId);
uuid.setOnClickListener(v -> {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
// 创建一个ClipData对象
ClipData clip = ClipData.newPlainText("label", androidId);
// 将ClipData对象设置到剪贴板中
clipboard.setPrimaryClip(clip);
show("已复制Android ID到剪切板");
});
TextView vits = binding.vits;
vits.setText("App version:" + getAppVersionName() + "\nLatest version:");
getLatestRelease();
WebView webView = binding.develop;
webView.setBackgroundColor(0x00000000);
webView.getSettings().setJavaScriptEnabled(true);
String url = "http://wekan.godserver.cn/b/eu5nNL7GzF9SLYc6i/findmaimaidx";
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() { " +
"document.body.style.backgroundColor = 'transparent'; " +
"})()");
}
});
webView.loadUrl(url); // 加载网页
return root;
}
private void openFileChooser() {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
startActivityForResult(intent, PICK_IMAGE_REQUEST);
}
}
private String getAppVersionName() {
try {
PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("SettingActivity", "onActivityResult called with requestCode: " + requestCode + ", resultCode: " + resultCode);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
startCropActivity(uri);
} else if (requestCode == UCrop.REQUEST_CROP && resultCode == RESULT_OK) {
handleCroppedImage(data);
} else if (requestCode == UCrop.REQUEST_CROP && resultCode == UCrop.RESULT_ERROR) {
final Throwable cropError = UCrop.getError(data);
Log.e("SettingActivity", "Cropping failed: ", cropError);
} else {
Log.w("SettingActivity", "Unexpected result from image picker or cropper");
}
}
private void startCropActivity(Uri uri) {
Uri destinationUri = Uri.fromFile(new File(requireActivity().getCacheDir(), "cropped_image.jpg"));
UCrop.Options options = new UCrop.Options();
options.setCompressionQuality(90);
options.setCompressionFormat(Bitmap.CompressFormat.JPEG);
// 计算屏幕宽高比
float[] aspectRatio = getScreenAspectRatio();
UCrop.of(uri, destinationUri)
.withAspectRatio(aspectRatio[0], aspectRatio[1]) // 设置裁剪比例为屏幕比例
.withMaxResultSize(getScreenWidth(), getScreenHeight()) // 设置最大结果尺寸
.withOptions(options)
.start(getActivity());
}
private void handleCroppedImage(Intent data) {
Uri croppedUri = UCrop.getOutput(data);
if (croppedUri != null) {
try {
Bitmap photo = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), croppedUri);
if (photo != null) {
File croppedFile = new File(getContext().getExternalFilesDir(null), "cropped_image.jpg");
try (FileOutputStream out = new FileOutputStream(croppedFile)) {
photo.compress(Bitmap.CompressFormat.JPEG, 90, out);
SharedPreferences.Editor editor = settingProperties.edit();
editor.putString("image_uri", croppedUri.toString());
editor.apply();
show("成功");
Log.d("SettingActivity", "图片已保存到: " + croppedFile.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
show("失败");
Log.e("SettingActivity", "保存图片失败: ", e);
}
} else {
show("无法获取裁剪后的图片");
Log.w("SettingActivity", "无法获取裁剪后的图片");
}
} catch (Exception e) {
e.printStackTrace();
show("无法获取裁剪后的图片");
Log.e("SettingActivity", "无法获取裁剪后的图片: ", e);
}
} else {
show("无法找到裁剪后的图片");
Log.w("SettingActivity", "无法找到裁剪后的图片");
}
}
private void saveSettings(boolean betaEnabled, String shuiyuUsername, String luoxueUsername, String userId) {
SharedPreferences.Editor editor = settingProperties.edit();
MaterialRadioButton materialRadioButton = binding.radioButton1;
MaterialRadioButton org = binding.org;
int use = 0;
if (org.isChecked()) {
use = 0;
} else if (materialRadioButton.isChecked()) {
use = 1;
} else {
use = 2;
}
editor.putInt("use_", use);
editor.putBoolean("setting_autobeta1", betaEnabled);
editor.putString("shuiyu_username", shuiyuUsername);
editor.putString("luoxue_username", luoxueUsername);
editor.putString("userId", userId);
editor.apply();
show("设置已保存");
}
private void loadSettings() {
SwitchMaterial switchMaterial = binding.switchBeta1;
shuiyuEditText = binding.shuiyu;
luoxueEditText = binding.luoxue;
MaterialRadioButton materialRadioButton = binding.radioButton1;
MaterialRadioButton materialRadioButton2 = binding.radioButton2;
MaterialRadioButton org = binding.org;
switchMaterial.setChecked(settingProperties.getBoolean("setting_autobeta1", false));
shuiyuEditText.setText(settingProperties.getString("shuiyu_username", ""));
luoxueEditText.setText(settingProperties.getString("luoxue_username", ""));
userId.setText(settingProperties.getString("userId", ""));
int use_ = settingProperties.getInt("use_", 1);
if (use_ == 0) {
use_ = 0;
org.setChecked(true);
SharedPreferences.Editor editorSetting = settingProperties.edit();
editorSetting.putInt("use_", use_);
editorSetting.apply();
} else if (use_ == 1) {
materialRadioButton.setChecked(true);
} else if (use_ == 2) {
materialRadioButton2.setChecked(true);
}
SharedPreferences mContextSp = this.getContext().getSharedPreferences(
"updater.data",
Context.MODE_PRIVATE);
SharedPreferences.Editor editorSetting = settingProperties.edit();
String username = mContextSp.getString("username", "");
if (Objects.requireNonNull(shuiyuEditText.getText()).toString().isEmpty()) {
if (mContextSp.contains("username")) {
editorSetting.putString("shuiyu_username", username);
editorSetting.apply();
shuiyuEditText.setText(username);
}
}
}
private void getLatestRelease() {
GitHubApiService service = GitHubApiClient.getClient();
Call<Release> call = service.getLatestRelease("Spaso1", "FindMaimaiDX_Phone"); // 替换为你的仓库信息
call.enqueue(new Callback<Release>() {
@SuppressLint("SetTextI18n")
@Override
public void onResponse(@NonNull Call<Release> call, @NonNull Response<Release> response) {
if (response.isSuccessful()) {
Release release = response.body();
if (release != null) {
String tagName = release.getTagName();
String name = release.getName();
String body = release.getBody();
String htmlUrl = release.getHtmlUrl();
TextView textView = binding.vits;
textView.setText(textView.getText() + tagName + "\n" + name + "\n" + body);
//Toast.makeText(SettingActivity.this, "Latest Release:\nTag Name: " + tagName + "\nName: " + name + "\nBody: " + body + "\nHTML URL: " + htmlUrl, Toast.LENGTH_SHORT).show();
} else {
}
} else {
}
}
@Override
public void onFailure(@NonNull Call<Release> call, @NonNull Throwable t) {
}
});
}
private int getScreenWidth() {
DisplayMetrics displayMetrics = new DisplayMetrics();
requireActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
private int getScreenHeight() {
DisplayMetrics displayMetrics = new DisplayMetrics();
requireActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
private float[] getScreenAspectRatio() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
float width = displayMetrics.widthPixels;
float height = displayMetrics.heightPixels;
return new float[]{width, height};
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,19 @@
package org.astral.findmaimaiultra.ui.slideshow;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class SlideshowViewModel extends ViewModel {
private final MutableLiveData<String> mText;
public SlideshowViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is slideshow fragment");
}
public LiveData<String> getText() {
return mText;
}
}

View File

@@ -0,0 +1,61 @@
package org.astral.findmaimaiultra.utill;
import org.astral.findmaimaiultra.ui.home.HomeFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AddressParser {
public static void parseAddress(String address) {
try {
// 定义正则表达式
String regex = "(.*?省|.*?市|.*?自治区|.*?自治州|.*?区|.*?县)(.*?市|.*?区|.*?县)";
// 创建Pattern对象
Pattern pattern = Pattern.compile(regex);
// 创建Matcher对象
Matcher matcher = pattern.matcher(address);
if (matcher.find()) {
String province = matcher.group(1);
String city = matcher.group(2);
List<String> zhixiashi = new ArrayList<>();
zhixiashi.add("北京市");
zhixiashi.add("上海市");
zhixiashi.add("重庆市");
zhixiashi.add("天津市");
if(zhixiashi.contains(province)) {
city = province;
}
HomeFragment.city = city;
HomeFragment.province = province;
} else {
System.out.println("无法解析地址");
if(address.contains("")) {
if(address.contains("北京市")) {
HomeFragment.city = "北京市";
HomeFragment.province = "北京市";
}else if(address.contains("上海市")) {
HomeFragment.city = "上海市";
HomeFragment.province = "上海市";
}else if(address.contains("重庆市")) {
HomeFragment.city = "重庆市";
HomeFragment.province = "重庆市";
}else if(address.contains("天津市")) {
HomeFragment.city = "天津市";
HomeFragment.province = "天津市";
}
}
}
}catch (Exception e) {
}
}
}

View File

@@ -0,0 +1,42 @@
package org.astral.findmaimaiultra.utill;
import android.os.Build;
public class DeviceInfoUtils {
/**
* 获取设备的机型
*
* @return 设备的机型
*/
public static String getDeviceModel() {
return Build.MODEL;
}
/**
* 获取设备的Android版本号
*
* @return 设备的Android版本号
*/
public static String getAndroidVersion() {
return Build.VERSION.RELEASE;
}
/**
* 获取设备的Android版本号整数形式
*
* @return 设备的Android版本号整数形式
*/
public static int getAndroidVersionCode() {
return Build.VERSION.SDK_INT;
}
/**
* 获取完整的设备信息
*
* @return 包含机型和Android版本的字符串
*/
public static String getDeviceInfo() {
return "设备机型: " + getDeviceModel() + ", Android版本: " + getAndroidVersion();
}
}

View File

@@ -0,0 +1,20 @@
package org.astral.findmaimaiultra.utill;
import org.astral.findmaimaiultra.service.GitHubApiService;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class GitHubApiClient {
private static final String BASE_URL = "https://api.github.com/";
private static Retrofit retrofit = null;
public static GitHubApiService getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit.create(GitHubApiService.class);
}
}

View File

@@ -0,0 +1,43 @@
package org.astral.findmaimaiultra.utill;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.astral.findmaimaiultra.been.ChartPlay;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class NetworkUtils {
private static final String BASE_URL = "http://mai.godserver.cn:11451/api/chartPlays/charts";
public static void fetchChartPlays(Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(BASE_URL).build();
client.newCall(request).enqueue(callback);
}
public static List<ChartPlay> parseChartPlays(String responseBody) throws JSONException {
List<ChartPlay> chartPlayList = new ArrayList<>();
JSONObject jsonObject = new JSONObject(responseBody);
JSONArray jsonArray = jsonObject.getJSONArray("content");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject chartJson = jsonArray.getJSONObject(i);
ChartPlay chartPlay = new ChartPlay();
chartPlay.setSongName(chartJson.getString("songName"));
chartPlay.setLength(chartJson.getString("length"));
chartPlay.setDifficulty(chartJson.getString("difficulty"));
chartPlay.setChartZipUrl(chartJson.getString("chartZipUrl"));
chartPlay.setLikes(chartJson.getInt("likes"));
chartPlay.setDownloads(chartJson.getInt("downloads"));
chartPlay.setAuthor(chartJson.getString("author"));
chartPlay.setId(chartJson.getInt("id"));
chartPlay.setUsed(chartJson.getBoolean("used"));
chartPlayList.add(chartPlay);
}
return chartPlayList;
}
}

View File

@@ -0,0 +1,52 @@
package org.astral.findmaimaiultra.utill;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.astral.findmaimaiultra.been.Place;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Map<String, String>> sharedMap = new MutableLiveData<>();
private final MutableLiveData<ArrayList<Place>> placelist = new MutableLiveData<>();
public SharedViewModel() {
placelist.setValue(null);
sharedMap.setValue(new HashMap<>());
}
public MutableLiveData<ArrayList<Place>> getPlacelist() {
return placelist;
}
public MutableLiveData<Map<String, String>> getSharedMap() {
return sharedMap;
}
public void addToMap(String key, String value) {
Map<String, String> currentMap = sharedMap.getValue();
if (currentMap != null) {
currentMap.put(key, value);
sharedMap.setValue(currentMap);
}
}
public void removeFromMap(String key) {
Map<String, String> currentMap = sharedMap.getValue();
if (currentMap != null) {
currentMap.remove(key);
sharedMap.setValue(currentMap);
}
}
public void setPlacelist(ArrayList<Place> placelist) {
this.placelist.setValue(placelist);
}
public void clearMap() {
sharedMap.setValue(new HashMap<>());
}
public void clearPlacelist() {
placelist.setValue(null);
}
}

View File

@@ -0,0 +1,84 @@
package org.astral.findmaimaiultra.utill;
import org.astral.findmaimaiultra.been.PlayerData;
import org.astral.findmaimaiultra.been.lx.Lx_chart;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
public class Shuiyu2Luoxue {
public static ArrayList<Lx_chart> shuiyu2luoxue(PlayerData playerData) {
ArrayList<Lx_chart> lx_charts = new ArrayList<>();
for (int i = 0; i < playerData.getCharts().getDx().size(); i++) {
Lx_chart lx_chart = new Lx_chart();
if(playerData.getCharts().getDx().get(i).getSongId() > 10000) {
lx_chart.setId(playerData.getCharts().getDx().get(i).getSongId() - 10000);
}else {
lx_chart.setId(playerData.getCharts().getDx().get(i).getSongId());
}
lx_chart.setSong_name(playerData.getCharts().getDx().get(i).getTitle());
lx_chart.setLevel(playerData.getCharts().getDx().get(i).getLevel());
lx_chart.setLevel_index(playerData.getCharts().getDx().get(i).getLevel_index());
lx_chart.setAchievements(playerData.getCharts().getDx().get(i).getAchievements());
lx_chart.setDx_rating(playerData.getCharts().getDx().get(i).getRa());
lx_chart.setDx_score(playerData.getCharts().getDx().get(i).getDxScore());
lx_chart.setFs(playerData.getCharts().getDx().get(i).getFs());
lx_chart.setFc(playerData.getCharts().getDx().get(i).getFc());
if(lx_chart.getFc().equals("")) {
lx_chart.setFc(null);
}
if(lx_chart.getFs().equals("")) {
lx_chart.setFs(null);
}
lx_chart.setRate(playerData.getCharts().getDx().get(i).getRate());
if(playerData.getCharts().getDx().get(i).getType().equals("SD")) {
lx_chart.setType("standard");
}else if(playerData.getCharts().getDx().get(i).getType().equals("DX")) {
lx_chart.setType("dx");
}
// 获取当前时间戳
Instant now = Instant.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
// 格式化时间为ISO 8601字符串
String iso8601String = now.toString().split("\\.")[0] + "Z";
lx_chart.setUpload_time(iso8601String);
lx_charts.add(lx_chart);
}
for (int i = 0; i < playerData.getCharts().getSd().size(); i++) {
Lx_chart lx_chart = new Lx_chart();
if(playerData.getCharts().getSd().get(i).getSongId() > 10000) {
lx_chart.setId(playerData.getCharts().getSd().get(i).getSongId() - 10000);
}else {
lx_chart.setId(playerData.getCharts().getSd().get(i).getSongId());
}
lx_chart.setSong_name(playerData.getCharts().getSd().get(i).getTitle());
lx_chart.setLevel(playerData.getCharts().getSd().get(i).getLevel());
lx_chart.setLevel_index(playerData.getCharts().getSd().get(i).getLevel_index());
lx_chart.setAchievements(playerData.getCharts().getSd().get(i).getAchievements());
lx_chart.setDx_rating(playerData.getCharts().getSd().get(i).getRa());
lx_chart.setDx_score(playerData.getCharts().getSd().get(i).getDxScore());
lx_chart.setFs(playerData.getCharts().getSd().get(i).getFs());
lx_chart.setFc(playerData.getCharts().getSd().get(i).getFc());
if(lx_chart.getFc().equals("")) {
lx_chart.setFc(null);
}
if(lx_chart.getFs().equals("")) {
lx_chart.setFs(null);
}
lx_chart.setRate(playerData.getCharts().getSd().get(i).getRate());
if (playerData.getCharts().getSd().get(i).getType().equals("SD")) {
lx_chart.setType("standard");
} else if (playerData.getCharts().getSd().get(i).getType().equals("DX")) {
lx_chart.setType("dx");
}
Instant now = Instant.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
String iso8601String = now.toString().split("\\.")[0] + "Z";
lx_chart.setUpload_time(iso8601String);
lx_charts.add(lx_chart);
}
return lx_charts;
}
}

View File

@@ -0,0 +1,100 @@
package org.astral.findmaimaiultra.utill;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import androidx.loader.content.CursorLoader;
import java.io.File;
public class UriToFileConverter {
public static File uriToFile(Context context, Uri uri) {
String filePath = getRealPathFromURI(context, uri);
if (filePath != null) {
return new File(filePath);
}
return null;
}
private static String getRealPathFromURI(Context context, Uri uri) {
String filePath = null;
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null);
Cursor cursor = loader.loadInBackground();
if (cursor != null) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
filePath = cursor.getString(column_index);
cursor.close();
}
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
filePath = uri.getPath();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
String id = DocumentsContract.getDocumentId(uri);
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
filePath = getDataColumn(context, contentUri, null, null);
} else if (isMediaDocument(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
String selection = "_id=?";
String[] selectionArgs = new String[] { split[1] };
filePath = getDataColumn(context, contentUri, selection, selectionArgs);
}
}
return filePath;
}
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
String column = MediaStore.Images.Media.DATA;
String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}

View File

@@ -0,0 +1,118 @@
package org.astral.findmaimaiultra.utill;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.FrameLayout;
public class ZoomableViewGroup extends FrameLayout {
private ScaleGestureDetector scaleGestureDetector;
private GestureDetector gestureDetector;
private final Matrix matrix = new Matrix();
private float scaleFactor = 1.0f;
public static float lastX, lastY;
private static final long REFRESH_RATE = 5; // 11ms 对应大约 90fps
private Handler mHandler;
private Runnable mRefreshRunnable;
public ZoomableViewGroup(Context context) {
super(context);
init(context);
}
public ZoomableViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomableViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
scaleGestureDetector = new ScaleGestureDetector(context, new ScaleListener());
gestureDetector = new GestureDetector(context, new GestureListener());
mHandler = new Handler(Looper.getMainLooper());
mRefreshRunnable = new Runnable() {
@Override
public void run() {
invalidate(); // 重新绘制视图
mHandler.postDelayed(this, REFRESH_RATE);
}
};
}
@Override
public boolean onTouchEvent(MotionEvent event) {
scaleGestureDetector.onTouchEvent(event);
gestureDetector.onTouchEvent(event);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 5.0f)); // 限制缩放范围
matrix.postScale(detector.getScaleFactor(), detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
return true;
}
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// 取反 distanceX 和 distanceY
matrix.postTranslate(-distanceX, -distanceY);
lastX = e2.getX();
lastY = e2.getY();
return true;
}
@Override
public boolean onDown(MotionEvent e) {
lastX = e.getX();
lastY = e.getY();
return true;
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.concat(matrix);
super.dispatchDraw(canvas);
canvas.restore();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
startRefreshing();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopRefreshing();
}
private void startRefreshing() {
mHandler.post(mRefreshRunnable);
}
private void stopRefreshing() {
mHandler.removeCallbacks(mRefreshRunnable);
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#673AB7</color>
<color name="purple_500">#673AB7</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#045D53</color>
<color name="night">#673AB7</color>
<color name="border_color">#FFFFFF</color> <!-- 白色 -->
<color name="teal_700">#FF018786</color>
<color name="black">#8A8282</color>
<color name="white">#FFFFFFFF</color>
<color name="primary">#673AB7</color>
<color name="primary_dark">#673AB7</color>
<color name="primary_light">#673AB7</color>
<color name="accent">#3F51B5</color>
<color name="primary_text">#212121</color>
<color name="secondary_text">#727272</color>
<color name="icons">#FFFFFF</color>
<color name="divider">#B6B6B6</color>
<color name="colorPrimary">#673AB7</color>
<color name="colorPrimaryVariant">#673AB7</color>
<color name="colorOnPrimary">#141313</color>
<color name="colorSecondary">#045D53</color>
<color name="colorSecondaryVariant">#018786</color>
<color name="colorOnSecondary">#000000</color>
<color name="lineBaseGreen">#045D53</color>
<color name="VlineBaseGreen">#C2F6C4</color>
<color name="textcolorPrimary">#FFFFFF</color>
<color name="red">#F44336</color>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- res/values-night/styles.xml -->
<resources>
<style name="BorderStyle">
<item name="android:background">@drawable/border</item>
</style>
</resources>

View File

@@ -0,0 +1,69 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.FindMaimaiDX" parent="Theme.AppCompat.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#673AB7</item>
<item name="colorPrimaryVariant">#2C2A30</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/night</item>
<item name="colorSecondaryVariant">@color/night</item>
<item name="colorOnSecondary">@color/night</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">@color/night</item>
<!-- Customize your theme here. -->
</style>
<style name="Theme.FindMaimaiDX2" parent="Theme.AppCompat.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/night</item>
<item name="colorPrimaryVariant">#673AB7</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/night</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/night</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">#FFFFFF</item>
<!-- Customize your theme here. -->
</style>
<style name="FindMaimaiDX2" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/night</item>
<item name="colorPrimaryVariant">@color/night</item>
<item name="colorOnPrimary">@color/night</item>
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorSecondaryVariant">@color/colorSecondaryVariant</item>
<item name="colorOnSecondary">@color/colorOnSecondary</item>
<item name="android:statusBarColor">@color/night</item>
</style>
<!-- Base application theme. -->
<style name="NewTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/night</item>
<item name="colorPrimaryVariant">@color/night</item>
<item name="colorOnPrimary">@color/colorOnPrimary</item>
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorSecondaryVariant">@color/colorSecondaryVariant</item>
<item name="colorOnSecondary">@color/colorOnSecondary</item>
<item name="android:statusBarColor">@color/night</item>
</style>
<!-- MaterialCardView 样式 -->
<style name="CustomMaterialCardView" parent="Widget.MaterialComponents.CardView"> <item name="cardCornerRadius">16dp</item>
<item name="cardElevation">8dp</item>
<item name="cardBackgroundColor">@color/white</item>
</style>
<!-- 上方 TextView 样式 -->
<style name="TopTextViewStyle"> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/black</item>
<item name="android:padding">16dp</item>
<item name="android:layout_alignParentTop">true</item>
</style>
<!-- 下方 TextView 样式 -->
<style name="BottomTextViewStyle"> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@android:color/black</item>
<item name="android:padding">16dp</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/border.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent" />
<stroke android:width="1dp" android:color="@color/border_color" />
<padding android:left="1dp" android:top="1dp" android:right="1dp" android:bottom="1dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#D5C4ED" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#007AFF" />
<corners android:radius="24dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="8dp" />
<stroke
android:width="1dp"
android:color="#BDBDBD" />
</shape>

View File

@@ -0,0 +1,9 @@
<!-- res/drawable/edittext_background.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#7F8183"/>
<corners android:radius="8dp" />
<stroke
android:width="1dp"
android:color="#E91E63" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@@ -0,0 +1,31 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="49.59793"
android:startX="42.9492"
android:endY="92.4963"
android:endX="85.84757"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeWidth="1"
android:strokeColor="#00000000"/>
</vector>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>

View File

@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="24dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#E0E0E0" />
<corners android:radius="8dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E8DAEF" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#BB8FCE" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF9999" />
<corners android:radius="8dp" />
</shape>

Some files were not shown because too many files have changed in this diff Show More