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 toJavaList(JsonElement node) { + return toJavaObject(node, new TypeToken>() { + }.getType()); + } + + public static Map toJavaMap(JsonElement node, Class clazz) { + return toJavaObject(node, makeJavaType(Map.class, String.class, clazz)); + } + + public static Map toJavaMap(JsonElement node) { + return toJavaObject(node, new TypeToken>() { + }.getType()); + } + + public static T toJavaObject(String content, Class clazz) { + JsonObject jsonObject = getJsonObject(content); + String jsonString = jsonObject.toString(); + return gson.fromJson(jsonString, clazz); + } + + public static T toJavaObject(String content, Type type) { + return gson.fromJson(content, type); + } + + public static T toJavaObject(String content, TypeToken typeToken) { + return toJavaObject(content, typeToken.getType()); + } + + public static List toJavaList(String content, Class clazz) { + return toJavaObject(content, makeJavaType(List.class, clazz)); + } + + public static List toJavaList(String content) { + return toJavaObject(content, new TypeToken>() { + }.getType()); + } + + public static Map toJavaMap(String content, Class clazz) { + return toJavaObject(content, makeJavaType(Map.class, String.class, clazz)); + } + + public static Map toJavaMap(String content) { + return toJavaObject(content, new TypeToken>() { + }.getType()); + } +} diff --git a/app/src/main/java/com/uiuipad/find/gson/IntegerDefault0Adapter.java b/app/src/main/java/com/uiuipad/find/gson/IntegerDefault0Adapter.java new file mode 100644 index 0000000..2a4eae8 --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/gson/IntegerDefault0Adapter.java @@ -0,0 +1,35 @@ +package com.uiuipad.find.gson; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonSyntaxException; + +import java.lang.reflect.Type; + +public class IntegerDefault0Adapter implements JsonSerializer, JsonDeserializer { + @Override + public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + try { + if (json.getAsString().equals("")) { + return 0; + } + } catch (Exception ignore) { + } + try { + return json.getAsInt(); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + @Override + public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uiuipad/find/gson/NullStringToEmptyAdapterFactory.java b/app/src/main/java/com/uiuipad/find/gson/NullStringToEmptyAdapterFactory.java new file mode 100644 index 0000000..cfb7103 --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/gson/NullStringToEmptyAdapterFactory.java @@ -0,0 +1,45 @@ +package com.uiuipad.find.gson; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; + +public class NullStringToEmptyAdapterFactory implements TypeAdapterFactory { + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + + Class rawType = (Class) type.getRawType(); + if (rawType != String.class) { + return null; + } + return (TypeAdapter) new StringAdapter(); + } + + public static class StringAdapter extends TypeAdapter { + @Override + public String read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return ""; + } + return reader.nextString(); + } + + @Override + public void write(JsonWriter writer, String value) throws IOException { + if (value == null) { + writer.nullValue(); + return; + } + writer.value(value); + } + } + +} + diff --git a/app/src/main/java/com/uiuipad/find/manager/MapManager.java b/app/src/main/java/com/uiuipad/find/manager/MapManager.java new file mode 100644 index 0000000..fa2cb8e --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/manager/MapManager.java @@ -0,0 +1,222 @@ +package com.uiuipad.find.manager; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.provider.Settings; +import android.util.Log; + +import com.baidu.location.BDAbstractLocationListener; +import com.baidu.location.BDLocation; +import com.baidu.location.LocationClient; +import com.baidu.location.LocationClientOption; +import com.tencent.mmkv.MMKV; +import com.uiuipad.find.bean.MapBean; +import com.uiuipad.find.comm.CommonConfig; +import com.uiuipad.find.gson.GsonUtils; + +public class MapManager { + private static final String TAG = MapManager.class.getSimpleName(); + + @SuppressLint("StaticFieldLeak") + private static MapManager sInstance; + private Context mContext; + @SuppressLint("StaticFieldLeak") + private LocationClient mLocationClient = null; + private LocationClientOption mOption; + + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private MapManager(Context context) { + this.mContext = context; + Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); + initAmap(); + } + + public static void init(Context context) { + if (context == null) { + throw new RuntimeException("Context is NULL"); + } + if (sInstance == null) { + sInstance = new MapManager(context); + } + } + + public static MapManager getInstance() { + if (sInstance == null) { + throw new IllegalStateException("You must be init MapManager first"); + } + return sInstance; + } + + public void initAmap() { + if (mLocationClient == null) { + mLocationClient = new LocationClient(mContext); + } + Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps"); + mLocationClient.setLocOption(getDefaultLocationClientOption()); + mLocationClient.registerLocationListener(mListener); + mLocationClient.stop(); + mLocationClient.start(); + } + + public LocationClient getLocationClient() { + if (mLocationClient == null) { + initAmap(); + } + return mLocationClient; + } + + /*** + * + * @return DefaultLocationClientOption 默认O设置 + */ + public LocationClientOption getDefaultLocationClientOption() { + if (mOption == null) { + mOption = new LocationClientOption(); + mOption.setCoorType("bd09ll"); // 可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll; + mOption.setScanSpan(0); // 可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的 + mOption.setIsNeedAddress(true); // 可选,设置是否需要地址信息,默认不需要 + mOption.setIsNeedLocationDescribe(true); // 可选,设置是否需要地址描述 + mOption.setNeedDeviceDirect(false); // 可选,设置是否需要设备方向结果 + mOption.setLocationNotify(false); // 可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果 + mOption.setIgnoreKillProcess(true); // 可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop + mOption.setIsNeedLocationDescribe(true); // 可选,默认false,设置是否需要位置语义化结果,可以在BDLocation + mOption.setIsNeedLocationPoiList(true); // 可选,默认false,设置是否需要POI结果,可以在BDLocation + mOption.SetIgnoreCacheException(false); // 可选,默认false,设置是否收集CRASH信息,默认收集 + mOption.setLocationMode(LocationClientOption.LocationMode.Battery_Saving); // 可选,默认高精度,设置定位模式,高精度,低功耗,仅设备,模糊 + mOption.setIsNeedAltitude(false); // 可选,默认false,设置定位时是否需要海拔信息,默认不需要,除基础定位版本都可用 + // 可选,设置首次定位时选择定位速度优先还是定位准确性优先,默认为速度优先 +// mOption.setFirstLocType(LocationClientOption.FirstLocType.SPEED_IN_FIRST_LOC); + } + return mOption; + } + + /***** + * + * 定位结果回调,重写onReceiveLocation方法,可以直接拷贝如下代码到自己工程中修改 + * + */ + private BDAbstractLocationListener mListener = new BDAbstractLocationListener() { + + /** + * 定位请求回调函数 + * @param location 定位结果 + */ + @Override + public void onReceiveLocation(BDLocation location) { + if (null != location) { + switch (location.getLocType()) { + case BDLocation.TypeGpsLocation:// GPS定位结果 + case BDLocation.TypeNetWorkLocation:// 网络定位结果 + case BDLocation.TypeOffLineLocation:// 离线定位结果 + Log.e(TAG, "onLocationChanged: " + "定位成功"); + Log.e(TAG, "onLocationChanged: longitude = " + location.getLongitude()); + Log.e(TAG, "onLocationChanged: latitude = " + location.getLatitude()); + Log.e(TAG, "onLocationChanged: " + location.getAddrStr() + location.getLocationDescribe()); + mMMKV.encode(CommonConfig.MAP_ADDRESS_KEY, location.getAddrStr() + location.getLocationDescribe()); + mMMKV.encode(CommonConfig.MAP_LONGITUDE_KEY, location.getLongitude()); + mMMKV.encode(CommonConfig.MAP_LATITUDE_KEY, location.getLatitude()); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, "-"); + saveMapResult(location); + break; + case BDLocation.TypeServerError: + Log.e(TAG, "onReceiveLocation: " + "服务端网络定位失败"); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, "服务端网络定位失败,可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com,会有人追查原因"); + break; + case BDLocation.TypeNetWorkException: + Log.e(TAG, "onReceiveLocation: " + "网络不同导致定位失败,请检查网络是否通畅"); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, "网络不同导致定位失败,请检查网络是否通畅"); + break; + case BDLocation.TypeCriteriaException: + Log.e(TAG, "onReceiveLocation: " + "无法获取有效定位依据导致定位失败"); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, "无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机"); + break; + default: + } + } + Log.e(TAG, "AmapAddress: " + mMMKV.decodeString(CommonConfig.MAP_ADDRESS_KEY, "-")); + Log.e(TAG, "AmapError: " + mMMKV.decodeString(CommonConfig.MAP_ERROR_KEY, "-")); + Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-network"); + Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-gps"); + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 0); + } + + @Override + public void onConnectHotSpotMessage(String s, int i) { + super.onConnectHotSpotMessage(s, i); + } + + /** + * 回调定位诊断信息,开发者可以根据相关信息解决定位遇到的一些问题 + * @param locType 当前定位类型 + * @param diagnosticType 诊断类型(1~9) + * @param diagnosticMessage 具体的诊断信息释义 + */ + @Override + public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) { + super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage); +// int tag = 2; + StringBuffer sb = new StringBuffer(256); + sb.append("诊断结果: "); + if (locType == BDLocation.TypeNetWorkLocation) { + if (diagnosticType == 1) { + sb.append("网络定位成功,没有开启GPS,建议打开GPS会更好"); + sb.append("\n" + diagnosticMessage); + } else if (diagnosticType == 2) { + sb.append("网络定位成功,没有开启Wi-Fi,建议打开Wi-Fi会更好"); + sb.append("\n" + diagnosticMessage); + } + } else if (locType == BDLocation.TypeOffLineLocationFail) { + if (diagnosticType == 3) { + sb.append("定位失败,请您检查您的网络状态"); + sb.append("\n" + diagnosticMessage); + } + } else if (locType == BDLocation.TypeCriteriaException) { + if (diagnosticType == 4) { + sb.append("定位失败,无法获取任何有效定位依据"); + sb.append("\n" + diagnosticMessage); + } else if (diagnosticType == 5) { + sb.append("定位失败,无法获取有效定位依据,请检查运营商网络或者Wi-Fi网络是否正常开启,尝试重新请求定位"); + sb.append(diagnosticMessage); + } else if (diagnosticType == 6) { + sb.append("定位失败,无法获取有效定位依据,请尝试插入一张sim卡或打开Wi-Fi重试"); + sb.append("\n" + diagnosticMessage); + } else if (diagnosticType == 7) { + sb.append("定位失败,飞行模式下无法获取有效定位依据,请关闭飞行模式重试"); + sb.append("\n" + diagnosticMessage); + } else if (diagnosticType == 9) { + sb.append("定位失败,无法获取任何有效定位依据"); + sb.append("\n" + diagnosticMessage); + } + } else if (locType == BDLocation.TypeServerError) { + if (diagnosticType == 8) { + sb.append("定位失败,请确认您定位的开关打开状态,是否赋予APP定位权限"); + sb.append("\n" + diagnosticMessage); + } + } + Log.e(TAG, "onLocationChanged: " + "定位失败"); + mMMKV.encode(CommonConfig.MAP_ERROR_KEY, sb.toString()); + Log.e(TAG, "onLocDiagnosticMessage: " + sb); + } + }; + + private void saveMapResult(BDLocation bdLocation) { + MapBean mapBean = new MapBean(); + mapBean.setLongitude(bdLocation.getLongitude()); + mapBean.setLatitude(bdLocation.getLatitude()); + mapBean.setAdcode(bdLocation.getAdCode()); + mapBean.setAddress(bdLocation.getAddrStr()); + mapBean.setCity(bdLocation.getCity()); + mapBean.setCityCode(bdLocation.getCityCode()); + mapBean.setCountry(bdLocation.getCountry()); + mapBean.setCountryCode(bdLocation.getCountryCode()); + mapBean.setDistrict(bdLocation.getDistrict()); + mapBean.setProvince(bdLocation.getProvince()); + mapBean.setStreet(bdLocation.getStreet()); + mapBean.setStreetNumber(bdLocation.getStreetNumber()); + mapBean.setTown(bdLocation.getTown()); + mapBean.setLocationDescribe(bdLocation.getLocationDescribe()); + + mMMKV.encode(CommonConfig.MAP_LOCATION_JSON_KEY, GsonUtils.toJSONString(mapBean)); + } +} diff --git a/app/src/main/java/com/uiuipad/find/push/PushManager.java b/app/src/main/java/com/uiuipad/find/push/PushManager.java new file mode 100644 index 0000000..0f6541a --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/push/PushManager.java @@ -0,0 +1,49 @@ +package com.uiuipad.find.push; + +import android.annotation.SuppressLint; +import android.content.ContentResolver; +import android.content.Context; + +import com.tencent.mmkv.MMKV; +import com.uiuipad.find.comm.CommonConfig; + +public class PushManager { + private static final String TAG = PushManager.class.getSimpleName(); + + @SuppressLint("StaticFieldLeak") + private static PushManager sInstance; + private Context mContext; + private ContentResolver mResolver; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private PushManager(Context context) { + if (context == null) { + throw new RuntimeException("Context is NULL"); + } + this.mContext = context; + this.mResolver = context.getContentResolver(); + } + + public static void init(Context context) { + if (sInstance == null) { + sInstance = new PushManager(context); + } + } + + public static PushManager getInstance() { + if (sInstance == null) { + throw new IllegalStateException("You must be init PushManager first"); + } + return sInstance; + } + + + public void setPushContent(String title, String extras) { + switch (title) { + + default: + } + } + + +} diff --git a/app/src/main/java/com/uiuipad/find/push/alipush/AliMessageIntentService.java b/app/src/main/java/com/uiuipad/find/push/alipush/AliMessageIntentService.java new file mode 100644 index 0000000..77a7ac3 --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/push/alipush/AliMessageIntentService.java @@ -0,0 +1,99 @@ +package com.uiuipad.find.push.alipush; + +import android.content.Context; +import android.util.Log; + +import com.alibaba.sdk.android.push.AliyunMessageIntentService; +import com.alibaba.sdk.android.push.notification.CPushMessage; + +import java.util.Map; + +/** + * Created by liyazhou on 17/8/22. + * 为避免推送广播被系统拦截的小概率事件,我们推荐用户通过IntentService处理消息互调,接入步骤: + * 1. 创建IntentService并继承AliyunMessageIntentService + * 2. 覆写相关方法,并在Manifest的注册该Service + * 3. 调用接口CloudPushService.setPushIntentService + * 详细用户可参考:https://help.aliyun.com/document_detail/30066.html#h2-2-messagereceiver-aliyunmessageintentservice + */ + +public class AliMessageIntentService extends AliyunMessageIntentService { + private static final String TAG = AliyunMessageIntentService.class.getSimpleName(); + + /** + * 推送通知的回调方法 + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + protected void onNotification(Context context, String title, String summary, Map extraMap) { + Log.i(TAG, "收到一条推送通知 : " + title + ", summary:" + summary); + } + + /** + * 推送消息的回调方法 + * + * @param context + * @param cPushMessage + */ + @Override + protected void onMessage(Context context, CPushMessage cPushMessage) { + Log.i(TAG, "收到一条推送消息 : " + cPushMessage.getTitle() + ", content:" + cPushMessage.getContent()); + } + + /** + * 从通知栏打开通知的扩展处理 + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + protected void onNotificationOpened(Context context, String title, String summary, String extraMap) { + Log.i(TAG, "onNotificationOpened : " + " : " + title + " : " + summary + " : " + extraMap); + } + + /** + * 无动作通知点击回调。当在后台或阿里云控制台指定的通知动作为无逻辑跳转时,通知点击回调为onNotificationClickedWithNoAction而不是onNotificationOpened + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + protected void onNotificationClickedWithNoAction(Context context, String title, String summary, String extraMap) { + Log.i(TAG, "onNotificationClickedWithNoAction : " + " : " + title + " : " + summary + " : " + extraMap); + } + + /** + * 通知删除回调 + * + * @param context + * @param messageId + */ + @Override + protected void onNotificationRemoved(Context context, String messageId) { + Log.i(TAG, "onNotificationRemoved : " + messageId); + } + + /** + * 应用处于前台时通知到达回调。注意:该方法仅对自定义样式通知有效,相关详情请参考https://help.aliyun.com/document_detail/30066.html#h3-3-4-basiccustompushnotification-api + * + * @param context + * @param title + * @param summary + * @param extraMap + * @param openType + * @param openActivity + * @param openUrl + */ + @Override + protected void onNotificationReceivedInApp(Context context, String title, String summary, Map extraMap, int openType, String openActivity, String openUrl) { + Log.i(TAG, "onNotificationReceivedInApp : " + " : " + title + " : " + summary + " " + extraMap + " : " + openType + " : " + openActivity + " : " + openUrl); + } +} diff --git a/app/src/main/java/com/uiuipad/find/push/alipush/AliyunMessageReceiver.java b/app/src/main/java/com/uiuipad/find/push/alipush/AliyunMessageReceiver.java new file mode 100644 index 0000000..ad6136f --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/push/alipush/AliyunMessageReceiver.java @@ -0,0 +1,116 @@ +package com.uiuipad.find.push.alipush; + +import android.content.Context; +import android.util.Log; + +import com.alibaba.sdk.android.push.MessageReceiver; +import com.alibaba.sdk.android.push.notification.CPushMessage; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.uiuipad.find.push.PushManager; + +import java.util.Map; + +/** + * @author: 正纬 + * @since: 15/4/9 + * @version: 1.1 + * @feature: 用于接收推送的通知和消息 + */ +public class AliyunMessageReceiver extends MessageReceiver { + // 消息接收部分的LOG_TAG + public static final String TAG = AliyunMessageReceiver.class.getSimpleName(); + + /** + * 推送通知的回调方法 + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + public void onNotification(Context context, String title, String summary, Map extraMap) { + // TODO 处理推送通知 + if (null != extraMap) { + for (Map.Entry entry : extraMap.entrySet()) { + Log.i(TAG, "@Get diy param : Key=" + entry.getKey() + " , Value=" + entry.getValue()); + } + } else { + Log.i(TAG, "@收到通知 && 自定义消息为空"); + } + Log.i(TAG, "收到一条推送通知 : " + title + ", summary:" + summary); + } + + /** + * 应用处于前台时通知到达回调。注意:该方法仅对自定义样式通知有效,相关详情请参考https://help.aliyun.com/document_detail/30066.html?spm=5176.product30047.6.620.wjcC87#h3-3-4-basiccustompushnotification-api + * + * @param context + * @param title + * @param summary + * @param extraMap + * @param openType + * @param openActivity + * @param openUrl + */ + @Override + protected void onNotificationReceivedInApp(Context context, String title, String summary, Map extraMap, int openType, String openActivity, String openUrl) { + Log.i(TAG, "onNotificationReceivedInApp : " + " : " + title + " : " + summary + " " + extraMap + " : " + openType + " : " + openActivity + " : " + openUrl); + } + + /** + * 推送消息的回调方法 + * + * @param context + * @param cPushMessage + */ + @Override + public void onMessage(Context context, CPushMessage cPushMessage) { + Log.e(TAG, "收到一条推送消息 : " + cPushMessage.getTitle() + ", content:" + cPushMessage.getContent()); + String title = cPushMessage.getTitle(); + String content = cPushMessage.getContent(); + JsonObject extrasJson = JsonParser.parseString(content).getAsJsonObject(); + String extras = ""; + if (extrasJson.get("extras") != null) { + extras = extrasJson.get("extras").toString(); + } + PushManager.getInstance().setPushContent(title, extras); + } + + /** + * 从通知栏打开通知的扩展处理 + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + public void onNotificationOpened(Context context, String title, String summary, String extraMap) { + Log.i(TAG, "onNotificationOpened : " + " : " + title + " : " + summary + " : " + extraMap); + } + + /** + * 通知删除回调 + * + * @param context + * @param messageId + */ + @Override + public void onNotificationRemoved(Context context, String messageId) { + Log.i(TAG, "onNotificationRemoved : " + messageId); + } + + /** + * 无动作通知点击回调。当在后台或阿里云控制台指定的通知动作为无逻辑跳转时,通知点击回调为onNotificationClickedWithNoAction而不是onNotificationOpened + * + * @param context + * @param title + * @param summary + * @param extraMap + */ + @Override + protected void onNotificationClickedWithNoAction(Context context, String title, String summary, String extraMap) { + Log.i(TAG, "onNotificationClickedWithNoAction : " + " : " + title + " : " + summary + " : " + extraMap); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/uiuipad/find/util/Utils.java b/app/src/main/java/com/uiuipad/find/util/Utils.java new file mode 100644 index 0000000..449a35f --- /dev/null +++ b/app/src/main/java/com/uiuipad/find/util/Utils.java @@ -0,0 +1,36 @@ +package com.uiuipad.find.util; + +import android.annotation.SuppressLint; +import android.os.Build; +import android.util.Log; + +import java.lang.reflect.Method; + +public class Utils { + + /** + * 获取设备序列号 + * + * @return + */ + @SuppressLint({"MissingPermission", "NewApi"}) + public static String getSerial() { +// return JGYUtils.getInstance().getIMEI(); + String serial = "unknown"; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//9.0+ + serial = Build.getSerial(); + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ + serial = Build.SERIAL; + } else {//8.0- + Class c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serial = (String) get.invoke(c, "ro.serialno"); + } + } catch (Exception e) { + e.printStackTrace(); + Log.e("e", "读取设备序列号异常:" + e.toString()); + } + return serial; + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..de1395d --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..030098f --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #6200EE + #3700B3 + #03DAC5 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..d969b5e --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + 设备查找 + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/test/java/com/uiuipad/find/ExampleUnitTest.java b/app/src/test/java/com/uiuipad/find/ExampleUnitTest.java new file mode 100644 index 0000000..3eaf46f --- /dev/null +++ b/app/src/test/java/com/uiuipad/find/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.uiuipad.find; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..008768b --- /dev/null +++ b/build.gradle @@ -0,0 +1,42 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + maven {url 'http://developer.huawei.com/repo/'} + maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } + maven { url 'http://maven.aliyun.com/nexus/content/repositories/releases/' } + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.4' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + maven {url 'http://developer.huawei.com/repo/'} + maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } + maven { url 'http://maven.aliyun.com/nexus/content/repositories/releases/' } + } + + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + //设置jar相对包路径或绝对路径 + options.compilerArgs.add('-Xbootclasspath/p:app/libs/framework.jar') + } + } +} + +task clean(type: Delete) { +// delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..199d16e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a5536ec --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri May 26 09:37:04 CST 2023 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..697b80e --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name='设备查找' +include ':app'