管灌系统巡查员智能手机App
zuoxiao
2024-01-16 6c5f3267bbf0ae2bb3ee256f5f32e92c06577c59
定位模块
10个文件已修改
10个文件已添加
890 ■■■■■ 已修改文件
app/build.gradle 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/proguard-rules.pro 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/AndroidManifest.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/MyApplication.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/activity/LoginActivity.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/activity/MainActivity.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/observer/LoginObserver.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/observer/MapFragmenObserver.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/service/MyCommonService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/service/MyLocationService.java 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/pipirrapp/utils/MyLog.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/drawable/ic_edt_gray_bg.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/drawable/vt_ps_close.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/drawable/vt_ps_open.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_login.xml 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/mipmap-xhdpi/login_bg1.jpeg 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/colors.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dycz.jks 补丁 | 查看 | 原始文档 | blame | 历史
gradle.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/build.gradle
@@ -3,17 +3,51 @@
}
android {
    signingConfigs {
        debug {
            storeFile file('../dycz.jks')
            storePassword 'dycz@2023'
            keyAlias 'dayu'
            keyPassword 'dycz@2023'
        }
    }
    namespace 'com.dayu.pipirrapp'
    compileSdk 33
    defaultConfig {
        applicationId "com.dayu.pipirrapp"
        minSdk 24
        targetSdk 33
        targetSdk 31
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.debug
        manifestPlaceholders = [
                JPUSH_PKGNAME : applicationId,
                //JPush 上注册的包名对应的 Appkey.
                JPUSH_APPKEY : "375adbd599ceb9977566b929",
                //暂时填写默认值即可.
                JPUSH_CHANNEL : "developer-default",
                //若不集成厂商通道,可直接跳过以下配置
                MEIZU_APPKEY : "MZ-魅族的APPKEY",
                MEIZU_APPID : "MZ-魅族的APPID",
                XIAOMI_APPID : "MI-小米的APPID",
                XIAOMI_APPKEY : "MI-小米的APPKEY",
                OPPO_APPKEY : "OP-oppo的APPKEY",
                OPPO_APPID : "OP-oppo的APPID",
                OPPO_APPSECRET : "OP-oppo的APPSECRET",
                VIVO_APPKEY : "vivo的APPKEY",
                VIVO_APPID : "vivo的APPID",
                HONOR_APPID : "Honor的APP ID",
        ]
        ndk {
            // 设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
            abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
        }
    }
    buildTypes {
@@ -50,11 +84,7 @@
//    implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10"
    //权限
    implementation('com.guolindev.permissionx:permissionx:1.7.1') {
        exclude group: 'androidx.core';
        exclude group: 'androidx.appcompat';
        exclude group: 'androidx.annotation';
    }
    implementation 'com.github.getActivity:XXPermissions:18.5'
    //列表
    implementation 'io.github.scwang90:refresh-layout-kernel:2.0.5'
    implementation 'io.github.scwang90:refresh-header-classics:2.0.5'
@@ -79,38 +109,39 @@
    //loding
    implementation 'com.pnikosis:materialish-progress:1.7'
    //定位
    implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.3.7'
    //推送相关
    // 此处以JPush 5.0.0 版本为例,5.0.0 版本开始可以自动拉取 JCore 包,无需另外配置
//    //推送相关
//    // 此处以JPush 5.0.0 版本为例,5.0.0 版本开始可以自动拉取 JCore 包,无需另外配置
    implementation 'cn.jiguang.sdk:jpush:5.2.2'
    //若不集成厂商通道,可直接跳过以下依赖
    // 极光厂商插件版本与接入 JPush 版本保持一致,下同
    // 接入华为厂商
//    //若不集成厂商通道,可直接跳过以下依赖
//    // 极光厂商插件版本与接入 JPush 版本保持一致,下同
//    // 接入华为厂商
    implementation 'com.huawei.hms:push:6.5.0.300'
    implementation 'cn.jiguang.sdk.plugin:huawei:5.2.2'
    // 接入 FCM 厂商
    implementation 'com.google.firebase:firebase-messaging:23.0.5'
    implementation 'cn.jiguang.sdk.plugin:fcm:5.2.2'
    // 接入魅族厂商
//    // 接入 FCM 厂商
//    implementation 'com.google.firebase:firebase-messaging:23.0.5'
//    implementation 'cn.jiguang.sdk.plugin:fcm:5.2.2'
//    // 接入魅族厂商
    implementation 'cn.jiguang.sdk.plugin:meizu:5.2.2'
    // 接入 VIVO 厂商
//    // 接入 VIVO 厂商
    implementation 'cn.jiguang.sdk.plugin:vivo:5.2.2'
    // 接入小米厂商
//    // 接入小米厂商
    implementation 'cn.jiguang.sdk.plugin:xiaomi:5.2.2'
    // 接入 OPPO 厂商
    implementation 'cn.jiguang.sdk.plugin:oppo:5.2.2'
    // JPush Android SDK v4.6.0 开始,需要单独引入 oppo 厂商 aar ,请下载官网 SDK 包并把 jpush-android-xxx-release/third-push/oppo/libs 下的 aar 文件单独拷贝一份到应用 module/libs 下
    implementation(name: 'com.heytap.msp-push-3.1.0', ext: 'aar')
    //以下为 OPPO 3.1.0 aar需要依赖
//    // 接入 OPPO 厂商
//    implementation 'cn.jiguang.sdk.plugin:oppo:5.2.2'
//    // JPush Android SDK v4.6.0 开始,需要单独引入 oppo 厂商 aar ,请下载官网 SDK 包并把 jpush-android-xxx-release/third-push/oppo/libs 下的 aar 文件单独拷贝一份到应用 module/libs 下
//    implementation(name: 'com.heytap.msp-push-3.1.0', ext: 'aar')
//    //以下为 OPPO 3.1.0 aar需要依赖
    implementation 'com.google.code.gson:gson:2.6.2'
    implementation 'commons-codec:commons-codec:1.6'
    implementation 'androidx.annotation:annotation:1.1.0'
    // 接入荣耀厂商
//    // 接入荣耀厂商
    implementation 'cn.jiguang.sdk.plugin:honor:5.2.2'
//    apply plugin: 'com.google.gms.google-services'
    apply plugin: 'com.huawei.agconnect'
//    apply plugin: 'com.huawei.agconnect'
}
app/proguard-rules.pro
@@ -18,4 +18,131 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
#---------------------------------基本指令区----------------------------------
-keepattributes SourceFile,LineNumberTable
-keepattributes Exceptions, Signature, InnerClasses
-keepclasseswithmembernames class * { # 保持native方法不被混淆
    native <methods>;
}
-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆
    public static final Android.os.Parcelable$Creator *;
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keepattributes *Annotation*        #保持注解
#---------------------------------默认保留区---------------------------------
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-keep class android.support.** {*;}
-keepclasseswithmembernames class * {
    native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
-keep class **.R$* {
 *;
}
-keepclassmembers class * {
    void *(**On*Event);
}
#----------------------------------------------------------------------------
-keep   class com.amap.api.maps.**{*;}
-keep   class com.autonavi.**{*;}
-keep   class com.amap.api.trace.**{*;}
-keep class com.amap.api.location.**{*;}
-keep class com.amap.api.fence.**{*;}
-keep class com.autonavi.aps.amapapi.model.**{*;}
-keep   class com.amap.api.services.**{*;}
-keep class com.amap.api.maps2d.**{*;}
-keep class com.amap.api.mapcore2d.**{*;}
-keep class com.amap.api.navi.**{*;}
-keep class com.autonavi.**{*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
-keep public class com.zuo.nfcproject.yanzhou.bean.** {*;}
-keep public class * extends android.view.View {
}
-keep class **.R$* {*;}
#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
-keep interface okhttp3.**{*;}
#rxjava
-keep public class io.reactivex.android.**{*;}
-keep public class io.reactivex.**{*;}
-keep public class rx.android.**{*;}
-keep public class rx.**{*;}
-keep public class javax.annotation.**{*;}
-keep public class javax.inject.**{*;}
-keep class com.google.gson.** { *; }
#glide
-keep public class com.bumptech.glide.**{*;}
-keep public class com.luck.picture.lib.**{*;}
-keep public class androidx.**{*;}
-keep public class com.bumptech.**{*;}
-keep public class com.scwang.**{*;}
-keep public class kotlin.**{*;}
-keep public class retrofit2.**{*;}
-keep public class okio.**{*;}
-keep public class com.zuo.nfcproject.yanzhou.net.**{*;}
# 若Android API 高于27添加以下(不需要/):
-dontwarn com.bumptech.glide.load.resource.bitmap.VideoDecoder
# for DexGuard only
#-keep resource xmlelements manifest/application/meta-data@value=GlideModule
-keep class com.xuexiang.xupdate.entity.** { *; }
# Note: if you use a custom API parser for parsing, you need to add confusion to your custom API entities. Here are the custom API entity obfuscation rules configured in this demo:
-keep class com.xuexiang.xupdatedemo.entity.** { *; }
-keep class com.hjq.permissions.** {*;}
app/src/main/AndroidManifest.xml
@@ -3,6 +3,35 @@
    xmlns:tools="http://schemas.android.com/tools">
    <!--允许访问网络,必选权限-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <!--用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <!--用于访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <!--用于写入缓存数据到扩展存储卡-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <!--用于申请调用A-GPS模块-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
    <!--如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <!--如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <!--     模拟位置-->
    <uses-permission
        android:name="android.permission.ACCESS_MOCK_LOCATION"
        tools:ignore="MockLocation,ProtectedPermissions" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
@@ -14,10 +43,13 @@
        android:theme="@style/Theme.PipIrrApp"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">
        <!-- 告知 XXPermissions 当前项目已经适配了分区存储特性 -->
        <meta-data
            android:name="ScopedStorage"
            android:value="true" />
        <activity
            android:name=".activity.MainActivity"
            android:name=".activity.LoginActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
@@ -25,7 +57,7 @@
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--        <activity android:name=".activity.MainActivity" />-->
        <activity android:name=".activity.MainActivity" />
        <!-- Required since 5.2.0 -->
        <!-- 新的 tag/alias 接口结果返回需要开发者配置一个自定义的Service -->
        <!-- 3.3.0开始所有事件将通过该类回调 -->
@@ -43,7 +75,8 @@
        <!-- Since JCore2.0.0 Required SDK核心功能-->
        <!-- 可配置android:process参数将Service放在其他进程中;android:enabled属性不能是false -->
        <!-- 这个是自定义Service,要继承极光JCommonService,可以在更多手机平台上使得推送通道保持的更稳定 -->
        <service android:name="xx.xx.XService"
        <service
            android:name=".service.MyCommonService"
            android:enabled="true"
            android:exported="false"
            android:process=":pushcore">
@@ -51,6 +84,22 @@
                <action android:name="cn.jiguang.user.service.action" />
            </intent-filter>
        </service>
        <service
            android:name=".service.MyLocationService"
            android:enabled="true"
            android:exported="false" />
        <!--百度定位-->
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="Ky5wvrB9A9Rztsh3rQO8v8oNRgQM27NV"></meta-data>
        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote"></service>
    </application>
</manifest>
app/src/main/java/com/dayu/pipirrapp/MyApplication.java
@@ -2,6 +2,8 @@
import android.app.Application;
import com.tencent.bugly.crashreport.CrashReport;
import cn.jpush.android.api.JPushInterface;
/**
@@ -19,5 +21,6 @@
        myApplication = this;
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
        CrashReport.initCrashReport(getApplicationContext(), "3d4bcf7046", false);
    }
}
app/src/main/java/com/dayu/pipirrapp/activity/LoginActivity.java
@@ -2,31 +2,46 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.dayu.pipirrapp.R;
import com.dayu.pipirrapp.databinding.ActivityLoginBinding;
import com.dayu.pipirrapp.observer.LoginObserver;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import java.util.List;
public class LoginActivity extends AppCompatActivity {
    private boolean isPasswordVisible = false;
public class LoginActivity extends BaseActivity {
    private final String TAG = "LoginActivity";
    ActivityLoginBinding binding;
    private boolean isPasswordVisible = false;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        Log.i(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        binding = ActivityLoginBinding.inflate(LayoutInflater.from(this));
        setContentView(binding.getRoot());
        getLifecycle().addObserver(new LoginObserver(this));
        binding.passwordBtn.setOnClickListener((view) -> {
            togglePasswordVisibility();
        });
        binding.loginBtn.setOnClickListener(v -> {
            Intent intent = new Intent(LoginActivity.this, MainActivity.class);
            startActivity(intent);
            this.finish();
        });
    }
@@ -35,11 +50,11 @@
            // 如果密码可见,隐藏密码
            binding.password.setInputType(
                    InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
            binding.passwordBtn.setImageResource(R.drawable.ic_visibility_off);
            binding.passwordBtn.setImageResource(R.drawable.vt_ps_close);
        } else {
            // 如果密码隐藏,显示密码
            binding.password.setInputType(InputType.TYPE_CLASS_TEXT);
            binding.passwordBtn.setImageResource(R.drawable.ic_visibility);
            binding.passwordBtn.setImageResource(R.drawable.vt_ps_open);
        }
        // 移动光标到末尾
@@ -48,4 +63,64 @@
        // 切换标志
        isPasswordVisible = !isPasswordVisible;
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
    }
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.i(TAG, "onSaveInstanceState");
    }
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        Log.i(TAG, "onSaveInstanceState---outPersistentState");
    }
    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }
}
app/src/main/java/com/dayu/pipirrapp/activity/MainActivity.java
@@ -33,7 +33,6 @@
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(LayoutInflater.from(this));
        MapFragment mapFragment = new MapFragment();
        setContentView(binding.getRoot());
        mFragment.add(mapFragment);
        mFragment.add(new MainFragment());
@@ -41,6 +40,12 @@
        initTab();
    }
    private void getPermission(){
    }
    private void initTab() {
        TabAdapter adapter = new TabAdapter(getSupportFragmentManager(), mFragment);
        binding.viewPager.setAdapter(adapter);
app/src/main/java/com/dayu/pipirrapp/fragment/MapFragment.java
@@ -1,13 +1,13 @@
package com.dayu.pipirrapp.fragment;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
@@ -16,12 +16,14 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import com.dayu.pipirrapp.databinding.FragmentMapBinding;
import com.dayu.pipirrapp.observer.MapFragmenObserver;
import com.dayu.pipirrapp.service.MyLocationService;
import com.dayu.pipirrapp.utils.ToastUtil;
import java.util.List;
/**
 * author: zuo
@@ -29,7 +31,7 @@
 * Time: 10:16
 * 备注:地图页
 */
public class MapFragment extends BaseFragment implements DefaultLifecycleObserver {
public class MapFragment extends BaseFragment {
    FragmentMapBinding binding;
    LocationManager locationManager;
@@ -39,13 +41,12 @@
    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        requireActivity().getLifecycle().addObserver(this);
        requireActivity().getLifecycle().addObserver(new MapFragmenObserver());
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
    }
    @Nullable
@@ -57,16 +58,13 @@
        initWebView();
        mWebView.loadUrl("http://192.168.3.178:3002/");
        initView();
        //开启定位
        Intent location = new Intent(this.getActivity(), MyLocationService.class);
        location.putExtra("isSingle", false);
        this.getActivity().startService(location);
        return binding.getRoot();
    }
    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onCreate(owner);
        Log.i("MapFragment", "onCreate");
    }
    @Override
    public void onResume() {
@@ -128,21 +126,21 @@
        webSettings.setBuiltInZoomControls(true); // 设置内置的缩放控件,若为 false,则该 WebView 不可缩放
        webSettings.setDisplayZoomControls(false); // 隐藏原生的缩放控件
        //webView弹JsAlert
        mWebView.setWebChromeClient(new WebChromeClient(){
            @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }
        });
    }
    void initView(){
        binding.flyBtn.setOnClickListener(v->{
            mWebView.evaluateJavascript("javascript:data()",value -> {
    void initView() {
        binding.flyBtn.setOnClickListener(v -> {
            mWebView.evaluateJavascript("javascript:moveTo(116.399565,39.89432)", value -> {
            });
        });
    }
}
app/src/main/java/com/dayu/pipirrapp/observer/LoginObserver.java
New file
@@ -0,0 +1,96 @@
package com.dayu.pipirrapp.observer;
import android.app.Activity;
import android.text.InputType;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import com.dayu.pipirrapp.R;
import com.dayu.pipirrapp.activity.LoginActivity;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import java.util.List;
/**
 * author: zuo
 * Date: 2024-01-11
 * Time: 15:47
 * 备注:登录页相关逻辑
 */
public class LoginObserver implements DefaultLifecycleObserver {
    protected String[] needPermissions = {
            Permission.ACCESS_COARSE_LOCATION,
            Permission.ACCESS_FINE_LOCATION,
            Permission.WRITE_EXTERNAL_STORAGE,
            Permission.READ_EXTERNAL_STORAGE,
            Permission.READ_PHONE_STATE
    };
    Activity myActivity;
    public LoginObserver(@NonNull Activity activity) {
        myActivity = activity;
    }
    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onCreate(owner);
        getPermissions();
    }
    private void getPermissions() {
        try {
            XXPermissions.with(myActivity)
                    // 申请单个权限
//                    .permission(Permission.RECORD_AUDIO)
                    // 申请多个权限
                    .permission(needPermissions)
                    // 设置权限请求拦截器(局部设置)
                    //.interceptor(new PermissionInterceptor())
                    // 设置不触发错误检测机制(局部设置)
                    //.unchecked()
                    .request(new OnPermissionCallback() {
                        @Override
                        public void onGranted(@NonNull List<String> permissions, boolean allGranted) {
                            if (!allGranted) {
//                                toast("获取部分权限成功,但部分权限未正常授予");
                                return;
                            }
//                            if (!XXPermissions.isGranted(myActivity, Permission.SYSTEM_ALERT_WINDOW)) {
//                                new TipDialog(MainActivity.this, "请开启悬浮窗权限,允许本应用显示在其他应用的上层", new TipUtil.TipListener() {
//                                    @Override
//                                    public void onCancle() {
//                                        XXPermissions.startPermissionActivity(MainActivity.this, Permission.SYSTEM_ALERT_WINDOW);
//                                    }
//                                }).show();
//                            }
//                            toast("获取录音和日历权限成功");
                        }
                        @Override
                        public void onDenied(@NonNull List<String> permissions, boolean doNotAskAgain) {
                            if (doNotAskAgain) {
//                                toast("被永久拒绝授权,请手动授予录音和日历权限");
                                // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            } else {
//                                toast("获取录音和日历权限失败");
                            }
                        }
                    });
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}
app/src/main/java/com/dayu/pipirrapp/observer/MapFragmenObserver.java
New file
@@ -0,0 +1,23 @@
package com.dayu.pipirrapp.observer;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
/**
 * author: zuo
 * Date: 2024-01-11
 * Time: 17:37
 * 备注:地图页相关逻辑
 */
public class MapFragmenObserver implements DefaultLifecycleObserver {
    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onCreate(owner);
    }
}
app/src/main/java/com/dayu/pipirrapp/service/MyCommonService.java
New file
@@ -0,0 +1,12 @@
package com.dayu.pipirrapp.service;
import cn.jpush.android.service.JCommonService;
/**
 * author: zuo
 * Date: 2024-01-10
 * Time: 11:51
 * 备注:
 */
public class MyCommonService extends JCommonService {
}
app/src/main/java/com/dayu/pipirrapp/service/MyLocationService.java
New file
@@ -0,0 +1,249 @@
package com.dayu.pipirrapp.service;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import androidx.annotation.Nullable;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.dayu.pipirrapp.R;
import com.dayu.pipirrapp.activity.MainActivity;
import com.dayu.pipirrapp.utils.MyLog;
import com.tencent.bugly.crashreport.CrashReport;
/**
 * author: zuo
 * Date: 2024-01-10
 * Time: 14:39
 * 备注:
 */
public class MyLocationService extends Service {
    private LocationManager locationManager;
    private MyLocationListener listener;
    private LocationClient mBDLocationClient = null;
    private MyBDLocationListener mBDLocationListener;
    /**
     * 是否一次性定位
     */
    boolean isSingle;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MyLog.i("onStartCommand()");
        isSingle = intent.getBooleanExtra("isSingle", false);
        if (!isSingle) {
            // 在API11之后构建Notification的方式
            Notification.Builder builder = new Notification.Builder
                    (this.getApplicationContext());
            //获取一个Notification构造器
            Intent nfIntent = new Intent(this, MainActivity.class);
            builder.setContentIntent(PendingIntent.
                            getActivity(this, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE)) // 设置PendingIntent
                    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
                            R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标)
                    .setContentTitle(getResources().getString(R.string.app_name)) // 设置下拉列表里的标题
                    .setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
                    .setContentText("正在后台运行") // 设置上下文内容
                    .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
            Notification notification = builder.build(); // 获取构建好的Notification
            notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
        }
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        createNativeLocation();
//        createBDLocation();
    }
//    /**
//     * @param isSingle 是否是单次定位
//     */
//    public MyLocationService(boolean isSingle) {
//        this.isSingle = isSingle;
//
//    }
    /**
     * 原生的定位服务
     */
    @SuppressLint("MissingPermission")
    private void createNativeLocation() {
        try {
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            listener = new MyLocationListener();
            Criteria criteria = new Criteria();
            // 查询精度:高,Criteria.ACCURACY_COARSE比较粗略,Criteria.ACCURACY_FINE则比较精确
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            //不要求海拔
            criteria.setAltitudeRequired(false);
            //不要求方位
            criteria.setBearingRequired(false);
            //允许有花费
            criteria.setCostAllowed(true);
            //低功耗
            criteria.setPowerRequirement(Criteria.POWER_LOW);
            String provider = locationManager.getBestProvider(criteria, true);
            MyLog.i("定位的provider:" + provider);
            //第二个参数是间隔时间 第三个参数是间隔多少距离,这里我试过了不同的各种组合,能获取到位置就是能,不能获取就是不能
            locationManager.requestLocationUpdates(provider, 1000, 0, listener);
        } catch (Exception e) {
            CrashReport.postCatchedException(e);
        }
    }
    /**
     * 第三方百度定位服务
     */
    private void createBDLocation() {
        try {
            LocationClient.setAgreePrivacy(true);
            mBDLocationClient = new LocationClient(this.getBaseContext());
            mBDLocationListener = new MyBDLocationListener();
            //注册监听函数
            mBDLocationClient.registerLocationListener(mBDLocationListener);
            //配置百度定位的选项
            LocationClientOption option = new LocationClientOption();
            //可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
            option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
            //可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll;
            option.setCoorType("WGS84");
            //可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的
            option.setScanSpan(1000);
            //可选,设置是否需要地址信息,默认不需要
            option.setIsNeedAddress(true);
            //可选,设置是否需要地址描述
            option.setIsNeedLocationDescribe(false);
            //可选,设置是否需要设备方向结果
            option.setNeedDeviceDirect(false);
            //可选,默认false,设置是否当卫星定位有效时按照1S1次频率输出卫星定位结果
            option.setLocationNotify(true);
            //可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
            option.setIgnoreKillProcess(true);
            //可选,默认false,设置是否开启卫星定位
            option.setOpenGnss(true);
            //可选,默认false,设置定位时是否需要海拔信息,默认不需要,除基础定位版本都可用
            option.setIsNeedAltitude(false);
            mBDLocationClient.setLocOption(option);
            //开启百度定位
            mBDLocationClient.start();
        } catch (Exception e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
        }
    }
    class MyLocationListener implements LocationListener {
        // 位置改变时获取经纬度
        @Override
        public void onLocationChanged(Location location) {
            String longitude = "Longitude:" + location.getLongitude();
            String latitude = "Latitude:" + location.getLatitude();
            MyLog.i("原生定位onLocationChanged:  Latitude:" + latitude + "  Longitude:" + longitude);
//            是否一次性定位
            if (isSingle) {
                stopSelf();  // 获取到经纬度以后,停止该service
            }
        }
        // 状态改变时
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            MyLog.i("onStatusChanged - provider:" + provider + " status:" + status);
        }
        // 提供者可以使用时
        @Override
        public void onProviderEnabled(String provider) {
            MyLog.i("GPS开启了");
        }
        // 提供者不可以使用时
        @Override
        public void onProviderDisabled(String provider) {
            MyLog.i("GPS关闭了");
        }
    }
    /**
     * 百度定位的监听
     */
    class MyBDLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            double latitude = location.getLatitude();    //获取纬度信息
            double longitude = location.getLongitude();    //获取经度信息
//            MyLog.i("百度的监听 latitude:" + latitude);
//            MyLog.i("百度的监听 longitude:" + longitude);
            MyLog.i("百度的监听  onBaiduLocationChanged:   latitude:" + latitude + "   longitude:" + longitude);
            if (isSingle) {
                stopSelf();  // 获取到经纬度以后,停止该service
            }
        }
    }
    @Override
    public void onDestroy() {
        MyLog.i("MyLocationService--onDestroy");
        // 停止前台服务--参数:表示是否移除之前的通知
        stopForeground(true);
        super.onDestroy();
        // 停止所有的定位服务
        try {
            if (locationManager != null) {
                locationManager.removeUpdates(listener);
            }
            if (mBDLocationClient != null) {
                mBDLocationClient.stop();
                mBDLocationClient.unRegisterLocationListener(mBDLocationListener);
            }
        } catch (Exception e) {
            CrashReport.postCatchedException(e);
        }
    }
}
app/src/main/java/com/dayu/pipirrapp/utils/MyLog.java
New file
@@ -0,0 +1,19 @@
package com.dayu.pipirrapp.utils;
import android.util.Log;
/**
 * author: zuo
 * Date: 2024-01-10
 * Time: 15:46
 * 备注:
 */
