Altbeacon 库无法 find/trace 在设备附近传输信标

Altbeacon library not able to find/trace transmitting beacon near device

我正在使用 altbeacon 库进行接触者追踪。但是当我的设备靠近我的其他扫描 phone 时,我无法 find/trace。我基本上有两部手机,一部用于扫描,另一部用作信标发射器。我可以从我的 phone 号码 2 作为信标进行传输。我还在 Locate Beacon 应用程序中进行了测试。它显示了我的 phone。但是当我测试我的 phone 1 号时,它不起作用。即使正在调用我的 didDetermineStateForRegiononBeaconServiceConnect,我也无法在任何日志上看到任何信标。

下面是我的申请class:

package com.example.mybeaconprojectaye

import android.app.*
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseSettings
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.RemoteException
import android.util.Log
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.altbeacon.beacon.*
import org.altbeacon.beacon.startup.BootstrapNotifier
import org.altbeacon.beacon.startup.RegionBootstrap
import java.util.*

class MyApplication : Application(), BootstrapNotifier, BeaconConsumer {


    val CHANNEL_ID = "myproximityservice"
    val CHANNEL_NAME = "My Proximity Service Channel"
    val backgroundBetweenScanPeriod = 6200L
    val backgroundScanPeriod = 3000L
    val TAG: String = "xoxo"
    val REGIONID = "rangeid"


    val uuidString: String= "id1"

    lateinit var beaconManager: BeaconManager
    private var regionBootstrap: RegionBootstrap? = null


    override fun onCreate() {
        super.onCreate()

        beaconManager = BeaconManager.getInstanceForApplication(this)
        setupBeaconScanning()
        beaconManager.bind(this)
    }

    override fun onBeaconServiceConnect() {

        Log.e(TAG, "Service connected ")
        val rangeNotifier = RangeNotifier { beacons, region ->
            if (beacons.size > 0) {
                Log.e(TAG, "found new beacons  " + beacons.size)
                for (beacon: Beacon in beacons){
                    Log.e(TAG,"New Beacon before condition check=${beacon.id2}-${beacon.id3}-${beacon.id1}")

                    GlobalScope.launch {

                        try {
                            val deviceUUID: String = beacon.id1.toString()
                            Log.e(TAG, "  before condition check=${deviceUUID}")
                                Log.e(
                                    TAG,
                                    "New Beacon=${beacon.id2}/${beacon.id3}/${beacon.id1}"
                                )
                              Log.e("xoxo","${beacon.id2}/${beacon.id3}/${beacon.id1} + "+ beacon.distance.toLong())


                                if (beacon.distance.toInt() < 2) {
                                    /*  val intentNotification = Intent(this@BeaconApp, HomeActivity::class.java)
                                  intentNotification.putExtra(Constants.DeviceConstants.IS_VIBRATOR, true)

                                  intentNotification.flags =
                                      Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

                                  startActivity(intentNotification)*/



                                    //sendSafetyNotification()



                            }
                        }catch (ex: Exception){

                            Log.e(TAG, "  EXCEPTION: "+ex.toString())

                        }

                    }
                }
                //  sendBroadcast(Intent(NEW_DEVICE_ACTION))
            }
        }
        try {
            beaconManager.startRangingBeaconsInRegion(
                Region(
                    REGIONID,
                    null,
                    null,
                    null
                )
            )
            beaconManager.addRangeNotifier(rangeNotifier)
        } catch (e: RemoteException) {
            e.printStackTrace()
        }

    }

    override fun didDetermineStateForRegion(state: Int, p1: Region?) {

        Log.e("xoxo", "didDetermineStateForRegion state: "+state )

    }

    override fun didEnterRegion(p0: Region?) {

        Log.e("xoxo", "i just saw a beacon")


    }

    override fun didExitRegion(p0: Region?) {
    }


