Hello, I have searched far and wide on Google for this and have not been able to find a solution.
I am trying to register a BroadcastReceiver for a bluetooth headset state change built into a speech recognition plugin.
Everything is fine and dandy, except the BroadcastReceiver is never fired, and no errors are being thrown either.
I have looked around at plugin source code and people are using BroadcasterReceivers fine, so it doesn't seem like an incompatibility issue.
Here is the source with the issue areas highlighted. Thank you for any help you can provide!
package com.phonegap.plugins.speech;
import java.util.ArrayList;
import java.util.Locale;
import org.json.JSONArray;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import android.util.Log;
import android.app.Activity;
import android.content.Intent;
import android.speech.RecognizerIntent;
//for bluetooth
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.widget.Adapter;
import java.util.List;
import android.media.AudioManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
/**
* Style and such borrowed from the TTS and PhoneListener plugins
*/
public class SpeechRecognizer extends CordovaPlugin {
private static final String LOG_TAG = SpeechRecognizer.class.getSimpleName();
private static int REQUEST_CODE = 1001;
private CallbackContext callbackContext;
private LanguageDetailsChecker languageDetailsChecker;
/*added for bluetooth*/
public BluetoothAdapter adapter;
public BluetoothHeadset headset;
public BluetoothDevice device;
/*added for bluetooth*/
//@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
Boolean isValidAction = true;
this.callbackContext= callbackContext;
/*added for bluetooth*/
adapter = BluetoothAdapter.getDefaultAdapter();
adapter.getProfileProxy(cordova.getActivity().getApplicationContext(), serviceListener, BluetoothProfile.HEADSET);
//found this on stack overflow for registering the broadcast receiver
cordova.getActivity().getApplicationContext().registerReceiver(audioStateReceiver, new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
/////////////////////////////////////////////////////////////////////
Log.d("BLUETOOTH","broadcast receiver: " + audioStateReceiver.getResultCode());
Boolean b = headset.startVoiceRecognition(device);
Log.d("BLUETOOTH","firing on the bluetooth headset: " + b);
/*added for bluetooth*/
// Action selector
if ("startRecognize".equals(action)) {
// recognize speech
startSpeechRecognitionActivity(args);
} else if ("getSupportedLanguages".equals(action)) {
getSupportedLanguages();
} else {
// Invalid action
this.callbackContext.error("Unknown action: " + action);
isValidAction = false;
}
return isValidAction;
}
/*added for bluetooth*/
public BluetoothProfile.ServiceListener serviceListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
// here you can get the headset, by casting proxy
headset = (BluetoothHeadset)proxy;
List<BluetoothDevice> list = headset.getConnectedDevices();
for(int i = 0;i < list.size(); i++){
Log.d("BLUETOOTH",list.get(i).getName());
}
device = list.get(0); // will grab first device in list
Log.d(LOG_TAG,"connected to a device");
}
public void onServiceDisconnected(int profile) {
// cleanup
}
};
public BroadcastReceiver audioStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
/*if (state == Bluetooth.STATE_AUDIO_CONNECTED) {
// start speech recognition
Log.d("BLUETOOTH","starting the recognition with bluetooth");
}*/
Log.d("BLUETOOTH","in the broadcast receiver");
Log.d("BLUETOOTH","intent action: " + intent.getAction());
}
};
/*added for bluetooth*/
// Get the list of supported languages
private void getSupportedLanguages() {
if (languageDetailsChecker == null){
languageDetailsChecker = new LanguageDetailsChecker(callbackContext);
}
// Create and launch get languages intent
Intent detailsIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
cordova.getActivity().sendOrderedBroadcast(detailsIntent, null, languageDetailsChecker, null, Activity.RESULT_OK, null, null);
}
/**
* Fire an intent to start the speech recognition activity.
*
* @param args Argument array with the following string args: [req code][number of matches][prompt string]
*/
private void startSpeechRecognitionActivity(JSONArray args) {
int maxMatches = 0;
String prompt = "";
String language = Locale.getDefault().toString();
try {
if (args.length() > 0) {
// Maximum number of matches, 0 means the recognizer decides
String temp = args.getString(0);
maxMatches = Integer.parseInt(temp);
}
if (args.length() > 1) {
// Optional text prompt
prompt = args.getString(1);
}
if (args.length() > 2) {
// Optional language specified
language = args.getString(2);
}
}
catch (Exception e) {
Log.e(LOG_TAG, String.format("startSpeechRecognitionActivity exception: %s", e.toString()));
}
// Create the intent and set parameters
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
if (maxMatches > 0)
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxMatches);
if (!prompt.equals(""))
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
cordova.startActivityForResult(this, intent, REQUEST_CODE);
}
/**
* Handle the results from the recognition activity.
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
// Fill the list view with the strings the recognizer thought it could have heard
ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
returnSpeechResults(matches);
}
else {
// Failure - Let the caller know
this.callbackContext.error(Integer.toString(resultCode));
}
super.onActivityResult(requestCode, resultCode, data);
}
private void returnSpeechResults(ArrayList<String> matches) {
JSONArray jsonMatches = new JSONArray(matches);
this.callbackContext.success(jsonMatches);
}
}