public class MyLog {
    public static final String TAG = "pipirrappTAG";
    public static void i(String data) {
        Log.i(TAG, data);
    }
}
app/src/main/res/drawable/ic_edt_gray_bg.xml
New file
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#F6F7FB" />
    <corners android:radius="5dp" />
    <stroke
        android:width="1dp"
        android:color="#ededed" />
</shape>
app/src/main/res/drawable/vt_ps_close.xml
New file
@@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="12dp"
    android:height="12dp"
    android:viewportWidth="48"
    android:viewportHeight="48">
  <path
      android:pathData="M9.858,18C6.239,21 4,24 4,24C4,24 12.954,36 24,36C25.37,36 26.708,35.815 28,35.492M20.032,12.5C21.314,12.182 22.641,12 24,12C35.046,12 44,24 44,24C44,24 41.761,27 38.142,30"
      android:strokeLineJoin="round"
      android:strokeWidth="4"
      android:fillColor="#00000000"
      android:strokeColor="#3a68fc"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M20.314,20.621C19.498,21.511 19,22.697 19,24C19,26.761 21.239,29 24,29C25.363,29 26.598,28.455 27.5,27.57"
      android:strokeLineJoin="round"
      android:strokeWidth="4"
      android:fillColor="#00000000"
      android:strokeColor="#3a68fc"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M42,42L6,6"
      android:strokeLineJoin="round"
      android:strokeWidth="4"
      android:fillColor="#00000000"
      android:strokeColor="#3a68fc"
      android:strokeLineCap="round"/>
