EDITED: I have changed my service code to implement as started service instead of IntentService as updated StreamService.java below Now, I am getting error regarding permission denial error as described in logcat messages after StreamService.java
EDITED:
As mentioned in Android Developer site that SpeechRecognizer API can only be used as Application Context. Is there any woraround with which I can get it working
I have implemented MainActivity class that has all the UI Components. Class is as below
CODE - MainActivity.java
package com.example.speechsensorservice;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "SpeechSensor";
private boolean headsetConnected = false;
public TextView txtText;
private BroadcastReceiver mReceiver;
private ImageButton btnSpeak;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtText = (TextView) findViewById(R.id.txtText);
btnSpeak = (ImageButton) findViewById(R.id.btnSpeak);
btnSpeak.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(),StreamService.class);
startService(intent);
}
});
}
protected void onResume() {
super.onResume();
IntentFilter sIF = new IntentFilter();
sIF.addAction(Intent.ACTION_HEADSET_PLUG);
sIF.addAction("com.example.speechsensorservice.TEXT");
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
String act = arg1.getAction();
Log.d(TAG, "Received Action = " + act);
if ( Intent.ACTION_HEADSET_PLUG.equals(act) ) {
if ( arg1.hasExtra("state")) {
if ( !headsetConnected && arg1.getIntExtra("state", 0) == 1 ) {
headsetConnected = true;
txtText.setText("Headset Plugged in");
startNoiseProcessService();
}
}
}
else if ( act.equals("com.example.speechsensorservice.TEXT") ){
if ( arg1.hasExtra("Identity")) {
String s = arg1.getStringExtra("Identity");
if ( s.equals("NA") ) {
Toast t = Toast.makeText(getApplicationContext(),
"Your Device doesnot support Speech to Text",
Toast.LENGTH_SHORT);
t.show();
}
else txtText.setText(s);
}
}
}
};
this.registerReceiver(mReceiver, sIF);
}
public void onPause() {
super.onPause();
this.unregisterReceiver(this.mReceiver);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void startNoiseProcessService() {
Intent intent = new Intent(this,StreamService.class);
startService(intent);
}
}
Another class that I have implemented to start Speech Recognition Service as a background task by inheriting IntentService class. The implementation is as below
Code - StreamService.java
package com.example.speechsensorservice;
import java.util.ArrayList;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.IBinder;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
public class StreamService extends Service {
private static final String TAG = "SpeechSensor";
private static final String ACTION = "com.example.speechsensorservice.TEXT";
private SpeechRecognizer sr;
private BroadcastReceiver sReceiver;
private boolean headsetConnected = true;
String text;
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate() StreamService Method");
super.onCreate();
sReceiver = new BroadcastReceiver() {
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
if ( Intent.ACTION_HEADSET_PLUG.equals(arg1.getAction()) ) {
if ( arg1.hasExtra("state")) {
if ( headsetConnected && arg1.getIntExtra("state", 0) == 0 ) {
headsetConnected = false;
stopStreaming();
}
}
}
}
};
this.registerReceiver(sReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"Inside onStartCommand()");
// Runnable r = new Runnable() {
// public void run() {
startStreaming();
// }
// };
// Thread t = new Thread(r);
// t.start();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy() StreamService Method");
super.onDestroy();
this.unregisterReceiver(this.sReceiver);
}
public void startStreaming() {
Log.d(TAG, "Inside startStreaming()");
Intent intent;
text = "";
if ( !SpeechRecognizer.isRecognitionAvailable(this) ) {
Log.d(TAG, "Not Applicable with your device");
text = "NA";
intent = new Intent(ACTION);
intent.putExtra("Identity", text);
sendBroadcast(intent);
}
else {
Log.d(TAG, "started taking input");
sr = SpeechRecognizer.createSpeechRecognizer(this.getApplicationContext());
intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
//intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "hi-IN");
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");//RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);//RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
// intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);
sr.setRecognitionListener( new mylistener());
sr.startListening(intent);
}
}
public void stopStreaming() {
if ( sr == null ) return;
Log.d(TAG, "stopped taking input");
sr.cancel();
sr.destroy();
sr = null;
this.stopSelf();
}
public boolean isStreaming() {
// TODO Auto-generated method stub
Log.d(TAG,"isStreaming : YES");
if ( sr != null ) return true;
return false;
}
class mylistener implements RecognitionListener {
@Override
public void onBeginningOfSpeech() {
// TODO Auto-generated method stub
Log.d(TAG, "onBeginningOfSpeech");
}
@Override
public void onBufferReceived(byte[] arg0) {
// TODO Auto-generated method stub
}
@Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
Log.d(TAG, "onEndOfSpeech");
}
@Override
public void onError(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onEvent(int arg0, Bundle arg1) {
// TODO Auto-generated method stub
}
@Override
public void onPartialResults(Bundle arg0) {
// TODO Auto-generated method stub
}
@Override
public void onReadyForSpeech(Bundle arg0) {
// TODO Auto-generated method stub
Log.d(TAG, "onReadyForSpeech");
}
@Override
public void onResults(Bundle arg0) {
// TODO Auto-generated method stub
Log.d(TAG, "Got Results");
ArrayList<String> al = arg0.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
text = al.get(0);
for ( int i =0 ; i < al.size(); i++ ) {
Log.d(TAG,"result=" + al.get(i));
}
Intent intent = new Intent(ACTION);
intent.putExtra("Identifier", text);
sendBroadcast(intent);
// startStreaming();
}
@Override
public void onRmsChanged(float arg0) {
// TODO Auto-generated method stub
}
}
}
Here I am getting error java.lang.RuntimeException: SpeechRecognizer should be used only from the application's main thread
Code flow is like this:
ImageButton->onClick()->Fire the service Intent for StreamService.class->onCreate()->onHandleIntent()->calling startStreaming() -> getting error
LogCat Message:
12-13 17:03:24.822 794 7381 E DatabaseUtils: Writing exception to parcel
12-13 17:03:24.822 794 7381 E DatabaseUtils: java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
12-13 17:03:24.822 794 7381 E DatabaseUtils: at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:12754)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:1998)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at com.android.providers.settings.SettingsProvider.call(SettingsProvider.java:574)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at android.content.ContentProvider$Transport.call(ContentProvider.java:256)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:256)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at android.os.Binder.execTransact(Binder.java:351)
12-13 17:03:24.822 794 7381 E DatabaseUtils: at dalvik.system.NativeStart.run(Native Method)