Android - Unsupported Service: audio

后端 未结 5 1203
挽巷
挽巷 2021-01-04 05:42

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 Ecli

相关标签:
5条回答
  • 2021-01-04 06:21

    This is a bug in android.inputmethodservice.KeyboardView

    The failing code is

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

    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!

    0 讨论(0)
  • 2021-01-04 06:25

    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.

    0 讨论(0)
  • 2021-01-04 06:34

    I found solution.

    Use KeyboardViewFix as replace 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);
            }       
        }
    }
    

    One note: On start your app, before any other code you need set KeyboardViewFix.inEditMode = false; or you can get some errors.

    0 讨论(0)
  • 2021-01-04 06:34

    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":

    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);
        }
    }
    

    Next step is create own class extends 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);
        }
    
    }
    

    And use KeyboardViewFix as replace KeyboardView.

    One note: On start your app, before any other code you need set KeyboardViewFix.inEditMode = false; or you can get some errors.

    0 讨论(0)
  • 2021-01-04 06:38

    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:

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

    There was probably a change in how Android Studio's Preview pane works.

    0 讨论(0)
提交回复
热议问题