    fun setupBeaconScanning() {
        beaconManager.beaconParsers.clear()

        val altbeaconParser =
            BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25")
        altbeaconParser.setHardwareAssistManufacturerCodes(intArrayOf(0x0118))
        beaconManager.beaconParsers
            .add(altbeaconParser)

        val iBeaconParser =
            BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")
        iBeaconParser.setHardwareAssistManufacturerCodes(intArrayOf(0x004c))

        beaconManager.beaconParsers
            .add(iBeaconParser)
        beaconManager.beaconParsers
            .add(BeaconParser().setBeaconLayout(BeaconParser.URI_BEACON_LAYOUT))
        beaconManager.beaconParsers
            .add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT))
        beaconManager.beaconParsers
            .add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
        beaconManager.beaconParsers
            .add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT))


        /* beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("x,s:0-1=feaa,m:2-2=20,d:3-3,d:4-5,d:6-7,d:8-11,d:12-15"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("s:0-1=feaa,m:2-2=10,p:3-3:-41,i:4-20v"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"))
         beaconManager.beaconParsers
             .add(BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"))


 */
        BeaconManager.setDebug(false)


        val builder = Notification.Builder(this)
        builder.setSmallIcon(R.drawable.ic_launcher_background)
        builder.setContentTitle("Proximity Service Running")
        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
        )
        builder.setContentIntent(pendingIntent)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT
            )
            channel.description = "Used for scanning near by device"
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE
            ) as NotificationManager
            notificationManager.createNotificationChannel(channel)
            builder.setChannelId(channel.id)
        }
        beaconManager.enableForegroundServiceScanning(builder.build(), 456)

        // For the above foreground scanning service to be useful, you need to disable
        // JobScheduler-based scans (used on Android 8+) and set a fast background scan
        // cycle that would otherwise be disallowed by the operating system.


        beaconManager.setEnableScheduledScanJobs(false)
        beaconManager.backgroundBetweenScanPeriod = backgroundBetweenScanPeriod
        beaconManager.backgroundScanPeriod = backgroundScanPeriod

        Log.d(TAG, "setting up background monitoring for beacons and power saving")
        // wake up the app when a beacon is seen
        // wake up the app when a beacon is seentitle getting
        val region = Region(
            REGIONID,
            null, null, null
        )
        regionBootstrap = RegionBootstrap(this, region)
    }


    fun startAdvertising(listener: AdvertiseListener):Boolean {

        val result = BeaconTransmitter.checkTransmissionSupported(this)
        Log.e("xoxo", "BLE TRANSMITTER STATUS " +(result== BeaconTransmitter.SUPPORTED).toString())
        if (BeaconTransmitter.SUPPORTED != result)
            return false
        val beacon = Beacon.Builder()
            .setId1("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6")
            .setId2("1")
            .setId3("2")
            .setManufacturer(0x0118) // Radius Networks.  Change this for other beacon layouts
            .setTxPower(-59)
            .setDataFields(Arrays.asList(*arrayOf(0L))) // Remove this for beacon layouts without d: fields
            .build()


        // Change the layout below for other beacon types
        val beaconParser = BeaconParser()
            .setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25")
        val beaconTransmitter =
            BeaconTransmitter(applicationContext, beaconParser)
        beaconTransmitter.startAdvertising(beacon, object : AdvertiseCallback() {
            override fun onStartFailure(errorCode: Int) {
                Log.e(TAG, "Advertisement start failed with code: $errorCode")
                listener.onAdvertiseStatus(false)
            }

            override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
                Log.e(TAG, "Advertisement start succeeded. uuid"+uuidString)
                listener.onAdvertiseStatus(true)

            }
        })
        return true
    }


    interface AdvertiseListener{
        fun onAdvertiseStatus(success:Boolean)
    }

}

和我的 MainActivity:

package com.example.mybeaconprojectaye

import android.Manifest
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
import org.altbeacon.beacon.BeaconTransmitter

class MainActivity : AppCompatActivity() {

    companion object {
        private const val PERMISSION_REQUEST_FINE_LOCATION = 1
        private const val PERMISSION_REQUEST_BACKGROUND_LOCATION = 2
    }

