AltBeacon 库后台服务

AltBeacon library background service

这是我用来检测进入区域事件的示例代码:

public class BeaconApplication extends android.app.Application implements BootstrapNotifier {

    private static final String TAG = "TAGTAG";
    
    @Override public void onCreate() {
        super.onCreate();
        Log.d(TAG, "App started up");
        new BackgroundPowerSaver(this);
        new RegionBootstrap(this, new Region(getPackageName(), null, null, null));
    }

    @Override public void didDetermineStateForRegion(int arg0, Region arg1) {
        Log.d(TAG, "didDetermineStateForRegion");
    }

    @Override public void didEnterRegion(Region arg0) {
        Log.d(TAG, "didEnterRegion");
    }

    @Override public void didExitRegion(Region arg0) {
        Log.d(TAG, "didExitRegion");
    }
}

问题在于,如果我使用以下 build.gradle 配置,那么一切都会像预期的那样工作

compileSdkVersion 21
    buildToolsVersion "21.0.0"
    defaultConfig {
        applicationId "com.test"
        minSdkVersion 18
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

LogCat:

D/TAGTAG: App started up

D/TAGTAG: didDetermineStateForRegion

D/TAGTAG: didEnterRegion

但如果我将 compileSdkVersion 更改为实际版本,则没有任何效果

compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
    applicationId "com.test"
    minSdkVersion 18
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

LogCat:

D/TAGTAG: App started up

从 Android 6.0 Marshmallow 开始,扫描蓝牙 LE 设备(包括信标)的应用程序必须先获得动态位置权限才能这样做。 对于遗留用途,该目标上的应用 运行 旧 Android SDK(在 API 23 之前)仍然允许扫描蓝牙 LE 设备,但仅限于前台。如果您以 SDK 21 而非 SDK 23 为目标,这就是您的应用程序运行的原因。

要在针对 SDK 23 时解决此问题,您只需添加动态权限请求即可。

  private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
  ...
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      ...
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {   
          // Android M Permission check    
          if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {        
              final AlertDialog.Builder builder = new AlertDialog.Builder(this);
              builder.setTitle("This app needs location access");
              builder.setMessage("Please grant location access so this app can detect beacons.");
              builder.setPositiveButton(android.R.string.ok, null);
              builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                      @Override?
                      public void onDismiss(DialogInterface dialog) {
                              requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);?            
                      }
              });
              builder.show();  
          }
      }   
  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                                             String permissions[], int[] grantResults) {
      switch (requestCode) {
          case PERMISSION_REQUEST_COARSE_LOCATION: {
              if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                  Log.d(TAG, "coarse location permission granted");
              } else {
                  final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                  builder.setTitle("Functionality limited");
                  builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
                  builder.setPositiveButton(android.R.string.ok, null);
                  builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                      @Override
                      public void onDismiss(DialogInterface dialog) {
                      }

                  });
                  builder.show();
              }
              return;
          }
      }
  }

此处提供了有关如何执行此操作的详细说明:https://altbeacon.github.io/android-beacon-library/requesting_permission.html

我在这里写了一篇关于这个主题的博客post:http://developer.radiusnetworks.com/2015/09/29/is-your-beacon-app-ready-for-android-6.html

编辑: 正如@Near1999 在下面的评论中指出的那样,一些 Android 5+ 版本也不会检测到 BLE 设备,除非在设置中打开定位服务。显然,此限制也仅适用于针对 SDK 23+ 的情况。有关详细信息,请参阅此处:https://github.com/AltBeacon/android-beacon-library/issues/301