3

我正在尝试在活动上下文之外使用 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);
        //}
    }

}

我在我的应用程序类中实例化信标管理器:

iBeaconManager = IBeaconManager.getInstanceForApplication(this);

我在onCreate()andonDestroy()方法中的活动中绑定了这个经理。

我错过了什么?

我在这样的活动中实例化我的自定义类:

private BeaconUtils beaconUtilities = new BeaconUtils(MainActivity.this);

装订部分:

beaconUtilities = new BeaconUtils(MainActivity.this);
ZonizApplication.iBeaconManager.bind(beaconUtilities);
4

2 回答 2

3

我能够通过一些修改获得上面的代码:

  1. 我注释掉了这verifyBluetooth((Activity) context);条线,因为它使我MainActivityNullPointerException. 如果您看到您的活动正确启动,您可能不需要这样做。如果您没有看到它启动,那么BeaconUtils将与您一起被 Android 处理,MainActivity并且在看到 iBeacons 时无法获得任何回调。

  2. 我必须改变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()等。一旦您这样做,您应该看到的任何消息都不会给您一个好主意哪里出了问题。

其他一些提示:

  1. 每次从 Eclipse/Android Studio 启动应用程序时,请务必更改一些代码,否则应用程序将不会被卸载并重新安装,并且 iBeacon 服务也不会重新启动。除非重新启动服务,否则您将不会收到已检测到的 iBeacons 的新输入区域通知。

  2. 请注意,您的 iBeaconManager 上只有一个monitorNotifier 或 rangeNotifier。无论最后一个通知集是什么,都会得到所有回调。

  3. 如果您没有看到onIBeaconServiceConnect()正在调用您的 on 方法(最好使用日志行来执行此操作),则停止一切,直到您可以正常工作。

  4. 通常,该接口IBeaconConsumer旨在与或实例一起使用。使用您的自定义类执行此操作没有任何问题,但是您必须格外小心,确保您的上下文设置正确,并且任何持有对您的自定义对象的引用都不会在 Android 生命周期中处理掉它。 编辑:此外,在制作自定义和方法时,这些方法必须链接到上下文中的等效方法。我很惊讶这完全按原样工作。在这里查看我的相关答案:https ://stackoverflow.com/a/21298560/1461050ActivityServiceApplicationBeaconUtilsbindServiceunbindService

于 2014-01-21T18:19:28.717 回答
0

对于其他感兴趣的人,我使用了原作者在此处完成的出色工作,并将其实现为 PhoneGap/Cordova 插件。请随时在以下位置贡献、评论等:

https://github.com/TheMattRay/iBeaconGap

于 2014-05-06T17:14:07.883 回答