我正在使用Android Beacon Library扫描ibeacon。在这些代码中,它将使用BootstrapNotifier界面在后台扫描ibeacon。一旦检测到iBeacon,RangeNotifier界面即会启动,并在textview中显示信标信息。当我关闭此应用程序时(通过在最近的应用程序列表中将其关闭),后台扫描停止了。正确地说,它不应基于示例here停止扫描。以下是代码。赞赏是否有人可以提供帮助。预先感谢。
package com.example.budakgigibesi.ibeacon_scan;
import android.app.Activity;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import org.altbeacon.beacon.startup.RegionBootstrap;
import java.util.Collection;
public class MainActivity extends AppCompatActivity implements BootstrapNotifier, BeaconConsumer, RangeNotifier {
private BeaconManager beaconManager;
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//enable beacon features///////////////////////////////////////////////////////////////////////
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setEnableScheduledScanJobs(false); // disable JobScheduler-based scans (used on Android 8+)
beaconManager.setBackgroundBetweenScanPeriod(0); // set the time between each scan to be 1 hour (3600 seconds)
beaconManager.setBackgroundScanPeriod(1100); // set the duration of the scan to be 1.1 seconds
Region region = new Region("backgroundRegion", null, null, null);
regionBootstrap = new RegionBootstrap(this, region); // wake up the app when a beacon is seen
backgroundPowerSaver = new BackgroundPowerSaver(this); //This reduces bluetooth power usage by about 60%
beaconManager.bind(this); //for beacon RangeNotifier
//////////////////////////////////////////////////////////////////////////////////////////////
}
//altbeacon bootstrapnotifier///////////////////////////////////////////////////////////////////////
@Override
public void didEnterRegion(Region region) {
TextView mTextView = (TextView) findViewById(R.id.id_tv);
mTextView.setText( "found a beacon");
//
try {
beaconManager.startRangingBeaconsInRegion(region); //Tells the BeaconService to start looking for beacons that match the passed Region object, and providing updates on the estimated mDistance every seconds while beacons in the Region are visible.
}
catch (RemoteException e) {
if (BuildConfig.DEBUG) Log.d("RangeNotifier", "Can't start ranging");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//altbeacon BeaconConsumer///////////////////////////////////////////////////////////////////////
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Log.i("beaconconsumer", "didRangeBeaconsInRegion called with beacon count: "+beacons.size());
for (Beacon b : beacons) {
Log.i("beaconconsumer", "The first beacon " + b.toString() + " is about " + b.getDistance() + " meters away.");
TextView mTextView = (TextView) findViewById(R.id.id_tv);
mTextView.setText( "The first beacon " + b.toString() + " is about " + b.getDistance() + " meters away.");
}
}catch (RemoteException e) { }
}
@Override
public void onBeaconServiceConnect() {
beaconManager.addRangeNotifier(this);
}
@Override
protected void onPause() {
super.onPause();
if (beaconManager.isBound(this)) beaconManager.setBackgroundMode(true);
}
@Override
protected void onResume() {
super.onResume();
if (beaconManager.isBound(this)) beaconManager.setBackgroundMode(false);
}
}
并在logcat中发现了一些错误
10-30 13:24:40.263 14712-30801/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 4096
10-30 13:24:40.263 14712-30801/? D/BtGatt.GattService: onScanResult() - address=7C:64:56:83:5E:71, rssi=-86
10-30 13:24:40.323 7928-7945/com.example.budakgigibesi.ibeacon_scan D/BluetoothAdapter: stopLeScan()
10-30 13:24:40.323 14712-14847/? D/BtGatt.GattService: stopScan() - queue=1
10-30 13:24:40.333 14712-14847/? D/BtGatt.GattService: stopScan() - queue empty; stopping scan
10-30 13:24:40.333 14712-14847/? D/BtGatt.btif: btif_gattc_scan
10-30 13:24:40.333 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1003
10-30 13:24:40.343 14712-14723/? D/BtGatt.GattService: unregisterClient() - clientIf=5
10-30 13:24:40.343 14712-14723/? D/BtGatt.btif: btif_gattc_unregister_app
10-30 13:24:40.353 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1001
10-30 13:24:40.353 14712-30801/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 1
10-30 13:24:40.363 7928-7945/com.example.budakgigibesi.ibeacon_scan D/BluetoothAdapter: startLeScan(): null
10-30 13:24:40.363 14712-14724/? D/BtGatt.GattService: registerClient() - UUID=6f27a4f0-4631-405a-8651-07c58b62f50d
10-30 13:24:40.373 14712-14724/? D/BtGatt.btif: btif_gattc_register_app
10-30 13:24:40.373 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1000
10-30 13:24:40.373 14712-30801/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 0
10-30 13:24:40.373 14712-30801/? D/BtGatt.GattService: onClientRegistered() - UUID=6f27a4f0-4631-405a-8651-07c58b62f50d, clientIf=5
10-30 13:24:40.373 7928-7998/com.example.budakgigibesi.ibeacon_scan D/BluetoothAdapter: onClientRegistered() - status=0 clientIf=5
10-30 13:24:40.383 14712-30801/? D/BtGatt.GattService: startScan() - queue=0
10-30 13:24:40.383 14712-30801/? D/BtGatt.GattService: startScan() - adding client=5
10-30 13:24:40.383 14712-30801/? D/BtGatt.btif: btif_gattc_scan
10-30 13:24:40.383 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1002
10-30 13:24:40.463 932-14195/? I/ActivityManager: Killing 7928:com.example.budakgigibesi.ibeacon_scan/u0a315 (adj 16): remove task
10-30 13:24:40.673 14712-16859/? D/BtGatt.GattService: Binder is dead - unregistering client (5)!
10-30 13:24:40.673 14712-16859/? D/BtGatt.GattService: stopScan() - queue=1
10-30 13:24:40.673 14712-16859/? D/BtGatt.GattService: stopScan() - queue empty; stopping scan
10-30 13:24:40.673 14712-16859/? D/BtGatt.btif: btif_gattc_scan
10-30 13:24:40.673 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1003
10-30 13:24:40.673 932-1593/? W/ActivityManager: Scheduling restart of crashed service com.example.budakgigibesi.ibeacon_scan/org.altbeacon.beacon.service.BeaconService in 1000ms
10-30 13:24:40.683 14712-16859/? D/BtGatt.GattService: unregisterClient() - clientIf=5
10-30 13:24:40.683 14712-16859/? D/BtGatt.btif: btif_gattc_unregister_app
10-30 13:24:40.683 14712-30801/? D/BtGatt.btif: btgattc_handle_event: Event 1001
10-30 13:24:40.683 14712-30801/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 1
10-30 13:24:41.204 932-932/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!
10-30 13:24:41.204 1189-1189/? D/StatusBar.NetworkController: refreshViews: Data not connected!! Set no data type icon / Roaming
10-30 13:24:41.204 932-932/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!
10-30 13:24:41.294 406-1066/? D/QC-QMI: Thread state: conn_id=18, state=RX_THREAD_WAKELOCK_ACQUIRE
10-30 13:24:41.294 406-1066/? D/QC-QMI: Thread state: conn_id=18, state=RX_THREAD_WAIT_READ
10-30 13:24:41.294 406-1066/? D/QC-QMI: Thread state: conn_id=18, state=RX_THREAD_CLIENT_TX
10-30 13:24:41.294 406-1066/? D/QC-QMI: qmi_qmux: TX/RX - RX 95 bytes on conn_id=18
10-30 13:24:41.294 406-1066/? D/QC-QMI: qmuxd: TX message on fd=24, to qmux_client_id=0x3, len=129
10-30 13:24:41.294 406-1066/? D/QC-QMI: Thread state: conn_id=18, state=RX_THREAD_WAKELOCK_RELEASE
10-30 13:24:41.294 406-1066/? D/QC-QMI: Thread state: conn_id=18, state=RX_THREAD_WAIT_POLL
答案 0 :(得分:0)
一些较小的Android制造商喜欢对操作系统进行的许多自定义操作中,其中之一就是自定义任务切换器。 Sone这样做的方式是使应用程序从屏幕上滑动,从而使应用程序处于“停止”状态。
在现有的Android设备上,从任务切换器上滑动应用程序不会使应用程序处于停止状态。从“设置”->“应用程序”进行面部停止。一旦应用程序处于停止状态,就好像从未启动过该应用程序一样。不允许它响应计时器或外部事件(如信标检测)来启动自己。用户必须及时启动它,以使其从停止的应用程序状态恢复。
目前尚不清楚这是这些制造商的有意更改还是错误更改。无论哪种方式,不幸的是您都无法做任何事情。
您可以通过运行stopped app detector来检查是否有其中一部电话。
有关更多信息,请参见此处:
https://altbeacon.github.io/android-beacon-library/resume-after-terminate.html
https://github.com/AltBeacon/android-beacon-library/issues/729
答案 1 :(得分:0)
要使自动重启正常工作,必须在自定义Application类(而不是显示的Activity类)的onCreate方法中构造RegionBootstap。该活动仅在手动启动时启动,因此在被杀死后自动重启后无法触发扫描。
答案 2 :(得分:0)
我设法解决了这个问题。下面是更正的代码。我将其分为2类。一种用于应用程序类,一种用于蓝牙扫描类。关闭应用程序(在最近的应用程序列表中将其关闭)时,应用程序类(MyApplication)将再次启动并启动蓝牙扫描类(ScanBT)。
MyApplication.java
public class MainApplication extends Application {
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, ScanBT.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
}
ScanBT.java
public class ScanBT extends AppCompatActivity implements BootstrapNotifier, BeaconConsumer, RangeNotifier {
private BeaconManager beaconManager;
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("foxy", "ScanBT - i am in onCreateeeeeeeee");
//enable beacon features///////////////////////////////////////////////////////////////////////
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setEnableScheduledScanJobs(false);
beaconManager.setBackgroundBetweenScanPeriod(0);
beaconManager.setBackgroundScanPeriod(1100);
Region region = new Region("backgroundRegion", null, null, null);
regionBootstrap = new RegionBootstrap(this, region);
backgroundPowerSaver = new BackgroundPowerSaver(this);
beaconManager.bind(this);
//////////////////////////////////////////////////////////////////////////////////////////////
}
//altbeacon bootstrapnotifier///////////////////////////////////////////////////////////////////////
@Override
public void didEnterRegion(Region region) {
Log.i("foxy", "ScanBT - a beacon entered the region");
try {
beaconManager.startRangingBeaconsInRegion(region);
}
catch (RemoteException e) {
if (BuildConfig.DEBUG) Log.d("RangeNotifier", "Can't start ranging");
}
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
}
@Override
public void didExitRegion(Region region) {
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//altbeacon BeaconConsumer///////////////////////////////////////////////////////////////////////
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Log.i("foxy", "ScanBT - didRangeBeaconsInRegion called with beacon count: "+beacons.size());
for (Beacon b : beacons) {
Log.i("foxy", "ScanBT - The first beacon " + b.toString() + " is about " + b.getDistance() + " meters away.");
}
}
}
@Override
public void onBeaconServiceConnect() {
beaconManager.addRangeNotifier(this);
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
}