Skip to content

Commit

Permalink
修复:手机GPS禁用时,启用增强功能GPS定位服务导致SmsF启动奔溃
Browse files Browse the repository at this point in the history
  • Loading branch information
pppscn committed Feb 11, 2024
1 parent 44ab934 commit c0afc9f
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Criteria
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import android.os.Environment
Expand Down Expand Up @@ -112,7 +113,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
switchEnableAppNotify(binding!!.sbEnableAppNotify, binding!!.scbCancelAppNotify, binding!!.scbNotUserPresent)

//启用GPS定位功能
switchEnableLocation(binding!!.sbEnableLocation, binding!!.layoutLocationSetting, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.etMinInterval, binding!!.etMinDistance)
switchEnableLocation(binding!!.sbEnableLocation, binding!!.layoutLocationSetting, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.xsbMinInterval, binding!!.xsbMinDistance)
//短信指令
switchEnableSmsCommand(binding!!.sbEnableSmsCommand, binding!!.etSafePhone)
//启动时异步获取已安装App信息
Expand Down Expand Up @@ -513,7 +514,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
}

//启用定位功能
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") sbEnableLocation: SwitchButton, layoutLocationSetting: LinearLayout, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, etMinInterval: EditText, etMinDistance: EditText) {
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") sbEnableLocation: SwitchButton, layoutLocationSetting: LinearLayout, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, xsbMinInterval: XSeekBar, xsbMinDistance: XSeekBar) {
//是否启用定位功能
sbEnableLocation.isChecked = SettingUtils.enableLocation
layoutLocationSetting.visibility = if (SettingUtils.enableLocation) View.VISIBLE else View.GONE
Expand Down Expand Up @@ -560,7 +561,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
R.id.rb_accuracy_no_requirement -> Criteria.NO_REQUIREMENT
else -> Criteria.ACCURACY_FINE
}
restartLocationService("rgAccuracy")
restartLocationService()
}

//设置电量消耗:低电耗(默认)
Expand All @@ -581,49 +582,38 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
R.id.rb_power_requirement_no_requirement -> Criteria.NO_REQUIREMENT
else -> Criteria.POWER_LOW
}
restartLocationService("rgPowerRequirement")
restartLocationService()
}

//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
etMinInterval.setText((SettingUtils.locationMinInterval / 1000).toString())
etMinInterval.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val changedText = s.toString()
if (changedText.isEmpty() || changedText == "0") {
etMinInterval.setText("1")
etMinInterval.setSelection(etMinInterval.text.length) // 将光标移至文本末尾
return
}
SettingUtils.locationMinInterval = changedText.toLong() * 1000
restartLocationService()
}
})
xsbMinInterval.setDefaultValue((SettingUtils.locationMinInterval / 1000).toInt())
xsbMinInterval.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
SettingUtils.locationMinInterval = newValue * 1000L
restartLocationService()
}

//设置位置更新最小距离(单位:米);默认距离:0米
etMinDistance.setText(SettingUtils.locationMinDistance.toString())
etMinDistance.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val changedText = s.toString()
if (changedText.isEmpty()) {
etMinDistance.setText("0")
etMinDistance.setSelection(etMinInterval.text.length) // 将光标移至文本末尾
return
}
SettingUtils.locationMinDistance = changedText.toInt()
restartLocationService()
}
})
xsbMinDistance.setDefaultValue(SettingUtils.locationMinDistance)
xsbMinDistance.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
SettingUtils.locationMinDistance = newValue
restartLocationService()
}
}

//重启定位服务
private fun restartLocationService(action: String = "RESTART") {
Log.d(TAG, "restartLocationService, action: $action")
val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = action
val locationManager = App.context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
val isGpsEnabled = locationManager?.isProviderEnabled(LocationManager.GPS_PROVIDER) == true
if (!isGpsEnabled && SettingUtils.enableLocation) {
XToastUtils.error(getString(R.string.toast_gps_not_enabled))
SettingUtils.enableLocation = false
binding!!.sbEnableLocation.isChecked = false
serviceIntent.action = "STOP"
} else {
serviceIntent.action = action
}
requireContext().startService(serviceIntent)
}

