Android7.0 系統添加默認輸入法

需求

    將我們自己的輸入法加到系統中,並設置成默認輸入法。


具體實現

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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章