需求
將我們自己的輸入法加到系統中,並設置成默認輸入法。
具體實現
1、將輸入法編入系統,一般可以將應用放到package/app/目錄下,mk文件如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyIME
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)
2、設置爲默認輸入法,diff如下:
------------ base/packages/SettingsProvider/res/values/defaults.xml ------------
index 9b50dc0..d46038c 100644
<!-- Default for Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED -->
<integer name="def_captive_portal_detection_enabled" translatable="false">1</integer>
+
+ <string name="config_default_input_method" translatable="false">com.test.myime/.MyIMEService</string>
+ <string name="config_enable_input_methods" translatable="false">com.test.myime/.MyIMEService</string>
</resources>
base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 998efd9..fcd5555 100644
@@ -2457,22 +2457,28 @@ class DatabaseHelper extends SQLiteOpenHelper {
String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
if (!TextUtils.isEmpty(wifiWatchList)) {
loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
}
// Don't do this. The SystemServer will initialize ADB_ENABLED from a
// persistent system property instead.
//loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
// Allow mock locations default, based on build
+
+ loadStringSetting(stmt, Settings.Secure.DEFAULT_INPUT_METHOD,
+ R.string.config_default_input_method );
+ loadStringSetting(stmt, Settings.Secure.ENABLED_INPUT_METHODS,
+ R.string.config_enable_input_methods );
+
loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
"1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
loadSecure35Settings(stmt);
loadBooleanSetting(stmt, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
R.bool.def_mount_play_notification_snd);
loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_AUTOSTART,
R.bool.def_mount_ums_autostart);
這個修改其實就是讓SettingProvider讀取配置並加到數據庫中,然後由InputMethodService來加載默認輸入法。bug處理
以上的修改如果是對於6.0系統就已經OK了,但是7.0有不一樣的地方。經過分析,原來是當手機已經通電開機但是用戶並有解鎖鎖屏的時候,Android N運行於一個安全的模式,也就是Dierect Boot模式。一般情況下,應用是無法在Direct Boot模式下運行的,如果需要某個app能夠在Direct Boot模式下運行,需要註冊相關APP的組件。
應用組件申請在Direct Boot模式下運行:在AndroidManinfest.xml中設置 android:directBootAware="true"。
在分析7.0過程中發現在啓動Launcher之前會先啓動一個FallbackHome,之後纔會啓動Launcher,通過調查發現FallbackHome屬於Settings中的一個activity,Settings的android:directBootAware爲true,並且FallbackHome在category中配置:
<application android:label="@string/settings_label"
android:icon="@mipmap/ic_launcher_settings"
............
android:directBootAware="true">
<!-- Triggered when user-selected home app isn't encryption aware -->
<activity android:name=".FallbackHome"
android:excludeFromRecents="true"
android:theme="@style/FallbackHome">
<intent-filter android:priority="-1000">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
所以在ActivityManagerService啓動Home界面時,從PackageManagerService中獲取到的Home界面就是FallbackHome。
這個安全模式就會導致我的輸入法在系統起來的時候服務沒起來,進而導致輸入法彈不出來。
解決方法
在輸入法的AndroidManifest.xml中聲明android:directBootAware爲true。