监控库中的位置设置

Posted

技术标签:

【中文标题】监控库中的位置设置【英文标题】:Monitoring Location Settings in a Library 【发布时间】:2015-08-08 16:14:03 【问题描述】:

我正在开发一个可用于监控 android 设备上的地理围栏的库。我注意到在设备设置中关闭并重新打开位置服务后,我在 Google Play 位置服务 GeofencingApi 类中注册的地理围栏丢失了。

我看到folks 建议我需要在我的AndroidManifest.xml 文件中注册android.location.PROVIDERS_CHANGED 广播接收器。我已经这样做了——但是只有当我在测试应用程序中添加和删除测试提供者时才会调用这个广播接收器。在设备设置中切换定位服务时,我根本没有收到它。

我做错了吗?有谁知道如何可靠地确定用户何时在设备设置中切换定位服务?我希望能够在后台看到这些事件——即使我的应用程序没有运行。

我想我可以设置一个在后台运行的重复任务,并定期检查位置服务是否已被切换,但这听起来很糟糕而且效率低下。

如果有帮助,我正在运行 Android 4.4.2 的 Moto G 上进行测试。到目前为止,我对地理围栏所做的一切都运行良好。

编辑:经过更多研究,我发现PROVIDERS_CHANGED 广播的行为因手机版本和型号而异。我的 Nexus 5 运行 Android 5.1 似乎工作正常 - 我能够定期收到 PROVIDERS_CHANGED 广播。我还有一部运行 4.4.x 的 Moto G 和 Moto X 手机,它们从未为我制作过 PROVIDERS_CHANGED 广播。 Android 4.2 上的三星 Galaxy S3 会为我生成广播,但在我将 Map Activity 与测试位置提供程序一起使用后停止播放。

无论如何,我决定暂时停止研究这个问题。我认为 Android 只是有缺陷。

【问题讨论】:

这可能会有所帮助***.com/questions/10311834/… 另外您是否尝试将地理围栏数据保存在本地或其他地方以防止其被删除? 我已经在本地保存了地理围栏,所以我不会永远丢失它们(除非用户清除缓存)。那不是我的问题。我的问题是我没有收到通知我位置提供程序设置已更改的事件。 (即:我没有被告知它们已被操作系统删除,也没有被告知何时可以安全地重新加载)。 ***.com/questions/25156977/… 我注册了 providers_changed in code 你实际上需要一些代码才能得到一个体面的答案。带有 4.4.2 的 IDK 可能不起作用。我已经好几个月没有启动我的 android 开发环境了。 【参考方案1】:

如果你做错了什么,很难在没有看到你的代码的情况下判断,但我只是通过使用来自 here 的代码作为指导,并对其进行调整以将 BroadcastReceiver 放在库中,从而得到了一个工作和测试的简单示例.

需要注意的一点:使用该库的应用需要在其 AndroidManifest.xml 中包含 receiver。 请参阅here 和here,两者都包含来自@CommonsWare 的信息。

在此处添加引用以防链接出错:

图书馆项目有没有办法独立注册 接收器在它自己的清单文件中?

暂时没有。

因此,任何使用您的库的应用都需要在其 AndroidManifest.xml 中添加 receiver

请注意,这是在三星 S4 上的 Android 4.4.4 上测试的。

我在编译为aar 的库项目中使用广播接收器来完成这项工作。

使用在主应用程序的 AndroidManifest.xml 中设置的 receiver 元素,该元素链接到库中的 BroadcastReceiver,当位置设置发生任何更改时,我能够接收到事件:

开启位置开关 位置开关关闭 将定位模式更改为高精度 将定位模式更改为省电模式 将定位模式更改为仅 GPS

每次更改位置设置时,都会触发库中的 BroadcastReceiver,即使应用程序没有运行。

我使用了一个简单的测试,每次更改位置设置时,库中的 BroadcastReceiver 都会显示一条 Toast 消息。

这里是库项目中的 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);

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


然后,在主应用程序中,我将编译好的myLibrary.aar放到libs文件夹中,并设置build.gradle来编译aar:

 repositories
        flatDir
            dirs 'libs'
        
    


dependencies 
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "com.android.support:appcompat-v7:22.1.1"
    compile "com.google.android.gms:play-services:7.3.0"

    compile 'com.mylibrary.daniel:mylibrary:1.0@aar'


在主应用的AndroidManifest.xml中设置receiver

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

然后,安装应用程序,并以几种不同的方式修改位置设置。每次都会触发库中的BroadcastReceiver:

【讨论】:

感谢您的回答。我的代码和你的基本一样。我尝试将我的 BroadcastReceiver 放在我的主应用程序和我的库中,并且行为是相同的。无论 BroadcastReceiver 是在图书馆还是应用程序中,我都可以定期在 Nexus 5 上接收广播。我认为,只要我在库的 AndroidManifest.xml 文件中声明我的 BroadcastReceiver 并使用 Gradle 进行构建,BroadcastReceiver 的位置就无关紧要。其他手机的可靠性要低得多。我认为 Android 只是有问题,我现在已经停止解决这个问题。 是的,当应用程序在附近时它可以工作,但是当它被任务管理器杀死/关闭时,它对我不起作用。我在 MI3 设备上使用 Android 4.4.4 Kitkat。【参考方案2】:

其实你可以使用location.MODE_CHANGED然后注册你的receiver来接收它的广播

<receiver android:name=".Receivers.LocationModeReceiver">
    <intent-filter>
        <action android:name="android.location.MODE_CHANGED" />
    </intent-filter>
</receiver>

【讨论】:

以上是关于监控库中的位置设置的主要内容,如果未能解决你的问题,请参考以下文章

将图像设置为库中的图像视图,而不从图像库中选择图像

SharePoint 库中的奇怪行为设置为需要内容批准

我可以在 SOTabBar 库中的按钮下设置文本吗?

如何在共享库中的确切行号上设置断点?

git将上游设置为存储库中的远程文件夹

VS Code 中的用户特定工作区设置