feat(location): 重构定位流程并支持定位结束后还原系统设置

This commit is contained in:
2026-10-22 15:13:21 +08:00
parent a85db9ad49
commit e95490b5ce
21 changed files with 645 additions and 88 deletions

View File

@@ -18,8 +18,8 @@ android {
defaultConfig {
applicationId "com.aoleyun.sn"
versionCode 250
versionName "1.6.1016"
versionCode 252
versionName "1.6.1021"
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
minSdkVersion 24
@@ -44,6 +44,9 @@ android {
buildConfigField "String", "ROOT_URL", '"https://led.aoleyun.cn/api/"'
buildConfigField "String", "WEBSOCKET_URL", '"wss://led.aoleyun.cn/wss/"'
// 百度定位 AK:统一在构建期注入,所有 buildType / flavor 共用同一份固定值。
// 严禁事后修改 APK(反编译重打包会破坏 liblocSDK8b.so 的未压缩与页对齐,导致 162 / .dynamic section header was not found)
}
compileOptions {
@@ -351,6 +354,7 @@ android {
G122JDebug.initWith(debug)
G122JDebug {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "qyYyTD4ahoebPRY2oRxyiw5Xw1T6ikxJ"]
buildConfigField "String", "platform", '"G122J"'
versionNameSuffix "_debug"
debuggable true
@@ -359,12 +363,14 @@ android {
G122JRelease.initWith(release)
G122JRelease {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "qyYyTD4ahoebPRY2oRxyiw5Xw1T6ikxJ"]
buildConfigField "String", "platform", '"G122J"'
signingConfig signingConfigs.G122J
}
G12NLDebug.initWith(debug)
G12NLDebug {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"G12NL"'
versionNameSuffix "_debug"
debuggable true
@@ -373,12 +379,14 @@ android {
G12NLRelease.initWith(release)
G12NLRelease {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"G12NL"'
signingConfig signingConfigs.MT6789
}
DX11Debug.initWith(debug)
DX11Debug {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"DX11"'
versionNameSuffix "_debug"
debuggable true
@@ -387,12 +395,14 @@ android {
DX11Release.initWith(release)
DX11Release {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"DX11"'
signingConfig signingConfigs.DX11
}
G122Debug.initWith(debug)
G122Debug {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"MT6765"'
versionNameSuffix "_debug"
debuggable true
@@ -401,12 +411,14 @@ android {
G122Release.initWith(release)
G122Release {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr"]
buildConfigField "String", "platform", '"MT6765"'
signingConfig signingConfigs.G122
}
QualcommDebug.initWith(debug)
QualcommDebug {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "qyYyTD4ahoebPRY2oRxyiw5Xw1T6ikxJ"]
buildConfigField "String", "platform", '"QualcommA"'
versionNameSuffix "_debug"
debuggable true
@@ -415,6 +427,7 @@ android {
QualcommRelease.initWith(release)
QualcommRelease {
manifestPlaceholders = [BAIDU_LBS_API_KEY: "qyYyTD4ahoebPRY2oRxyiw5Xw1T6ikxJ"]
buildConfigField "String", "platform", '"QualcommA"'
signingConfig signingConfigs.SM8150
}
@@ -838,7 +851,7 @@ dependencies {
implementation files('libs/ebf_tools_v1.0.jar')
implementation files('libs/vendor.mediatek.hardware.nvram-V1.0-java.jar')
implementation files('libs/BaiduTraceSDK_v3_1_10.jar')
implementation files('libs/BaiduTraceSDK_v3_2_2.jar')
// 基础注解库
implementation "androidx.annotation:annotation:1.10.0"

View File

@@ -0,0 +1,143 @@
应用签名 SHA1 汇总(来源:app/build.gradle signingConfigs)
生成时间:2026-10-21 18:34:04
signingConfig: zhanRui
keystore: zhanxun.keystore
别名: zhanxun
SHA1: F1:A5:4A:3F:02:4A:8D:1B:74:D1:FF:1F:74:D3:BE:66:ED:79:31:2E
signingConfig: zhanRuiUserdebug
keystore: zhanxunUserdebug.keystore
别名: zhanxunuserdebug
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: zhanRui12
keystore: zhanrui12.jks
别名: zhanrui12
SHA1: 00:CF:12:B7:18:7F:6D:9E:5A:62:6C:61:8E:F5:E2:72:88:E7:01:36
signingConfig: mtk
keystore: xueshibaoos.jks
别名: xueshibaoos
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: G10P
keystore: G10PMTK11.jks
别名: g10pmtk11
SHA1: D0:A7:1B:AE:9C:FF:86:25:A1:28:13:3E:F3:1E:1A:99:E5:B5:17:6B
signingConfig: G11Userdebug
keystore: G11Userdebug.keystore
别名: g11userdebug
SHA1: 33:C0:99:B3:96:81:4C:33:5F:C8:0A:AB:1E:B9:95:86:C2:C7:03:00
signingConfig: G10PUserDebug
keystore: G10PUserDebug.jks
别名: g10puserdebug
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: zhanruiG10Z
keystore: zhanruiG10Z.keystore
别名: zhanruig10z
SHA1: F1:A5:4A:3F:02:4A:8D:1B:74:D1:FF:1F:74:D3:BE:66:ED:79:31:2E
signingConfig: G10ZUserDebug
keystore: G10zUserDebug.keystore
别名: g10zuserdebug
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: mtk12
keystore: mtkAndroid12.keystore
别名: mtk12
SHA1: 4B:8C:A5:4E:A4:A2:33:2B:ED:27:36:DF:15:F5:39:9B:9F:B5:02:40
signingConfig: P20S
keystore: MTKP20S.keystore
别名: mtkp20s
SHA1: 48:03:96:C6:0B:6B:70:CA:03:1F:43:EF:55:DC:6F:E1:FD:AE:2F:56
signingConfig: iPlay50mini
keystore: iPlay50Mini.keystore
别名: platform
SHA1: C7:0A:5D:ED:5A:47:27:FD:EC:93:6C:4E:A3:D0:55:AB:08:F6:4F:1A
signingConfig: teclast8183
keystore: TeclastMTK12.jks
别名: teclastmtk12
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: Huaruian8768
keystore: Huaruian8768.jks
别名: huaruian8768
SHA1: 33:C0:99:B3:96:81:4C:33:5F:C8:0A:AB:1E:B9:95:86:C2:C7:03:00
signingConfig: T40Air
keystore: T40Air.jks
别名: t40air
SHA1: AB:56:8F:41:E8:20:20:4D:5F:4C:1F:8E:11:58:17:C8:C9:42:4C:B0
signingConfig: BCM310
keystore: BCM310.keystore
别名: bcm310
SHA1: AB:56:8F:41:E8:20:20:4D:5F:4C:1F:8E:11:58:17:C8:C9:42:4C:B0
signingConfig: P50
keystore: P50TD.jks
别名: p50td
SHA1: EC:84:AB:FA:7D:53:AB:12:23:61:12:49:7C:A6:09:FF:B1:75:66:19
signingConfig: seewo
keystore: aiud.keystore
别名: androidreleasekey
SHA1: 21:2D:1A:D8:4A:A8:65:AD:90:42:D1:40:CF:30:CE:6C:BC:EA:63:4F
signingConfig: iPlay50miniPro
keystore: iPlay50miniPro.jks
别名: iplay50minipro
SHA1: 78:71:78:2A:CF:E9:83:97:92:7C:56:0B:58:2C:96:C2:BA:17:BB:3A
signingConfig: U1302
keystore: U1302.keystore
别名: u1302
SHA1: 70:C8:F5:02:D9:FB:53:E3:28:3B:11:03:2F:3D:60:ED:BA:D1:97:6C
signingConfig: MT6765
keystore: MT6765.keystore
别名: mt6765
SHA1: 4B:8C:A5:4E:A4:A2:33:2B:ED:27:36:DF:15:F5:39:9B:9F:B5:02:40
signingConfig: G128T
keystore: HuaruianG128T.jks
别名: g128t
SHA1: 33:C0:99:B3:96:81:4C:33:5F:C8:0A:AB:1E:B9:95:86:C2:C7:03:00
signingConfig: G122
keystore: 6789U.p12
别名: 6789u
SHA1: 3C:E5:B0:D8:24:AF:BC:5B:23:3D:AE:20:04:A5:7A:24:15:F9:93:E2
signingConfig: DX11
keystore: DX11.p12
别名: dx11
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
signingConfig: MT6789
keystore: MT6789.keystore
别名: mt6789
SHA1: 78:71:78:2A:CF:E9:83:97:92:7C:56:0B:58:2C:96:C2:BA:17:BB:3A
signingConfig: SM8150
keystore: sm8150.jks
别名: platformkey
SHA1: 15:18:76:80:C2:32:60:E7:27:3F:45:D8:EE:40:F6:E0:9E:D6:01:5D
signingConfig: G122J
keystore: G122J.p12
别名: g122j
SHA1: 33:C0:99:B3:96:81:4C:33:5F:C8:0A:AB:1E:B9:95:86:C2:C7:03:00
signingConfig: crosshatch
keystore: AospCrosshatch.keystore
别名: aospcrosshatch
SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA

Binary file not shown.

Binary file not shown.

View File

@@ -392,15 +392,21 @@
<meta-data
android:name="com.aoleyun.sn.base.CustomGlideModule"
android:value="AppGlideModule" />
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="CjFhFE1UP5G14tMBz1kWs7ca92bgHuLr" /> <!-- 请填写你自己的- appKey -->
android:value="${BAIDU_LBS_API_KEY}" />
<!-- 请填写你自己的- appKey -->
<meta-data
android:name="com.alibaba.app.appkey"
android:value="333598267" /> <!-- 请填写你自己的appSecret -->
android:value="333598267" />
<!-- 请填写你自己的appSecret -->
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="300dfca550f248598bc8b86c6cb9e76e" />
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="face" />

View File

@@ -8,6 +8,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
@@ -19,6 +20,7 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Observer;
import com.aoleyun.sn.BuildConfig;
@@ -219,6 +221,12 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
// Settings.Global.putInt(getContentResolver(), Settings.Global.ADB_ENABLED, 1);
// }
registerReceiver();
int development_settings_enabled = Settings.Global.getInt(getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
int adb_enabled = Settings.Global.getInt(getContentResolver(), Settings.Global.ADB_ENABLED, 0);
if (development_settings_enabled == 1 || adb_enabled == 1) {
mViewDataBinding.tvName.setTextColor(Color.parseColor("#0871f4"));
}
}
private void getDevicesInfo() {
@@ -384,15 +392,31 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
Log.e(TAG, "setLockedState: " + aBoolean);
if (aBoolean) {
mViewModel.getStudesInfo();
mViewDataBinding.ivLockStatus.setVisibility(View.VISIBLE);
// mViewDataBinding.ivLockStatus.setVisibility(View.VISIBLE);
mViewDataBinding.ivLockStatus.setColorFilter(ContextCompat.getColor(MainActivity.this, R.color.unlock_red));
} else {
mViewDataBinding.ivLockStatus.setVisibility(View.GONE);
// mViewDataBinding.ivLockStatus.setVisibility(View.GONE);
mViewDataBinding.ivLockStatus.setColorFilter(ContextCompat.getColor(MainActivity.this, R.color.lock_color));
setNumberText("", View.GONE);
setNameText("", View.GONE);
setClassText("", View.GONE);
setBatchText("", View.GONE);
SysSettingUtils.setEnableSetting(MainActivity.this);
}
int restore = Settings.System.getInt(getContentResolver(), CommonConfig.AOLE_ACTION_RESTORE_FORBID_ON, 1);
if (restore == 0) {
mViewDataBinding.ivLockStatus.setColorFilter(ContextCompat.getColor(MainActivity.this, R.color.blue_restore));
} else {
if (aBoolean) {
mViewDataBinding.ivLockStatus.setColorFilter(ContextCompat.getColor(MainActivity.this, R.color.unlock_red));
} else {
mViewDataBinding.ivLockStatus.setColorFilter(ContextCompat.getColor(MainActivity.this, R.color.lock_color));
}
}
mViewModel.getEBagCode();
}
});

View File

@@ -1,7 +1,11 @@
package com.aoleyun.sn.manager;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
@@ -34,6 +38,16 @@ import com.tencent.mmkv.MMKV;
public class MapManager {
private String TAG = "MapManager";
/**
* 单次定位超时时间,超时后强制停止定位并还原系统设置
*/
private static final long LOCATION_TIMEOUT = 60 * 1000L;
/**
* AGPS 开关设置项(Settings.Global.ASSISTED_GPS_ENABLED 是隐藏常量,这里直接用字符串)
*/
private static final String KEY_ASSISTED_GPS_ENABLED = "assisted_gps_enabled";
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
@SuppressLint("StaticFieldLeak")
@@ -43,6 +57,45 @@ public class MapManager {
private LocationClientOption mOption;
private LBSTraceClient mLBSTraceClient;
private final Handler mHandler = new Handler(Looper.getMainLooper());
/**
* 定位前记录下来的系统定位设置
*/
private LocationSettingsSnapshot mSnapshot;
/**
* 是否修改过系统定位设置(只有修改过才需要还原)
*/
private boolean mSettingsApplied = false;
/**
* 当前是否有定位进行中
*/
private boolean mLocationRunning = false;
/**
* 外部注册的定位监听(例如推送下发的定位请求)
*/
private BDAbstractLocationListener mExtraListener;
/**
* 定位相关系统设置的快照,用于定位结束后原样还原
*/
private static final class LocationSettingsSnapshot {
/**
* LOCATION_MODE 是否读取成功
*/
boolean locationModeValid;
int locationMode;
int assistedGpsEnabled;
String providersAllowed;
}
private final Runnable mLocationTimeoutRunnable = new Runnable() {
@Override
public void run() {
Log.e(TAG, "定位超时,停止定位并还原系统设置");
stopLocation();
}
};
private MapManager(Context context) {
this.mContext = context;
//3.1.10以上
@@ -68,31 +121,206 @@ public class MapManager {
}
public void initMap() {
LocationClient.setAgreePrivacy(true);
ensureLocationClient();
startLocation();
}
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 1);
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps");
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+network");
//百度定位 SDK 9.7.0 起 LocationClient 构造方法声明了 throws Exception
try {
mLocationClient = new LocationClient(mContext);
mLocationClient.setLocOption(getDefaultLocationClientOption());
mLocationClient.registerLocationListener(mListener);
mLocationClient.stop();
mLocationClient.start();
} catch (Exception e) {
Log.e(TAG, "initMap: LocationClient 创建失败: " + e.getMessage(), e);
private synchronized LocationClient ensureLocationClient() {
if (mLocationClient == null) {
LocationClient.setAgreePrivacy(true);
//百度定位 SDK 9.7.0 起 LocationClient 构造方法声明了 throws Exception
try {
mLocationClient = new LocationClient(mContext);
mLocationClient.setLocOption(getDefaultLocationClientOption());
mLocationClient.registerLocationListener(mListener);
} catch (Exception e) {
mLocationClient = null;
Log.e(TAG, "initMap: LocationClient 创建失败: " + e.getMessage(), e);
}
}
return mLocationClient;
}
public LocationClient getLocationClient() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 1);
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps");
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+network");
if (mLocationClient == null) {
initMap();
return ensureLocationClient();
}
/**
* 发起一次定位:定位前记录 GPS 开关与相关系统设置,定位结束(成功或失败)后原样还原。
*/
public void startLocation() {
startLocation(null);
}
/**
* 发起一次定位,并额外注册一个只针对本次定位的监听(定位结束后自动注销)。
*
* @param listener 可为空,仅关心本次定位结果的监听
*/
public void startLocation(BDAbstractLocationListener listener) {
synchronized (this) {
LocationClient client = ensureLocationClient();
if (client == null) {
Log.e(TAG, "startLocation: LocationClient 未初始化,无法定位");
restoreLocationSettings();
return;
}
if (!mLocationRunning) {
recordLocationSettings();
}
if (listener != null) {
if (mExtraListener != null && mExtraListener != listener) {
unRegisterListener(client, mExtraListener);
}
mExtraListener = listener;
client.registerLocationListener(listener);
}
mLocationRunning = true;
mHandler.removeCallbacks(mLocationTimeoutRunnable);
mHandler.postDelayed(mLocationTimeoutRunnable, LOCATION_TIMEOUT);
try {
client.stop();
client.start();
} catch (Exception e) {
Log.e(TAG, "startLocation: 启动定位失败: " + e.getMessage(), e);
stopLocation();
}
}
return mLocationClient;
}
/**
* 结束定位:停止定位客户端并还原定位前的系统设置(可重复调用)。
*/
public void stopLocation() {
LocationClient client;
BDAbstractLocationListener extraListener;
synchronized (this) {
mHandler.removeCallbacks(mLocationTimeoutRunnable);
mLocationRunning = false;
extraListener = mExtraListener;
mExtraListener = null;
client = mLocationClient;
}
if (client != null) {
if (extraListener != null) {
unRegisterListener(client, extraListener);
}
try {
client.stop();
} catch (Exception e) {
Log.e(TAG, "stopLocation: 停止定位失败: " + e.getMessage(), e);
}
}
restoreLocationSettings();
}
private void unRegisterListener(LocationClient client, BDAbstractLocationListener listener) {
try {
client.unRegisterLocationListener(listener);
} catch (Exception e) {
Log.e(TAG, "unRegisterListener: 注销定位监听失败: " + e.getMessage(), e);
}
}
/**
* GPS 是否已开启
*/
public boolean isGpsEnabled() {
try {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
return locationManager != null && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception e) {
Log.e(TAG, "isGpsEnabled: " + e.getMessage(), e);
return false;
}
}
/**
* 记录定位前的系统设置;若 GPS 未开启则临时打开,定位结束后由 {@link #restoreLocationSettings()} 还原。
*/
private void recordLocationSettings() {
ContentResolver resolver = mContext.getContentResolver();
LocationSettingsSnapshot snapshot = new LocationSettingsSnapshot();
try {
snapshot.locationMode = Settings.Secure.getInt(resolver, Settings.Secure.LOCATION_MODE);
snapshot.locationModeValid = true;
} catch (Exception e) {
Log.e(TAG, "recordLocationSettings: 读取 LOCATION_MODE 失败: " + e.getMessage());
}
snapshot.assistedGpsEnabled = Settings.Global.getInt(resolver, KEY_ASSISTED_GPS_ENABLED, 0);
snapshot.providersAllowed = Settings.Secure.getString(resolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
mSnapshot = snapshot;
mSettingsApplied = false;
boolean gpsEnabled = isGpsEnabled();
Log.e(TAG, "recordLocationSettings: gpsEnabled = " + gpsEnabled
+ ", LOCATION_MODE = " + (snapshot.locationModeValid ? snapshot.locationMode : "unknown")
+ ", ASSISTED_GPS_ENABLED = " + snapshot.assistedGpsEnabled
+ ", LOCATION_PROVIDERS_ALLOWED = " + snapshot.providersAllowed);
if (gpsEnabled) {
//GPS 已开启,无需改动系统设置
return;
}
//先置位,避免部分写入失败时漏还原
mSettingsApplied = true;
try {
Settings.Secure.putInt(resolver, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
} catch (Exception e) {
Log.e(TAG, "recordLocationSettings: 开启 LOCATION_MODE 失败: " + e.getMessage(), e);
}
try {
Settings.Global.putInt(resolver, KEY_ASSISTED_GPS_ENABLED, 1);
} catch (Exception e) {
Log.e(TAG, "recordLocationSettings: 开启 ASSISTED_GPS_ENABLED 失败: " + e.getMessage(), e);
}
try {
Settings.Secure.putString(resolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps,+network");
} catch (Exception e) {
Log.e(TAG, "recordLocationSettings: 开启 LOCATION_PROVIDERS_ALLOWED 失败: " + e.getMessage(), e);
}
Log.e(TAG, "recordLocationSettings: GPS 未开启,已临时开启定位");
}
/**
* 还原定位前的系统设置
*/
private void restoreLocationSettings() {
LocationSettingsSnapshot snapshot;
synchronized (this) {
if (!mSettingsApplied || mSnapshot == null) {
mSnapshot = null;
mSettingsApplied = false;
return;
}
snapshot = mSnapshot;
mSnapshot = null;
mSettingsApplied = false;
}
ContentResolver resolver = mContext.getContentResolver();
if (snapshot.locationModeValid) {
try {
Settings.Secure.putInt(resolver, Settings.Secure.LOCATION_MODE, snapshot.locationMode);
} catch (Exception e) {
Log.e(TAG, "restoreLocationSettings: 还原 LOCATION_MODE 失败: " + e.getMessage(), e);
}
}
try {
Settings.Global.putInt(resolver, KEY_ASSISTED_GPS_ENABLED, snapshot.assistedGpsEnabled);
} catch (Exception e) {
Log.e(TAG, "restoreLocationSettings: 还原 ASSISTED_GPS_ENABLED 失败: " + e.getMessage(), e);
}
try {
Settings.Secure.putString(resolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
snapshot.providersAllowed == null ? "" : snapshot.providersAllowed);
} catch (Exception e) {
Log.e(TAG, "restoreLocationSettings: 还原 LOCATION_PROVIDERS_ALLOWED 失败: " + e.getMessage(), e);
}
Log.e(TAG, "restoreLocationSettings: 已还原 LOCATION_MODE = " + snapshot.locationMode
+ ", ASSISTED_GPS_ENABLED = " + snapshot.assistedGpsEnabled
+ ", LOCATION_PROVIDERS_ALLOWED = " + snapshot.providersAllowed);
}
/***
@@ -135,6 +363,7 @@ public class MapManager {
@Override
public void onReceiveLocation(BDLocation location) {
if (null != location) {
Log.e(TAG, "onReceiveLocation: getLocType = " + location.getLocType());
switch (location.getLocType()) {
case BDLocation.TypeGpsLocation:// GPS定位结果
case BDLocation.TypeNetWorkLocation:// 网络定位结果
@@ -158,16 +387,17 @@ public class MapManager {
Log.e(TAG, "onReceiveLocation: " + "无法获取有效定位依据导致定位失败");
mMMKV.encode("MapError", "无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");
break;
case BDLocation.TypeServerDecryptError:
Log.e(TAG, "onReceiveLocation: 服务端解密错误(162),通常是 AK 校验失败/包名或 SHA1 与 AK 不匹配");
mMMKV.encode("MapError", "服务端解密错误,请检查 AK 与该包名、签名的绑定关系");
break;
default:
}
}
Log.e(TAG, "MapAddress: " + mMMKV.decodeString("MapAddress", "-"));
Log.e(TAG, "MapError: " + mMMKV.decodeString("MapError", "-"));
// Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-network");
// Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-gps");
// Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "");
// Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ASSISTED_GPS_ENABLED, 0);
mLocationClient.stop();
//定位结束(成功或失败),停止定位并还原定位前的系统设置
stopLocation();
}
@Override
@@ -299,7 +529,7 @@ public class MapManager {
//因为startTrace与startGather是异步执行,且startGather依赖startTrace执行开启服务成功,
// 所以建议startGather在public void onStartTraceCallback(int errorNo, String message)回调返回错误码为0后,
// 再进行调用执行,否则会出现服务开启失败12002的错误。
switch (status){
switch (status) {
case 10001:
case 10002:
case 12002:
@@ -344,6 +574,11 @@ public class MapManager {
public void onInitBOSCallback(int status, String message) {
Log.e(TAG, "mTraceListener onInitBOSCallback: status = " + status + " message = " + message);
}
@Override
public void onTraceDataUploadCallBack(int i, String s, int i1, int i2) {
}
};
private OnTraceListener mGatherTraceListener = new OnTraceListener() {
@@ -386,6 +621,11 @@ public class MapManager {
public void onInitBOSCallback(int status, String message) {
Log.e(TAG, "mGatherTraceListener onInitBOSCallback: status = " + status + " message = " + message);
}
@Override
public void onTraceDataUploadCallBack(int i, String s, int i1, int i2) {
}
};
public void createClientFence(ElectronicFenceInfo fenceInfo) {

View File

@@ -408,8 +408,24 @@ public class NetInterfaceManager {
* @return 带自动缓存的Observable
*/
public static <T> Observable<T> withCache(Observable<T> networkObservable, String cacheKey, long expireTimeMillis) {
return withCache(networkObservable, cacheKey, expireTimeMillis, false);
}
/**
* @param cacheWhenOffline 无网络时是否允许命中缓存
* true :离线时读缓存(离线兜底,兼容原有行为)
* false:离线时直接走网络(不读缓存、不写缓存),请求会失败
*/
public static <T> Observable<T> withCache(Observable<T> networkObservable, String cacheKey,
long expireTimeMillis, boolean cacheWhenOffline) {
return Observable.defer(() -> {
// Log.e(TAG, "withCache: cacheKey = " + cacheKey);
boolean online = isNetworkAvailable();
// 没有网络且不允许使用缓存:直接走网络,不读缓存也不写缓存
if (!online && !cacheWhenOffline) {
Log.e(TAG, "withCache: no network, skip cache " + cacheKey);
return networkObservable.subscribeOn(Schedulers.io());
}
// 1. 读取缓存
T cacheData = CACHE_MANAGER.getCache(cacheKey);
if (cacheData != null) {
@@ -418,15 +434,47 @@ public class NetInterfaceManager {
}
Log.e(TAG, "withCache: request " + cacheKey);
// 2. 无缓存则发起网络请求,成功后缓存
// 2. 无缓存则发起网络请求,成功且在线时才缓存
return networkObservable
.subscribeOn(Schedulers.io())
.doOnNext(data -> CACHE_MANAGER.saveCache(cacheKey, data, expireTimeMillis));
.doOnNext(data -> {
if (isNetworkAvailable() && isCacheableData(data)) {
CACHE_MANAGER.saveCache(cacheKey, data, expireTimeMillis);
} else {
Log.e(TAG, "withCache: not cacheable " + cacheKey);
}
});
})
.subscribeOn(Schedulers.io()) // 缓存IO切到子线程
.observeOn(AndroidSchedulers.mainThread());
}
/**
* 当前是否有可用网络(取不到状态时按有网处理,避免误判导致接口不可用)
*/
private static boolean isNetworkAvailable() {
try {
return INSTANCE != null && NetStateUtils.isNetworkConnected(INSTANCE.mContext);
} catch (Exception e) {
Log.e(TAG, "isNetworkAvailable error: " + e);
return true;
}
}
/**
* 只有成功的响应才允许写入缓存,避免把错误/空数据缓存下来
*/
private static <T> boolean isCacheableData(T data) {
if (data == null) {
return false;
}
if (data instanceof BaseResponse) {
BaseResponse<?> response = (BaseResponse<?>) data;
return response.isSuccess() && response.data != null;
}
return true;
}
/*
*
* API

View File

@@ -59,7 +59,6 @@ import com.aoleyun.sn.utils.Utils;
import com.arialyy.aria.core.Aria;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
@@ -444,10 +443,8 @@ public class PushManager {
Toaster.debugShow("收到管控:获取设备信息");
getBatteryInfo(mContext);
sendRefreshBroadcast(mContext);
LocationClient locationClient = MapManager.getInstance().getLocationClient();
locationClient.stop();
locationClient.start();
locationClient.registerLocationListener(new BDAbstractLocationListener() {
//定位前记录并临时开启系统定位设置,定位结束自动还原
MapManager.getInstance().startLocation(new BDAbstractLocationListener() {
@Override
public void onReceiveLocation(BDLocation location) {
if (null != location) {
@@ -479,7 +476,8 @@ public class PushManager {
}
Log.e(TAG, "MapAddress: " + mMMKV.decodeString("MapAddress", "-"));
Log.e(TAG, "MapError: " + mMMKV.decodeString("MapError", "-"));
locationClient.stop();
//定位结束(成功或失败),停止定位并还原定位前的系统设置
MapManager.getInstance().stopLocation();
}
@Override
@@ -1240,10 +1238,13 @@ public class PushManager {
}
String default_browser = jsonObject.get("default_browser").getAsString();
Log.e(TAG, "setDefalutApp: default_browser = " + default_browser);
Intent intent = new Intent("setDefaultBrowser");
intent.putExtra("package", default_browser);
if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.QualcommPlatform) {
intent.setPackage("com.onyx.neoservice");
// } else if (JgyUtils.getInstance().checkAppPlatform() == JgyUtils.G122JPlatform) {
} else {
intent.setPackage("com.android.settings");
}

View File

@@ -6,6 +6,7 @@ import android.util.Log;
import com.alibaba.sdk.android.push.MessageReceiver;
import com.alibaba.sdk.android.push.notification.CPushMessage;
import com.aoleyun.sn.push.PushManager;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@@ -69,12 +70,18 @@ public class AliyunMessageReceiver extends MessageReceiver {
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();
try {
JsonObject extrasJson = JsonParser.parseString(content).getAsJsonObject();
String extras = "";
JsonElement extrasElement = extrasJson.get("extras");
if (extrasElement != null && !extrasElement.isJsonNull()) {
extras = extrasElement.toString();
}
PushManager.getInstance().setPushContent(title, extras);
} catch (Exception e) {
//避免推送处理异常被sdk当成消息解析失败
Log.e(TAG, "onMessage error: " + Log.getStackTraceString(e));
}
PushManager.getInstance().setPushContent(title, extras);
}
/**

View File

@@ -67,7 +67,6 @@ import com.aoleyun.sn.utils.XAPKUtils;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.task.DownloadTask;
import com.baidu.location.LocationClient;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
@@ -323,9 +322,8 @@ public class GuardService extends Service {
break;
case Intent.ACTION_SCREEN_ON: {
long time = System.currentTimeMillis();
LocationClient locationClient = MapManager.getInstance().getLocationClient();
locationClient.stop();
locationClient.start();
//定位前记录并临时开启系统定位设置,定位结束自动还原
MapManager.getInstance().startLocation();
// getLockState("2", String.valueOf(time));
// sendScreenStatus(1);
}

View File

@@ -1567,6 +1567,9 @@ public class JgyUtils {
private Set<String> getWhitePkgList() {
HashSet<String> pkgSet = new HashSet<>(defaultPackages);
if (BuildConfig.DEBUG) {
pkgSet.add("com.android.launcher3");
}
pkgSet.addAll(showAppList);
pkgSet.addAll(ApkUtils.desktopAPP);
pkgSet.addAll(ApkUtils.aoleyunAPP);

View File

@@ -51,34 +51,105 @@ public class SysSettingUtils {
return status == 0 ? 1 : 0;
}
private interface SettingHandler {
void apply(Context context, JsonObject jsonObject);
}
/**
* 单项管控单独执行,避免某个字段异常导致整条下发数据中断
*/
private static void applySafely(String action, SettingHandler handler, Context context, JsonObject jsonObject) {
try {
handler.apply(context, jsonObject);
} catch (Exception e) {
Log.e(TAG, action + " error: " + Log.getStackTraceString(e));
}
}
/**
* 安全取值,字段不存在、为 JsonNull、类型不符时返回默认值,不再抛出异常
*/
public static String getStr(JsonObject jsonObject, String key, String defaultValue) {
if (jsonObject == null) {
return defaultValue;
}
JsonElement element = jsonObject.get(key);
if (element == null || element.isJsonNull()) {
Log.e(TAG, "getStr: " + key + " is null, use default: " + defaultValue);
return defaultValue;
}
try {
return element.getAsString();
} catch (Exception e) {
Log.e(TAG, "getStr: " + key + " = " + element + " parse error, use default: " + defaultValue);
return defaultValue;
}
}
/**
* 安全取值,字段不存在、为 JsonNull、类型不符时返回默认值,不再抛出异常
*/
public static int getNum(JsonObject jsonObject, String key, int defaultValue) {
if (jsonObject == null) {
return defaultValue;
}
JsonElement element = jsonObject.get(key);
if (element == null || element.isJsonNull()) {
Log.e(TAG, "getNum: " + key + " is null, use default: " + defaultValue);
return defaultValue;
}
try {
return element.getAsInt();
} catch (Exception e) {
Log.e(TAG, "getNum: " + key + " = " + element + " parse error, use default: " + defaultValue);
return defaultValue;
}
}
public static void setSystemSetting(Context context, String jsonObj) {
if (null == context) {
throw new RuntimeException("Context it's null");
}
JsonObject jsonObject = GsonUtils.getJsonObject(jsonObj);
setPhoneList(context, jsonObject);
setBluetooth(context, jsonObject);
setHotspot(context, jsonObject);
setBar(context, jsonObject);
setCamera(context, jsonObject);
setTF(context, jsonObject);
setIcon(context, jsonObject);
setCanReset(context, jsonObject);
setAutoTime(context, jsonObject);
String navJsonString = jsonObject.get("setting_nav").getAsString();
JsonObject navJson = JsonParser.parseString(navJsonString).getAsJsonObject();
mMMKV.encode(JGYActions.ACTION_STATUSBAR_STATUS, navJsonString);
setStatusBar(context, navJson);
setBrowserInput(context, jsonObject);
JsonObject jsonObject;
try {
jsonObject = GsonUtils.getJsonObject(jsonObj);
} catch (Exception e) {
Log.e(TAG, "setSystemSetting: json parse error, data = " + jsonObj + "\n" + Log.getStackTraceString(e));
return;
}
if (jsonObject == null) {
Log.e(TAG, "setSystemSetting: jsonObject is null, data = " + jsonObj);
return;
}
applySafely("setPhoneList", SysSettingUtils::setPhoneList, context, jsonObject);
applySafely("setBluetooth", SysSettingUtils::setBluetooth, context, jsonObject);
applySafely("setHotspot", SysSettingUtils::setHotspot, context, jsonObject);
applySafely("setBar", SysSettingUtils::setBar, context, jsonObject);
applySafely("setCamera", SysSettingUtils::setCamera, context, jsonObject);
applySafely("setTF", SysSettingUtils::setTF, context, jsonObject);
applySafely("setIcon", SysSettingUtils::setIcon, context, jsonObject);
applySafely("setCanReset", SysSettingUtils::setCanReset, context, jsonObject);
applySafely("setAutoTime", SysSettingUtils::setAutoTime, context, jsonObject);
applySafely("setStatusBar", (ctx, json) -> {
String navJsonString = getStr(json, "setting_nav", "");
mMMKV.encode(JGYActions.ACTION_STATUSBAR_STATUS, navJsonString);
if (TextUtils.isEmpty(navJsonString)) {
Log.e(TAG, "setStatusBar: setting_nav is empty, skip");
return;
}
JsonObject navJson = JsonParser.parseString(navJsonString).getAsJsonObject();
setStatusBar(ctx, navJson);
}, context, jsonObject);
applySafely("setBrowserInput", SysSettingUtils::setBrowserInput, context, jsonObject);
// TODO: 2022/4/11 不是酷比定制的会报错,无法抛出异常
setUsbStatus(context, jsonObject);
setAdminApp(context, jsonObject);
setSystemAppDisable(context, jsonObject);
setNotification(context, jsonObject);
setPanelShow(context, jsonObject);
setDisAllowCamera(context, jsonObject);
setSettingsMenuShow(context, jsonObject);
setEyeProtectionModeEntrance(context, jsonObject);
applySafely("setUsbStatus", SysSettingUtils::setUsbStatus, context, jsonObject);
applySafely("setAdminApp", SysSettingUtils::setAdminApp, context, jsonObject);
applySafely("setSystemAppDisable", SysSettingUtils::setSystemAppDisable, context, jsonObject);
applySafely("setNotification", SysSettingUtils::setNotification, context, jsonObject);
applySafely("setPanelShow", SysSettingUtils::setPanelShow, context, jsonObject);
applySafely("setDisAllowCamera", SysSettingUtils::setDisAllowCamera, context, jsonObject);
applySafely("setSettingsMenuShow", SysSettingUtils::setSettingsMenuShow, context, jsonObject);
applySafely("setEyeProtectionModeEntrance", SysSettingUtils::setEyeProtectionModeEntrance, context, jsonObject);
}
/**
@@ -410,22 +481,22 @@ public class SysSettingUtils {
MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
//需要转换
//总开关
int setting_bht = changeNum(jsonObject.get("setting_bht").getAsInt());
int setting_bht = changeNum(getNum(jsonObject, "setting_bht", 1));
Log.e(TAG, "setBluetooth: setting_bht = " + setting_bht);
//蓝牙数据功能管控
int setting_bluetooth = changeNum(jsonObject.get("setting_bluetooth").getAsInt());
int setting_bluetooth = changeNum(getNum(jsonObject, "setting_bluetooth", 1));
Log.e(TAG, "setBluetooth: setting_bluetooth = " + setting_bluetooth);
//蓝牙音频功能管控
int setting_bhtvideo = changeNum(jsonObject.get("setting_bhtvideo").getAsInt());
int setting_bhtvideo = changeNum(getNum(jsonObject, "setting_bhtvideo", 1));
Log.e(TAG, "setBluetooth: setting_bhtvideo = " + setting_bhtvideo);
//蓝牙设备连接类型开关
int setting_bluetooth_type = changeNum(jsonObject.get("setting_bluetooth_type").getAsInt());
int setting_bluetooth_type = changeNum(getNum(jsonObject, "setting_bluetooth_type", 1));
Log.e(TAG, "setBluetooth: setting_bluetooth_type = " + setting_bluetooth_type);
if (setting_bluetooth_type == 1) {
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BT_DEVICE_TYPE, "");
} else {
String bluetooth_type_control = jsonObject.get("bluetooth_type_control").getAsString();
String bluetooth_type_control = getStr(jsonObject, "bluetooth_type_control", "");
Log.e(TAG, "setBluetooth: bluetooth_type_control = " + bluetooth_type_control);
if (TextUtils.isEmpty(bluetooth_type_control)) {
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BT_DEVICE_TYPE, "");
@@ -485,14 +556,12 @@ public class SysSettingUtils {
if (old_setting_bhtvideo != setting_bhtvideo) {
mmkv.encode(CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, setting_bhtvideo);
if (setting_bhtvideo == 0) {
if (jsonObject.get("setting_context").isJsonNull()) {
String setting_context = jsonObject.get("setting_context").getAsString();
if (null != setting_context && !"".equals(setting_context) && !" ".equals(setting_context) && !"null".equals(setting_context)) {
Log.e(TAG, "setting_context:" + setting_context);
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, setting_context);
} else {
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty");
}
String setting_context = getStr(jsonObject, "setting_context", "");
if (!TextUtils.isEmpty(setting_context) && !" ".equals(setting_context) && !"null".equals(setting_context)) {
Log.e(TAG, "setting_context:" + setting_context);
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, setting_context);
} else {
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty");
}
} else if (setting_bhtvideo == 1) {
Settings.System.putString(context.getContentResolver(), CommonConfig.AOLE_ACTION_BHTVIDEO_FORBID_ON, "Empty");
@@ -506,7 +575,7 @@ public class SysSettingUtils {
AllwinnerCubeMdmManager.getInstance().setBluetoothEnable(setting_bht == 0);
}
int bt_rename = jsonObject.get("bluetooth_name_change").getAsInt();
int bt_rename = getNum(jsonObject, "bluetooth_name_change", 1);
Settings.System.putInt(context.getContentResolver(), CommonConfig.AOLE_ACTION_BT_RENAME_ALLOW, bt_rename);
}

Binary file not shown.

Binary file not shown.

View File

@@ -5,5 +5,5 @@
android:viewportHeight="1024">
<path
android:pathData="M469.33,85.33a213.33,213.33 0,0 0,-213.33 213.33v42.67a170.67,170.67 0,0 0,-170.67 170.67v256a170.67,170.67 0,0 0,170.67 170.67h512a170.67,170.67 0,0 0,170.67 -170.67v-256a170.67,170.67 0,0 0,-170.67 -170.67L768,298.67a213.33,213.33 0,0 0,-213.33 -213.33h-85.33zM256,426.67h512a85.33,85.33 0,0 1,85.33 85.33v256a85.33,85.33 0,0 1,-85.33 85.33L256,853.33a85.33,85.33 0,0 1,-85.33 -85.33v-256a85.33,85.33 0,0 1,85.33 -85.33zM341.33,298.67a128,128 0,0 1,128 -128h85.33a128,128 0,0 1,128 128v42.67L341.33,341.33L341.33,298.67zM469.33,554.67a42.67,42.67 0,1 0,0 85.33h85.33a42.67,42.67 0,1 0,0 -85.33h-85.33z"
android:fillColor="#2c2c2c"/>
android:fillColor="@color/lock_color" />
</vector>

View File

@@ -67,4 +67,9 @@
<color name="contact_text_color">#98999a</color>
<color name="lightGray">#FFD3D3D3</color>
<color name="default_blue">#0166ff</color>
<color name="unlock_red">#FF0000</color>
<color name="lock_color">#2c2c2c</color>
<color name="blue_restore">#0871f4</color>
</resources>