Android Beacon Library - BLE beacons detecting is not working - android

I am trying to detecting beacons with Android Beacon Library in Android. I created a service which is running in background and detecting beacons.
The problem is that app is not detecting beacons when bluetooth is turned off. But if I turn on bluetooth is working properly. There is a really weird thing as well. If I turn off bluetooth again while app is running, it still continue detecting. It means that BLE detecting is working but only if I turn on bluetooth and turn it off again.
How can I enable BLE detecting? There is my implementation below. Do I miss something?
Beacon Service class
public class BeaconDiscoverer extends Service implements BeaconConsumer {
private static final String TAG = BeaconDiscoverer.class.getSimpleName();
private static BeaconManager beaconManager;
private static Region region;
private BackgroundPowerSaver backgroundPowerSaver;
public BeaconDiscoverer() {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
region = new Region("myRangingUniqueId", null, null, null);
beaconManager = BeaconManager.getInstanceForApplication(this);
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"));
configureBatterySaverMode();
beaconManager.bind(this);
}
#Override
public void onDestroy() {
beaconManager.unbind(this);
super.onDestroy();
}
private void configureBatterySaverMode() {
BeaconManager.setAndroidLScanningDisabled(true);
backgroundPowerSaver = new BackgroundPowerSaver(getApplicationContext());
// set the duration of the scan to be 5 seconds
beaconManager.setBackgroundScanPeriod(Utility.convertToMilliseconds(2));
// set the time between each scan to be 1 min (60 seconds)
beaconManager.setBackgroundBetweenScanPeriod(Utility.convertToMilliseconds(25));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "BeaconDiscoverer started up");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onBeaconServiceConnect() {
Log.d(TAG, "onBeaconServiceConnect");
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Beacon firstBeacon = beacons.iterator().next();
Log.i(TAG, "Beacon detected: " + firstBeacon.getDistance() + " m. - " + firstBeacon.getBluetoothAddress());
}
}
});
startRanging();
}
public void stopRanging() {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void startRanging() {
if (User.currentUser() == null)
return;
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
Application class
public class App extends Application {
private static final String TAG = App.class.getSimpleName();
#Override
public void onCreate() {
super.onCreate();
startService(new Intent(this, BeaconDiscoverer.class));
}
}

Simple answer: you must have Bluetooth enabled to detect beacons with the library. Beacons use Bluetooth LE to advertise their presence, and the Bluetooth radio must be on to hear the signals.
I cannot explain why you continue to detect beacons after turning off Bluetooth. One possibility is that you just see them from memory cache for the library's brief scan cycle period before they disappear. Another possibility is that the Android device is saying Bluetooth is off when you switch it off, but it is not really off.
The typical approach is to detect if Bluetooth is off when the app is launched, and prompt the user to turn it on. There is sample code in the Reference Application that does this here.

private void registerBoradcastReceiver() {
IntentFilter stateChangeFilter = new IntentFilter(
BluetoothAdapter.ACTION_STATE_CHANGED);
IntentFilter connectedFilter = new IntentFilter(
BluetoothDevice.ACTION_ACL_CONNECTED);
//IntentFilter connectedFilter = new IntentFilter(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
IntentFilter disConnectedFilter = new IntentFilter(
BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(stateChangeReceiver, stateChangeFilter);
registerReceiver(stateChangeReceiver, connectedFilter);
registerReceiver(stateChangeReceiver, disConnectedFilter);
}
private BroadcastReceiver stateChangeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED == action) {
startService;
}
if (BluetoothDevice.ACTION_ACL_DISCONNECTED == action) {
stopService;
}
if (BluetoothAdapter.ACTION_STATE_CHANGED == action) {
}
}
};

Related

iBeacons' background ranging with Altbeacon Library

