I am trying to understand and resolve and error I am seeing in the Eclipse workspace log while working on an Android app that implements an IME. I am new to Android and Eclipse.
The error is "com.utterkaos.keyboard.LatinKeyboardView failed to instantiate."
The associated stack trace is:
java.lang.UnsupportedOperationException: Unsupported Service: audio at com.android.layoutlib.bridge.android.BridgeContext.getSystemService(BridgeContext.java:434) at android.inputmethodservice.KeyboardView.(KeyboardView.java:376) at android.inputmethodservice.KeyboardView.(KeyboardView.java:279) at com.utterkaos.keyboard.LatinKeyboardView.(LatinKeyboardView.java:30) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:402) at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:166) at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207) at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135) at android.view.LayoutInflater.inflate(LayoutInflater.java:466) at android.view.LayoutInflater.inflate(LayoutInflater.java:372) at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:321) at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:324) at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325) at com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService.createRenderSession(RenderService.java:372) at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.renderWithBridge(GraphicalEditorPart.java:1361) at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.recomputeLayout(GraphicalEditorPart.java:1115) at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.activated(GraphicalEditorPart.java:941) at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegatePageChange(LayoutEditorDelegate.java:450) at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.pageChange(CommonXmlEditor.java:358) at org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1067) at org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:607) at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.selectDefaultPage(AndroidXmlEditor.java:380) at com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:285) at com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283) at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) at org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) at org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:355) at org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164) at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) at org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251) at org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376) at org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart$4.open(PackageExplorerPart.java:538) at org.eclipse.ui.OpenAndLinkWithEditorHelper$InternalListener.open(OpenAndLinkWithEditorHelper.java:48) at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864) at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152) at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1256) at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275) at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4165) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3754) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) at org.eclipse.equinox.launcher.Main.run(Main.java:1410) at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
The relevant part of LatinKeyboardView.java is:
public class LatinKeyboardView extends KeyboardView {
static final int KEYCODE_OPTIONS = -100;
public LatinKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
Line 30 is "super(context, attrs);"
Looking at KeyboardView.java, line 376:
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
Here "Context.AUDIO_SERVICE" appears to be the string "audio", which appears in the error stack trace.
The relevant bit of BridgeContext.java is:
public Object getSystemService(String service) {
414 if (LAYOUT_INFLATER_SERVICE.equals(service)) {
415 return mBridgeInflater;
416 }
417
418 if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
419 // we need to return a valid service to avoid NPE
420 return TextServicesManager.getInstance();
421 }
422
423 // AutoCompleteTextView and MultiAutoCompleteTextView want a window
424 // service. We don't have any but it's not worth an exception.
425 if (WINDOW_SERVICE.equals(service)) {
426 return null;
427 }
428
429 // needed by SearchView
430 if (INPUT_METHOD_SERVICE.equals(service)) {
431 return null;
432 }
433
434 throw new UnsupportedOperationException("Unsupported Service: " + service);
435 }
What I find particularly puzzling in this routine is that I don't see how it could ever handle the "audio" service, yet BridgeContext.java and KeyboardView.java are both part of the Android code, not classes I have written incorrectly.
Any pointers to help me understand why this error is occurring and how to avoid it would be much appreciated.
Are you using API 14 or higher? If so thats the problem. I guess it is a bug in that version. In API 11 it works.
If you try API 11 you have to do some hack with overriding the getResources() method. Check this for more info. After this it will work.
Actually i think there is no way to jump through this from your LatinKeyboardView on API 14 (or maybe higher) because you can not even use the isInEditMode() because you definitely have to invoke the View's constructor with super. And that constructor will try to get the audio system service which just simply fails because i guess you try to run this in eclipse graphical editor (actually i got this error when i tried to place my custom view into a layout in the grapical layout editor)
I think that the only way to hack this is to implement your own KeyboardView without the getSystemService. Maybe should not call that method if isInEditMode == true.
I've had this issue in the past, now I updated to Android Studio 3.0.1 and I cannot reproduce any more (may have been fixed a long time ago, I didn't open this project for a while).
Two configurations I tried with AS3:
There was probably a change in how Android Studio's Preview pane works.
I improved the solution by @Enyvy by extending ContextWrapper instead of Context (far less code). Uses ContextWrapper class with delegation of all methods to the base Context, except for the getService() method that is forbid to ask for "audio":
Next step is create own class extends KeyboardView:
And use
KeyboardViewFix
as replaceKeyboardView
.One note: On start your app, before any other code you need set
KeyboardViewFix.inEditMode = false;
or you can get some errors.I found solution.
Use
KeyboardViewFix
as replaceKeyboardView
:One note: On start your app, before any other code you need set
KeyboardViewFix.inEditMode = false;
or you can get some errors.This is a bug in android.inputmethodservice.KeyboardView
The failing code is
It should be wrapped in
isInEditMode()
check to skip getting audio manager during layout editing. Strange but I cannot find any issue reported in the Android bug tracker!