简体   繁体   English

Android 12 - 信标扫描......最奇怪的事情

[英]Android 12 - Beacon scanning... weirdest thing

Ok so here is my situation:好的,这是我的情况:

I have my app installed.我安装了我的应用程序。 It is now targeting Android 12. I also have Kontakt.io Android sample app installed.它现在的目标是 Android 12。我还安装了 Kontakt.io Android 示例应用程序。

When I use Kontakt.io's sample app to scan for beacons, it works.当我使用 Kontakt.io 的示例应用程序扫描信标时,它可以正常工作。 Among other devices, I can see my beacons appear in the list and logs.在其他设备中,我可以看到我的信标出现在列表和日志中。

When I use the same exact code (from their sample app) in my app with exactly the same configuration and exactly the same permission scheme I am unable to scan my beacons.当我在我的应用程序中使用完全相同的代码(来自他们的示例应用程序)时,具有完全相同的配置和完全相同的权限方案,我无法扫描我的信标。 I can see in Logcat there are a lot of other devices that are being scanned and reported but none of my beacons are scanned.我可以在 Logcat 中看到有很多其他设备正在被扫描和报告,但我的信标都没有被扫描。

Then - and here is the weird thing - while my app is in the background, I switch back to Kontakt.io sample app and initiate a new scan.然后 - 奇怪的是 - 当我的应用程序在后台时,我切换回 Kontakt.io 示例应用程序并启动新的扫描。 The second I start that scan, MY app suddenly starts seeing my beacons and I can see them in the logs.在我开始扫描的那一刻,我的应用程序突然开始看到我的信标,我可以在日志中看到它们。 If I shut down that Kontakt.io sample app scan, I can still see the beacons appear in my app's scan.如果我关闭 Kontakt.io 示例应用程序扫描,我仍然可以看到信标出现在我的应用程序扫描中。 If I kill both apps and try to scan again in my app alone, again, I cannot see my beacons any more.如果我关闭这两个应用程序并尝试单独在我的应用程序中再次扫描,我再也看不到我的信标了。

I've been struggling with this for days now and it simply does not make any sense.几天来我一直在为此苦苦挣扎,它根本没有任何意义。 I'll add here that if I do not target API 31 (Android 12) everything is perfect.我要在这里补充一点,如果我不以 API 31 (Android 12) 为目标,一切都是完美的。 As it's been for the past few years.就像过去几年一样。

Please?请? Any ideas?有任何想法吗?

EDIT1: adding some source code EDIT1:添加一些源代码

The code is identical to the one in Kontakt.io's sample app.该代码与 Kontakt.io 示例应用程序中的代码相同。 It is a simple copy paste:这是一个简单的复制粘贴:

In an activity, on a button click I call checkPermissions() :在一个活动中,点击一个按钮我调用checkPermissions()

private void checkPermissions() {
        String[] requiredPermissions = Build.VERSION.SDK_INT < Build.VERSION_CODES.S
                ? new String[]{Manifest.permission.ACCESS_FINE_LOCATION}
                : new String[]{ Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION };
        if(isAnyOfPermissionsNotGranted(requiredPermissions)) {
            ActivityCompat.requestPermissions(getScreen().getHostingActivity(), requiredPermissions, 100);
        } else {
            setupProximityManager();
            setupSpaces();
        }
    }

private void setupProximityManager() {
    proximityManager = ProximityManagerFactory.create(this);

    //Configure proximity manager basic options
    proximityManager.configuration()
        //Using ranging for continuous scanning or MONITORING for scanning with intervals
        .scanPeriod(ScanPeriod.RANGING)
        //Using BALANCED for best performance/battery ratio
        .scanMode(ScanMode.BALANCED)
        //OnDeviceUpdate callback will be received with 5 seconds interval
        .deviceUpdateCallbackInterval(TimeUnit.SECONDS.toMillis(5));

    //Setting up iBeacon and Eddystone listeners
    proximityManager.setIBeaconListener(createIBeaconListener());
    proximityManager.setEddystoneListener(createEddystoneListener());
  }
