«

Android:自定义输入法(输入密码时防止第三方窃取)

时间:2024-3-2 18:53     作者:韩俊     分类: Android


对于Android用户而言,一般都会使用第三方的输入法。可是,在输入密码时(尤其是支付相关的密码),使用第三方输入法有极大的安全隐患。目前很多网银类的APP和支付宝等软件在用户输入密码时,都会弹出自定义的输入法而不是直接使用系统输入法。

本文介绍的就是如何实现一个简单的自定义输入法。当然,也可以自己写一个Dialog加上几十个按钮让用户输入,只不过这样显得不够专业。

(一)首先上效果图:

1.前面两个输入框使用了自定义的输入法:


2.第三个输入框没有进行任何设置,因此将使用默认的输入法:


(二)代码简介:

1.主页面布局,由3个输入框加上一个android.inputmethodservice.KeyboardView组成。android.inputmethodservice.KeyboardView是一个系统自带的继承自View的组件,但是它不在android.view这个包下面,因此这里需要写上完整的包名。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--前两个EditText均使用自定义的输入法-->
    <EditText
        android:id="@+id/input_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:hint="one password"
        android:layout_alignParentTop="true"
        android:inputType="textPassword" />

    <EditText
        android:id="@+id/input_password2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/input_password"
        android:layout_margin="8dp"
        android:hint="another password"
        android:inputType="textPassword" />

    <!--这个EditText使用默认的输入法-->
    <EditText
        android:id="@+id/input_normal_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/input_password2"
        android:layout_margin="8dp"
        android:hint="normal text" />

    <android.inputmethodservice.KeyboardView
        android:id="@+id/keyboardview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:visibility="gone" />

</RelativeLayout>
2.KeyboardView是一个显示输入法的容器控件,使用时需要设置具体的输入法面板内容。

(1)首先在res下新建xml目录,然后创建文件keys_layout.xml,即输入法面板的内容。每个row表示一行,Keyboad的属性keyWidth和keyHeight表示每个按键的大小,25%p表示占父组件的25%. Key的属性codes表示该按键的编号(点击时系统回调方法中会返回这个值,用以区分不同的按键),keyLabel表示按键上面显示的文字。还有很多其它的属性,不再陈述。

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="25%p"
    android:keyHeight="10%p">

    <Row>
        <Key
            android:codes="55"
            android:keyLabel="7"
            android:keyEdgeFlags="left" />
        <Key
            android:codes="56"
            android:keyLabel="8" />
        <Key
            android:codes="57"
            android:keyLabel="9" />
       <!--删除按键长按时连续响应-->
        <Key
            android:codes="60001"
            android:keyLabel="DEL"
            android:isRepeatable="true" />
    </Row>
    <Row>
        <Key
            android:codes="52"
            android:keyLabel="4"
            android:keyEdgeFlags="left" />
        <Key
            android:codes="53"
            android:keyLabel="5" />
        <Key
            android:codes="54"
            android:keyLabel="6" />
        <Key
            android:codes="48"
            android:keyLabel="0" />
    </Row>
    <Row>
        <Key
            android:codes="49"
            android:keyLabel="1"
            android:keyEdgeFlags="left" />
        <Key
            android:codes="50"
            android:keyLabel="2" />
        <Key
            android:codes="51"
            android:keyLabel="3" />
        <Key
            android:codes="60002"
            android:keyLabel="Cancel" />
    </Row>
</Keyboard>
(2)为了使用方便,新建一个类:KeyboardBuilder.java,用于初始化自定义输入法和绑定EditText,代码如下:
public class KeyboardBuilder {
    private static final String TAG = "KeyboardBuilder";
    private Activity mActivity;

    private KeyboardView mKeyboardView;

    public KeyboardBuilder(Activity ac, KeyboardView keyboardView, int keyBoardXmlResId) {
        mActivity = ac;
        mKeyboardView = keyboardView;

        Keyboard mKeyboard = new Keyboard(mActivity, keyBoardXmlResId);
        // Attach the keyboard to the view
        mKeyboardView.setKeyboard(mKeyboard);
        // Do not show the preview balloons
        mKeyboardView.setPreviewEnabled(false);

        KeyboardView.OnKeyboardActionListener keyboardListener = new KeyboardView.OnKeyboardActionListener() {
            @Override
            public void onKey(int primaryCode, int[] keyCodes) {
                // Get the EditText and its Editable
                View focusCurrent = mActivity.getWindow().getCurrentFocus();
                if (focusCurrent == null || !(focusCurrent instanceof EditText)) {
                    return;
                }

                EditText edittext = (EditText) focusCurrent;
                Editable editable = edittext.getText();
                int start = edittext.getSelectionStart();

                // Handle key
                if (primaryCode == Constant.CodeCancel) {
                    hideCustomKeyboard();
                } else if (primaryCode == Constant.CodeDelete) {
                    if (editable != null && start > 0) {
                        editable.delete(start - 1, start);
                    }
                } else {
                    // Insert character
                    editable.insert(start, Character.toString((char) primaryCode));
                }
            }

            @Override
            public void onPress(int arg0) {
            }

            @Override
            public void onRelease(int primaryCode) {
            }

            @Override
            public void onText(CharSequence text) {
            }

            @Override
            public void swipeDown() {
            }

            @Override
            public void swipeLeft() {
            }

            @Override
            public void swipeRight() {
            }

            @Override
            public void swipeUp() {
            }
        };
        mKeyboardView.setOnKeyboardActionListener(keyboardListener);
    }

    //绑定一个EditText
    public void registerEditText(EditText editText) {
        // Make the custom keyboard appear
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    showCustomKeyboard(v);
                } else {
                    hideCustomKeyboard();
                }
            }
        });
        editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick");

                showCustomKeyboard(v);
            }
        });

        editText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d(TAG, "onTouch");

                EditText edittext = (EditText) v;
                int inType = edittext.getInputType();       // Backup the input type
                edittext.setInputType(InputType.TYPE_NULL); // Disable standard keyboard
                edittext.onTouchEvent(event);               // Call native handler
                edittext.setInputType(inType);              // Restore input type
                edittext.setSelection(edittext.getText().length());

                return true;
            }
        });
    }

    public void hideCustomKeyboard() {
        mKeyboardView.setVisibility(View.GONE);
        mKeyboardView.setEnabled(false);
    }

    public void showCustomKeyboard(View v) {
        mKeyboardView.setVisibility(View.VISIBLE);
        mKeyboardView.setEnabled(true);

        if (v != null) {
            ((InputMethodManager) mActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
        }
    }

    public boolean isCustomKeyboardVisible() {
        return mKeyboardView.getVisibility() == View.VISIBLE;

    }
3.最后是主Activity的代码,这里就很简单了。
/**
 * 自定义安全输入法
 */
public class MainActivity extends ActionBarActivity {
    private KeyboardBuilder builder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        KeyboardView keyboardView = (KeyboardView) findViewById(R.id.keyboardview);
        builder = new KeyboardBuilder(this, keyboardView, R.xml.keys_layout);

        EditText editText = (EditText) findViewById(R.id.input_password);
        builder.registerEditText(editText);
        EditText editText2 = (EditText) findViewById(R.id.input_password2);
        builder.registerEditText(editText2);
    }

    @Override
    public void onBackPressed() {
        if (builder != null && builder.isCustomKeyboardVisible()) {
            builder.hideCustomKeyboard();
        } else {
            this.finish();
        }
    }
}

参考文档:http://www.fampennings.nl/maarten/android/09keyboard/index.htm


标签: android

热门推荐