Android 地理围栏广播接收器

2024-05-07

我已经使用 GoogleApiClient 实现了地理围栏 -> 触发时,服务会连接到 GoogleApiClient 并添加多个地理围栏。

在我将另一个 IntentService 注册为地理围栏事件的“回调”之前。这或多或少有效,但仅限于应用程序位于前台时。由于我也想在应用程序处于后台/关闭时获取地理围栏事件,因此我进行了一些搜索并将回调从 IntentService 移至 BroadcastReceiver,现在当应用程序位于前台时我什至没有获取地理围栏事件。

我已经向互联网询问解决方案(最常见的答案:将事件侦听器从 Service 更改为 BroadCastReceiver - 但这使事情变得更糟)

这是我的设置:

显现:

    <receiver
        android:name=".service.GeofenceReceiver">
        <intent-filter>
            <action android:name="com.example.geofence.ACTION_RECEIVE" />
        </intent-filter>
    </receiver>

    <receiver android:name=".service.BootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <service
        android:name=".service.GeofenceRegistrationService"
        android:enabled="true"
        android:exported="false" />

启动接收器:

public class BootReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
      GeofenceRegistrationService.startService(context,true);
  }
}

地理围栏接收器:

public class GeofenceReceiver extends BroadcastReceiver {

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

      Logger.e(this, "GeofenceReceiver called");

      GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);

      if (geofencingEvent.hasError()) {
          Logger.e(this, String.valueOf(geofencingEvent.getErrorCode()));

      } else {
        Logger.i(this, geofencingEvent.getTriggeringLocation().getLatitude() + ", " +geofencingEvent.getTriggeringLocation().getLongitude());

      }
  }
}

地理围栏注册服务:

public class GeofenceRegistrationService extends Service implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> {


  public static final String KEY_FORCE_CLEAN = "FORCE_CLEAN";

  public static void startService(Context context, boolean forceClean) {

      Intent intent = new Intent(context, GeofenceRegistrationService.class);

      intent.putExtra(KEY_FORCE_CLEAN, forceClean);

      context.startService(intent);

  }

  private GoogleApiClient mGoogleApiClient;
  private PendingIntent mGeofencePendingIntent;

  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {

    if (isLocationPermissionGranted() && intent != null) {

        startGeofenceRegistration();

    } else {

        this.stopSelf(startId);

    }

    return START_REDELIVER_INTENT;
  }

  public void startGeofenceRegistration() {

    if (mGoogleApiClient == null) {
        mGoogleApiClient = buildAPIClient();
    }

    if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) {
        mGoogleApiClient.connect();
    } else {
        registerGeofences();
    }
  }


  private boolean isLocationPermissionGranted() {
    return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
  }

  private synchronized GoogleApiClient buildAPIClient() {

    return new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

  }

  private void addGeoFences() {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        try {
            LocationServices.GeofencingApi.addGeofences(
                    mGoogleApiClient,
                    createGeofencesRequest(),
                    getGeofencePendingIntent()
            ).setResultCallback(this);
        } catch (SecurityException securityException) {
            Logger.e(this, securityException);
        }
    }
  }

  private void removeGeoFences() {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        try {
            LocationServices.GeofencingApi.removeGeofences(
                    mGoogleApiClient,
                    getGeofencePendingIntent()
            ).setResultCallback(this);
        } catch (SecurityException securityException) {
            Logger.e(this, securityException);
        }
    }
 }

 private PendingIntent getGeofencePendingIntent() {
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    //Intent intent = new Intent(this, GeofenceEventHandlingService.class);
    Intent intent = new Intent("com.example.geofence.ACTION_RECEIVE");
    mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    return mGeofencePendingIntent;
  }

  @Override
  public void onConnectionFailed(@NonNull ConnectionResult  connectionResult) {
    Logger.d(this, "CONNECTION_FAILED");
  }

  @Override
  public void onConnected(@Nullable Bundle bundle) {
    Logger.d(this, "CONNECTED");
    registerGeofences();

  }

  private void registerGeofences() {
    removeGeoFences();
    addGeoFences();
  }

  @Override
  public void onConnectionSuspended(int i) {
    Logger.d(this, "connection suspended");
  }

  private GeofencingRequest createGeofencesRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();

    List<Poi> pois = Config.getPersistenceService().getPois();

    int counter = 0;
    for (Poi p : pois) {
        if (p.isCoordinateSet()) {
            Geofence fence = new Geofence.Builder()
                    .setRequestId(String.valueOf(p.getId()))
                    .setCircularRegion(p.getLat(), p.getLon(), 2500) // TODO
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
                    .build();

            builder.addGeofence(fence);

            counter++;
        }
    }

    Logger.i(this, "added geofences: " + counter);

    return builder.build();
  }


  @Override
  public void onDestroy() {

    if (mGoogleApiClient != null && (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting())) {
        mGoogleApiClient.disconnect();
    }

    super.onDestroy();
  }

  @Override
  public void onResult(@NonNull Status status) {
    if (status.isSuccess()) {
        Logger.d(this, "Geofences added");

    } else {
        Logger.d(this, "Failed to add geofences");
    }
  }


}

