我正在尝试在活动上下文之外使用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);
答案 0 :(得分:3)
我能够通过一些修改获得上面的代码:
我注释了verifyBluetooth((Activity) context);
行,因为它使MainActivity
与NullPointerException
一起崩溃。如果您发现活动正常启动,则可能不需要执行此操作。如果您没有看到它启动,那么BeaconUtils
将由Android与您的MainActivity
一起处理,并且在看到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服务将不会重新启动。除非重新启动服务,否则您将无法获得已检测到的iBeacons的新输入区域通知。
请注意,iBeaconManager上只有一个 monitorNotifier或rangesNotifier。无论最后一个通知器集是什么,它将获得所有回调。
如果您没有看到正在调用您的on onIBeaconServiceConnect()
方法(最好使用日志行进行此操作),请停止所有操作直到您正常工作。
通常,IBeaconConsumer
界面旨在与Activity
,Service
或Application
实例配合使用。使用像BeaconUtils
这样的自定义类来执行此操作没有任何问题,但您必须格外小心,以正确设置上下文,并且无论是什么持有对自定义对象的引用都不会在Android生命周期。 修改另外,在制作自定义bindService
和unbindService
方法时,方法必须链接到上下文中的等效方法。我很惊讶这一切都是按原样运作的。请在此处查看我的相关答案:https://stackoverflow.com/a/21298560/1461050
答案 1 :(得分:0)
对于任何感兴趣的人,我都使用了原作者在这里所做的出色工作,并将其作为PhoneGap / Cordova插件实现。请随时在以下网址上发表评论,评论等。