Expand Down
123 changes: 69 additions & 54 deletions app/src/main/java/com/idormy/sms/forwarder/service/LocationService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package com.idormy.sms.forwarder.service

import android.annotation.SuppressLint
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.location.Location
import android.location.LocationManager
import android.os.IBinder
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
Expand All @@ -23,14 +27,20 @@ import com.king.location.LocationErrorCode
import com.king.location.OnExceptionListener
import com.king.location.OnLocationListener
import com.xuexiang.xaop.util.PermissionUtils
import com.yanzhenjie.andserver.Server
import java.util.Date

@SuppressLint("SimpleDateFormat")
@Suppress("PrivatePropertyName", "DEPRECATION")
class LocationService : Service(), Server.ServerListener {
class LocationService : Service() {

private val TAG: String = LocationService::class.java.simpleName
private val gpsStatusReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == LocationManager.PROVIDERS_CHANGED_ACTION) {
handleGpsStatusChanged()
}
}
}

companion object {
var isRunning = false
Expand All @@ -45,13 +55,16 @@ class LocationService : Service(), Server.ServerListener {
super.onCreate()

if (!SettingUtils.enableLocation) return

//注册广播接收器
registerReceiver(gpsStatusReceiver, IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION))
startService()
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)

if (!SettingUtils.enableLocation || intent == null) return START_NOT_STICKY
if (intent == null) return START_NOT_STICKY

Log.i(TAG, "onStartCommand: ${intent.action}")

Expand All @@ -60,11 +73,10 @@ class LocationService : Service(), Server.ServerListener {
} else if (intent.action == "STOP" && isRunning) {
stopService()
} else if (intent.action == "RESTART") {
stopService()
startService()
restartLocation()
}

return START_NOT_STICKY
return START_STICKY
}

