Android BLE Scan in Background Service -
i'm trying make android app scan bluetooth device background service. once phone within range of bluetooth device, measured reading rssi, background service start activity displayed user. if phone moved out of range of bluetooth device, (after rssi value beyond threshold,) activity should killed.
here code background service:
public class beaconscanservice extends service implements bluetoothadapter.lescancallback { private service self = this; public static final string unlock = "unlock"; public static final string status = "status"; public static final string signal = "signal"; public static final string get_signal = "get_signal"; //desired device find private static final string targetmac = "e1:be:a8:1a:8b:a0"; //class handle saving rssi values , detecting bluetooth proximity private proxdetector proxy; //boolean determine if phone in bt range static boolean inprox = false; private bluetoothadapter mbluetoothadapter; @override public ibinder onbind(intent intent) { // todo auto-generated method stub return null; } @override public void oncreate() { super.oncreate(); //proximity detector proxy = new proxdetector(); final bluetoothmanager bluetoothmanager = (bluetoothmanager) getsystemservice(context.bluetooth_service); mbluetoothadapter = bluetoothmanager.getadapter(); } @override public int onstartcommand(intent intent, int flags, int startid){ /* * need enforce bluetooth first enabled, , take * user settings enable if have not done so. */ if (mbluetoothadapter == null || !mbluetoothadapter.isenabled()) { //bluetooth disabled intent enablebtintent = new intent(bluetoothadapter.action_request_enable); enablebtintent.addflags(intent.flag_activity_new_task); startactivity(enablebtintent); } /* * check bluetooth le support. in production, our manifest entry keep * installing on these devices, allow test devices or other * sideloads report whether or not feature exists. */ if (!getpackagemanager().hassystemfeature(packagemanager.feature_bluetooth_le)) { toast.maketext(this, "no le support.", toast.length_short).show(); return start_sticky; } //begin scanning le devices startscan(); return start_sticky; } @override public void ondestroy() { super.ondestroy(); //cancel scans in progress mhandler.removecallbacks(mstoprunnable); mhandler.removecallbacks(mstartrunnable); mbluetoothadapter.stoplescan(this); } private runnable mstoprunnable = new runnable() { @override public void run() { stopscan(); } }; private runnable mstartrunnable = new runnable() { @override public void run() { startscan(); } }; private void startscan() { toast.maketext(this, "scanning", toast.length_short).show(); //scan bluetooth device specified mac mbluetoothadapter.startlescan(this); mhandler.postdelayed(mstoprunnable, 5000); } private void stopscan() { toast.maketext(this, "not scanning", toast.length_short).show(); mbluetoothadapter.stoplescan(this); mhandler.postdelayed(mstartrunnable, 2500); } /* bluetoothadapter.lescancallback */ @override public void onlescan(bluetoothdevice device, int rssi, byte[] scanrecord) { /* * create new beacon , pass main thread */ toast.maketext(self, "onlescan", toast.length_short).show(); bt_beacon beacon = new bt_beacon(device.getaddress(), rssi); mhandler.sendmessage(message.obtain(null, 0, beacon)); } /* * have handler process scan results on main thread */ private handler mhandler = new handler() { @override public void handlemessage(message msg) { toast.maketext(self, "handlering", toast.length_short).show(); bt_beacon beacon = (bt_beacon) msg.obj; if(beacon.getaddress().equals(targetmac)){//only target device toast.maketext(self, string.format("%ddbm", beacon.getsignal()), toast.length_short).show(); //handle proximity detection intent i1 = new intent(unlock); proxy.processprox(beacon.getsignal()); intent i2 = new intent(signal); i2.putextra(get_signal, proxy.prox); sendbroadcast(i2); if(proxy.crossedline()){ i1.putextra(status, 1); sendbroadcast(i1); inprox = true; intent = new intent(self,myactivity.class); i.addflags(intent.flag_activity_new_task); startactivity(i); }else{ i1.putextra(status, 0); sendbroadcast(i1); inprox = false; } } } }; }
ultimately want background service started on boot, testing purposes, able create or destroy service activity should display rssi value:
public class mainactivity extends activity implements onclicklistener { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); button btnscan = (button) findviewbyid(r.id.btnscan); button btnunscan = (button) findviewbyid(r.id.btnunscan); btnscan.setonclicklistener(this); btnunscan.setonclicklistener(this); } @override protected void onresume() { super.onresume(); registerreceiver(mreceiver, new intentfilter(beaconscanservice.signal)); } @override protected void onpause() { super.onpause(); unregisterreceiver(mreceiver); } @override public void onclick(view v) { switch (v.getid()) { case r.id.btnscan: intent = new intent(this,beaconscanservice.class); startservice(i); break; case r.id.btnunscan: intent = new intent(this,beaconscanservice.class); stopservice(i); break; } } private final broadcastreceiver mreceiver = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { bundle bundle = intent.getextras(); if(bundle != null) { int sig = bundle.getint(beaconscanservice.get_signal); textview rssiview = (textview) findviewbyid(r.id.text_rssi); rssiview.settext(string.format("%ddbm", sig)); } } }; }
this layout for mainactivity:
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" android:paddingbottom="@dimen/activity_vertical_margin" tools:context=".mainactivity"> <button android:id="@+id/btnscan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="scan"/> <button android:id="@+id/btnunscan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="stop scan" android:layout_below="@+id/btnscan"/> <textview android:id="@+id/text_rssi" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:textappearance="?android:attr/textappearancelistitem" android:text="dbm" android:layout_below="@+id/btnunscan"/> </relativelayout>
in activity started , ended beaconscanservice, broadcastreceiver registered this:
@override protected void onresume() { super.onresume(); registerreceiver(beaconscanreceiver, new intentfilter(beaconscanservice.unlock)); }
and broadcastreceiver looks this:
private final broadcastreceiver beaconscanreceiver = new broadcastreceiver() { @override public void onreceive(context context, intent intent) { bundle bundle = intent.getextras(); if(bundle != null) { int status = bundle.getint(beaconscanservice.status); if(status == 0) { finish(); } } } };
when run code, can start , stop beaconscanservice fine, , know service scanning bluetooth device due debug toasts being displayed. far can tell, code breaks down somewhere in handler of service. no rssi value displayed in textview, , myactivity not started when phone brought close enough bluetooth device.
i'm not familiar interprocess communication aspects of android programming, i'm doing wrong there. thoughts?
Comments
Post a Comment