Java 权限拒绝错误 - SpeechRecognizer 作为持续服务?(android.permission.INTERACT_ACROSS_USERS_FULL)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20562874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Permission Denial Error - SpeechRecognizer as a continuous service? (android.permission.INTERACT_ACROSS_USERS_FULL)
提问by Aki008
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
编辑:我已经更改了我的服务代码以实现作为启动服务而不是 IntentService 作为下面更新的 StreamService.java 现在,我收到关于 StreamService.java 之后的 logcat 消息中描述的权限拒绝错误的错误
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
我已经实现了包含所有 UI 组件的 MainActivity 类。类如下
CODE - MainActivity.java
代码 - 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
我已经实现的另一个类通过继承 IntentService 类来启动语音识别服务作为后台任务。实现如下
Code - StreamService.java
代码 - 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
在这里我收到错误 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
ImageButton->onClick()->Fire the service Intent for StreamService.class->onCreate()->onHandleIntent()->calling startStreaming() -> 获取错误
LogCat Message:
LogCat 消息:
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)
回答by Khay
well the problem is self solution explaining , the first line in your logCat is giving you the solution that, the current thread does not have the permission for executing user task , so just add the following permission in manifest and see if it works out .
好吧,问题是自我解决方案的解释,您的 logCat 中的第一行为您提供了解决方案,即当前线程没有执行用户任务的权限,因此只需在清单中添加以下权限,看看它是否有效。
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL">
lemme know if I had understood the problem correctly
让我知道我是否正确理解了问题
回答by Kevin Hunter
There are times when this particular error is actually misleading, and is caused by other runtime problems.
有时,此特定错误实际上具有误导性,并且是由其他运行时问题引起的。
I documented one such example here- a NullPointerException thrown down deep ended up being reported as this same error, even though it had nothing to do with cross-user permissions.
我在这里记录了一个这样的例子——一个 NullPointerException 被抛出很深,最终被报告为同样的错误,即使它与跨用户权限无关。
In my particular case, ProGuard was stripping out a method that I needed, which caused a NullPointerException to be thrown. The stack trace looked like this:
在我的特殊情况下,ProGuard 剥离了我需要的方法,这导致抛出 NullPointerException。堆栈跟踪如下所示:
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
java.lang.NullPointerException
at java.lang.Enum.create(Enum.java:43)
at java.lang.Enum.create(Enum.java:35)
at libcore.util.BasicLruCache.get(BasicLruCache.java:54)
at java.lang.Enum.getSharedConstants(Enum.java:209)
at java.lang.Enum.valueOf(Enum.java:189)
at com.my.app.package.b.c.a(Unknown Source)
at com.my.app.package.b.a.onCreate(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
at android.support.v4.app.BackStackRecord.run(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5455)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
at dalvik.system.NativeStart.main(Native Method)
I haven't a clue in the world why Android turned the NullPointerException into the android.permission.INTERACT_ACROSS_USERS_FULL error, but the obvious solution was to tweak the ProGuard configuration so that the method wasn't being stripped.
我不知道为什么 Android 将 NullPointerException 转换为 android.permission.INTERACT_ACROSS_USERS_FULL 错误,但显而易见的解决方案是调整 ProGuard 配置,以便该方法不会被剥离。
The method I was calling that wasn't there was the "valueOf" method on an enum. It turns out that there's some interesting reflection involved under the hood (which I go into at the link above), but the solution for me was to add the following to my ProGuard configuration.
我调用的方法不存在枚举上的“valueOf”方法。事实证明,引擎盖下涉及一些有趣的反射(我在上面的链接中进行了介绍),但我的解决方案是将以下内容添加到我的 ProGuard 配置中。
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}