3

Я пытаюсь использовать библиотеку iBeacon вне контекста активности, чтобы написать ее эффективную реализацию, но у меня что-то не хватает, поскольку я не получаю желаемую функциональность.Использование библиотеки iBeacon для Android за пределами активности

Это, скорее всего, кажется, что служба не связана с моей недавно созданного класса .... и я не уверен, что я здесь отсутствует ...

Вот мой пользовательский класс:

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

Что вы получаете и то, что желаемая функциональность? –

+0

Единственный журнал, который я получаю отсюда: 'Этот потребитель не связан. binding: ro.gebs.zonizbeacon.utils.BeaconUtils @ 41e3c040. Это похоже на то, что пользовательский класс не связан с активностью .... Я хотел бы видеть уведомление, поскольку я получал его, когда весь этот код был в моей деятельности класс –

+0

System.exit (0); не должны использоваться на Android. – Kitesurfer

ответ

3

Я был в состоянии получить код выше работы с некоторыми изменениями:

  1. Я прокомментировал линию verifyBluetooth((Activity) context);, потому что это сбой моего MainActivity с NullPointerException. Если вы видите, что ваша деятельность запускается правильно, вам может и не понадобиться это делать. Если вы не увидите его, то 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 

И отображалось следующее уведомление:

enter image description here

Как правило, лучший способ устранения таких проблем - добавить сообщения журнала. В случае, когда вы не видите много сообщений журнала, я бы добавил их вверху каждого цикла жизненного цикла и метода обратного вызова, включая onCreate, onIBeaconServiceConnect() и т. Д. После этого вы должны просмотреть любые сообщения, но не дать вам хорошая идея, когда что-то идет не так.

Несколько советов:

  1. Каждый раз, когда вы запускаете приложение из Затмения/Android Studio, не забудьте сделать некоторые изменения кода, в противном случае приложение не будет удалено и переустановить, и IBeacon Служба не перезапустится.Если служба не перезапущена, вы не получите новые зарегистрированные уведомления о зоне для iBeacons, которые уже были обнаружены.

  2. Осторожно, что у вас есть только один monitorNotifier или rangeNotifier на вашем iBeaconManager. Какой бы ни был последний набор уведомлений, тот, который получит все обратные вызовы.

  3. Если вы не видите, что ваш метод на onIBeaconServiceConnect() вызывается (лучше всего сделать это с помощью строки журнала), а затем остановите все, пока не получите эту работу.

  4. В целом, интерфейс IBeaconConsumer предназначен для работы с экземпляром Activity, Service или Application. Нет ничего плохого в том, что вы делаете это с помощью специального класса, такого как ваш BeaconUtils, но вам нужно быть более осторожным, чтобы ваш контекст был настроен правильно, и что все, что держит ссылку на ваш пользовательский объект, не удаляет его во время жизненного цикла Android. Редактировать: Кроме того, при создании пользовательских методов bindService и unbindService методы должны связываться с эквивалентными методами в контексте. Я удивлен, что это работает вообще как есть. Смотрите мой связанный ответ здесь: https://stackoverflow.com/a/21298560/1461050

+0

Еще раз спасибо за ваш ответ. Я медленно, но уверенно начинаю наилучшим образом использовать эту библиотеку. –

+0

См. Мое редактирование выше – davidgyoung

0

Для тех, кто еще заинтересован, я использовал большую работу, проделанную здесь первоначальным автором и реализовали его как плагин PhoneGap/Кордова. Пожалуйста, не стесняйтесь вносить свой вклад, комментарии и т.д. по адресу:

https://github.com/TheMattRay/iBeaconGap

Смежные вопросы