override fun onDestroy() {
Expand All @@ -73,18 +85,8 @@ class LocationService : Service(), Server.ServerListener {

if (!SettingUtils.enableLocation) return
stopService()
}

override fun onException(e: Exception?) {
Log.i(TAG, "onException: ")
}

override fun onStarted() {
Log.i(TAG, "onStarted: ")
}

override fun onStopped() {
Log.i(TAG, "onStopped: ")
//在 Service 销毁时记得注销广播接收器
unregisterReceiver(gpsStatusReceiver)
}

private fun startService() {
Expand All @@ -94,16 +96,6 @@ class LocationService : Service(), Server.ServerListener {
TaskUtils.locationInfoOld = LocationInfo()

if (SettingUtils.enableLocation && PermissionUtils.isGranted(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
val locationOption = App.LocationClient.getLocationOption().setAccuracy(SettingUtils.locationAccuracy)//设置位置精度:高精度
.setPowerRequirement(SettingUtils.locationPowerRequirement) //设置电量消耗:低电耗
.setMinTime(SettingUtils.locationMinInterval)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
.setMinDistance(SettingUtils.locationMinDistance)//设置位置更新最小距离(单位:米);默认距离:0米
.setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位
.setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true
//设置定位配置参数
App.LocationClient.setLocationOption(locationOption)
App.LocationClient.startLocation()

//设置定位监听
App.LocationClient.setOnLocationListener(object : OnLocationListener() {
Expand All @@ -125,7 +117,7 @@ class LocationService : Service(), Server.ServerListener {
HttpServerUtils.apiLocationCache = locationInfoNew
TaskUtils.locationInfoNew = locationInfoNew

//TODO: 触发自动任务
//触发自动任务
val locationInfoOld = TaskUtils.locationInfoOld
if (locationInfoOld.longitude != locationInfoNew.longitude || locationInfoOld.latitude != locationInfoNew.latitude || locationInfoOld.address != locationInfoNew.address) {
Log.d(TAG, "locationInfoOld = $locationInfoOld")
Expand All @@ -139,34 +131,18 @@ class LocationService : Service(), Server.ServerListener {
TaskUtils.locationInfoOld = locationInfoNew
}
}

override fun onProviderEnabled(provider: String) {
super.onProviderEnabled(provider)
Log.d(TAG, "onProviderEnabled(provider = ${provider})")
}

override fun onProviderDisabled(provider: String) {
super.onProviderDisabled(provider)
Log.d(TAG, "onProviderDisabled(provider = ${provider})")
}

})

//设置异常监听
App.LocationClient.setOnExceptionListener(object : OnExceptionListener {
override fun onException(@LocationErrorCode errorCode: Int, e: Exception) {
//定位出现异常
//定位出现异常 && 尝试重启定位
Log.w(TAG, "onException(errorCode = ${errorCode}, e = ${e})")

//TODO: 重启定位
App.LocationClient.startLocation()
restartLocation()
}
})

if (App.LocationClient.isStarted()) {//如果已经开始定位,则先停止定位
App.LocationClient.stopLocation()
}
App.LocationClient.startLocation()
restartLocation()
isRunning = true
} else if (!SettingUtils.enableLocation && App.LocationClient.isStarted()) {
Log.d(TAG, "stopLocation")
Expand Down Expand Up @@ -200,20 +176,59 @@ class LocationService : Service(), Server.ServerListener {
}
}

private fun restartLocation() {
//如果已经开始定位,则先停止定位
if (App.LocationClient.isStarted()) {
App.LocationClient.stopLocation()
}
if (isGpsEnabled()) {
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
val locationOption = App.LocationClient.getLocationOption().setAccuracy(SettingUtils.locationAccuracy)//设置位置精度:高精度
.setPowerRequirement(SettingUtils.locationPowerRequirement) //设置电量消耗:低电耗
.setMinTime(SettingUtils.locationMinInterval)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
.setMinDistance(SettingUtils.locationMinDistance)//设置位置更新最小距离(单位:米);默认距离:0米
.setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位
.setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true
//设置定位配置参数
App.LocationClient.setLocationOption(locationOption)
App.LocationClient.startLocation()
} else {
Log.w(TAG, "onException: GPS未开启")
}
}

private fun enqueueLocationWorkerRequest(
conditionType: Int,
locationJsonOld: String,
locationJsonNew: String
conditionType: Int, locationJsonOld: String, locationJsonNew: String
) {
val locationWorkerRequest = OneTimeWorkRequestBuilder<LocationWorker>().setInputData(
workDataOf(
TaskWorker.conditionType to conditionType,
"locationJsonOld" to locationJsonOld,
"locationJsonNew" to locationJsonNew
TaskWorker.conditionType to conditionType, "locationJsonOld" to locationJsonOld, "locationJsonNew" to locationJsonNew
)
).build()

WorkManager.getInstance(applicationContext).enqueue(locationWorkerRequest)
}

private fun handleGpsStatusChanged() {
val isGpsEnabled = isGpsEnabled()
//处理 GPS 状态变化
if (isGpsEnabled) {
//GPS 已启用
Log.d(TAG, "handleGpsStatusChanged: GPS 已启用")
if (SettingUtils.enableLocation && !App.LocationClient.isStarted()) {
App.LocationClient.startLocation()
}
} else {
//GPS 已停用
Log.d(TAG, "handleGpsStatusChanged: GPS 已停用")
if (SettingUtils.enableLocation && App.LocationClient.isStarted()) {
App.LocationClient.stopLocation()
}
}
}

private fun isGpsEnabled(): Boolean {
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager?
return locationManager?.isProviderEnabled(LocationManager.GPS_PROVIDER) == true
}
}
Loading

0 comments on commit c0afc9f

Please sign in to comment.