private void setupSpaces() {
        //Setting up single iBeacon region. Put your own desired values here.
        IBeaconRegion region = new BeaconRegion.Builder().identifier("My Region") //Region identifier is mandatory.
                .proximity(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e")) //Default Kontakt.io proximity.
                //Optional major and minor values
                //.major(1)
                //.minor(1)
                .build();

        proximityManager.spaces().iBeaconRegion(region)
                .forceResolveRegions(Collections.singleton(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e")));

        //Setting up single Eddystone namespace. Put your own desired values here.
        IEddystoneNamespace namespace = new EddystoneNamespace.Builder().identifier("My Namespace") //Namespace identifier is mandatory.
                .namespace("f7826da64fa24e988024") //Default Kontakt.io namespace.
                //Optional instance id value
                //.instanceId("instanceId")
                .build();
        proximityManager.spaces().eddystoneNamespace(namespace).forceResolveNamespaces(Collections.singletonList("f7826da64fa24e988024"));
    }

On a different button click I call:在不同的按钮上单击我调用:

private void startScanning() {
        //Connect to scanning service and start scanning when ready
        proximityManager.connect(new OnServiceReadyListener() {
            @Override
            public void onServiceReady() {
                //Check if proximity manager is already scanning
                if (proximityManager.isScanning()) {
                    Toast.makeText(((Application)Application.getContextFromApplicationClass()).getActivityContext(), "Already scanning", Toast.LENGTH_SHORT).show();
                    return;
                }
                proximityManager.startScanning();
//                progressBar.setVisibility(View.VISIBLE);
                Toast.makeText(((Application)Application.getContextFromApplicationClass()).getActivityContext(), "Scanning started", Toast.LENGTH_SHORT).show();
            }
        });
    }

androidmanifest.xml contains the needed permissions (copied from the sample app): androidmanifest.xml 包含所需的权限(从示例应用程序复制):

<uses-permission android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

I already have a foreground service in my app if it makes any difference.如果有什么不同的话,我的应用程序中已经有前台服务了。

I also declared as instructed another service that is used by the Kontakt SDK:我还按照指示声明了 Kontakt SDK 使用的另一项服务:

<service
            android:name="com.kontakt.sdk.android.ble.service.ProximityService"
            android:exported="false" />

All the runtime permissions are requested in the same manner they are requested in the Kontakt.io sample app and the actual permissionCheck passes.所有运行时权限的请求方式与在 Kontakt.io 示例应用程序中请求的方式相同,并且实际的 permissionCheck 通过。

Ok... so I found the cause.好的...所以我找到了原因。 For years our app used 2 libraries: RxBleClient for scanning and AltBeacon for parsing the result.多年来,我们的应用程序使用了 2 个库:用于扫描的 RxBleClient 和用于解析结果的 AltBeacon。 Not entirely sure why use 2 libs but that was the case.不完全确定为什么使用 2 个库,但事实就是如此。 When we targeted API 12, I assume both libs overwrote some of the androidmanifest.xml permission declarations during merge in some manner.当我们以 API 12 为目标时,我假设这两个库在合并期间以某种方式覆盖了一些 androidmanifest.xml 权限声明。 I did not dive deep into the actual cause, but this seems to be the issue.我没有深入研究实际原因,但这似乎是问题所在。 At any rate, to resolve the issue, we removed ALL libs that relate to beacon scanning and put a single one.无论如何,为了解决这个问题,我们删除了所有与信标扫描相关的库并放了一个。 Currently we picked Kontakt.io SDK. Scanning is working now perfectly.目前我们选择了 Kontakt.io SDK。现在扫描工作正常。 This also explains why on their own, each sample app from each library was working as expected.这也解释了为什么每个库中的每个示例应用程序都按预期工作。 But when you combine more than 1 lib and target api 31, they seem to interfere with each other and the "delicate" permissions required for BLE scanning in android. This problem took me waaaay to long to solve.但是,当您将超过 1 个库和目标 api 31 组合在一起时,它们似乎会相互干扰,并且会干扰 android 中 BLE 扫描所需的“微妙”权限。这个问题花了我很长时间才解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM