使用 Android Beacon 库启动和停止 Beacon 扫描器应用程序
Starting and Stopping a Beacon Scanner App with Android Beacon Library
我构建了一个小应用程序,当用户按照本教程启动应用程序时,它使用 Android 信标库查找附近的信标:http://www.software7.com/blog/creating-a-beacon-app-for-android-in-less-than-10-minutes-from-scratch/
如果应用程序已启动并且找到属于特定区域的信标,它会在控制台和文本中打印信息UI.
中的标签
我在我的 OnCreate 和 OnDestroy 方法中启动和关闭信标管理器,它管理搜索过程。
当我第一次启动应用程序时,它运行良好。但是当我用 phone 上的箭头后退按钮关闭它并 再次打开它时 ,将 不再有控制台消息 也不会更新文本标签。当屏幕进入休眠状态并且我必须再次解锁它时也会发生这种情况 - 没有控制台更新,没有 UI 更新。
根据控制台消息,OnBeaconServiceConnect 正在恢复应用程序,但我没有收到来自 didEnterRegion[=39= 的日志消息] 也不再 setRangeNotifier。
我也尝试过将绑定和解除绑定放入 OnPause 和 OnResume,但也没有成功。
如何才能正确恢复搜索和查找过程?
感谢您的帮助:)
如果您想快速浏览一下,这是我的注释代码:
package de.mediatoni.beacontut01;
import android.graphics.Region;
import android.os.RemoteException;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
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.Identifier;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import java.util.Collection;
public class BeaconActivity extends ActionBarActivity implements BeaconConsumer{
public static final String TAG = "BeaconsEverywhere";
// Beacon Manager Variable
private BeaconManager beaconManager;
//GUI Text Label
TextView rangeElement;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_beacon);
// Vars for XML Elements
rangeElement = (TextView) findViewById(R.id.range);
// Instantiate a Beacon Manager via factory method
beaconManager = BeaconManager.getInstanceForApplication(this);
// Tell Library how to decode the signal
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
// Start the Beacon Manager
beaconManager.bind(this);
}
// When the Beacon Service starts, search for Beacons with the following Identifier
@Override
public void onBeaconServiceConnect() {
final org.altbeacon.beacon.Region region = new org.altbeacon.beacon.Region("myBeacons", Identifier.parse("73676723-7400-0000-ffff-0000ffff0005"), null, null);
beaconManager.setMonitorNotifier(new MonitorNotifier() {
// If the phone enters a Beacon region
@Override
public void didEnterRegion(org.altbeacon.beacon.Region region) {
try {
Log.d(TAG, "did Enter Region");
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// If the phone leaves a Beacon region
@Override
public void didExitRegion(org.altbeacon.beacon.Region region) {
try {
Log.d(TAG, "did Exit Region");
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void didDetermineStateForRegion(int i, org.altbeacon.beacon.Region region) {
}
});
// If the phone finds a Beacon fitting the rules, print it in the console
beaconManager.setRangeNotifier(new RangeNotifier() {
@Override
//Log out welche beacons in der Nähe sind
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, org.altbeacon.beacon.Region region) {
for(final Beacon oneBeacon : beacons) {
Log.d(TAG, "distance: " + oneBeacon.getDistance() + "id: " + oneBeacon.getId1() + "/" + oneBeacon.getId2() + "/" + oneBeacon.getId3());
// Access UI thread and make changes to the UI
// Placing rangeElement.setText outside of the Runnable will crash the App
runOnUiThread(new Runnable() {
@Override
public void run() {
// Change the text label in the UI
rangeElement.setText(String.valueOf(oneBeacon.getDistance()));
}
});
}
}
});
try {
beaconManager.startMonitoringBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// When the App gets closed, stop the Beacon Manager
@Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_beacon, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
问题可能是当 Activity 重新启动时您没有收到第二次进入事件,因为信标仍然可见并且从未离开视野。从库版本 2.8 开始,除非有相应的退出事件,否则重复进入事件将被抑制。
为了在每次开始监控时都能得到一个入口事件,只需在再次开始监控之前停止对该区域的监控即可。像这样:
beaconManager.stopMonitoringBeaconsInRegion(region);
beaconManager.startMonitoringBeaconsInRegion(region);
我构建了一个小应用程序,当用户按照本教程启动应用程序时,它使用 Android 信标库查找附近的信标:http://www.software7.com/blog/creating-a-beacon-app-for-android-in-less-than-10-minutes-from-scratch/
如果应用程序已启动并且找到属于特定区域的信标,它会在控制台和文本中打印信息UI.
中的标签我在我的 OnCreate 和 OnDestroy 方法中启动和关闭信标管理器,它管理搜索过程。
当我第一次启动应用程序时,它运行良好。但是当我用 phone 上的箭头后退按钮关闭它并 再次打开它时 ,将 不再有控制台消息 也不会更新文本标签。当屏幕进入休眠状态并且我必须再次解锁它时也会发生这种情况 - 没有控制台更新,没有 UI 更新。
根据控制台消息,OnBeaconServiceConnect 正在恢复应用程序,但我没有收到来自 didEnterRegion[=39= 的日志消息] 也不再 setRangeNotifier。
我也尝试过将绑定和解除绑定放入 OnPause 和 OnResume,但也没有成功。
如何才能正确恢复搜索和查找过程? 感谢您的帮助:)
如果您想快速浏览一下,这是我的注释代码:
package de.mediatoni.beacontut01;
import android.graphics.Region;
import android.os.RemoteException;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
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.Identifier;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import java.util.Collection;
public class BeaconActivity extends ActionBarActivity implements BeaconConsumer{
public static final String TAG = "BeaconsEverywhere";
// Beacon Manager Variable
private BeaconManager beaconManager;
//GUI Text Label
TextView rangeElement;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_beacon);
// Vars for XML Elements
rangeElement = (TextView) findViewById(R.id.range);
// Instantiate a Beacon Manager via factory method
beaconManager = BeaconManager.getInstanceForApplication(this);
// Tell Library how to decode the signal
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
// Start the Beacon Manager
beaconManager.bind(this);
}
// When the Beacon Service starts, search for Beacons with the following Identifier
@Override
public void onBeaconServiceConnect() {
final org.altbeacon.beacon.Region region = new org.altbeacon.beacon.Region("myBeacons", Identifier.parse("73676723-7400-0000-ffff-0000ffff0005"), null, null);
beaconManager.setMonitorNotifier(new MonitorNotifier() {
// If the phone enters a Beacon region
@Override
public void didEnterRegion(org.altbeacon.beacon.Region region) {
try {
Log.d(TAG, "did Enter Region");
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// If the phone leaves a Beacon region
@Override
public void didExitRegion(org.altbeacon.beacon.Region region) {
try {
Log.d(TAG, "did Exit Region");
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void didDetermineStateForRegion(int i, org.altbeacon.beacon.Region region) {
}
});
// If the phone finds a Beacon fitting the rules, print it in the console
beaconManager.setRangeNotifier(new RangeNotifier() {
@Override
//Log out welche beacons in der Nähe sind
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, org.altbeacon.beacon.Region region) {
for(final Beacon oneBeacon : beacons) {
Log.d(TAG, "distance: " + oneBeacon.getDistance() + "id: " + oneBeacon.getId1() + "/" + oneBeacon.getId2() + "/" + oneBeacon.getId3());
// Access UI thread and make changes to the UI
// Placing rangeElement.setText outside of the Runnable will crash the App
runOnUiThread(new Runnable() {
@Override
public void run() {
// Change the text label in the UI
rangeElement.setText(String.valueOf(oneBeacon.getDistance()));
}
});
}
}
});
try {
beaconManager.startMonitoringBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// When the App gets closed, stop the Beacon Manager
@Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_beacon, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
问题可能是当 Activity 重新启动时您没有收到第二次进入事件,因为信标仍然可见并且从未离开视野。从库版本 2.8 开始,除非有相应的退出事件,否则重复进入事件将被抑制。
为了在每次开始监控时都能得到一个入口事件,只需在再次开始监控之前停止对该区域的监控即可。像这样:
beaconManager.stopMonitoringBeaconsInRegion(region);
beaconManager.startMonitoringBeaconsInRegion(region);