    val TAG = "xoxo"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var result : Int = BeaconTransmitter.checkTransmissionSupported(this@MainActivity)

        Log.e("xoxo", "result: "+result)



        btn.setOnClickListener(object : View.OnClickListener {
            override fun onClick(v: View?) {

                requestPerms()


            }
        })

    }


    fun requestPerms() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    if (checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                        != PackageManager.PERMISSION_GRANTED
                    ) {
                        val builder =
                            AlertDialog.Builder(this)
                        builder.setTitle("Location is off")
                        builder.setMessage("Please allow location permission.")
                        builder.setPositiveButton(android.R.string.ok, null)
                        builder.setOnDismissListener {
                            requestPermissions(
                                arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                                PERMISSION_REQUEST_BACKGROUND_LOCATION
                            )
                        }
                        builder.show()
                    } else startAdvertiseBeacons()

                } else startAdvertiseBeacons()
            } else {
                requestPermissions(
                    arrayOf(
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_BACKGROUND_LOCATION
                    ),
                    PERMISSION_REQUEST_FINE_LOCATION
                )
            }
        } else startAdvertiseBeacons()
    }


    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
            PERMISSION_REQUEST_FINE_LOCATION -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "fine location permission granted")
                    requestPerms()
                } else {
                    val builder =
                        AlertDialog.Builder(this)
                    builder.setTitle("Functionality limited")
                    builder.setMessage("Since location access has not been granted, this app will not be able to discover devices.")
                    builder.setPositiveButton(android.R.string.ok, null)
                    builder.setOnDismissListener { }
                    builder.show()
                }
                return
            }
            PERMISSION_REQUEST_BACKGROUND_LOCATION -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "background location permission granted")
                    requestPerms()
                } else {
                    val builder =
                        AlertDialog.Builder(this)
                    builder.setTitle("Functionality limited")
                    builder.setMessage("Since background location access has not been granted, this app will not be able to discover devices when in the background.")
                    builder.setPositiveButton(
                        android.R.string.ok,
                        DialogInterface.OnClickListener { dialog, which ->
                            dialog.cancel()
                            requestPerms()
                        })
                    builder.setOnDismissListener {
                        requestPerms()
                    }
                    builder.show()
                }
                return
            }
        }
    }

    private fun startAdvertiseBeacons() {
        (application as MyApplication).startAdvertising(object : MyApplication.AdvertiseListener {
            override fun onAdvertiseStatus(success: Boolean) {

            }
        })
    }

}

下面是正在打印的所有日志:

2020-06-07 05:20:25.566 23822-23822/? E/libc: Access denied finding property "persist.vendor.sys.activitylog"
2020-06-07 05:20:26.468 23822-23822/com.example.mybeaconprojectaye E/xoxo: result: 0
2020-06-07 05:20:26.810 23822-23822/com.example.mybeaconprojectaye E/xoxo: Service connected 
2020-06-07 05:20:26.848 23822-23822/com.example.mybeaconprojectaye E/xoxo: didDetermineStateForRegion state: 0

任何人都可以告诉我我做错了什么或者是否缺少某些步骤。我尝试查看有关 Whosebug 的其他答案,但这是我在所有答案中随处看到新 classes 和接口的唯一库。太多的混乱。

P.S.

我正在尝试制作接触者追踪应用程序。任何其他图书馆或您可以建议的东西也将不胜感激。

尝试颠倒 phones 1 和 2 进行测试。如果你用BeaconScope扫描,它能看到phones 1&2的传输吗?如果您使用 BeaconScope 进行传输,您在 phone 1 或 2 上的应用能否看到信标传输?

如果您无法在一个或两个 phone 上检测到信标范围,请检查应用权限以确认您的应用已获得位置权限。转到设置 -> 应用程序 -> 您的应用程序并检查授予的权限。

还要检查 phone 上是否已全局启用位置信息并且蓝牙是否已打开。