2014-07-09 3 views
10

최근에 Estimote 비콘 테스트를 시작했으며 비컨 영역에 들어갈 때 백그라운드 서비스에서 알림을 시작하려고하지만 불행히도 내 솔루션이 작동하지 않습니다. 오류는 발생하지 않지만 비컨이 발견되면 알림이 시작되지 않습니다. 나는 그것이 약간의 코드 오류인지 또는 단순히 그것을하는 방식이 잘못되었는지 나는 모른다. 여기 백그라운드에서 서비스의 Estimote 비콘 지역 감지

내 서비스 코드

입니다 ... 나는 this 다른 질문을 읽었습니다하지만 내가 사용하는 대신 활동의 서비스이지만, 어쩌면 대답은 (응용 프로그램 컨텍스트 관련)과 유사하기 때문에 그것은 조금 다른 것 같습니다
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(); 
     } 



} 

감사합니다. 사전에 감사의 말을 전합니다.

답변

8

이 코드는 나를위한 작동 코드입니다. 올바른 UUID, 보조 번호 및 주요 번호를 입력했는지 확인하십시오.

//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"); 
       } 
      } 
     }); 
    } 
} 

*** 편집 : 코드 정확도

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

이 솔루션이 작동 중입니다. 감사합니다. 하지만 그것에 대해 의심이 하나 있는데, 어떻게 근접성을 계산합니까? sdk 또는 공식 코드에있는 것이거나 자신의 솔루션입니까? 그래서 이걸로 저는 BeaconManager.setMonitoringListener()가이 경우에 사용할 수 없다는 것을 이해하고 대신 setRangingListener()를 사용해야합니다. – Hugo

+0

정확도를 계산하는 코드는 SDK에 있어야합니다. 하지만 난 당신에게 코드를 보여 주 답변을 편집 사용자 정의 SDK를 구현을 사용하고 있습니다. About setMonitoringListener 나는이 솔루션을 사용하기 위해 작동하지 못했습니다. – jDur

+0

Xamarin 응용 프로그램을 통합하려고합니다. 여기 EnterRegion 및 ExitRegion이 여러 번 순차적으로 호출됩니다. 왜 그런지 모르시겠습니까? 나는 그것에 대해 읽었을 때, 장치가 지역 범위 아래에있을 때에 만 트리거되어야한다. 그러나 그것이 범위에 올 때 장치가 신호의 범위를 나갈 때까지 순차적으로 트리거됩니다. 이걸 정렬하는 것이 도움이됩니다. –

0

확인 나는이 당신을 도울 것입니다 희망이 하나를 계산합니다. 이 함수를 사용하여 근접 거리를 찾을 수 있습니다 Utils.computeProximity(nearestBeacon).

서비스에서
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

, 당신은 또한 iBeacons를 검색하려면이 library을 사용할 수 있습니다. 사용자를 다소 절약 할 수 있습니다. battery. 또한 BeaconManager가 실제로 자체 서비스를 생성하므로이 서비스를 선호하므로 iBeacons를 검색하기 위해 2 개의 서비스가 실행됩니다. 그러나 거리 계산이 부족합니다.

또한 당신이 필요로하는 iBeacons를 검색하는 그 마음 :

  • 는 블루투스 LE 칩 유무 : 어떤.
  • 블루투스 켜기 : any.
  • 위치 정보 : Android 6 이상.
  • 위치 런타임 권한이 있어야합니다 (Android 6 이상).
  • 최대 시작 : 5 초, 30 초 후 : Android 7 이상.

그리고 당신은 다음과 같은 브로드 캐스트 리스너를 추가해야합니다 실행 서비스를 유지하기 :

  • 위치 상태 변경
  • 이에서 블루투스 상태 변경
  • 부팅 수신기

수신기를 다시 시작해야합니다.

관련 문제