</vector>
app/src/main/res/drawable/vt_ps_open.xml
New file
@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="12dp"
    android:height="12dp"
    android:viewportWidth="48"
    android:viewportHeight="48">
  <path
      android:pathData="M24,36C35.046,36 44,24 44,24C44,24 35.046,12 24,12C12.954,12 4,24 4,24C4,24 12.954,36 24,36Z"
      android:strokeLineJoin="round"
      android:strokeWidth="4"
      android:fillColor="#00000000"
      android:strokeColor="#3a68fc"/>
  <path
      android:pathData="M24,29C26.761,29 29,26.761 29,24C29,21.239 26.761,19 24,19C21.239,19 19,21.239 19,24C19,26.761 21.239,29 24,29Z"
      android:strokeLineJoin="round"
      android:strokeWidth="4"
      android:fillColor="#00000000"
      android:strokeColor="#3a68fc"/>
</vector>
app/src/main/res/layout/activity_login.xml
@@ -2,41 +2,53 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    android:background="@mipmap/login_bg1"
    android:orientation="vertical"
    android:padding="20dp">
    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_height="45dp"
        android:layout_above="@+id/psLL"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="10dp"
        android:hint="请输入账号" />
        android:layout_marginBottom="20dp"
        android:background="@drawable/ic_edt_gray_bg"
        android:hint="请输入账号"
        android:paddingLeft="15dp" />
    <RelativeLayout
        android:id="@+id/psLL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_height="45dp"
        android:layout_above="@+id/loginBtn"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="20dp"
        android:layout_marginBottom="30dp"
        android:background="@drawable/ic_edt_gray_bg"
        android:gravity="center"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/passwordBtn"
            android:background="@color/white"
            android:hint="请输入密码"
            android:inputType="textPassword" />
            android:inputType="textPassword"
            android:paddingLeft="15dp"
           />
        <ImageButton
        <ImageView
            android:id="@+id/passwordBtn"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_height="25dp"
            android:src="@drawable/vt_ps_close"
            android:layout_marginRight="5dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true" />
    </RelativeLayout>
@@ -48,10 +60,10 @@
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="20dp"
        android:layout_marginBottom="50dp"
        android:background="@drawable/ic_blue_background"
        android:gravity="center"
        android:text="登录"
        android:text="登    录"
        android:textColor="@color/white"
        android:textSize="20sp" />
app/src/main/res/mipmap-xhdpi/login_bg1.jpeg
app/src/main/res/values/colors.xml
@@ -3,6 +3,7 @@
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="base_blue">#3C9CFF</color>
    <color name="down_blue">#0C2DEA</color>
    <color name="down_blue">#3a68fc</color>
    <color name="ws_pay_alpha">#00000000</color>
    <color name="title_color">#3a68fc</color>
</resources>
dycz.jks
Binary files differ
gradle.properties
@@ -15,6 +15,7 @@
# 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
android.enableJetifier=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library