/*
LinkingBeaconManager.java
Copyright (c) 2016 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.linking.beacon;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.deviceconnect.android.deviceplugin.linking.BuildConfig;
import org.deviceconnect.android.deviceplugin.linking.R;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.AtmosphericPressureData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.BatteryData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.ButtonData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.GattData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.HumidityData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.LinkingBeacon;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.RawData;
import org.deviceconnect.android.deviceplugin.linking.beacon.data.TemperatureData;
import org.deviceconnect.android.deviceplugin.linking.util.PreferenceUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class LinkingBeaconManager {
private static final String TAG = "LinkingPlugIn";
private static final int INTERVAL = 20 * 1000;
private Context mContext;
private LinkingBeaconUtil.ScanState mScanState;
private LinkingBeaconUtil.ScanDetail mScanDetail;
private LinkingBeaconUtil.ScanMode mScanMode;
private ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture mScheduledFuture;
private final List<LinkingBeacon> mLinkingBeacons = Collections.synchronizedList(new ArrayList<LinkingBeacon>());
private final List<OnBeaconConnectListener> mOnBeaconConnectListeners = Collections.synchronizedList(new ArrayList<OnBeaconConnectListener>());
private final List<OnBeaconEventListener> mOnBeaconEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconEventListener>());
private final List<OnBeaconButtonEventListener> mOnBeaconButtonEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconButtonEventListener>());
private final List<OnBeaconProximityEventListener> mOnBeaconProximityEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconProximityEventListener>());
private final List<OnBeaconBatteryEventListener> mOnBeaconBatteryEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconBatteryEventListener>());
private final List<OnBeaconAtmosphericPressureEventListener> mOnBeaconAtmosphericPressureEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconAtmosphericPressureEventListener>());
private final List<OnBeaconHumidityEventListener> mOnBeaconHumidityEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconHumidityEventListener>());
private final List<OnBeaconTemperatureEventListener> mOnBeaconTemperatureEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconTemperatureEventListener>());
private final List<OnBeaconRawDataEventListener> mOnBeaconRawDataEventListeners = Collections.synchronizedList(new ArrayList<OnBeaconRawDataEventListener>());
private final List<OnBeaconScanStateListener> mOnBeaconScanStateListeners = Collections.synchronizedList(new ArrayList<OnBeaconScanStateListener>());
private LinkingDBAdapter mDBAdapter;
private TimeoutRunnable mTimeoutRunnable;
private boolean mScanFlag;
public LinkingBeaconManager(final Context context) {
mContext = context;
mDBAdapter = new LinkingDBAdapter(context);
mLinkingBeacons.addAll(mDBAdapter.queryBeacons());
mScanMode = LinkingBeaconUtil.ScanMode.valueOf(PreferenceUtil.getInstance(mContext).getBeaconScanMode());
boolean scan = isStartedForceBeaconScan();
if (scan) {
stopForceBeaconScan();
}
startCheckConnectionOfBeacon();
}
public boolean isScanState() {
return isStartedForceBeaconScan() || isStartedBeaconScan();
}
public void destroy() {
stopBeaconScan();
stopCheckConnectionOfBeacon();
mScheduledExecutorService.shutdown();
mOnBeaconEventListeners.clear();
mOnBeaconConnectListeners.clear();
mOnBeaconButtonEventListeners.clear();
mOnBeaconProximityEventListeners.clear();
mOnBeaconBatteryEventListeners.clear();
mOnBeaconAtmosphericPressureEventListeners.clear();
mOnBeaconHumidityEventListeners.clear();
mOnBeaconTemperatureEventListeners.clear();
mOnBeaconRawDataEventListeners.clear();
}
public Context getContext() {
return mContext;
}
public List<LinkingBeacon> getLinkingBeacons() {
return mLinkingBeacons;
}
public void startForceBeaconScan() {
startBeaconScanInternal(null);
PreferenceUtil.getInstance(mContext).setForceBeaconScanStatus(true);
}
public void stopForceBeaconScan() {
PreferenceUtil.getInstance(mContext).setForceBeaconScanStatus(false);
if (BuildConfig.DEBUG) {
Log.d(TAG, "stopForceBeaconScan: " + isStartedBeaconScan());
}
if (!isStartedBeaconScan()) {
stopBeaconScanInternal();
}
}
public boolean isStartedForceBeaconScan() {
return PreferenceUtil.getInstance(mContext).getForceBeaconScanStatus();
}
public synchronized void startBeaconScanWithTimeout(final int timeout) {
if (isStartedBeaconScan()) {
return;
}
if (BuildConfig.DEBUG) {
Log.d(TAG, "startBeaconScanWithTimeout");
}
if (mTimeoutRunnable != null) {
mTimeoutRunnable.cancel();
}
mTimeoutRunnable = new TimeoutRunnable(timeout) {
@Override
public void onTimeout() {
if (BuildConfig.DEBUG) {
Log.d(TAG, "startBeaconScanWithTimeout:onTimeout");
}
if (!isStartedBeaconScan()) {
stopBeaconScan();
}
}
};
startBeaconScanInternal(LinkingBeaconUtil.ScanMode.HIGH);
}
public void startBeaconScan() {
startBeaconScan(null);
}
public synchronized void startBeaconScan(final LinkingBeaconUtil.ScanMode scanMode) {
mScanMode = scanMode;
startBeaconScanInternal(scanMode);
mScanFlag = true;
if (scanMode != null) {
PreferenceUtil.getInstance(mContext).setBeaconScanMode(mScanMode.getValue());
}
}
public synchronized void stopBeaconScan() {
mScanFlag = false;
if (!isStartedForceBeaconScan()) {
stopBeaconScanInternal();
}
}
public synchronized boolean isStartedBeaconScan() {
return mScanFlag;
}
public LinkingBeacon findBeacon(final int extraId, final int vendorId) {
synchronized (mLinkingBeacons) {
for (LinkingBeacon beacon : mLinkingBeacons) {
if (beacon.getExtraId() == extraId &&
beacon.getVendorId() == vendorId) {
return beacon;
}
}
}
return null;
}
public void removeBeacon(final LinkingBeacon beacon) {
if (beacon != null) {
mLinkingBeacons.remove(beacon);
mDBAdapter.delete(beacon);
}
}
public void removeAllBeacons() {
mLinkingBeacons.clear();
mDBAdapter.deleteAll();
}
public void onReceivedBeacon(final Intent intent) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "@@ LinkingBeaconManager#onReceivedBeacon");
Log.i(TAG, "intent=" + intent);
}
if (intent == null) {
return;
}
String action = intent.getAction();
if (LinkingBeaconUtil.ACTION_BEACON_SCAN_RESULT.equals(action)) {
parseBeaconResult(intent);
} else if (LinkingBeaconUtil.ACTION_BEACON_SCAN_STATE.equals(action)) {
parseBeaconScanState(intent);
}
}
public void addOnBeaconConnectListener(final OnBeaconConnectListener listener) {
mOnBeaconConnectListeners.add(listener);
}
public void removeOnBeaconConnectListener(final OnBeaconConnectListener listener) {
mOnBeaconConnectListeners.remove(listener);
}
public void addOnBeaconEventListener(final OnBeaconEventListener listener) {
mOnBeaconEventListeners.add(listener);
}
public void removeOnBeaconEventListener(final OnBeaconEventListener listener) {
mOnBeaconEventListeners.remove(listener);
}
public void addOnBeaconButtonEventListener(final OnBeaconButtonEventListener listener) {
mOnBeaconButtonEventListeners.add(listener);
}
public void removeOnBeaconButtonEventListener(final OnBeaconButtonEventListener listener) {
mOnBeaconButtonEventListeners.remove(listener);
}
public void addOnBeaconProximityEventListener(final OnBeaconProximityEventListener listener) {
mOnBeaconProximityEventListeners.add(listener);
}
public void removeOnBeaconProximityEventListener(final OnBeaconProximityEventListener listener) {
mOnBeaconProximityEventListeners.remove(listener);
}
public void addOnBeaconBatteryEventListener(final OnBeaconBatteryEventListener listener) {
mOnBeaconBatteryEventListeners.add(listener);
}
public void removeOnBeaconBatteryEventListener(final OnBeaconBatteryEventListener listener) {
mOnBeaconBatteryEventListeners.remove(listener);
}
public void addOnBeaconAtmosphericPressureEventListener(final OnBeaconAtmosphericPressureEventListener listener) {
mOnBeaconAtmosphericPressureEventListeners.add(listener);
}
public void removeOnBeaconAtmosphericPressureEventListener(final OnBeaconAtmosphericPressureEventListener listener) {
mOnBeaconAtmosphericPressureEventListeners.remove(listener);
}
public void addOnBeaconHumidityEventListener(final OnBeaconHumidityEventListener listener) {
mOnBeaconHumidityEventListeners.add(listener);
}
public void removeOnBeaconHumidityEventListener(final OnBeaconHumidityEventListener listener) {
mOnBeaconHumidityEventListeners.remove(listener);
}
public void addOnBeaconTemperatureEventListener(final OnBeaconTemperatureEventListener listener) {
mOnBeaconTemperatureEventListeners.add(listener);
}
public void removeOnBeaconTemperatureEventListener(final OnBeaconTemperatureEventListener listener) {
mOnBeaconTemperatureEventListeners.remove(listener);
}
public void addOnBeaconRawDataEventListener(final OnBeaconRawDataEventListener listener) {
mOnBeaconRawDataEventListeners.add(listener);
}
public void removeOnBeaconRawDataEventListener(final OnBeaconRawDataEventListener listener) {
mOnBeaconRawDataEventListeners.remove(listener);
}
public void addOnBeaconScanStateListener(final OnBeaconScanStateListener listener) {
mOnBeaconScanStateListeners.add(listener);
}
public void removeOnBeaconScanStateListener(final OnBeaconScanStateListener listener) {
mOnBeaconScanStateListeners.remove(listener);
}
private void startBeaconScanInternal(final LinkingBeaconUtil.ScanMode scanMode) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "LinkingBeaconManager#startBeaconScan");
}
Intent intent = new Intent();
intent.setClassName(LinkingBeaconUtil.LINKING_PACKAGE_NAME, LinkingBeaconUtil.BEACON_SERVICE_NAME);
intent.setAction(mContext.getPackageName() + LinkingBeaconUtil.ACTION_START_BEACON_SCAN);
// intent.putExtra(mContext.getPackageName() + LinkingBeaconUtil.EXTRA_SERVICE_ID, new int[] {0, 1, 2, 3, 4, 5, 15});
if (scanMode != null) {
intent.putExtra(mContext.getPackageName() + LinkingBeaconUtil.EXTRA_SCAN_MODE, scanMode.getValue());
}
mContext.startService(intent);
}
private void stopBeaconScanInternal() {
if (BuildConfig.DEBUG) {
Log.i(TAG, "LinkingBeaconManager#stopBeaconScan");
}
Intent intent = new Intent();
intent.setClassName(LinkingBeaconUtil.LINKING_PACKAGE_NAME, LinkingBeaconUtil.BEACON_SERVICE_NAME);
intent.setAction(mContext.getPackageName() + LinkingBeaconUtil.ACTION_STOP_BEACON_SCAN);
mContext.startService(intent);
}
private void parseBeaconScanState(final Intent intent) {
mScanState = LinkingBeaconUtil.ScanState.valueOf(intent.getIntExtra(LinkingBeaconUtil.SCAN_STATE, 0));
mScanDetail = LinkingBeaconUtil.ScanDetail.valueOf(intent.getIntExtra(LinkingBeaconUtil.DETAIL, 0));
if (mScanState == LinkingBeaconUtil.ScanState.RESULT_NG) {
switch (mScanDetail) {
case DETAIL_TIMEOUT:
if (BuildConfig.DEBUG) {
Log.d(TAG, "@@ Restart the beacon scan.");
}
stopBeaconScan();
stopForceBeaconScan();
break;
case DETAIL_META_DATA_NONE:
if (BuildConfig.DEBUG) {
Log.w(TAG, "@@ meta data is not defined.");
}
break;
default:
if (BuildConfig.DEBUG) {
Log.e(TAG, "Unknown detail. detail=" + mScanDetail);
}
break;
}
}
if (BuildConfig.DEBUG) {
Log.d(TAG, "mScanState: " + mScanState);
Log.d(TAG, "mScanDetail: " + mScanDetail);
}
for (OnBeaconScanStateListener listener : mOnBeaconScanStateListeners) {
listener.onScanState(mScanState, mScanDetail);
}
}
private void parseBeaconResult(final Intent intent) {
if (intent.getExtras() == null) {
if (BuildConfig.DEBUG) {
Log.w(TAG, "extras is null.");
}
return;
}
if (!intent.getExtras().containsKey(LinkingBeaconUtil.EXTRA_ID) ||
!intent.getExtras().containsKey(LinkingBeaconUtil.VENDOR_ID) ||
!intent.getExtras().containsKey(LinkingBeaconUtil.VERSION)) {
if (BuildConfig.DEBUG) {
Log.w(TAG, "extraId, vendorId, version is null.");
}
return;
}
int extraId = intent.getIntExtra(LinkingBeaconUtil.EXTRA_ID, -1);
int vendorId = intent.getIntExtra(LinkingBeaconUtil.VENDOR_ID, -1);
int version = intent.getIntExtra(LinkingBeaconUtil.VERSION, -1);
LinkingBeacon beacon = findBeacon(extraId, vendorId);
if (beacon == null) {
beacon = new LinkingBeacon();
beacon.setExtraId(extraId);
beacon.setVendorId(vendorId);
beacon.setVersion(version);
beacon.setDisplayName(mContext.getString(R.string.linking_beacon_display_name, extraId));
mLinkingBeacons.add(beacon);
if (!mDBAdapter.insertBeacon(beacon)) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Failed to insert LinkingBeacon.");
}
}
}
parseGattData(intent, beacon);
parseBatteryData(intent, beacon);
parseAtmosphericPressureData(intent, beacon);
parseHumidityData(intent, beacon);
parseTemperatureData(intent, beacon);
parseRawData(intent, beacon);
parseButtonId(intent, beacon);
if (!beacon.isOnline()) {
beacon.setOnline(true);
notifyBeaconConnectionListener(beacon);
}
if (beacon.isOnline()) {
notifyBeaconEventListener(beacon);
}
}
private void parseGattData(final Intent intent, final LinkingBeacon beacon) {
GattData gatt = beacon.getGattData();
if (gatt == null) {
gatt = new GattData();
beacon.setGattData(gatt);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
int rssi = intent.getIntExtra(LinkingBeaconUtil.RSSI, 0);
int txPower = intent.getIntExtra(LinkingBeaconUtil.TX_POWER, 0);
int distance = intent.getIntExtra(LinkingBeaconUtil.DISTANCE, -1);
gatt.setTimeStamp(timeStamp);
gatt.setRssi(rssi);
gatt.setTxPower(txPower);
gatt.setDistance(distance);
mDBAdapter.insertGatt(beacon, gatt);
notifyBeaconProximityEventListener(beacon, gatt);
}
private void parseAtmosphericPressureData(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.ATMOSPHERIC_PRESSURE)) {
AtmosphericPressureData atm = beacon.getAtmosphericPressureData();
if (atm == null) {
atm = new AtmosphericPressureData();
beacon.setAtmosphericPressureData(atm);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
float value = intent.getFloatExtra(LinkingBeaconUtil.ATMOSPHERIC_PRESSURE, 0);
atm.setTimeStamp(timeStamp);
atm.setValue(value);
mDBAdapter.insertAtmosphericPressure(beacon, atm);
notifyBeaconAtmosphericPressureEventListener(beacon, atm);
}
}
private void parseBatteryData(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.LOW_BATTERY) ||
intent.getExtras().containsKey(LinkingBeaconUtil.BATTERY_LEVEL)) {
BatteryData battery = beacon.getBatteryData();
if (battery == null) {
battery = new BatteryData();
beacon.setBatteryData(battery);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
boolean lowBattery = intent.getBooleanExtra(LinkingBeaconUtil.LOW_BATTERY, false);
float level = intent.getFloatExtra(LinkingBeaconUtil.BATTERY_LEVEL, 0);
battery.setTimeStamp(timeStamp);
battery.setLowBatteryFlag(lowBattery);
battery.setLevel(level);
mDBAdapter.insertBattery(beacon, battery);
notifyBeaconBatteryEventListener(beacon, battery);
}
}
private void parseHumidityData(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.HUMIDITY)) {
HumidityData humidity = beacon.getHumidityData();
if (humidity == null) {
humidity = new HumidityData();
beacon.setHumidityData(humidity);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
float value = intent.getFloatExtra(LinkingBeaconUtil.HUMIDITY, 0);
humidity.setTimeStamp(timeStamp);
humidity.setValue(value);
mDBAdapter.insertHumidity(beacon, humidity);
notifyBeaconHumidityEventListener(beacon, humidity);
}
}
private void parseTemperatureData(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.TEMPERATURE)) {
TemperatureData temp = beacon.getTemperatureData();
if (temp == null) {
temp = new TemperatureData();
beacon.setTemperatureData(temp);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
float value = intent.getFloatExtra(LinkingBeaconUtil.TEMPERATURE, 0);
temp.setTimeStamp(timeStamp);
temp.setValue(value);
mDBAdapter.insertTemperature(beacon, temp);
notifyBeaconTemperatureEventListener(beacon, temp);
}
}
private void parseRawData(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.RAW_DATA)) {
RawData raw = beacon.getRawData();
if (raw == null) {
raw = new RawData();
beacon.setRawData(raw);
}
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
int value = intent.getIntExtra(LinkingBeaconUtil.RAW_DATA, 0);
raw.setTimeStamp(timeStamp);
raw.setValue(value);
mDBAdapter.insertRawData(beacon, raw);
notifyBeaconRawDataEventListener(beacon, raw);
}
}
private void parseButtonId(final Intent intent, final LinkingBeacon beacon) {
if (intent.getExtras().containsKey(LinkingBeaconUtil.BUTTON_ID)) {
long timeStamp = intent.getLongExtra(LinkingBeaconUtil.TIME_STAMP, 0);
int keyCode = intent.getIntExtra(LinkingBeaconUtil.BUTTON_ID, -1);
ButtonData button = beacon.getButtonData();
if (button == null) {
button = new ButtonData();
beacon.setButtonData(button);
}
button.setTimeStamp(timeStamp);
button.setKeyCode(keyCode);
notifyBeaconButtonEventListener(beacon, timeStamp, keyCode);
}
}
private synchronized void startCheckConnectionOfBeacon() {
if (mScheduledFuture == null) {
mScheduledFuture = mScheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
checkConnectionOfBeacon();
}
}, INTERVAL / 2, INTERVAL / 2, TimeUnit.MILLISECONDS);
}
}
private synchronized void stopCheckConnectionOfBeacon() {
if (mScheduledFuture != null) {
mScheduledFuture.cancel(true);
mScheduledFuture = null;
}
}
private void checkConnectionOfBeacon() {
if (BuildConfig.DEBUG) {
Log.i(TAG, "LinkingBeaconManager#checkConnectionOfBeacon");
}
synchronized (mLinkingBeacons) {
long now = System.currentTimeMillis();
for (LinkingBeacon beacon : mLinkingBeacons) {
if (beacon.isOnline()) {
if (now - beacon.getTimeStamp() > INTERVAL) {
beacon.setOnline(false);
notifyBeaconConnectionListener(beacon);
}
}
}
}
}
private void notifyBeaconAtmosphericPressureEventListener(final LinkingBeacon beacon, final AtmosphericPressureData atm) {
synchronized (mOnBeaconAtmosphericPressureEventListeners) {
for (OnBeaconAtmosphericPressureEventListener listener : mOnBeaconAtmosphericPressureEventListeners) {
listener.onAtmosphericPressure(beacon, atm);
}
}
}
private void notifyBeaconBatteryEventListener(final LinkingBeacon beacon, final BatteryData battery) {
synchronized (mOnBeaconBatteryEventListeners) {
for (OnBeaconBatteryEventListener listener : mOnBeaconBatteryEventListeners) {
listener.onBattery(beacon, battery);
}
}
}
private void notifyBeaconTemperatureEventListener(final LinkingBeacon beacon, final TemperatureData temp) {
synchronized (mOnBeaconTemperatureEventListeners) {
for (OnBeaconTemperatureEventListener listener : mOnBeaconTemperatureEventListeners) {
listener.onTemperature(beacon, temp);
}
}
}
private void notifyBeaconHumidityEventListener(final LinkingBeacon beacon, final HumidityData humidity) {
synchronized (mOnBeaconHumidityEventListeners) {
for (OnBeaconHumidityEventListener listener : mOnBeaconHumidityEventListeners) {
listener.onHumidity(beacon, humidity);
}
}
}
private void notifyBeaconRawDataEventListener(final LinkingBeacon beacon, final RawData raw) {
synchronized (mOnBeaconRawDataEventListeners) {
for (OnBeaconRawDataEventListener listener : mOnBeaconRawDataEventListeners) {
listener.onRawData(beacon, raw);
}
}
}
private void notifyBeaconProximityEventListener(final LinkingBeacon beacon, final GattData gatt) {
synchronized (mOnBeaconProximityEventListeners) {
for (OnBeaconProximityEventListener listener : mOnBeaconProximityEventListeners) {
listener.onProximity(beacon, gatt);
}
}
}
private void notifyBeaconButtonEventListener(final LinkingBeacon beacon, final long timeStamp, final int keyCode) {
synchronized (mOnBeaconButtonEventListeners) {
for (OnBeaconButtonEventListener listener: mOnBeaconButtonEventListeners) {
listener.onClickButton(beacon, keyCode, timeStamp);
}
}
}
private void notifyBeaconEventListener(final LinkingBeacon beacon) {
synchronized (mOnBeaconEventListeners) {
for (OnBeaconEventListener listener : mOnBeaconEventListeners) {
listener.onNotify(beacon);
}
}
}
private void notifyBeaconConnectionListener(final LinkingBeacon beacon) {
synchronized (mOnBeaconConnectListeners) {
for (OnBeaconConnectListener listener : mOnBeaconConnectListeners) {
listener.onDisconnected(beacon);
}
}
}
private abstract class TimeoutRunnable implements Runnable {
protected ScheduledExecutorService mExecutorService = Executors.newSingleThreadScheduledExecutor();
protected ScheduledFuture<?> mScheduledFuture;
private boolean mDestroyFlag;
TimeoutRunnable(final int timeout) {
mScheduledFuture = mExecutorService.schedule(this, timeout, TimeUnit.MILLISECONDS);
}
@Override
public synchronized void run() {
if (mDestroyFlag) {
return;
}
mDestroyFlag = true;
onTimeout();
mScheduledFuture.cancel(false);
mExecutorService.shutdown();
}
public synchronized void cancel() {
if (mDestroyFlag) {
return;
}
mDestroyFlag = true;
mScheduledFuture.cancel(false);
mExecutorService.shutdown();
}
public abstract void onTimeout();
}
public interface OnBeaconConnectListener {
void onConnected(LinkingBeacon beacon);
void onDisconnected(LinkingBeacon beacon);
}
public interface OnBeaconEventListener {
void onNotify(LinkingBeacon beacon);
}
public interface OnBeaconButtonEventListener {
void onClickButton(LinkingBeacon beacon, int keyCode, long timeStamp);
}
public interface OnBeaconProximityEventListener {
void onProximity(LinkingBeacon beacon, GattData gatt);
}
public interface OnBeaconBatteryEventListener {
void onBattery(LinkingBeacon beacon, BatteryData battery);
}
public interface OnBeaconAtmosphericPressureEventListener {
void onAtmosphericPressure(LinkingBeacon beacon, AtmosphericPressureData atmosphericPressure);
}
public interface OnBeaconHumidityEventListener {
void onHumidity(LinkingBeacon beacon, HumidityData humidity);
}
public interface OnBeaconTemperatureEventListener {
void onTemperature(LinkingBeacon beacon, TemperatureData temperature);
}
public interface OnBeaconRawDataEventListener {
void onRawData(LinkingBeacon beacon, RawData rawData);
}
public interface OnBeaconScanStateListener {
void onScanState(LinkingBeaconUtil.ScanState state, LinkingBeaconUtil.ScanDetail detail);
}
}