I need to range beacons on the background using Altbeacons library(work properly on foreground mode)
On my android monitor the log never shows the message for the didRangeBeaconsInRegion method.
On the didEnterRegion, the messages are displayed correctly.
I tried the code below but no success, can any one guide me how to do it?
public class INBeaconApplication extends Application implements BootstrapNotifier, RangeNotifier {
private BeaconManager beaconManager;
private ArrayList<INBeacon> userBeaconArrayList;
private INBeaconUser inBeaconUser;
#Override
public void onCreate() {
super.onCreate();
Log.d("INBeacon", "Application created");
//BeaconManager and custom beaconParser layout
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.setRegionStatePeristenceEnabled(false);
//Set the BeacomManager background between scan periods
long period = 1000 * 30; //equal to 30 seconds
beaconManager.setBackgroundBetweenScanPeriod(period);
// wake up the app when a beacon is seen
Region region = new Region(Utils.REGION_ID, Identifier
.parse(Utils.INBEACON_UUID), null, null);
new RegionBootstrap(this, region);
new BackgroundPowerSaver(this);
}
boolean checkPermissionForRange(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return getApplicationContext().checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED;
}
return true;
}
#Override
public void didEnterRegion(Region region) {
Log.d("INBeacon", "didEnterRegion");
Utils.sendNotification(this, "Test");
if (checkPermissionForRange()) return;
Log.d("INBeacon", "permissions ok");
try {
beaconManager.startRangingBeaconsInRegion(region);
Log.d("INBeacon","startRanging");
} catch (RemoteException e) {
Log.e("INBeacon",e.getMessage());
}
}
#Override
public void didExitRegion(Region region) {
Log.d("INBeacon", "didExitRegion");
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
Log.d("INBeacon", "didRangeBeaconsInRegion");
ArrayList<Beacon> newBeacons = new ArrayList<>(collection);
.............code to do what i need with the beacons.....
}
It looks like the code simply needs to call:
beaconManager.setRangeNotifier(this);

Android speech recognition over Bluetooth headset sometimes omits beep to prompt user to speak

My app already does speech recognition. A user told me it didn't work with a Bluetooth headset. I was able to, mostly, get speech recognition working over the Bluetooth headset (thanks to another Stack Overflow contributor, no thanks to the official Android documentation).
There is one annoying problem, however: when switching to use the Bluetooth headset, it can obliterate audio output briefly during the switchover. In particular, it can sometimes omit the beep that ordinarily prompts the user for speech recognition.
My current workaround is to put in a one-second delay, after the Bluetooth headset has been connected to the SCO audio channel, before doing speech recognition.
My question: is there a more reliable method of avoiding this conflict?
static AudioManager sAudioManager;
static BluetoothHeadset sBluetoothHeadset;
static BluetoothDevice sBluetoothDevice;
static public void initBluetooth(Context pContext)
{
sAudioManager = (AudioManager) pContext.getSystemService(Context.AUDIO_SERVICE);
// Register to get notifications about Bluetooth profiles
sBluetoothAdapter.getProfileProxy(
pContext, new BluetoothProfileListener(), BluetoothProfile.HEADSET);
// Register to receive notification when the headset is dis/connected
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
pContext.registerReceiver(
new BluetoothHeadsetBroadcastReceiver(), intentFilter);
}
public static void startSpeechRecognition()
{
sAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
sAudioManager.startBluetoothSco();
sAudioManager.setBluetoothScoOn(true);
sBluetoothHeadset.startVoiceRecognition(sBluetoothDevice);
}
public static void stopSpeechRecognition()
{
sBluetoothHeadset.stopVoiceRecognition(sBluetoothDevice);
sAudioManager.stopBluetoothSco();
sAudioManager.setBluetoothScoOn(false);
sAudioManager.setMode(AudioManager.MODE_NORMAL);
}
static public void doSpeechRecognition(Context pContext)
{
SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(pContext);
Intent intent =
new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
sr.startListening(intent);
}
static public class BluetoothHeadsetBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context pContext, Intent pIntent)
{
int state = pIntent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)
{
// CURRENT WORKAROUND
// Delay speech recognition to avoid obliterating beep prompt
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
};
doSpeechRecognition(pContext);
}
}
}
static public class BluetoothProfileListener implements BluetoothProfile.ServiceListener
{
#Override
public void onServiceConnected(int pProfile, BluetoothProfile pProxy)
{
sBluetoothHeadset = (BluetoothHeadset) pProxy;
List<BluetoothDevice> devices = pProxy.getConnectedDevices();
int numDevices = devices.size();
if (numDevices > 0)
{
BluetoothDevice device = devices.get(0);
sBluetoothDevice = device;
}
}
}

