2014-07-09 6 views
10

Ich habe vor kurzem begonnen, Estimote Beacons zu testen, und ich versuche, eine Benachrichtigung von einem Hintergrunddienst beim Betreten eines Beacon Region zu starten, aber meine Lösung funktioniert leider nicht. Es gibt keine Fehler, aber die Benachrichtigung wird nicht gestartet, wenn ein Beacon entdeckt wird. Ich weiß nicht, ob es ein Code-Fehler ist oder einfach die Art, es zu tun, ist falsch. Ich habe this andere Frage zu lesen, aber es scheint ein wenig anders, da ich verwende, was ein Dienst anstelle einer Tätigkeit ist, aber vielleicht die Antwort ist ähnlich (app kontextbezogene) ...Estimote Beacons Region Erkennung von einem Dienst im Hintergrund

hier ist mein Service-Code

public class BeaconsMonitoringService extends Service{ 

    private BeaconManager beaconManager; 

    private String user; 

    @Override 
     public void onCreate() { 
     // Configure BeaconManager. 
     beaconManager = new BeaconManager(this); 

     } 

     @Override 
     public int onStartCommand(Intent intent, int flags, int startId) { 
      Toast.makeText(this, "Beacons monitoring service starting", Toast.LENGTH_SHORT).show(); 

      user = intent.getStringExtra("user"); 

      // Check if device supports Bluetooth Low Energy. 
      if (!beaconManager.hasBluetooth()||!beaconManager.isBluetoothEnabled()) { 
       Toast.makeText(this, "Device does not have Bluetooth Low Energy or it is not enabled", Toast.LENGTH_LONG).show(); 
       this.stopSelf(); 
      } 

       connectToService(); 


      // If we get killed, after returning from here, restart 
      return START_STICKY; 
     } 

     @Override 
     public IBinder onBind(Intent intent) { 
      // We don't provide binding, so return null 
      return null; 
     } 

     @Override 
     public void onDestroy() { 
     Toast.makeText(this, "Beacons monitoring service done", Toast.LENGTH_SHORT).show(); 
     } 

     private void connectToService() { 


      beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 

      @Override 
      public void onServiceReady() { 
       notifyEnterRegion(0); 
//   try { 
        beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0); 
        Log.i("BEACOON ", "ANTES DE"); 
        beaconManager.setMonitoringListener(new MonitoringListener() { 
        @Override 
        public void onEnteredRegion(Region region, List<Beacon> beacons) { 
         Log.i("BEACOON ", String.valueOf(beacons.get(1).getMinor())); 
        for (Beacon beacon: beacons){ 
         Log.i("BEACOON ", String.valueOf(beacon.getMinor())); 
         if (beacon.getMinor() == 64444) { 

          notifyEnterRegion(6444); 

         } else if (beacon.getMinor() == 36328) { 

          notifyEnterRegion(36328); 

         } else if (beacon.getMinor() == 31394) { 

          notifyEnterRegion(31394); 

         } 
        } 
        } 

        @Override 
        public void onExitedRegion(Region region) { 

         notifyExitRegion(); 

        } 
        }); 

      } 
      }); 
     } 

     public void notifyEnterRegion(int code) { 

      Toast.makeText(this, "Beacon "+code, Toast.LENGTH_SHORT).show(); 

      Intent targetIntent = new Intent(this, MainActivity.class); 
      PendingIntent contentIntent = PendingIntent.getActivity(this, 0, targetIntent, PendingIntent.FLAG_UPDATE_CURRENT); 

      Notification noti = new Notification.Builder(this) 
      .setContentTitle("Bienvenido "+user+"!") 
      .setContentText("Sólo por estar aquí has ganado....") 
      .setSmallIcon(com.smt.beaconssmt.R.drawable.beacon_gray) 
      .setContentIntent(contentIntent) 
      .getNotification(); 

      NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
      nManager.notify(1, noti); 
     } 

     public void notifyExitRegion(){ 

      AlertDialog.Builder builder = new AlertDialog.Builder(this); 

      builder.setMessage("Hasta pronto!") 
        .setTitle(user+", estás abandonando la zona de beacons"); 

      builder.setPositiveButton("Ver web", new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog, int id) { 
          // User clicked OK button 
          Intent i = new Intent(BeaconsMonitoringService.this, WebViewActivity.class); 
          i.putExtra("web", "http://www.google.com/"); 
          startActivity(i); 
         } 
        }); 
      builder.setNegativeButton("Adios!", new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog, int id) { 
          // User cancelled the dialog 
         } 
        }); 

      AlertDialog dialog = builder.create(); 

      dialog.show(); 
     } 



} 

Ich werde sehr jede Art von Hilfe zu schätzen wissen, danke im Voraus!

Antwort

8

Dieser Code funktioniert für mich. Stellen Sie sicher, dass Sie die richtige UUID, Minor und Major-Nummern eingeben.

//Using something like that as global variable 

    private static final Region[] BEACONS = new Region[] { 
    new Region("beacon1", "uuid1", 1, 19227), //uuid without "-" 
    new Region("beacon2", "uuid2", 1, 61690), 
    new Region("beacon3", "uuid3", null, null) 
}; 
//Note: setting minor == null and major == null will detect every beacon with that uuid 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     startMonitoring(); 
     return START_STICKY; 
    } 



