【问题标题】:How to detect when user turn on/off GPS state?如何检测用户何时打开/关闭 GPS 状态?
【发布时间】:2013-04-03 04:21:13
【问题描述】:

我想阻止用户从我的应用程序更改 WiFi、GPS 和加载设置。运行我的应用程序时,用户不需要打开/关闭 WiFi 和 GPS。(来自通知栏)。是否有任何BroadcastReceiver 用于监听 GPS 开/关?

【问题讨论】:

    标签: android gps broadcastreceiver


    【解决方案1】:

    好吧,我做了很多挖掘工作,发现 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())
    • 您的意思是应该删除或改进该检查吗?
    • 可以不使用硬编码字符串“android.location.PROVIDERS_CHANGED”来更改,而是LocationManager.PROVIDERS_CHANGED_ACTION
    • @sud007:今后,应用程序将不再监听广播接收器,除非它被列入白名单。所以现在我们需要根据答案将我们的接收器从清单声明更改为 java/kotlin 声明。现在,如果应用程序被杀死并且我打开 GPS,我没有其他方法可以让我的应用程序知道 GPS 已打开/关闭,我担心如果我遵循上述方法,我的应用程序将如何收听?
    • @Rohit 感谢您指出这一点!因为这个答案很久以前就被提出了。如果您能够根据更新的文档推断出其他一些解决方案,那就太好了。我一定会尽快尝试更新解决方案。谢谢!
    【解决方案2】:

    您可以使用 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”类中)。

    【讨论】:

    • 所以从 Nougat 开始 addGpsStatusListener was deprecated in API level 24. use registerGnssStatusCallback(GnssStatus.Callback) instead. 根据 Android 文档 here
    【解决方案3】:

    在活动的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);
    

    【讨论】:

    • 我运行这段代码,当我手动打开 gps 时它可以工作,否则如果 gps 关闭,它不会显示任何内容你知道为什么吗?我使用相同的代码。
    【解决方案4】:

    这是不可能的。您无法随心所欲地控制/限制硬件的状态。这在 API 中是很危险的,因此不存在这样的 API 是理所当然的。

    【讨论】:

    • 我想让 gps 状态在用户更改它时恢复到以前的状态。我需要广播接收器之类的东西来监听 android.net.conn.CONNECTIVITY_CHANGE
    • 然后重组你的问题,因为那不是你要问的。你问的是限制改变不听。
    【解决方案5】:

    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))
        }}
    

    【讨论】:

      【解决方案6】:

      您可以注册BroadcastReceiver 以收听Intent 操作PROVIDERS_CHANGED_ACTION。这将在配置的位置提供程序更改时广播。你可以参考这个link

      【讨论】:

        【解决方案7】:

        我们可以使用 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

        【讨论】:

          【解决方案8】:

          您可以通过以下方式检测 GPS 的状态。

          看看GpsStatus.Listener。使用 locationManager.addGpsStatusListener(gpsStatusListener) 注册它。

          也请查看此 SO link 以获得更好的理解。

          【讨论】:

            【解决方案9】:

            从 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
            

            【讨论】:

              【解决方案10】:

              您不能使用 GpsStatus.Listener 来执行此操作。您必须使用广播接收器。使用 LocationManager.PROVIDERS_CHANGE_ACTION。不使用 Intent.ACTION_PROVIDER_CHANE。 祝你好运!

              【讨论】:

                【解决方案11】:

                我为此使用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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-18
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-12-29
                  相关资源
                  最近更新 更多