Android - 不支持的服务:音频

时间:2012-06-18 20:34:44

标签: android audio ime

我正在尝试理解并解决我在Eclipse工作区日志中看到的错误,同时处理实现IME的Android应用程序。我是Android和Eclipse的新手。

错误是" com.utterkaos.keyboard.LatinKeyboardView无法实例化。"

关联的堆栈跟踪是:

  

java.lang.UnsupportedOperationException:不支持的服务:音频     在   com.android.layoutlib.bridge.android.BridgeContext.getSystemService(BridgeContext.java:434)     在   android.inputmethodservice.KeyboardView。(KeyboardView.java:376)     在   android.inputmethodservice.KeyboardView。(KeyboardView.java:279)     在   com.utterkaos.keyboard.LatinKeyboardView。(LatinKeyboardView.java:30)     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native   方法)at   sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown   来自java.lang.reflect.Constructor.newInstance(未知来源)     在   com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:402)     在   com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:166)     在   android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207)     在   android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135)     在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)     在com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:324)     在   com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325)     在   com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService.createRenderSession(RenderService.java:372)     在   com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.renderWithBridge(GraphicalEditorPart.java:1361)     在   com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.recomputeLayout(GraphicalEditorPart.java:1115)     在   com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.activated(GraphicalEditorPart.java:941)     在   com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate.delegatePageChange(LayoutEditorDelegate.java:450)     在   com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.pageChange(CommonXmlEditor.java:358)     在   org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1067)     在   org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:607)     在   com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.selectDefaultPage(AndroidXmlEditor.java:380)     在   com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor.addPages(AndroidXmlEditor.java:285)     在   com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor.addPages(CommonXmlEditor.java:283)     在   org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138)     在   org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348)     在   org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670)     在   org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465)     在   org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595)     在   org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289)     在   org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945)     在   org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850)     在   org.eclipse.ui.internal.WorkbenchPage.access $ 11(WorkbenchPage.java:2842)     在   org.eclipse.ui.internal.WorkbenchPage $ 10.run(WorkbenchPage.java:2793)     在   org.eclipse.swt.custom.BusyIndi​​cator.showWhile(BusyIndi​​cator.java:70)     在   org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789)     在   org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773)     在   org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764)     在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)     在   org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor(EditorUtility.java:164)     在org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249)at   org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:228)at at   org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun(SelectionDispatchAction.java:275)     在   org.eclipse.jdt.ui.actions.SelectionDispatchAction.run(SelectionDispatchAction.java:251)     在   org.eclipse.jdt.internal.ui.packageview.PackageExplorerActionGroup.handleOpen(PackageExplorerActionGroup.java:376)     在   org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart $ 4.open(PackageExplorerPart.java:538)     在   org.eclipse.ui.OpenAndLinkWithEditorHelper $ InternalListener.open(OpenAndLinkWithEditorHelper.java:48)     在   org.eclipse.jface.viewers.StructuredViewer $ 2.run(StructuredViewer.java:866)     在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 at   org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:864)     在   org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1152)     在   org.eclipse.jface.viewers.StructuredViewer $ 6.handleOpen(StructuredViewer.java:1256)     在   org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:275)     在   org.eclipse.jface.util.OpenStrategy.access $ 2(OpenStrategy.java:269)     在   org.eclipse.jface.util.OpenStrategy $ 1.handleEvent(OpenStrategy.java:309)     在org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)     在org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)at   org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4165)     在org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3754)     在   org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701)     在org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)at   org.eclipse.ui.internal.Workbench.access $ 4(Workbench.java:2499)at at   org.eclipse.ui.internal.Workbench $ 7.run(Workbench.java:679)at   org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)     在   org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)     在   org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)     在   org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)     在   org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)     在   org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)     在   org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)     在   org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)     在   org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)at   sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)at   java.lang.reflect.Method.invoke(未知来源)at   org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)at at   org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)at at   org.eclipse.equinox.launcher.Main.run(Main.java:1410)at   org.eclipse.equinox.launcher.Main.main(Main.java:1386)

LatinKeyboardView.java的相关部分是:

public class LatinKeyboardView extends KeyboardView {

    static final int KEYCODE_OPTIONS = -100;

    public LatinKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);

}

第30行是" super(context,attrs);"

查看KeyboardView.java,第376行:

mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

这里" Context.AUDIO_SERVICE"似乎是字符串" audio",它出现在错误堆栈跟踪中。

