【发布时间】:2013-04-03 04:21:13
【问题描述】:
我想阻止用户从我的应用程序更改 WiFi、GPS 和加载设置。运行我的应用程序时,用户不需要打开/关闭 WiFi 和 GPS。(来自通知栏)。是否有任何BroadcastReceiver 用于监听 GPS 开/关?
【问题讨论】:
标签: android gps broadcastreceiver
我想阻止用户从我的应用程序更改 WiFi、GPS 和加载设置。运行我的应用程序时,用户不需要打开/关闭 WiFi 和 GPS。(来自通知栏)。是否有任何BroadcastReceiver 用于监听 GPS 开/关?
【问题讨论】:
标签: android gps broadcastreceiver
好吧,我做了很多挖掘工作,发现 addGpsStatusListener(gpsStatusListener) 在 API 24 中已被弃用。对我来说,这甚至不起作用!所以,这里有另一种解决方案。
如果在您的应用中,您想监听 GPS 状态变化(我的意思是用户开/关)。使用广播无疑是最好的方法。
实施:
/**
* Following broadcast receiver is to listen the Location button toggle state in Android.
*/
private BroadcastReceiver mGpsSwitchStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
// Make an action or refresh an already managed state.
}
}
};
不要忘记在 Fragment/Activity 生命周期中有效地注册和取消注册。
registerReceiver(mGpsSwitchStateReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
例如,如果您使用的是Fragment,请在onResume 中注册并在onDestroy 中取消注册。此外,如果您将用户引导至启用位置开关的设置,则在onStop 中取消注册将不起作用,因为您的活动转到onPause 并且片段已停止。
这个解决方案可能有很多答案,但这个解决方案很容易管理和使用。如果有,请提出您的解决方案。
【讨论】:
onReceive 甚至可以通过不检查正则表达式来简化:LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())
LocationManager.PROVIDERS_CHANGED_ACTION。
您可以使用 GpsStatus.Listener 监听 GPS 状态 并将其注册到 LocationManager。
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.addGpsStatusListener(new android.location.GpsStatus.Listener()
{
public void onGpsStatusChanged(int event)
{
switch(event)
{
case GPS_EVENT_STARTED:
// do your tasks
break;
case GPS_EVENT_STOPPED:
// do your tasks
break;
}
}
});
您需要能够访问上下文(例如在“Activity”或“Application”类中)。
【讨论】:
addGpsStatusListener was deprecated in API level 24. use registerGnssStatusCallback(GnssStatus.Callback) instead. 根据 Android 文档 here
在活动的onResume() 方法中收听LocationManager.PROVIDERS_CHANGED_ACTION 事件:
IntentFilter filter = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
mActivity.registerReceiver(gpsSwitchStateReceiver, filter);
将此BroadcastReceiver 实例添加到您的活动中:
private BroadcastReceiver gpsSwitchStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isGpsEnabled || isNetworkEnabled) {
// Handle Location turned ON
} else {
// Handle Location turned OFF
}
}
}
};
在您的活动的onPause() 方法中取消注册接收器:
mActivity.unregisterReceiver(gpsSwitchStateReceiver);
【讨论】:
这是不可能的。您无法随心所欲地控制/限制硬件的状态。这在 API 中是很危险的,因此不存在这样的 API 是理所当然的。
【讨论】:
在 Kotlin 中试试这个:
添加一个扩展BroadcastReceiver的类:
class GPSCheck(private val locationCallBack: LocationCallBack) :
BroadcastReceiver() {
interface LocationCallBack {
fun turnedOn()
fun turnedOff()
}
override fun onReceive(context: Context, intent: Intent) {
val locationManager =
context.getSystemService(LOCATION_SERVICE) as LocationManager
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) locationCallBack.turnedOn() else locationCallBack.turnedOff()
}
}
然后作为一个例子这样使用它:
class MainActivity :AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
registerReceiver(GPSCheck(object : GPSCheck.LocationCallBack {
override fun turnedOn() {
Log.d("GpsReceiver", "is turned on")
}
override fun turnedOff() {
Log.d("GpsReceiver", "is turned off")
}
}), IntentFilter(LocationManager.MODE_CHANGED_ACTION))
}}
【讨论】:
您可以注册BroadcastReceiver 以收听Intent 操作PROVIDERS_CHANGED_ACTION。这将在配置的位置提供程序更改时广播。你可以参考这个link。
【讨论】:
我们可以使用 LocationListener 了解 GPS 何时开启和何时关闭。
class HomeActivity : AppCompatActivity() {
private var locManager: LocationManager? = null
private val locListener: LocationListener =
object : LocationListener {
override fun onLocationChanged(loc: Location) {
}
override fun onProviderEnabled(provider: String) {
Log.d("abc", "enable")
}
override fun onProviderDisabled(provider: String) {
Log.d("abc", "disable")
}
override fun onStatusChanged(
provider: String,
status: Int,
extras: Bundle
) {
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
locManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
}
override fun onResume() {
super.onResume()
startRequestingLocation()
}
override fun onStop() {
super.onStop()
try {
locManager!!.removeUpdates(locListener)
} catch (e: SecurityException) {
}
}
private fun startRequestingLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST
)
return
}
locManager!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, locListener)
}
companion object {
private const val PERMISSION_REQUEST = 1
}
}
查看此项目了解更多详情:https://github.com/pR0Ps/LocationShare
【讨论】:
您可以通过以下方式检测 GPS 的状态。
看看GpsStatus.Listener。使用 locationManager.addGpsStatusListener(gpsStatusListener) 注册它。
也请查看此 SO link 以获得更好的理解。
【讨论】:
从 API 19 开始,您可以注册 BroadcastReceiver 用于监听意图操作 LocationManager.MODE_CHANGED_ACTION
参考:https://developer.android.com/reference/android/location/LocationManager.html#MODE_CHANGED_ACTION
您可以通过
获得定位模式try
{
int locationMode = android.provider.Settings.Secure.getInt(context.getContentResolver(), android.provider.Settings.Secure.LOCATION_MODE);
} catch (android.provider.Settings.SettingNotFoundException e)
{
e.printStackTrace();
}
返回的值应该是以下之一:
android.provider.Settings.Secure.LOCATION_MODE_BATTERY_SAVING
android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
android.provider.Settings.Secure.LOCATION_MODE_OFF
android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY
【讨论】:
您不能使用 GpsStatus.Listener 来执行此操作。您必须使用广播接收器。使用 LocationManager.PROVIDERS_CHANGE_ACTION。不使用 Intent.ACTION_PROVIDER_CHANE。 祝你好运!
【讨论】:
我为此使用android.location.LocationListener:
`class MyOldAndroidLocationListener implements android.location.LocationListener {
@Override public void onLocationChanged(Location location) { }
//here are the methods you need
@Override public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override public void onProviderEnabled(String provider) { }
@Override public void onProviderDisabled(String provider) { }
}`
注意(来自docs):如果 LocationListener 已使用 LocationManager.requestLocationUpdates(String, long, float, LocationListener) 方法向位置管理器服务注册,则会调用这些方法
因为我使用 Fused Location API 来处理与位置相关的内容,所以我只是设置了
long minTime = 1 小时,
float minDistance = 1 公里,在 requestLocationUpdates
这对我的应用程序的开销很小。
当然,完成后别忘了locationManager.removeUpdates。
【讨论】: