Android Framework 常见解决方案(17)Broadcast调起输入法界面并实现文本传输的方法

1 原理

  • 首先,我们要知道 如果想直接调出输入法的弹窗并显示内容,一定是通过三方输入法来操作,但是三方的输入法代码我们是无法改变的,因此要调用他们的父类中的公共接口。
  • 其次,所有的输入法应用都是要继承 InputMethodService来写,所有的三方输入法都是可以用InputMethodService方法中的getCurrentInputConnection().commitText(text,0) 方法来提交文本。
  • 最后,我们的思路就是 使用广播给InputMethodService发消息,InputMethodService收到消息后调用getCurrentInputConnection().commitText(text,0) 方法来提交并显示文本内容。

修改方案(Android Q)

发广播,在android上层使用以下方法实现广播的发送,关键代码如下所示:

//...
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class AGSManager {
	private static final String TAG = "AGSManager";
	public static int MSG_INPUT_TEXT = 1104;
	private Context mContext;
	private static final String BROADCAST_ACTION = "ags.input.text";
	//...
	public String parseInputMetodData(String val){
		//...
		//关键代码部分
		JSONObject jsonObject = new JSONObject(val);
		int id = jsonObject.getInt("event");
		if(id == MSG_INPUT_TEXT){
			JSONObject dataJsonObj = jsonObject.optJSONObject("data");
			String text = dataJsonObj.getString("text");
			Intent intent = new Intent(BROADCAST_ACTION);
			intent.putExtra("text",text);
			mContext.sendBroadcast(intent);
			return text;
		}
		//...
	}
	//...
}

收广播,在android framework层需要修改InputMethodService.java,文件对应的具体路径为:$AOSP/frameworks/base/core/java/android/inputmethodservice/InputMethodService.java。其中的修改内容如下所示:

package android.inputmethodservice;

//...
//添加广播需要的包
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;

public class InputMethodService extends AbstractInputMethodService {
    static final String TAG = "InputMethodService";
    static final boolean DEBUG = false;
	//...
    int mBackDisposition;
    private static final String BROADCAST_ACTION = "ags.input.text";
    IntentFilter mIntentFilter = null;
	//添加一个广播接受者
    private BroadcastReceiver mSeedlandTextReceiver = new BroadcastReceiver() {
    	@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if(BROADCAST_ACTION.equals(action)){
				String text = intent.getStringExtra("text");
                //提交字符串给到输入法上层显示框。
				getCurrentInputConnection().commitText(text,0);
			}
		}
    };
	//...
    @Override public void onCreate() {
        mTheme = Resources.selectSystemTheme(mTheme,
                getApplicationInfo().targetSdkVersion,
                android.R.style.Theme_InputMethod,
                android.R.style.Theme_Holo_InputMethod,
                android.R.style.Theme_DeviceDefault_InputMethod,
                android.R.style.Theme_DeviceDefault_InputMethod);
        super.setTheme(mTheme);
        super.onCreate();
        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
        mSettingsObserver = SettingsObserver.createAndRegister(this);
        // If the previous IME has occupied non-empty inset in the screen, we need to decide whether
        // we continue to use the same size of the inset or update it
        mShouldClearInsetOfPreviousIme = (mImm.getInputMethodWindowVisibleHeight() > 0);
        mInflater = (LayoutInflater)getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
                WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
        initViews();
        mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
		//添加 注册广播
		if(mIntentFilter == null){
			mIntentFilter = new IntentFilter();
			mIntentFilter.addAction(BROADCAST_ACTION);
			mIntentFilter.setPriority(Integer.MAX_VALUE);
			registerReceiver(mSeedlandTextReceiver,mIntentFilter);
		}
    }
	//...
    @Override public void onDestroy() {
        super.onDestroy();
        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                mInsetsComputer);
        doFinishInput();
        if (mWindowAdded) {
            mWindow.getWindow().setWindowAnimations(0);
            mWindow.dismiss();
        }
        if (mSettingsObserver != null) {
            mSettingsObserver.unregister();
            mSettingsObserver = null;
        }
		//添加 注销广播
		if(mIntentFilter !=null){
			unregisterReceiver(mSeedlandTextReceiver);
		}
    }
	//...
}

你可能感兴趣的:(android,常见解决方案,framework,android,java,apache)