广播ACTION_INPUT_METHOD_CHANGED
在Android Developers ACTION_INPUT_METHOD_CHANGED中说:Broadcast Action: An input method has been changed.
。
如果输入法由A切到B,A应该能收到该广播,如果再由B切到C,还能收到吗?
我在AndroidIMESample中拉出分支验证此问题。
创建IMChangedReceiver来处理该广播:添加
onReceiver()
函数:1
2
3
4
5
6
7
8
9
10public class IMChangedReceiver extends BroadcastReceiver {
public IMChangedReceiver(){
}
public void onReceive(Context context, Intent intent){
Toast.makeText(context, "接收到IMChanged广播", Toast.LENGTH_SHORT).show();
}
}
静态注册广播
在AndroidManifest.xml
中添加如下行:1
2
3
4
5
6
7
8
9
10
11
12 ...
<application>
...
<service> ... </service>
<receiver android:name=".IMChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED"/>
</intent-filter>
</receiver>
</application>
</manifest>
执行Build
> Build APK
> Reveal in Finder
,把apk拖到模拟器里完成安装。实验结果是:
- 从
SGDXAndroidIMESample
切到别的输入法时,SGDXAndroidIMESample
能收到广播。 - 从
Android键盘(AOSP)
切到Sample Soft Keyboard
时,SGDXAndroidIMESample
也能收到广播。也就是说不管切换和被切换的输入法和SGDXAndroidIMESample
有没有关系,它都能收到切换的广播。 - 重启机器,无需先切出
SGDXAndroidIMESample
,依然是:不管切换和被切换的输入法和SGDXAndroidIMESample
有没有关系,它都能收到切换的广播。
代码详见这里
动态注册广播
删除AndroidManifest.xml
中静态注册receiver
的代码,在AndroidIMESampleService
中添加如下代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AndroidIMESampleService extends InputMethodService
implements KeyboardView.OnKeyboardActionListener {
...
private IMChangedReceiver mIMChangedReceiver = new IMChangedReceiver(); // 声明广播接收器
public View onCreateInputView() {
...
// 动态注册IMChanged广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_INPUT_METHOD_CHANGED);
registerReceiver(mIMChangedReceiver, intentFilter);
return mKeyboardView;
}
安装完成,尝试切换,实验结果是:
- 仅从
SGDXAndroidIMESample
切到别的输入法时,SGDXAndroidIMESample
才能收到广播,其它的切换均收不到。 - 重启机器,依然是:仅从
SGDXAndroidIMESample
切到别的输入法时,SGDXAndroidIMESample
才能收到广播,其它的切换均收不到。
代码详见这里
分析
也就是说如果是静态注册,只要不是被切入,输入法总能收到切换的广播;如果是动态注册,输入法仅能收到被切出的广播。
问题:输入法被切走以后进程还在吗?重启后如果不切入输入法,进程还在吗?如果在,为什么收不到动态注册的广播?如果不在,又是怎么收到静态注册广播的呢?
可以通过命令adb shell ps
来查看进程。
当输入法被设为默认
重启手机后,输入法进程就会被启动,并且Service的onStartInput()函数也会被调用:1
2
3
4
5
6
7
8
9
10adb shell ps
USER PID PPID VSZ RSS WCHAN ADDR S NAME
...
u0_a84 2185 1393 1426324 65160 SyS_epoll_wait 0 S com.palanceli.ime.androidimesample
...
adb logcat|grep "palanceli"
07-18 15:30:39.426 1495 1706 I ActivityManager: Start proc 2172:com.palanceli.ime.androidimesample/u0a84 for service com.palanceli.ime.androidimesample/.AndroidIMESampleService
07-18 15:30:40.250 2172 2172 D class com.palanceli.ime.androidimesample.AndroidIMESampleService: onStartInput:
07-18 15:30:40.637 2172 2172 D class com.palanceli.ime.androidimesample.AndroidIMESampleService: onStartInput:当输入法为非默认
重启手机后,输入法进程不会被启动,除非手动调起键盘。
如果是静态注册的BroadCastReceiver,即使进程没有启动,当广播发生时,系统会启动进程再把广播发送给它,这与输入法是否默认无关,而是静态注册BroadCastReceiver的性质。这在广播机制学习笔记(二)的源码分析中也能找到。
如果是动态注册的BroadCastReceiver,则进程必须是启动的才能收到广播。在Android源码的Activity或Service等组件被销毁时,应该能找到清理广播接收器的代码[待查]。