活动之外的Android iBeacon库使用情况
作者:互联网
我正在尝试在活动上下文之外使用iBeacon库,以编写其有效的实现,但是由于缺少所需的功能,我错过了一些东西.
很有可能该服务未绑定到我新创建的类….而且我不确定此处缺少什么…
这是我的自定义类:
public class BeaconUtils implements IBeaconConsumer, RangeNotifier, IBeaconDataNotifier {
private Context context;
protected static final String TAG = "BeaconUtils";
public BeaconUtils(Context context) {
this.context = context;
verifyBluetooth((Activity) context);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static void verifyBluetooth(final Activity activity) {
try {
if (!IBeaconManager.getInstanceForApplication(activity).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
activity.finish();
//System.exit(0);
}
});
builder.show();
}
} catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
activity.finish();
//System.exit(0);
}
});
builder.show();
}
}
@Override
public void onIBeaconServiceConnect() {
Region region = new Region("MainActivityRanging", null, null, null);
try {
ZonizApplication.iBeaconManager.startMonitoringBeaconsInRegion(region);
ZonizApplication.iBeaconManager.setRangeNotifier(this);
ZonizApplication.iBeaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
ZonizApplication.iBeaconManager.setMonitorNotifier(new MonitorNotifier() {
@Override
public void didEnterRegion(Region region) {
//createNotification();
//Log.i(TAG, "I am in the range of an IBEACON: "+region.getProximityUuid());
//SyncServiceHelper.getInst().trySyncOffers(region.getProximityUuid());
}
@Override
public void didExitRegion(Region region) {
NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(0);
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
Log.i(TAG, "I have just switched from seeing/not seeing iBeacons: " + region.getProximityUuid());
createNotification();
}
});
}
@Override
public Context getApplicationContext() {
return this.context;
}
@Override
public void unbindService(ServiceConnection serviceConnection) {
ZonizApplication.iBeaconManager.unBind(this);
}
@Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
ZonizApplication.iBeaconManager.bind(this);
return true;
}
@Override
public void iBeaconDataUpdate(IBeacon iBeacon, IBeaconData iBeaconData, DataProviderException e) {
if (e != null) {
Log.d(TAG, "data fetch error:" + e);
}
if (iBeaconData != null) {
String displayString = iBeacon.getProximityUuid() + " " + iBeacon.getMajor() + " " + iBeacon.getMinor() + "\n" + "Welcome message:" + iBeaconData.get("welcomeMessage");
Log.d(TAG, displayString);
}
}
@Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
for (IBeacon iBeacon : iBeacons) {
iBeacon.requestData(this);
String displayString = iBeacon.getProximityUuid() + " " + iBeacon.getMajor() + " " + iBeacon.getMinor() + "\n";
Log.d(TAG, displayString);
}
}
public void createNotification() {
// Prepare intent which is triggered if the
// notification is selected
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Build notification
// Actions are just fake
//if (currentUIID != null && !currentUIID.isEmpty()) {
Notification noti = new Notification.Builder(context)
.setContentTitle("New beacon in range")
.setContentText("You are currently in the range of a new beacon.").setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent).build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// hide the notification after its selected
noti.flags |= Notification.FLAG_AUTO_CANCEL;
noti.defaults |= Notification.DEFAULT_SOUND;
noti.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, noti);
//}
}
}
我在我的Application类中实例化了信标管理器:
iBeaconManager = IBeaconManager.getInstanceForApplication(this);
并且我在onCreate()和onDestroy()方法的活动中绑定了该管理器.
我想念什么?
我在这样的活动中实例化自定义类:
private BeaconUtils beaconUtilities = new BeaconUtils(MainActivity.this);
绑定部分:
beaconUtilities = new BeaconUtils(MainActivity.this);
ZonizApplication.iBeaconManager.bind(beaconUtilities);
解决方法:
经过一些修改,我就能得到上面的代码:
>我注释掉verifyBluetooth((Activity)context);行,因为它使我的MainActivity崩溃,并带有NullPointerException.如果您看到活动正常启动,则可能不需要这样做.如果您没有看到它启动,那么BeaconUtils将与您的MainActivity一起被Android处理,并且在看到iBeacons时无法获得任何回调.
>我必须更改createNotification方法才能使其正常工作-原始代码没有为我显示通知,尽管我不清楚原因为何.我要工作的代码是:
private void createNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setContentTitle("New beacon in range")
.setContentText("You are currently in the range of a new beacon.")
.setSmallIcon(R.drawable.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(new Intent(context, MainActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
进行此更改后,启动后日志将显示以下行:
01-21 12:52:43.112 I/BeaconUtils﹕ I have just switched from seeing/not seeing iBeacons: null
并显示以下通知:
通常,解决此类问题的最佳方法是添加日志消息.如果您没有看到很多日志消息,则将它们添加到每个生命周期和回调方法的顶部,包括onCreate,onIBeaconServiceConnect()等.一旦执行此操作,您应该看到但不显示的任何消息您是哪里出了问题的好主意.
其他一些技巧:
>每次从Eclipse / Android Studio启动应用程序时,请确保进行一些代码更改,否则将不会卸载并重新安装该应用程序,并且iBeacon服务也不会重新启动.除非重新启动该服务,否则您将不会获得已检测到的iBeacon的新输入区域通知.
>请注意,iBeaconManager上只能有一个monitorNotifier或rangingNotifier.最后一个通知程序集是将获取所有回调的通知程序集.
>如果看不到您的onIBeaconServiceConnect()方法被调用(最好使用日志行来执行此操作),则停止所有操作,直到一切正常为止.
>通常,IBeaconConsumer接口旨在与活动,服务或应用程序实例一起使用.使用像BeaconUtils这样的自定义类来执行此操作没有错,但是您必须格外小心,以确保上下文设置正确,并且在Android生命周期中,对自定义对象的引用都不会对其进行处理.编辑:此外,当制作自定义bindService和unbindService方法时,这些方法必须链接到上下文中的等效方法.令我惊讶的是,这项功能一成不变.在这里查看我的相关答案:https://stackoverflow.com/a/21298560/1461050
标签:android-service,android-service-binding,ibeacon,ibeacon-android,android 来源: https://codeday.me/bug/20191122/2058021.html