Android create thread for pusher to run at background

In my app, I am getting my messages instantly from my server via pusher. I have created a service designated to handle connections and firing broadcast messages to other activities in my app.
The problem that I face now is to have this service run in a new thread to have it still run even when my app goes to the background. I've found from this that I should create and connect it to the "service thread", but I cannot find examples for it with pusher.
If anyone can, could you please provide an example to do so? If not, insights to writing code with these "service threads" would be helpful as well. Thanks in advance for the help :D
PusherService.java
public class PusherService extends Service {
private static final String TAG = "PusherService";
private Pusher pusher = new Pusher("myKey");
private Channel channel = pusher.subscribe("cafe_channel");
private JSONObject pusherJSONObj;
private Order order;
public PusherService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//this service will run until we stop it
setupPusher();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
private void setupPusher() {
Log.d(TAG, System.currentTimeMillis()+"");
channel.bind("customer_order", new SubscriptionEventListener() {
#Override
public void onEvent(String channelName, String eventName, final String data) {
Intent broadcastIntent = new Intent();
try {
pusherJSONObj = new JSONObject(data);
order = new Order(pusherJSONObj);
broadcastIntent.setAction("customer_order");
broadcastIntent.putExtra("message", "success");
broadcastIntent.putExtra("order", order);
} catch (JSONException e) {
e.printStackTrace();
Log.d("Pusher", "conversion failed");
broadcastIntent.setAction("customer_order");
broadcastIntent.putExtra("message", "JSON conversion error");
}
sendBroadcast(broadcastIntent);
}
});
pusher.connect();
}
}
OrdersActivity.java
private BroadcastReceiver pusherReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("customer_order")) {
adapter.newOrder((Order) intent.getParcelableExtra("order"));
}
}
};
It turns out that multithreading on one process does not solve my problem.
So instead, I split the service into a new process, which will keep the service running independent of the status of the main thread & process. Tested and found that service does not stall when my activities go background.

Updating UI from Service in Android

