Skip to content

Instantly share code, notes, and snippets.

@y-takagi
Created April 14, 2021 00:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save y-takagi/fe1b5aa36c9319c5cb006dcf6834001b to your computer and use it in GitHub Desktop.
Save y-takagi/fe1b5aa36c9319c5cb006dcf6834001b to your computer and use it in GitHub Desktop.
iBeacon Plugin for capacitor2.
package io.ionic.starter.plugins
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import com.getcapacitor.NativePlugin
import com.getcapacitor.Plugin
import com.getcapacitor.PluginCall
import com.getcapacitor.PluginMethod
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.altbeacon.beacon.*
@Serializable
data class BeaconDto(val id: String, val uuid: String, val major: Int, val minor: Int, val rssi: Int)
@Serializable
data class BeaconsDto(val data: List<BeaconDto>)
@NativePlugin(
permissions = [Manifest.permission.ACCESS_FINE_LOCATION],
permissionRequestCode = 1000
)
class BeaconPlugin : Plugin(), BeaconConsumer, MonitorNotifier, RangeNotifier {
private var beaconManager: BeaconManager? = null
override fun load() {
super.load()
beaconManager = BeaconManager.getInstanceForApplication(activity)
beaconManager?.also {
it.beaconParsers.clear()
it.beaconParsers.add(BeaconParser().apply { setBeaconLayout(iBEACON_FORMAT) })
it.bind(this)
}
}
override fun handleOnDestroy() {
super.handleOnDestroy()
beaconManager?.unbind(this)
}
override fun handleRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.handleRequestPermissionsResult(requestCode, permissions, grantResults)
val savedCall = savedCall ?: return
for (result in grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
savedCall.reject("User denied location permission")
return
}
}
savedCall.resolve()
savedCall.release(bridge)
}
override fun onBeaconServiceConnect() {
beaconManager?.removeAllMonitorNotifiers()
beaconManager?.removeAllRangeNotifiers()
beaconManager?.addMonitorNotifier(this)
beaconManager?.addRangeNotifier(this)
}
override fun getApplicationContext(): Context {
return activity
}
override fun unbindService(connection: ServiceConnection) {
activity.unbindService(connection)
}
override fun bindService(intent: Intent, connection: ServiceConnection, mode: Int): Boolean {
return activity.bindService(intent, connection, mode)
}
override fun didEnterRegion(region: Region) {
}
override fun didExitRegion(region: Region) {
}
override fun didDetermineStateForRegion(state: Int, region: Region) {
when (state) {
MonitorNotifier.INSIDE -> beaconManager?.startRangingBeaconsInRegion(region)
MonitorNotifier.OUTSIDE -> beaconManager?.stopRangingBeaconsInRegion(region)
}
}
override fun didRangeBeaconsInRegion(beacons: MutableCollection<Beacon>, region: Region) {
if (beacons.isEmpty()) {
return
}
val beaconsDto = BeaconsDto(beacons.map { BeaconDto(region.uniqueId, it.id1.toString(), it.id2.toInt(), it.id3.toInt(), it.rssi) })
val json = Json.encodeToString(beaconsDto)
bridge.triggerWindowJSEvent("didrangebeaconsinregion", json)
}
@PluginMethod
fun startMonitoring(call: PluginCall) {
val id = call.getString("id")
val uuid = call.getString("uuid")
val major = call.getInt("major")
val minor = call.getInt("minor")
try {
this.startMonitoring(id, uuid, major?.toString(), minor?.toString())
call.resolve()
} catch (e: Exception) {
call.reject("Fail to start beacon monitoring.", e)
}
}
@PluginMethod
fun stopMonitoring(call: PluginCall) {
val id = call.getString("id")
try {
this.stopMonitoring(id)
call.resolve()
} catch (e: Exception) {
call.reject("Fail to stop beacon monitoring.", e)
}
}
@PluginMethod
fun stopMonitoringAll(call: PluginCall) {
try {
this.stopMonitoringAll()
call.resolve()
} catch (e: Exception) {
call.reject("Fail to stop beacon monitoring.", e)
}
}
private fun startMonitoring(id: String, uuid: String? = null, major: String? = null, minor: String? = null) {
val region = Region(
id,
uuid?.let { Identifier.parse(it) },
major?.let { Identifier.parse(it) },
minor?.let { Identifier.parse(it) }
)
beaconManager?.startMonitoringBeaconsInRegion(region)
}
private fun stopMonitoring(id: String) {
val monitoredRegion = beaconManager?.monitoredRegions?.find { it.uniqueId == id }
if (monitoredRegion != null) {
beaconManager?.stopRangingBeaconsInRegion(monitoredRegion)
beaconManager?.stopMonitoringBeaconsInRegion(monitoredRegion)
}
}
private fun stopMonitoringAll() {
val monitoredRegions = beaconManager?.monitoredRegions
monitoredRegions?.forEach { this.stopMonitoring(it.uniqueId) }
}
companion object {
private const val iBEACON_FORMAT = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment