Android iBeacon 应用程序无法在后台运行
Android iBeacon App not working in the background
我开发了 Android 应用程序来检测客户是否接近 1 米距离的信标。我正在使用 Android 信标库来开发 application.When 我们在前台收到通知,但是一旦应用程序进入后台.. 通知就停止工作了。你能帮我看看我哪里错了吗?
下面是 BeaconApp 和 MainActivity 的代码。
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);
}
}
问题在于,当您的应用进入后台时,MainActivity
将调用 onPause
,并且该方法中的代码会调用 mBeaconManager.unbind(this);
方法,从而有效地停止信标测距。
如果你想在后台继续测距,最简单的方法就是移动以下两行:
mBeaconManager.startRangingBeaconsInRegion(new Region("treewalker", null, null, null));
mBeaconManager.addRangeNotifier(this);
到 BeaconApp
class' didDetermineStateForRegion
方法。您还需要将 didRangeBeaconsInRegion
和 showNotification
方法移到那里。
我开发了 Android 应用程序来检测客户是否接近 1 米距离的信标。我正在使用 Android 信标库来开发 application.When 我们在前台收到通知,但是一旦应用程序进入后台.. 通知就停止工作了。你能帮我看看我哪里错了吗? 下面是 BeaconApp 和 MainActivity 的代码。
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);
}
}
问题在于,当您的应用进入后台时,MainActivity
将调用 onPause
,并且该方法中的代码会调用 mBeaconManager.unbind(this);
方法,从而有效地停止信标测距。
如果你想在后台继续测距,最简单的方法就是移动以下两行:
mBeaconManager.startRangingBeaconsInRegion(new Region("treewalker", null, null, null));
mBeaconManager.addRangeNotifier(this);
到 BeaconApp
class' didDetermineStateForRegion
方法。您还需要将 didRangeBeaconsInRegion
和 showNotification
方法移到那里。