2017-07-07 52 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