2017-07-07 96 views
0

我開發了Android應用程序來檢測信標,如果客戶接近1公里的距離。我正在使用Android Beacon Library來開發應用程序。當我們處於前臺時,我會收到通知,但只要應用程序進入後臺,通知就會退出工作。你能幫助我,我錯在哪裏? 以下是BeaconApp和MainActivity的代碼。Android iBeacon應用程序不能在後臺工作

BeaconApp.java

public class BeaconApp extends Application implements BootstrapNotifier { 
    private static final String TAG = "BeaconApp"; 
    private RegionBootstrap regionBootstrap; 
    private Region allbeaconsregions; 
    private BackgroundPowerSaver bgSaver; 
    BeaconManager beaconManager; 
    @Override 
    public void onCreate() { 
     super.onCreate(); 
     Log.d(TAG, "App started up"); 
     // To detect proprietary beacons, you must add a line likebelowcorresponding to your beacon 
     // type. Do a web search for "setBeaconLayout" to get the proper expression. 
     // beaconManager.getBeaconParsers().add(new BeaconParser(). 
     //  setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25")); 

     // wake up the app when any beacon is seen (you can specify specific id filers in the parameters below) 
     beaconManager = BeaconManager.getInstanceForApplication(this); 
     Beacon.setHardwareEqualityEnforced(true); 
     bgSaver = new BackgroundPowerSaver(this); 
     beaconManager.getBeaconParsers().add(new BeaconParser(). 
       setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); 


     allbeaconsregions = new Region("treewalker", null, null, null); 
     regionBootstrap = new RegionBootstrap(this, allbeaconsregions); 
     //beaconManager.bind(this); 
    } 

    @Override 
    public void didDetermineStateForRegion(int arg0, Region arg1) { 
     // Don't care 
     Log.d(TAG, "Enter in didDetermineStateForRegion call"); 
    } 

    @Override 
    public void didEnterRegion(Region arg0) { 
     Log.d(TAG, "Got a didEnterRegion call"); 
     // This call to disable will make it so the activity below only gets launched the first time a beacon is seen (until the next time the app is launched) 
     // if you want the Activity to launch every single time beacons come into view, remove this call. 
     regionBootstrap.disable(); 
     Intent intent = new Intent(this, MainActivity.class); 
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

     // Important: make sure to add android:launchMode="singleInstance" in the manifest 
     // to keep multiple copies of this activity from getting created if the user has 
     // already manually launched the app. 
     this.startActivity(intent); 


    } 

    @Override 
    public void didExitRegion(Region arg0) { 
     // Don't care 
     Log.d(TAG, "Enter in didExitRegion call"); 
    } 



} 

在MainActivity.java

public class MainActivity extends AppCompatActivity implements BeaconConsumer,RangeNotifier { 
    protected static final String TAG = "MainActivity"; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mBeaconManager = BeaconManager.getInstanceForApplication(this); 
     Beacon.setHardwareEqualityEnforced(true); 
     BackgroundPowerSaver bgSaver = new BackgroundPowerSaver(this); 
     mBeaconManager.getBeaconParsers().add(new BeaconParser(). 
       setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); 
     mBeaconManager.bind(this); 


    } 

    private BeaconManager mBeaconManager; 

    public void onResume() { 
     super.onResume(); 
     mBeaconManager = BeaconManager.getInstanceForApplication(this.getApplicationContext()); 
     // Detect the main Eddystone-UID frame: 
     mBeaconManager.getBeaconParsers().add(new BeaconParser(). 
       setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); 
     mBeaconManager.bind(this); 
    } 


    public void onBeaconServiceConnect() { 


      try { 
       mBeaconManager.startRangingBeaconsInRegion(new Region("treewalker", null, null, null)); 
       mBeaconManager.addRangeNotifier(this); 
      }catch (RemoteException e){ 
       e.printStackTrace(); 
      } 


    } 

    @Override 
    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) { 

     if(beacons.size() > 0) { 
      for (Beacon beacon : beacons) { 
       if (beacon.getDistance() < 1.0) { 
        Log.d(TAG, "I see a beacon transmitting a : " + 
          " approximately " + beacon.getDistance() + " meters away."); 

        Log.d(TAG, "BEACON DATA : " +beacon.getBluetoothAddress()+":"+beacon.getBluetoothName()+":"+beacon.getId1()); 

        showNotification("Treewalker","You are near beacon range"); 
        Intent intent = new Intent(this,MainActivity.class); 
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
        this.startActivity(intent); 


       } 


      } 
     } 
    } 

    public void showNotification(String title, String message) { 
     Intent notifyIntent = new Intent(this, DashboardActivity.class); 
     notifyIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
     PendingIntent pendingIntent = PendingIntent.getActivities(this, 0, 
       new Intent[] { notifyIntent }, PendingIntent.FLAG_UPDATE_CURRENT); 
     Notification notification = new Notification.Builder(this) 
       .setSmallIcon(android.R.drawable.ic_dialog_info) 
       .setContentTitle(title) 
       .setContentText(message) 
       .setAutoCancel(true) 
       .setContentIntent(pendingIntent) 
       .build(); 
     notification.defaults |= Notification.DEFAULT_SOUND; 
     NotificationManager notificationManager = 
       (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     notificationManager.notify(1, notification); 
    } 
    @Override 
    public void onPause() { 
     super.onPause(); 
     //mBeaconManager.unbind(this); 
    } 
} 

回答

1

的問題是,當你的應用程序去的背景下,MainActivity將調用,而且方法調用中的代碼該方法有效地停止了信標測距。

如果你想爲繼續的背景下,最容易做的事情是將以下兩行:

mBeaconManager.startRangingBeaconsInRegion(new Region("treewalker", null, null, null)); 
mBeaconManager.addRangeNotifier(this); 

BeaconApp類的didDetermineStateForRegion方法。您還需要在那裏移動didRangeBeaconsInRegionshowNotification方法。

+0

但問題是,當我試圖這樣做時,它會引發錯誤「信標管理器未綁定到此類」。在BeaconApp中,我實現了不支持綁定方法的BootstrapNotifier ..它在該類中可用。 – ssnegi

+0

瞭解。這就是爲什麼我建議在didDetermineState方法內開始測距。因爲在啓動時調用該方法時,服務始終是綁定的。 – davidgyoung

+0

我有另一個問題..我可以看到,如果我輸入信標範圍..它調用「didEnterRegion」函數,但它永遠不會進入「didExitRegion」。我正在考慮上面的代碼。除此之外,還有什麼辦法可以減少距離檢測,因爲我經常這樣做,因爲從邏輯上講,我想記錄數據,並在客戶輸入1 mt範圍內的信標時發送一次通知。 – ssnegi