如何?侦听位置设置已开启(Android App)

时间:2016-03-31 05:45:55

标签: java android gps broadcastreceiver locationmanager

所以我花了几个星期的时间在我的Android应用程序上工作,并研究实现我需要做的最好的方法,但仍然无法做到正确..非常感谢任何/所有帮助,因为我仍然掌握着一切......

任务:

(假设“位置”/ GPS设置当前已关闭),我需要让我的应用程序一直在监听“位置”设置是否打开..此时,只需启动一个活动。

思路:

这些是我认为它可能起作用的所有不同方式:

  • 使用“onProviderEnabled”

  • 的LocationListener
  • GpsStatusListener使用“onGpsStatusChanged”和“GPS_EVENT_STARTED”

  • GpsProvider需要卫星(以确定它是否开始),或以某种方式使用GpsProvider的“AVAILABLE”Constant / int

  • 使用“ACTION_SERVICE_INTENT”(和/或)“ACTION_INJECTED_SETTING_CHANGED”与“onGetEnabled”或“isEnabled”的

  • 的SettingInjectorService
  • 使用“LOCATION_MODE”设置.Secure!=“LOCATION_MODE_OFF”

  • ContentObserver / ContentResolver

  • 意图getAction(...)

  • 某种“if / else”

问题:

非常感谢任何以下任何问题的建议或答案。

  • 上述哪些想法是完成任务的最佳方式?越简单越好,但最重要的是它需要随时监听,并在打开位置设置时立即响应。

  • 对于上述哪一个最佳效果,我将如何实施? (例如,我需要一个BroadcastListener?还是一个服务?它将如何组合在一起?

我非常感谢你能给我的任何建议或帮助..我仍然掌握所有这些,但有足够的信心去做,并渴望发布我的第一个应用程序..所以,谢谢你,它意味着很多,并将极大地帮助我

编辑:

好的,这就是我到目前为止所得到的......
继承人我的接管人:

MyReceiver.Java

public class MyReceiver extends BroadcastReceiver {

    private final static String TAG = "LocationProviderChanged";

    boolean isGpsEnabled;
    boolean isNetworkEnabled;



    public MyReceiver() {
    // EMPTY

    // MyReceiver Close Bracket
    }



    // START OF onReceive
    @Override
    public void onReceive(Context context, Intent intent) {


        // PRIMARY RECEIVER
        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {

            Log.i(TAG, "Location Providers Changed");

            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            Toast.makeText(context, "GPS Enabled: " + isGpsEnabled + " Network Location Enabled: " + isNetworkEnabled, Toast.LENGTH_LONG).show();

            // START DIALOG ACTIVITY
            if (isGpsEnabled || isNetworkEnabled) {
                Intent runDialogActivity = new Intent(context, DialogActivity.class);
                context.startActivity(runDialogActivity);

            }

        }



        // BOOT COMPLETED (REPLICA OF PRIMARY RECEIVER CODE FOR WHEN BOOT_COMPLETED)
        if (intent.getAction().matches("android.intent.action.BOOT_COMPLETED")) {

            Log.i(TAG, "Location Providers Changed Boot");

            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            Toast.makeText(context, "GPS Enabled Boot: " + isGpsEnabled + " Network Location Enabled Boot: " + isNetworkEnabled, Toast.LENGTH_LONG).show();

            // START DIALOG ACTIVITY
            if (isGpsEnabled || isNetworkEnabled) {
                Intent runDialogActivity = new Intent(context, DialogActivity.class);
                context.startActivity(runDialogActivity);

            }

        }



    // onReceive CLOSE BRACKET
    }



// CLOSE OF FULL CLASS
}

这是Manifest的样子:

的Manifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ender.projects.receivertest">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:fullBackupContent="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".DialogActivity">
        </activity>

        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.location.PROVIDERS_CHANGED" />

                <action android:name="android.intent.action.BOOT_COMPLETED" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

    </application>

</manifest>

除了这些文件,我还有以下文件:
MainActivity.JavaDialogActivity.Java,都有布局文件,
activity_main.xmlactivity_dialog.xml与他们匹配。

因此,如果我理解正确,当用户下载应用程序并打开它时,我的MainActivity.Java和相应的布局将启动。但我只是将其用作首选屏幕。因此,一旦他们第一次打开应用程序,广播接收器应该自动开始侦听LOCATION设置是否打开,是否正确?我还希望广播监听器保持收听,即使它收到初始广播后(如果他们关闭LOCATION设置我的onReceive仍然会触发,然后再将它们再次打开..

那么(A)到目前为止我的代码看起来如何? (B)要完成我刚才描述的内容,需要添加什么? 和(C)当我打开LOCATION设置时,运行它会抛出此错误 ..我该怎么办呢? java.lang.RuntimeException: Unable to start receiver com.bryce.projects.servicesthreadsetc.MyReceiver: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?


再次感谢您的帮助!

3 个答案:

答案 0 :(得分:20)

由于您不需要实际获取位置,因此您需要的最佳实现将是BroadcastReceiver。

这是最好的选择,因为您不需要一直运行服务(导致额外的电池消耗),并且您可以从BroadcastReceiver启动您的活动。

使用intent过滤器和BroadcastReceiver,只要位置设置已更改(启用或禁用),操作系统就会启动您的应用程序,如果已启用,则可以从BroadcastReceiver启动您的活动。

首先添加intent过滤器,当操作系统发出设置已更改的隐式Intent时,将会捕获该过滤器。

<receiver
    android:name=".LocationProviderChangedReceiver"
    android:exported="false" >
    <intent-filter>
        <action android:name="android.location.PROVIDERS_CHANGED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>

请注意,为了在Android Oreo及更高版本上运行,您需要在运行时注册广播接收器,请参阅此处:https://developer.android.com/guide/components/broadcasts#context-registered-receivers

然后,在LocationProviderChangedReceiver.java中,您的实现将是这样的:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.util.Log;
import android.widget.Toast;

public class LocationProviderChangedReceiver extends BroadcastReceiver {
    private final static String TAG = "LocationProviderChanged";

    boolean isGpsEnabled;
    boolean isNetworkEnabled;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().matches("android.location.PROVIDERS_CHANGED"))
        {
            Log.i(TAG, "Location Providers changed");

            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            //Start your Activity if location was enabled:
            if (isGpsEnabled || isNetworkEnabled) {
                  Intent i = new Intent(context, YourActivity.class);
                  context.startActivity(i);
            }
        }
    }
}

答案 1 :(得分:0)

以下是使用动态注册的解决方案:

在片段或活动的onResume()方法中,收听LocationManager.PROVIDERS_CHANGED_ACTION中的更改

IntentFilter filter = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
mActivity.registerReceiver(gpsSwitchStateReceiver, filter);

以下是gpsSwitchStateReceiver对象的代码示例:

private BroadcastReceiver gpsSwitchStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {


            if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())) {
                // Make an action or refresh an already managed state.

                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) {
                    Log.i(this.getClass().getName(), "gpsSwitchStateReceiver.onReceive() location is enabled : isGpsEnabled = " + isGpsEnabled + " isNetworkEnabled = " + isNetworkEnabled);
                } else {
                    Log.w(this.getClass().getName(), "gpsSwitchStateReceiver.onReceive() location disabled ");
                }
            }
        }
    };

在您的onPause()方法中,取消注册接收者

mActivity.unregisterReceiver(gpsSwitchStateReceiver);

答案 2 :(得分:0)

LocationListeners的onProvideEnabled()方法将立即起作用。致电时,请记住如果您在LocationManager.removeUpdates()之间执行onProviderEnabled(),将无法正常工作。

这非常简单。您不需要广播接收者进一步收听和交流