我在Play商店发布了Android软键盘,发现以下设备在一天内发生了5次崩溃:
以下是崩溃报告:
java.lang.NullPointerException: Attempt to read from field 'int android.inputmethodservice.Keyboard$Key.width' on a null object reference
at com.sunzala.afghankeyboard.android.LatinKeyboard.setLanguageSwitchKeyVisibility(LatinKeyboard.java:93)
at com.sunzala.afghankeyboard.android.SoftKeyboard.setLatinKeyboard(SoftKeyboard.java:210)
at com.sunzala.afghankeyboard.android.SoftKeyboard.onStartInputView(SoftKeyboard.java:368)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2187)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2081)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:651)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:216)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7237)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
这是LatinKeyboard.setLanguageSwitchKeyVisibility的代码(LatinKeyboard.java:93:
public class LatinKeyboard extends Keyboard {
private Key mEnterKey;
private Key mSpaceKey;
/**
* Stores the current state of the mode change key. Its width will be dynamically updated to
* match the region of {@link #mModeChangeKey} when {@link #mModeChangeKey} becomes invisible.
*/
private Key mModeChangeKey;
/**
* Stores the current state of the language switch key (a.k.a. globe key). This should be
* returns true. When this key becomes invisible, its width will be shrunk to zero.
*/
private Key mLanguageSwitchKey;
/**
* Stores the size and other information of {@link #mModeChangeKey} when
* {@link #mLanguageSwitchKey} is visible. This should be immutable and will be used only as a
* reference size when the visibility of {@link #mLanguageSwitchKey} is changed.
*/
private Key mSavedModeChangeKey;
/**
* Stores the size and other information of {@link #mLanguageSwitchKey} when it is visible.
* This should be immutable and will be used only as a reference size when the visibility of
* {@link #mLanguageSwitchKey} is changed.
*/
private Key mSavedLanguageSwitchKey;
public LatinKeyboard(Context context, int xmlLayoutResId) {
super(context, xmlLayoutResId);
}
public LatinKeyboard(Context context, int layoutTemplateResId,
CharSequence characters, int columns, int horizontalPadding) {
super(context, layoutTemplateResId, characters, columns, horizontalPadding);
}
@Override
protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
XmlResourceParser parser) {
Key key = new LatinKey(res, parent, x, y, parser);
if (key.codes[0] == 10) {
mEnterKey = key;
} else if (key.codes[0] == ' ') {
mSpaceKey = key;
} else if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
mModeChangeKey = key;
mSavedModeChangeKey = new LatinKey(res, parent, x, y, parser);
} else if (key.codes[0] == LatinKeyboardView.KEYCODE_LANGUAGE_SWITCH) {
mLanguageSwitchKey = key;
mSavedLanguageSwitchKey = new LatinKey(res, parent, x, y, parser);
}
return key;
}
/**
* Dynamically change the visibility of the language switch key (a.k.a. globe key).
*
* @param visible True if the language switch key should be visible.
*/
void setLanguageSwitchKeyVisibility(boolean visible) {
if (visible) {
// The language switch key should be visible. Restore the size of the mode change key
// and language switch key using the saved layout.
mModeChangeKey.width = mSavedModeChangeKey.width;
mModeChangeKey.x = mSavedModeChangeKey.x;
mLanguageSwitchKey.width = mSavedLanguageSwitchKey.width;
mLanguageSwitchKey.icon = mSavedLanguageSwitchKey.icon;
mLanguageSwitchKey.iconPreview = mSavedLanguageSwitchKey.iconPreview;
} else {
// The language switch key should be hidden. Change the width of the mode change key
// to fill the space of the language key so that the user will not see any strange gap.
mModeChangeKey.width = mSavedModeChangeKey.width + mSavedLanguageSwitchKey.width;
mLanguageSwitchKey.width = 0;
mLanguageSwitchKey.icon = null;
mLanguageSwitchKey.iconPreview = null;
}
}
/**
* This looks at the ime options given by the current editor, to set the
* appropriate label on the keyboard's enter key (if it has one).
*/
void setImeOptions(Resources res, int options) {
if (mEnterKey == null) {
return;
}
switch (options & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
case EditorInfo.IME_ACTION_GO:
mEnterKey.label = null;
mEnterKey.icon = res.getDrawable(R.drawable.ic_go_circle_filled_24dp);
break;
case EditorInfo.IME_ACTION_NEXT:
mEnterKey.label = null;
mEnterKey.icon = res.getDrawable(R.drawable.ic_next_circle_filled_24dp);
break;
case EditorInfo.IME_ACTION_SEARCH:
mEnterKey.icon = res.getDrawable(R.drawable.ic_search_24dp);
mEnterKey.label = null;
break;
case EditorInfo.IME_ACTION_SEND:
mEnterKey.label = null;
mEnterKey.icon = res.getDrawable(R.drawable.ic_send_24dp);
break;
default:
mEnterKey.label = null;
mEnterKey.icon = res.getDrawable(R.drawable.ic_check_circle_24dp);
break;
}
}
void setSpaceIcon(final Drawable icon) {
if (mSpaceKey != null) {
mSpaceKey.icon = icon;
}
}
static class LatinKey extends Keyboard.Key {
public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
XmlResourceParser parser) {
super(res, parent, x, y, parser);
}
/**
* Overriding this method so that we can reduce the target area for the key that
* closes the keyboard.
*/
@Override
public boolean isInside(int x, int y) {
return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
}
}
}
以下是SoftKeyboard.setLatinKeyboard的代码(SoftKeyboard.java:210) nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
修改 我认为问题是由于以下代码引起的:
private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
boolean shouldSupportLanguageSwitchKey = true;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
shouldSupportLanguageSwitchKey = mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
}
nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
mInputView.setKeyboard(nextKeyboard);
}
我试图在Android版本5.0和6.0的模拟器上运行软键盘,但没有收到任何错误。导致错误的原因是什么?如何解决?
答案 0 :(得分:2)
您似乎根据mModeChangedKey
中的mSavedModeChangeKey
初始化key.codes
和createKeyFromXml()
,但setLanguageSwitchKeyVisibility()
将根据完全不同的参数使用其中一个密钥 - 可视性。
所以,正在发生的事情是在createKeyFromXml()
中创建了一个密钥,但在setLanguageSwitchKeyVisibility()
中使用了另一个密钥(仍为空引用)。