13

我试图理解和解决我在 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) at com.utterkaos.keyboard.LatinKeyboardView.(LatinKeyboardView.java:30) 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)在 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) at 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。com.android.ide.eclipse.adt.internal 的 com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.recomputeLayout(GraphicalEditorPart.java:1115) 的 renderWithBridge(GraphicalEditorPart.java:1361)。 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) 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) 在 org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2945) 在 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) 在 org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) 在 org.eclipse.ui.internal 的 org.eclipse.swt.custom.BusyIndi​​cator.showWhile(BusyIndi​​cator.java:70) .WorkbenchPage.openEditor(WorkbenchPage.java:2773) 在 org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) 在 org.eclipse.ui.ide.IDE.openEditor(IDE.java:651) 在org.eclipse.ui.ide.IDE.openEditor(IDE.java:610) 在 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:228) 在 org.eclipse.jdt 的 org.eclipse.jdt.ui.actions.OpenAction.run(OpenAction.java:249) .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.core.runtime.SafeRunner.run(SafeRunner.java:42) 在 org.eclipse.org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:866)。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) 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) at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:269) at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:309 ) 在 org.eclipse.swt.widgets.Display 的 org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) 的 org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)。在 org.runDeferredEvents(Display.java:4165)。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) 在 org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499) 在 org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679) 在 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.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) 中的 org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) 中。 core.runtime.internal.adaptor.EclipseAppLauncher。在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java: 344) 在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在 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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)第1386章)第1386章)110) 在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) 在 org.eclipse. .core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在 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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)110) 在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) 在 org.eclipse. .core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在 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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)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) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 在 java.lang.reflect.Method.invoke(Unknown来源)在 org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) 在 org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) 在 org.eclipse.equinox.launcher.Main .run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)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) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 在 java.lang.reflect.Method.invoke(Unknown来源)在 org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) 在 org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) 在 org.eclipse.equinox.launcher.Main .run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)java:344) 在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386 )java:344) 在 org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 在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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386 )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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 org.eclipse.equinox.launcher.Main.main(Main.java:1386)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) 在 org.eclipse.equinox.launcher.Main.run(Main.java:1410) 在 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 代码的一部分,而不是我写错的类。

任何帮助我理解为什么会发生此错误以及如何避免它的指针将不胜感激。

4

5 回答 5

4

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

如果您尝试 API 11,则必须通过覆盖 getResources() 方法来做一些修改。检查以获取更多信息。在此之后它将起作用。

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

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

于 2013-03-14T23:55:37.190 回答
4

这是android.inputmethodservice.KeyboardView中的一个错误

失败的代码是

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

它应该包含在isInEditMode()检查中以在布局编辑期间跳过获取音频管理器。奇怪,但我在 Android 错误跟踪器中找不到任何报告的问题!

于 2013-04-25T17:49:52.130 回答
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;否则您可能会遇到一些错误。

于 2015-11-28T22:29:55.480 回答
1

我通过扩展 ContextWrapper 而不是 Context(代码少得多)改进了 @Enyvy 的解决方案。使用 ContextWrapper 类,将所有方法委托给基本 Context,但禁止请求“音频”的 getService() 方法除外:

public class ContextWrapperFix extends ContextWrapper {
    private boolean editMode;

    public ContextWrapperFix(Context context, boolean editMode) {
        super(context);
        this.editMode = editMode;
    }

    public Object getSystemService(String name) {
        if (editMode && Context.AUDIO_SERVICE.equals(name)) {
            return null;
        }
        return super.getSystemService(name);
    }
}

下一步是创建自己的类扩展 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(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);
    }

}

KeyboardViewFix用作替换KeyboardView

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

于 2016-01-15T10:56:29.153 回答
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 的预览窗格的工作方式可能发生了变化。

于 2017-12-15T00:37:29.540 回答