commit ba9a7688db133b62bf944dfab9ea6e8c05c0f0a7
Author: Fanhuitong <981964879@qq.com>
Date: Fri May 26 11:43:28 2023 +0800
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b1123a0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+/.idea/
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..4d75a39
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,178 @@
+apply plugin: 'com.android.application'
+
+static def appName() {
+ return "设备绑定"
+}
+
+static def releaseTime() {
+ return new Date().format("yyyyMMdd-HHmmss", TimeZone.getDefault())
+}
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.3"
+
+ defaultConfig {
+ applicationId "com.uiuipad.find"
+ minSdkVersion 24
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ multiDexEnabled true
+
+ ndk {
+ //选择要添加的对应 cpu 类型的 .so 库。
+ abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', "x86"
+ // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
+ }
+ }
+
+ lintOptions {
+ checkReleaseBuilds false
+ // Or, if you prefer, you can continue to check for errors in release builds,
+ // but continue the build even when errors are found:
+ abortOnError false
+ }
+
+ dexOptions {
+ jumboMode true
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ //签名
+ signingConfigs {
+ //iPlay50 mini,iPlay50 android13 共用签名
+ iPlay50mini {
+ storeFile file("keystore/iPlay50Mini.keystore")
+ storePassword "android"
+ keyAlias "platform"
+ keyPassword "android"
+ v2SigningEnabled false
+ }
+
+
+ }
+
+ buildTypes {
+ debug {
+ versionNameSuffix "-debug"
+ debuggable true
+ //Zipalign优化
+ zipAlignEnabled true
+ minifyEnabled false
+ signingConfig signingConfigs.iPlay50mini
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ if (outputFile != null) {
+ def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk"
+ output.outputFileName = fileName
+ }
+ }
+ }
+ }
+
+ release {
+ //Zipalign优化
+ zipAlignEnabled true
+ //混淆
+ minifyEnabled false
+ //前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ //签名
+ signingConfig signingConfigs.iPlay50mini
+// 将release版本的包名重命名,加上版本及日期
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ def outputFile = ""
+ if (outputFile != null) {
+ def fileName = "${appName()}-${variant.versionCode}-V${variant.versionName}-${releaseTime()}-${buildType.name}.apk"
+ output.outputFileName = new File(outputFile, fileName)
+ }
+ }
+ }
+ }
+ }
+
+}
+
+dependencies {
+// implementation fileTree(dir: 'libs', include: ['*.jar'])
+ compileOnly files('libs/framework.jar')
+
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+
+
+ //BindView
+ implementation 'com.jakewharton:butterknife:10.2.3'
+// If you are using Kotlin, replace annotationProcessor with kapt.
+// annotationProcessor rootProject.ext.dependencies["butterknife-compiler"]
+ annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
+
+ //okhttp
+ implementation 'com.squareup.okhttp3:okhttp:4.10.0'
+ //Retrofit
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+ implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
+ //RxJava
+ implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
+ implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
+ //生命周期管理
+ implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
+ implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
+ implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
+ implementation 'com.trello.rxlifecycle4:rxlifecycle-components-preference:4.0.2'
+ implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
+ //Google
+ implementation 'com.google.code.gson:gson:2.10.1'
+ implementation 'com.google.zxing:core:3.5.0'
+ //图片加载框架
+ implementation 'com.github.bumptech.glide:glide:4.15.1'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'
+
+ //MMKV
+ implementation 'com.tencent:mmkv-static:1.2.14'
+ //阿里云推送
+ implementation 'com.aliyun.ams:alicloud-android-push:3.8.0'
+ //百度地图
+ implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.1.8'
+ //工具类
+ implementation 'com.blankj:utilcodex:1.31.0'
+ //沉浸状态栏
+ implementation 'com.gitee.zackratos:UltimateBarX:0.8.0'
+
+ implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0'
+
+}
+
+preBuild {
+ doLast {
+ def imlFile = file(project.name + ".iml")
+ println 'Change ' + project.name + '.iml order'
+ try {
+ def parsedXml = (new XmlParser()).parse(imlFile)
+ def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
+ parsedXml.component[1].remove(jdkNode)
+ def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
+ println 'what' + sdkString
+ new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
+ groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
+ } catch (FileNotFoundException e) {
+ // nop, iml not found
+ println "no iml found"
+ }
+ }
+ //https://www.pianshen.com/article/93481144911/
+ //使用系统编译后的framework.jar
+}
\ No newline at end of file
diff --git a/app/keystore/iPlay50Mini.keystore b/app/keystore/iPlay50Mini.keystore
new file mode 100644
index 0000000..fa4d77f
Binary files /dev/null and b/app/keystore/iPlay50Mini.keystore differ
diff --git a/app/libs/framework.jar b/app/libs/framework.jar
new file mode 100644
index 0000000..fefe7ec
Binary files /dev/null and b/app/libs/framework.jar differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/com/uiuipad/find/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/uiuipad/find/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..e6c8d1a
--- /dev/null
+++ b/app/src/androidTest/java/com/uiuipad/find/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.uiuipad.find;
+
+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 Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ assertEquals("com.uiuipad.find", appContext.getPackageName());
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f97a69f
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/uiuipad/find/activity/MainActivity.java b/app/src/main/java/com/uiuipad/find/activity/MainActivity.java
new file mode 100644
index 0000000..822270a
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/activity/MainActivity.java
@@ -0,0 +1,18 @@
+package com.uiuipad.find.activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+
+import com.uiuipad.find.R;
+
+public class MainActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+
+
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseActivity.java b/app/src/main/java/com/uiuipad/find/base/BaseActivity.java
new file mode 100644
index 0000000..6ad1783
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseActivity.java
@@ -0,0 +1,129 @@
+package com.uiuipad.find.base;
+
+import android.os.Bundle;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.CheckResult;
+import androidx.annotation.ContentView;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.trello.rxlifecycle4.LifecycleProvider;
+import com.trello.rxlifecycle4.LifecycleTransformer;
+import com.trello.rxlifecycle4.RxLifecycle;
+import com.trello.rxlifecycle4.android.ActivityEvent;
+import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
+import com.uiuipad.find.R;
+import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
+
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.subjects.BehaviorSubject;
+
+
+public abstract class BaseActivity extends AppCompatActivity implements LifecycleProvider {
+ public final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
+
+ public BaseActivity() {
+ super();
+ }
+
+ @ContentView
+ public BaseActivity(@LayoutRes int contentLayoutId) {
+ super(contentLayoutId);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final Observable lifecycle() {
+ return lifecycleSubject.hide();
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
+ return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindToLifecycle() {
+ return RxLifecycleAndroid.bindActivity(lifecycleSubject);
+ }
+
+ @Override
+ @CallSuper
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ lifecycleSubject.onNext(ActivityEvent.CREATE);
+// StatusBarUtil.init(this);
+ UltimateBarX.statusBar(this)
+ .transparent()
+ .colorRes(R.color.colorPrimaryDark)
+// .light(true)
+ .apply();
+ UltimateBarX.navigationBar(this)
+ .transparent()
+ .colorRes(R.color.colorPrimaryDark)
+// .light(true)
+ .apply();
+ setContentView(this.getLayoutId());
+ initView();
+ initData();
+ }
+
+ /**
+ * 设置布局
+ */
+ public abstract int getLayoutId();
+
+ /**
+ * 初始化视图
+ */
+ public abstract void initView();
+
+
+ /**
+ * 初始化数据
+ */
+ public abstract void initData();
+
+ @Override
+ @CallSuper
+ protected void onStart() {
+ super.onStart();
+ lifecycleSubject.onNext(ActivityEvent.START);
+ }
+
+ @Override
+ @CallSuper
+ protected void onResume() {
+ super.onResume();
+ lifecycleSubject.onNext(ActivityEvent.RESUME);
+ }
+
+ @Override
+ @CallSuper
+ protected void onPause() {
+ lifecycleSubject.onNext(ActivityEvent.PAUSE);
+ super.onPause();
+ }
+
+ @Override
+ @CallSuper
+ protected void onStop() {
+ lifecycleSubject.onNext(ActivityEvent.STOP);
+ super.onStop();
+ }
+
+ @Override
+ @CallSuper
+ protected void onDestroy() {
+ lifecycleSubject.onNext(ActivityEvent.DESTROY);
+ super.onDestroy();
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseApplication.java b/app/src/main/java/com/uiuipad/find/base/BaseApplication.java
new file mode 100644
index 0000000..f7a0696
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseApplication.java
@@ -0,0 +1,123 @@
+package com.uiuipad.find.base;
+
+import android.app.Application;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.alibaba.sdk.android.push.CloudPushService;
+import com.alibaba.sdk.android.push.CommonCallback;
+import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
+import com.tencent.mmkv.MMKV;
+import com.uiuipad.find.BuildConfig;
+import com.uiuipad.find.manager.MapManager;
+import com.uiuipad.find.push.PushManager;
+import com.uiuipad.find.util.Utils;
+
+public class BaseApplication extends Application {
+ private static final String TAG = BaseApplication.class.getSimpleName();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ init();
+ }
+
+ private void init() {
+ if (!BuildConfig.DEBUG) {
+ catchException();
+ }
+ String rootDir = MMKV.initialize(this);
+ Log.i(TAG, "mmkv root: " + rootDir);
+
+ PushManager.init(this);
+ MapManager.init(this);
+ aliyunPushInit();
+ }
+
+ private void catchException() {
+ Thread.setDefaultUncaughtExceptionHandler(
+ new Thread.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ Log.e("捕获异常子线程:", Thread.currentThread().getName() +
+ "在:" + e.getStackTrace()[0].getClassName());
+ }
+ }
+ );
+ //下面是新增方法!
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ Looper.loop(); //会先执行这个方法,然后在执行下面的异常捕获方法!
+ } catch (Exception e) {
+ Log.e("捕获异常主线程:", Thread.currentThread().getName() +
+ "在:" + e.getStackTrace()[0].getClassName());
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ }
+
+ private void aliyunPushInit() {
+ PushServiceFactory.init(this);
+ final CloudPushService pushService = PushServiceFactory.getCloudPushService();
+ pushService.setLogLevel(CloudPushService.LOG_DEBUG);
+ pushService.register(this, new CommonCallback() {
+ @Override
+ public void onSuccess(String response) {
+ Log.e("AliyunPush", "init cloudchannel success");
+ Log.e("AliyunPush", "init cloudchannel success " + pushService.getDeviceId());
+ String sn = Utils.getSerial();
+ Log.e(TAG, "AliyunPush: sn=" + sn);
+ if (TextUtils.isEmpty(sn)) {
+ return;
+ }
+ pushService.bindAccount(sn, new CommonCallback() {
+ @Override
+ public void onSuccess(String s) {
+ Log.e("AliyunPush", "bind account " + sn + " success\n");
+ }
+
+ @Override
+ public void onFailed(String errorCode, String errorMsg) {
+ Log.e("AliyunPush", "bind account " + sn + " failed." +
+ "errorCode: " + errorCode + ", errorMsg:" + errorMsg);
+ }
+ });
+ pushService.addAlias(sn, new CommonCallback() {
+ @Override
+ public void onSuccess(String s) {
+ Log.e("AliyunPush", "add alias " + sn + " success\n");
+ }
+
+ @Override
+ public void onFailed(String errorCode, String errorMsg) {
+ Log.e("AliyunPush", "add alias " + sn + " failed." +
+ "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
+ }
+ });
+ }
+
+ @Override
+ public void onFailed(String errorCode, String errorMessage) {
+ Log.e("AliyunPush", "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
+ }
+ });
+ }
+
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseLifecycleActivity.java b/app/src/main/java/com/uiuipad/find/base/BaseLifecycleActivity.java
new file mode 100644
index 0000000..bf56c00
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseLifecycleActivity.java
@@ -0,0 +1,116 @@
+package com.uiuipad.find.base;
+
+import android.os.Bundle;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.CheckResult;
+import androidx.annotation.ContentView;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.trello.rxlifecycle4.LifecycleProvider;
+import com.trello.rxlifecycle4.LifecycleTransformer;
+import com.trello.rxlifecycle4.RxLifecycle;
+import com.trello.rxlifecycle4.android.ActivityEvent;
+import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
+
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.subjects.BehaviorSubject;
+
+
+public abstract class BaseLifecycleActivity extends AppCompatActivity implements LifecycleProvider {
+ public final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
+
+ public BaseLifecycleActivity() {
+ super();
+ }
+
+ @ContentView
+ public BaseLifecycleActivity(@LayoutRes int contentLayoutId) {
+ super(contentLayoutId);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final Observable lifecycle() {
+ return lifecycleSubject.hide();
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
+ return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindToLifecycle() {
+ return RxLifecycleAndroid.bindActivity(lifecycleSubject);
+ }
+
+ @Override
+ @CallSuper
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ lifecycleSubject.onNext(ActivityEvent.CREATE);
+ setContentView(this.getLayoutId());
+ initView();
+ initData();
+ }
+
+ /**
+ * 设置布局
+ */
+ public abstract int getLayoutId();
+
+ /**
+ * 初始化视图
+ */
+ public abstract void initView();
+
+
+ /**
+ * 初始化数据
+ */
+ public abstract void initData();
+
+ @Override
+ @CallSuper
+ protected void onStart() {
+ super.onStart();
+ lifecycleSubject.onNext(ActivityEvent.START);
+ }
+
+ @Override
+ @CallSuper
+ protected void onResume() {
+ super.onResume();
+ lifecycleSubject.onNext(ActivityEvent.RESUME);
+ }
+
+ @Override
+ @CallSuper
+ protected void onPause() {
+ lifecycleSubject.onNext(ActivityEvent.PAUSE);
+ super.onPause();
+ }
+
+ @Override
+ @CallSuper
+ protected void onStop() {
+ lifecycleSubject.onNext(ActivityEvent.STOP);
+ super.onStop();
+ }
+
+ @Override
+ @CallSuper
+ protected void onDestroy() {
+ lifecycleSubject.onNext(ActivityEvent.DESTROY);
+ super.onDestroy();
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseLightActivity.java b/app/src/main/java/com/uiuipad/find/base/BaseLightActivity.java
new file mode 100644
index 0000000..dac55c3
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseLightActivity.java
@@ -0,0 +1,129 @@
+package com.uiuipad.find.base;
+
+import android.os.Bundle;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.CheckResult;
+import androidx.annotation.ContentView;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.trello.rxlifecycle4.LifecycleProvider;
+import com.trello.rxlifecycle4.LifecycleTransformer;
+import com.trello.rxlifecycle4.RxLifecycle;
+import com.trello.rxlifecycle4.android.ActivityEvent;
+import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
+import com.uiuipad.find.R;
+import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
+
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.subjects.BehaviorSubject;
+
+
+public abstract class BaseLightActivity extends AppCompatActivity implements LifecycleProvider {
+ public final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
+
+ public BaseLightActivity() {
+ super();
+ }
+
+ @ContentView
+ public BaseLightActivity(@LayoutRes int contentLayoutId) {
+ super(contentLayoutId);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final Observable lifecycle() {
+ return lifecycleSubject.hide();
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
+ return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindToLifecycle() {
+ return RxLifecycleAndroid.bindActivity(lifecycleSubject);
+ }
+
+ @Override
+ @CallSuper
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ lifecycleSubject.onNext(ActivityEvent.CREATE);
+// StatusBarUtil.init(this);
+ UltimateBarX.statusBar(this)
+ .transparent()
+ .colorRes(R.color.colorPrimaryDark)
+ .light(true)
+ .apply();
+ UltimateBarX.navigationBar(this)
+ .transparent()
+ .colorRes(R.color.colorPrimaryDark)
+ .light(true)
+ .apply();
+ setContentView(this.getLayoutId());
+ initView();
+ initData();
+ }
+
+ /**
+ * 设置布局
+ */
+ public abstract int getLayoutId();
+
+ /**
+ * 初始化视图
+ */
+ public abstract void initView();
+
+
+ /**
+ * 初始化数据
+ */
+ public abstract void initData();
+
+ @Override
+ @CallSuper
+ protected void onStart() {
+ super.onStart();
+ lifecycleSubject.onNext(ActivityEvent.START);
+ }
+
+ @Override
+ @CallSuper
+ protected void onResume() {
+ super.onResume();
+ lifecycleSubject.onNext(ActivityEvent.RESUME);
+ }
+
+ @Override
+ @CallSuper
+ protected void onPause() {
+ lifecycleSubject.onNext(ActivityEvent.PAUSE);
+ super.onPause();
+ }
+
+ @Override
+ @CallSuper
+ protected void onStop() {
+ lifecycleSubject.onNext(ActivityEvent.STOP);
+ super.onStop();
+ }
+
+ @Override
+ @CallSuper
+ protected void onDestroy() {
+ lifecycleSubject.onNext(ActivityEvent.DESTROY);
+ super.onDestroy();
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseLightLifecycleActivity.java b/app/src/main/java/com/uiuipad/find/base/BaseLightLifecycleActivity.java
new file mode 100644
index 0000000..b25eeed
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseLightLifecycleActivity.java
@@ -0,0 +1,115 @@
+package com.uiuipad.find.base;
+
+import android.os.Bundle;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.CheckResult;
+import androidx.annotation.ContentView;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.trello.rxlifecycle4.LifecycleProvider;
+import com.trello.rxlifecycle4.LifecycleTransformer;
+import com.trello.rxlifecycle4.RxLifecycle;
+import com.trello.rxlifecycle4.android.ActivityEvent;
+import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
+
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.subjects.BehaviorSubject;
+
+public abstract class BaseLightLifecycleActivity extends AppCompatActivity implements LifecycleProvider {
+ public final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
+
+ public BaseLightLifecycleActivity() {
+ super();
+ }
+
+ @ContentView
+ public BaseLightLifecycleActivity(@LayoutRes int contentLayoutId) {
+ super(contentLayoutId);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final Observable lifecycle() {
+ return lifecycleSubject.hide();
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
+ return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
+ }
+
+ @Override
+ @NonNull
+ @CheckResult
+ public final LifecycleTransformer bindToLifecycle() {
+ return RxLifecycleAndroid.bindActivity(lifecycleSubject);
+ }
+
+ @Override
+ @CallSuper
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ lifecycleSubject.onNext(ActivityEvent.CREATE);
+ setContentView(this.getLayoutId());
+ initView();
+ initData();
+ }
+
+ /**
+ * 设置布局
+ */
+ public abstract int getLayoutId();
+
+ /**
+ * 初始化视图
+ */
+ public abstract void initView();
+
+
+ /**
+ * 初始化数据
+ */
+ public abstract void initData();
+
+ @Override
+ @CallSuper
+ protected void onStart() {
+ super.onStart();
+ lifecycleSubject.onNext(ActivityEvent.START);
+ }
+
+ @Override
+ @CallSuper
+ protected void onResume() {
+ super.onResume();
+ lifecycleSubject.onNext(ActivityEvent.RESUME);
+ }
+
+ @Override
+ @CallSuper
+ protected void onPause() {
+ lifecycleSubject.onNext(ActivityEvent.PAUSE);
+ super.onPause();
+ }
+
+ @Override
+ @CallSuper
+ protected void onStop() {
+ lifecycleSubject.onNext(ActivityEvent.STOP);
+ super.onStop();
+ }
+
+ @Override
+ @CallSuper
+ protected void onDestroy() {
+ lifecycleSubject.onNext(ActivityEvent.DESTROY);
+ super.onDestroy();
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BasePresenter.java b/app/src/main/java/com/uiuipad/find/base/BasePresenter.java
new file mode 100644
index 0000000..ee378d7
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BasePresenter.java
@@ -0,0 +1,7 @@
+package com.uiuipad.find.base;
+
+public interface BasePresenter {
+ void attachView(V view);
+
+ void detachView();
+}
diff --git a/app/src/main/java/com/uiuipad/find/base/BaseView.java b/app/src/main/java/com/uiuipad/find/base/BaseView.java
new file mode 100644
index 0000000..85b7e4e
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/base/BaseView.java
@@ -0,0 +1,4 @@
+package com.uiuipad.find.base;
+
+public interface BaseView {
+}
diff --git a/app/src/main/java/com/uiuipad/find/bean/MapBean.java b/app/src/main/java/com/uiuipad/find/bean/MapBean.java
new file mode 100644
index 0000000..337d6fc
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/bean/MapBean.java
@@ -0,0 +1,145 @@
+package com.uiuipad.find.bean;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParser;
+
+import java.io.Serializable;
+
+public class MapBean implements Serializable {
+ private static final long serialVersionUID = -4356064111098876676L;
+
+ double longitude;
+ double latitude;
+ String adcode;
+ String address;
+ String city;
+ String cityCode;
+ String country;
+ String countryCode;
+ String district;
+ String province;
+ String street;
+ String streetNumber;
+ String town;
+ String locationDescribe;
+
+ public double getLongitude() {
+ return longitude;
+ }
+
+ public void setLongitude(double longitude) {
+ this.longitude = longitude;
+ }
+
+ public double getLatitude() {
+ return latitude;
+ }
+
+ public void setLatitude(double latitude) {
+ this.latitude = latitude;
+ }
+
+ public String getAdcode() {
+ return adcode;
+ }
+
+ public void setAdcode(String adcode) {
+ this.adcode = adcode;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCityCode() {
+ return cityCode;
+ }
+
+ public void setCityCode(String cityCode) {
+ this.cityCode = cityCode;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getCountryCode() {
+ return countryCode;
+ }
+
+ public void setCountryCode(String countryCode) {
+ this.countryCode = countryCode;
+ }
+
+ public String getDistrict() {
+ return district;
+ }
+
+ public void setDistrict(String district) {
+ this.district = district;
+ }
+
+ public String getProvince() {
+ return province;
+ }
+
+ public void setProvince(String province) {
+ this.province = province;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getStreetNumber() {
+ return streetNumber;
+ }
+
+ public void setStreetNumber(String streetNumber) {
+ this.streetNumber = streetNumber;
+ }
+
+ public String getTown() {
+ return town;
+ }
+
+ public void setTown(String town) {
+ this.town = town;
+ }
+
+ public String getLocationDescribe() {
+ return locationDescribe;
+ }
+
+ public void setLocationDescribe(String locationDescribe) {
+ this.locationDescribe = locationDescribe;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString();
+ }
+}
diff --git a/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java b/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java
new file mode 100644
index 0000000..acb9f77
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/comm/CommonConfig.java
@@ -0,0 +1,11 @@
+package com.uiuipad.find.comm;
+
+public class CommonConfig {
+ public static final String MMKV_ID = "InterProcessKV";
+
+ public static final String MAP_LOCATION_JSON_KEY = "MAPLOCATION_JSON_STRING";
+ public static final String MAP_LONGITUDE_KEY = "map_longitude_key";
+ public static final String MAP_LATITUDE_KEY = "map_latitude_key";
+ public static final String MAP_ADDRESS_KEY = "map_address_key";
+ public static final String MAP_ERROR_KEY = "map_error_key";
+}
diff --git a/app/src/main/java/com/uiuipad/find/gson/GsonUtils.java b/app/src/main/java/com/uiuipad/find/gson/GsonUtils.java
new file mode 100644
index 0000000..601faba
--- /dev/null
+++ b/app/src/main/java/com/uiuipad/find/gson/GsonUtils.java
@@ -0,0 +1,144 @@
+package com.uiuipad.find.gson;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+public class GsonUtils {
+ //https://blog.csdn.net/zte1055889498/article/details/122400299
+
+ public static JsonObject getJsonObject(String jsonString) {
+ JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
+ return jsonObject;
+ }
+
+ private static final Gson gson;
+
+ static {
+ GsonBuilder builder = new GsonBuilder();
+ builder.registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory());
+ builder.registerTypeAdapter(Integer.class, new IntegerDefault0Adapter());
+ builder.registerTypeAdapter(int.class, new IntegerDefault0Adapter());
+ builder.disableHtmlEscaping();
+ builder.enableComplexMapKeySerialization();
+ // builder.excludeFieldsWithoutExposeAnnotation();
+ builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
+ gson = builder.create();
+ }
+
+ public static Type makeJavaType(Type rawType, Type... typeArguments) {
+ return TypeToken.getParameterized(rawType, typeArguments).getType();
+ }
+
+ public static String toString(Object value) {
+ if (Objects.isNull(value)) {
+ return null;
+ }
+ if (value instanceof String) {
+ return (String) value;
+ }
+ return toJSONString(value);
+ }
+
+ public static String toJSONString(Object value) {
+ return gson.toJson(value);
+ }
+
+ public static String toPrettyString(Object value) {
+ return gson.newBuilder().setPrettyPrinting().create().toJson(value);
+ }
+
+ public static JsonElement fromJavaObject(Object value) {
+ JsonElement result = null;
+ if (Objects.nonNull(value) && (value instanceof String)) {
+ result = parseObject((String) value);
+ } else {
+ result = gson.toJsonTree(value);
+ }
+ return result;
+ }
+
+ public static JsonElement parseObject(String content) {
+ return JsonParser.parseString(content);
+ }
+
+ public static JsonElement getJsonElement(JsonObject node, String name) {
+ return node.get(name);
+ }
+
+ public static JsonElement getJsonElement(JsonArray node, int index) {
+ return node.get(index);
+ }
+
+ public static T toJavaObject(JsonElement node, Class clazz) {
+ return gson.fromJson(node, clazz);
+ }
+
+ public static T toJavaObject(JsonElement node, Type type) {
+ return gson.fromJson(node, type);
+ }
+
+ public static T toJavaObject(JsonElement node, TypeToken> typeToken) {
+ return toJavaObject(node, typeToken.getType());
+ }
+
+ public static List toJavaList(JsonElement node, Class clazz) {
+ return toJavaObject(node, makeJavaType(List.class, clazz));
+ }
+
+ public static List