我究竟做错了什么?我负责监督什么?


这是我所做的工作,但请记住,我正在从活动中添加和删除地理围栏,并在 IntentService 中接收地理围栏转换。

我认为你应该尝试建立你的Intent指定new Intent(context, YourReceiverClass)并创建你的PendingIntent using PendingIntent.getBroadcast()。这是我使用的:

private PendingIntent getGeofencePendingIntent(){
    // Re-use the Pending Intent if it already exists
    if(mGeofencePendingIntent != null){
        return mGeofencePendingIntent;
    }

    // The intent for the IntentService to receive the transitions
    Intent intent = new Intent(getContext(), GeofenceTransitionsIntentService.class);

    // Create the pending intent
    mGeofencePendingIntent = PendingIntent
            .getService(getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    return mGeofencePendingIntent;
}

在我的 IntentService 中:

@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    if (geofencingEvent.hasError()) {
        String errorMessage = GeofenceErrorMessages.getErrorString(this,
                geofencingEvent.getErrorCode());
        Log.e(LOG_TAG, errorMessage);
        return;
    }

    // Get the transition type.
    int geofenceTransition = geofencingEvent.getGeofenceTransition();

    // Test that the reported transition was of interest.
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
            geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

        // Get the geofences that were triggered. A single event can trigger multiple geofences.
        List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();

       // Do something with geofences

    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 地理围栏广播接收器 的相关文章

随机推荐

  • 如何在Python中打印颜色/颜色?

    我对 Python 和 StackOverflow 都是新手 需要一点帮助 我想用 Python 打印颜色 并在 Google 上搜索过 但运气不佳 每次我都很困惑 但都没有成功 这是我输入的代码 answer input Wanna go
  • 哪个 C++ 草案?

    我对当前的 C 标准感兴趣 并且对以下链接有点困惑http www open std org jtc1 sc22 wg21 docs papers 2014 http www open std org jtc1 sc22 wg21 docs
  • Scala 中两个地图的交集和合并/连接

    假设我有两张类似这样的地图 val m1 Map 1 gt One 2 gt Two 3 gt Three val m2 Map 2 gt 2 0 3 gt 3 0 4 gt 4 0 我想根据键获取交集并返回一个表示合并值的元组 结果看起来
  • cout 可以以某种方式改变变量吗?

    所以我有一个看起来像这样的函数 float function float x SomeValue return x SomeOtherValue 在某些时候 这个函数会溢出并返回一个非常大的负值 为了尝试准确追踪发生这种情况的位置 我添加了
  • C++中exit和kill的区别

    我已经编写了一个信号处理程序来处理SIG 如果我得到的进程太多 我想终止该进程 那么 以下哪个代码更好 或者我应该同时使用它们 exit 1 or some other exit code kill getpid SIGKILL 您可能不想
  • 如何研究.NET 中的非托管内存泄漏?

    我有一个通过 MSMQ 运行的 WCF 服务 内存随着时间的推移逐渐增加 表明存在某种内存泄漏 我在本地运行该服务并使用 PerfMon 监视一些计数器 CLR 内存托管堆字节总数保持相对恒定 而进程的私有字节随着时间的推移而增加 这让我相
  • 如何将现场 prestashop 站点移至本地主机?

    我在将 PS 1 7 从服务器域传输到本地主机时遇到问题 我已按照 Prestashop 文档中的文件传输的所有步骤进行操作 我执行此步骤 1 将所有 prestashop 文件从服务器下载到我的 mac 并将其放入 mamp htdocs
  • iphone XMPP 应用程序运行后台

    我使用 XMPP 框架创建了一个聊天应用程序 当我退出应用程序 进入后台模式 时 我想接收聊天消息 并且还需要显示图标徽章 我该怎么做 您确实可以通过将基于 XMPP 框架的应用程序称为 VoIP 应用程序来在 iOS4 中的后台运行该应用
  • SBT - 运行任务来设置SettingKey

    所以我的一般问题是我想根据任务的结果设置版本密钥 但是版本密钥是在任务运行之前设置的 据我了解 一旦设置了键的值 我就无法更改它 因此我无法在我的任务中更改它 我想要做的是将任务作为发布任务的依赖项运行并更改版本的值 我觉得一定有办法做到这
  • 从列表视图启动活动

    您好 我有一个列表视图 我正在尝试通过以下方式从列表视图启动一项活动startActivity class java public class ll2 extends Activity public void onCreate Bundle
  • dplyr - 分组并选择 TOP x %

    使用 dplyr 包和函数sample frac可以从每个组中抽取一定比例的样本 我需要的是首先对每个组中的元素进行排序 然后从每个组中选择前 x 有一个功能top n 但这里我只能确定行数 并且我需要一个相对值 例如 以下数据按齿轮分组并
  • Python - 在和不在列表中语法错误

    我正在尝试从另一个现有的浮点数列表构建一个新的浮点数列表 通过示例更容易识别第一个列表的预期内容 price list 39 99 74 99 24 99 49 99 预期的后期功能 print new price list gt gt 2
  • java中filewriter的flush和close函数之间的区别

    我需要知道Java中的flush和close函数之间的确切区别是什么 当在写入文件期间将数据转储到文件中时 请提供一个例子 flush just确保所有缓冲数据都写入磁盘 在这种情况下 更一般地说 通过您正在使用的任何 IO 通道刷新 之后
  • Windows 7 VM 上的 Android Studio 虚拟设备不兼容

    我的计算机上有一个 VirtualBox VM 该 VM 运行 Windows 7 64 位 我在该虚拟机上安装了 Android Studio 我只有基本的 Hello World 应用程序 当我尝试运行 AVD 时 我收到以下消息 运行
  • java:在目录和子目录中根据文件名搜索文件

    我需要根据目录树中的名称查找文件 然后显示该文件的路径 我发现了类似的东西 但它根据扩展名进行搜索 谁能帮助我如何根据我的需要重新编写这段代码 谢谢 public class filesFinder public static void m
  • 使用传感器方向

    在我的应用程序中 我想显示设备方向 例如北 南 东 西 为此 我使用加速度计和磁传感器并尝试使用以下代码 public class MainActivity extends Activity implements SensorEventLi
  • 数据库被锁定?

    我如何修复数据库锁 因为我的测试没有通过 它使同一类别中的一堆测试失败 谢谢 1 UsersController GET edit should have a link to change the Gravatar Failure Erro
  • 在 Go 中修改导入的库

    我的问题 弹性节拍 https www elastic co products beats是一个用 Go 编写的日志传送程序的开源项目 它具有多种日志输出功能 包括控制台 Elasticsearch 和 Redis 我想将我自己的输出添加到
  • 使用 array.map 后如何运行函数?

    我想做的是在使用 array map 之后运行一个函数 理论上 我应该能够在 array map 之后运行 但是 由于某种原因 它在 array map 完成之前运行该函数 我该如何解决 这是我的代码 var channelIds chan
  • Android 地理围栏广播接收器

    我已经使用 GoogleApiClient 实现了地理围栏 gt 触发时 服务会连接到 GoogleApiClient 并添加多个地理围栏 在我将另一个 IntentService 注册为地理围栏事件的 回调 之前 这或多或少有效 但仅限于