BridgeContext.java的相关位是:

    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    }

我觉得在这个例行程序中特别令人费解的是,我不知道它如何处理音频"服务,但BridgeContext.java和KeyboardView.java都是Android代码的一部分,而不是我编写错误的类。

有任何指示可以帮助我理解为什么会出现这种错误以及如何避免错误。

5 个答案:

答案 0 :(得分:4)

您使用的是API 14或更高版本吗?如果是这样就是问题所在。我想这是该版本中的一个错误。在API 11中它可以工作。

如果您尝试使用API​​ 11,则需要重写getResources()方法。查看this了解详情。在此之后它将起作用。

实际上我认为没有办法从API 14上的LatinKeyboardView(或者更高版本)跳过这个,因为你甚至不能使用isInEditMode()因为你必须用super调用View的构造函数。并且该构造函数将尝试获得刚刚失败的音频系统服务,因为我猜你试图在eclipse图形编辑器中运行它(实际上当我试图将我的自定义视图放入图形布局编辑器中的布局时出现此错误)

我认为解决这个问题的唯一方法是在没有getSystemService的情况下实现自己的KeyboardView。如果isInEditMode == true,也许不应该调用该方法。

答案 1 :(得分:4)

这是android.inputmethodservice.KeyboardView

中的错误

失败的代码是

public KeyboardView(Context context, AttributeSet attrs, int defStyle) { 
...
    mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 
...
}

它应该包含在isInEditMode()检查中,以便在布局编辑期间跳过获取音频管理器。奇怪,但我发现Android bug跟踪器中没有任何问题报告!

答案 2 :(得分:2)

我找到了解决方案。

使用KeyboardViewFix替换KeyboardView

public class KeyboardViewFix extends KeyboardView {
    public static boolean inEditMode = true;

    @TargetApi(21) // Build.VERSION_CODES.L
    public KeyboardViewFix(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(inEditMode ? new ContextWrapperInner(context) : context, attrs, defStyleAttr, defStyleRes);
    }

    public KeyboardViewFix(Context context, AttributeSet attrs, int defStyleAttr) {
        super(inEditMode ? new ContextWrapperInner(context) : context, attrs, defStyleAttr);
    }

    public KeyboardViewFix(Context context, AttributeSet attrs) {
        super(inEditMode ? new ContextWrapperInner(context) : context, attrs);
    }

    public static class ContextWrapperInner extends ContextWrapper {
        Context base;
        public ContextWrapperInner(Context base) {
            super(base);
            this.base = base;
        }
        public Object getSystemService(String name) {
            return Context.AUDIO_SERVICE.equals(name) ? null : base.getSystemService(name);
        }       
    }
}

一个注意事项:在启动您的应用时,在您需要设置KeyboardViewFix.inEditMode = false;的任何其他代码之前,您可能会遇到一些错误。

答案 3 :(得分:1)

我通过扩展ContextWrapper而不是Context(远远少于代码)来改进@Enyvy的解决方案。 使用ContextWrapper类将所有方法委托给基本Context,但禁止请求" audio"的

的getService()方法除外
public class KeyboardViewFix extends KeyboardView {
    public static boolean inEditMode = true;

    @TargetApi(21) // Build.VERSION_CODES.L
    public KeyboardViewFix(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(new ContextWrapperFix(context, inEditMode), attrs, defStyleAttr, defStyleRes);
    }

    public KeyboardViewFix(Context context, AttributeSet attrs, int defStyleAttr) {
        super(new ContextWrapperFix(context, inEditMode), attrs, defStyleAttr);
    }

    public KeyboardViewFix(Context context, AttributeSet attrs) {
        super(new ContextWrapperFix(context, inEditMode), attrs);
    }

}

下一步是创建自己的类扩展KeyboardView:

KeyboardViewFix

并使用KeyboardView替换KeyboardViewFix.inEditMode = false;

一个注意事项:在启动您的应用时,在您需要设置{{1}}的任何其他代码之前,您可能会遇到一些错误。

答案 4 :(得分:0)

我以前遇到过这个问题,现在我更新到Android Studio 3.0.1并且我不能再复制(很久以前可能已经修复了,我暂时没有打开这个项目)。

我尝试使用AS3的两种配置:

minSdkVersion 10, compileSdkVersion 26, support library 25.4.0
minSdkVersion 14, compileSdkVersion 26, support library 27.0.2

Android Studio预览窗格的工作方式可能发生了变化。