1.概要
上一篇我们已经实现了室内定位的简单功能,接下来我们来实现怎么判断进入区域和离开区域,其实现原理也十分简单,进入区域的功能添加一个变量来进行判断就可以了,离开区域则可以根据连续搜索到的结果来进行判断,比如连续10次都搜不到我们需要的beacon标签我们则判断已经离开区域了,具体次数可以根据需求做调整,最好不要在5次以内,因为有的安卓手机搜索确实不是很稳定,有时候周围明明有很多标签,但搜到的标签个数还是为0,就可能产生错误的判断,但一般这种情况都是很快就会继续搜到标签;
刚才已经说了,安卓手机搜索不稳定,所以很有可能你搜到了离你比较近的beacon1,但有时候会蹦到beacon2或者beacon3等其他beacon标签去,然后又回到beacon1,这种用户体验是十分不好的,所以如果想搜索结果与实际出入不那么大,我们还需要做一些判断,来解决这个问题
所以这篇文章总得来说解决以下几个问题:
1.判断用户进入区域
2.判断用户离开区域
3.解决搜索不稳定的问题
2.修改
我们先把上一篇的代码修改一下,将前台搜索改成后台搜索,将MainActivity里面的beacon搜索功能挪到一个service里面去,使用EventBus让activity与service进行信息交互。先导入eventbus的库
compile 'org.greenrobot:eventbus:3.0.0'
在数据里多添加一个标签信息进行对比切换
public class BeaconLocationData {
public Map<String, Map<String, String>> locations =new HashMap<>();
public BeaconLocationData() {
initLocationData();
}
private void initLocationData() {
Map<String, String> minorLocations = new HashMap<>();
minorLocations.put("16101", "A栋 6层");
minorLocations.put("17101", "A栋 7层");
minorLocations.put("10101", "A栋 1层");
locations.put("10001", minorLocations);
}
public String getLocationMsg(String major, String minor) {
String location;
// location = locations.get(major).get(minor);
Map<String,String> minorMap = locations.get(major);
if (minorMap == null || minorMap.size() == 0) {
return "暂无位置信息";
}
location = minorMap.get(minor);
if (location == null || location.equals("")) {
return "暂无位置信息";
}
return location;
}
}
下面直接贴出MainAcitivty和service(即MyBeaconService)类的代码
public class MainActivity extends AppCompatActivity{
private static final String TAG = "MainActivity";
private TextView tvLocationMsg;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
requestLocationPermissions();
EventBus.getDefault().register(this);
}
private void requestLocationPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect beacons.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
@Override
protected void onResume() {
super.onResume();
MyBeaconService.startMyBeaconService(this);
}
private void initView() {
tvLocationMsg = (TextView) findViewById(R.id.tv_location_msg);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void eventBussCallBack(String location) {
tvLocationMsg.setText(location);
}
@Override
protected void onDestroy() {
super.onDestroy();
MyBeaconService.stopMyBeaconService(this);
}
}
public class MyBeaconService extends Service implements BeaconConsumer {
private static final long DEFAULT_FOREGROUND_SCAN_PERIOD = 1000L;
private static final long DEFAULT_FOREGROUND_BETWEEN_SCAN_PERIOD = 1000L;
private static final String TAG = "MyBeaconService";
private BeaconManager beaconManager;
/** 重新调整格式*/
public static final String IBEACON_FORMAT = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24";
/** 设置兴趣UUID*/
public static final String FILTER_UUID = "FDA50693-A4E2-4FB1-AFCF-C6EB07647825";
public BeaconLocationData beaconLocationData;
private Region region;
@Nullable
@Override
public IBinder onBind(Intent