I have an App that Monitors room noise levels, I initially got the Code from Github, in the original code, the programmer was monitoring noise levels from Main Activity and displaying the results in textviews, but I want to monitor using a service, I have implemented everything and its working but the textviews seem to be lagging behind, lets say I make a bit of noise and the noise level reach 5, it sticks at 5 even when there is no noise in the room, but in the original app, it was so sensitive that it would go back to 0 or another value depending on the noise levels, I do not know where I have gone wrong but below is my code:
Main Activity
public class StartingPoint extends Activity {
private String volumeBars;
private String volumeLevel;
private TextView volumeBarView;
private TextView volumeLevelView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(getBaseContext(), "Loading...", Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_starting_point);
//starting Service
startService(new Intent(this, VolumeListerner.class));
volumeBarView = (TextView) findViewById(R.id.volumeBars);
volumeLevelView = (TextView) findViewById(R.id.volumeLevel);
}
#Override
public void onResume() {
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter("UI_UPDATER"));
super.onResume();
// Sound based code
}
#Override
public void onPause() {
super.onPause();
}
public void updateTextView() {
volumeBarView.setText(volumeBars);
volumeLevelView.setText(volumeLevel);
return;
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
volumeBars = intent.getStringExtra("VolumeBars");
volumeLevel = intent.getStringExtra("volumeLevel");
Log.d("receiver", "Got message: " + volumeBars + " : " + volumeLevel);
updateTextView();
}
};
Service:
public class VolumeListerner extends Service {
private static String volumeVisual = "";
private static int volumeToSend;
private Handler handler;
private SoundMeter mSensor;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
/** The service is starting, due to a call to startService() */
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
soundLevelCheck();
return super.onStartCommand(intent, flags, startId);
}
private void soundLevelCheck()
{
mSensor = new SoundMeter();
try {
mSensor.start();
Toast.makeText(getBaseContext(), "Sound sensor initiated.", Toast.LENGTH_SHORT).show();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
// Get the volume from 0 to 255 in 'int'
double volume = 10 * mSensor.getTheAmplitude() / 32768;
volumeToSend = (int) volume;
volumeVisual = "";
for( int i=0; i<volumeToSend; i++){
volumeVisual += "|";
updateUI();
}
handler.postDelayed(this, 250); // amount of delay between every cycle of volume level detection + sending the data out
}
};
// Is this line necessary? --- YES IT IS, or else the loop never runs
// this tells Java to run "r"
handler.postDelayed(r, 250);
}
private void updateUI()
{
Intent intent = new Intent( "UI_UPDATER" );
intent.putExtra("VolumeBars", "Volume Bars: " + String.valueOf(volumeVisual));
intent.putExtra("volumeLevel","Volume Levels: " + String.valueOf(volumeToSend));
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
I recommmand you to use an enhanced event bus with emphasis on Android support. you have a choice between :
1- Otto
2- Event Bus

Is it possible to have Android Voice Recognition (as a custom service) on Google Glass?

We have a demo android application (Android 4.0.3) that runs voice recognition as a service, and (continuosly) logs the results of the recognition on the view.
Everything is working fine in our smartphones.
We would like to replicate this scenario in a Google Glass immersion application, but we always have this error message when we try to start the service:
no selected voice recognition service
Are there some known limitations? Or have someone figured out how to resolve this kind of problem?
Thanks in advance
This is some significant code of the activity:
public class MainActivity extends Activity implements Observer {
...
#Override
protected void onStart() {
super.onStart();
//Toast.makeText(this, "Hi guys", Toast.LENGTH_LONG);
startService(new Intent(this, SilentVoiceRecognitionService.class));
}
...
}
And this is the code of the service:
public class SilentVoiceRecognitionService extends Service {
protected AudioManager mAudioManager;
protected SpeechRecognizer mSpeechRecognizer;
protected Intent mSpeechRecognizerIntent;
protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));
private Model model = Model.getInstance();
static final String TAG = "SilentRecognizer";
static final int MSG_RECOGNIZER_START_LISTENING = 1;
static final int MSG_RECOGNIZER_CANCEL = 2;
protected boolean mIsListening;
#Override
public void onCreate()
{
super.onCreate();
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener());
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
this.getPackageName());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
return START_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
if (mSpeechRecognizer != null)
{
mSpeechRecognizer.destroy();
}
}
protected class SpeechRecognitionListener implements RecognitionListener
{
...
}
protected static class IncomingHandler extends Handler
{
private WeakReference<SilentVoiceRecognitionService> mtarget;
IncomingHandler(SilentVoiceRecognitionService target)
{
mtarget = new WeakReference<SilentVoiceRecognitionService>(target);
}
#Override
public void handleMessage(Message msg)
{
final SilentVoiceRecognitionService target = mtarget.get();
switch (msg.what)
{
case MSG_RECOGNIZER_START_LISTENING:
if (!target.mIsListening)
{
target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent);
target.mIsListening = true;
//Log.d(TAG, "message start listening"); //$NON-NLS-1$
}
break;
case MSG_RECOGNIZER_CANCEL:
target.mSpeechRecognizer.cancel();
target.mIsListening = false;
//Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$
break;
}
}
}
}
This feature has been recently accepted but not yet available, see https://code.google.com/p/google-glass-api/issues/detail?id=245
You can load the additional mentioned apk to get the functionality for the mean time.
See Using Android Speech Recognition APIs from Google Glass
As of XE16 it is now possible to use the SpeechRecognizer directly and get the results through the SpeechRecognitionListener.
Unfortunately this still dosen't work offline.

Categories

Resources