private void startMonitoring() { 
    if (beaconManager == null) { 
     beaconManager = new BeaconManager(this); 

     // Configure verbose debug logging. 
     L.enableDebugLogging(true); 

     /** 
     * Scanning 
     */ 
     beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 1); 

     beaconManager.setRangingListener(new RangingListener() { 

      @Override 
      public void onBeaconsDiscovered(Region paramRegion, List<Beacon> paramList) { 
       if (paramList != null && !paramList.isEmpty()) { 
        Beacon beacon = paramList.get(0); 
        Proximity proximity = Utils.computeProximity(beacon); 
        if (proximity == Proximity.IMMEDIATE) { 
         Log.d(TAG, "entered in region " + paramRegion.getProximityUUID()); 
         postNotification(paramRegion); 
        } else if (proximity == Proximity.FAR) { 
         Log.d(TAG, "exiting in region " + paramRegion.getProximityUUID()); 
         removeNotification(paramRegion); 
        } 
       } 
      } 

     }); 

     beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 
      @Override 
      public void onServiceReady() { 
       try { 
        Log.d(TAG, "connected"); 
        for (Region region : BEACONS) { 
         beaconManager.startRanging(region); 
        } 
       } catch (RemoteException e) { 
        Log.d("TAG", "Error while starting monitoring"); 
       } 
      } 
     }); 
    } 
} 

*** Schnitt: Code berechnen Genauigkeit

public static double computeAccuracy(Beacon beacon) 
{ 
    if (beacon.getRssi() == 0) 
    { 
     return -1.0D; 
    } 

    double ratio = beacon.getRssi()/beacon.getMeasuredPower(); 
    double rssiCorrection = 0.96D + Math.pow(Math.abs(beacon.getRssi()), 3.0D) % 10.0D/150.0D; 

    if (ratio <= 1.0D) 
    { 
     return Math.pow(ratio, 9.98D) * rssiCorrection; 
    } 
    return (0.103D + 0.89978D * Math.pow(ratio, 7.71D)) * rssiCorrection; 
} 

public static Proximity proximityFromAccuracy(double accuracy) 
{ 
    if (accuracy < 0.0D) 
    { 
     return Proximity.UNKNOWN; 
    } 
    if (accuracy < 0.5D) 
    { 
     return Proximity.IMMEDIATE; 
    } 
    if (accuracy <= 3.0D) { 
     return Proximity.NEAR; 
    } 
    return Proximity.FAR; 
} 



public static Proximity computeProximity(Beacon beacon) { 
    return proximityFromAccuracy(computeAccuracy(beacon)); 
} 
+0

Ok, diese Lösung funktioniert, danke! aber ich habe einen Zweifel daran, wie Sie "Nähe berechnen"? ist etwas im SDK oder offiziellen Code oder ist Ihre eigene Lösung? Also verstehe ich, dass BeaconManager.setMonitoringListener() in diesem Fall nicht verwendbar ist und wir stattdessen setRangingListener() verwenden müssen ?? – Hugo

+0

Der Code zur Berechnung der Genauigkeit sollte im SDK enthalten sein. Aber ich benutze eine benutzerdefinierte SDK-Implementierung, also habe ich die Antwort bearbeitet, um Ihnen den Code zu zeigen. Über setMonitoringListener konnte ich nicht funktionieren, also beende ich diese Lösung. – jDur

+0

Ich bin für meine Xamarin-Anwendung integrieren, hier ruft EnterRegion und ExitRegion mehrere Zeit nacheinander, weiß nicht warum? Ich lese darüber, es sollte nur auslösen, wenn das Gerät in den Bereich der Region kommt. Aber wenn es in Reichweite kommt, löst es sequentiell aus, bis das Gerät die Reichweite der Bake verlässt. Bitte helfen Sie diese –

0

prüfen dieses Ich hoffe, dies wird Ihnen helfen. Sie können die Nähe durch diese Funktion Utils.computeProximity(nearestBeacon) finden.

beaconManager.setRangingListener(new BeaconManager.RangingListener() { 

     @Override 
     public void onBeaconsDiscovered(Region region, final List<Beacon> beaconList) { 
      if (!beaconList.isEmpty()) { 
       Beacon nearestBeacon = beaconList.get(0); 
       Log.e("Current Proximity - ", String.valueOf(Utils.computeProximity(nearestBeacon))); 
      } 
     } 
}); 
0

Von Ihrem Service, können Sie auch diese library für iBeacons scannen verwenden. Es kann Ihre Benutzer einige battery speichern. Ich würde es auch bevorzugen, da BeaconManager tatsächlich seinen eigenen Dienst hervorbringt, und so haben Sie 2 Dienste, die nur laufen, um iBeacons zu scannen. Es fehlt jedoch die Entfernungsberechnung.

dagegen auch, dass für iBeacons scannen Sie benötigen:

  • Haben Sie einen Chip Bluetooth LE: beliebig.
  • Bluetooth haben: any.
  • Standort auf: Android 6+.
  • Have Location Runtime-Berechtigung: Android 6+.
  • Maximale Start 5 Scans in 30 Sekunden: Android 7+.

Und Ihren Dienst am Laufen halten Sie folgende Sendung Zuhörer hinzufügen:

  • Lage Zustand geändert
  • bluetooth Zustand geändert
  • Boot-Empfänger

Aus diesem Empfänger sollten Sie Ihren Dienst erneut starten.

Verwandte Themen