Question

I am trying to access an InputMethodService from an Activity, and I am running into issues with the permissions. This is for a custom keyboard app.

What I am trying to achieve is to bind the text, which is created in the Activity back into the InputMethodService. The Activity is opened from the InputMethodService, then from the Activity, I try to start the Service(which may be the issue. Here is how I open the Activity from the InputMethodService:

    @Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
    super.onStartInputView(attribute, restarting);

    Intent intent = new Intent(this, MyKeyboard.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
    context.startActivity(intent);

}

Here is where I try to communicate with the InputMethodService from the Activity:

    @Override
public void onCreate(Bundle bundle){
    super.onCreate(bundle);
    setContentView(R.xml.keyboard);

    startService(new Intent(this, MyService.class));
}

Here is my Manifest File:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.my.package">
<application android:label="@string/ime_name">
    <service android:name="MyService"
            android:permission="android.permission.BIND_INPUT_METHOD">
        <intent-filter>
            <action android:name="android.view.InputMethod" />
        </intent-filter>
        <meta-data android:name="android.view.im" android:resource="@xml/method" />
    </service>
    <activity android:name=".MyKeyboard" android:theme="@style/Theme.Transparent">
    </activity>
</application>

and here is my stack trace:

11-18 15:58:34.732: E/AndroidRuntime(5458): Uncaught handler: thread main exiting due to uncaught exception
11-18 15:58:34.752: E/AndroidRuntime(5458): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mypackage/com.mypackage.MyActivity}: java.lang.SecurityException: Not allowed to start service Intent { cmp=com.mypackage/.MyService} without permission android.permission.BIND_INPUT_METHOD
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread.access$2200(ActivityThread.java:119)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.os.Looper.loop(Looper.java:123)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread.main(ActivityThread.java:4363)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at  java.lang.reflect.Method.invokeNative(Native Method)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at java.lang.reflect.Method.invoke(Method.java:521)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at dalvik.system.NativeStart.main(Native Method)
11-18 15:58:34.752: E/AndroidRuntime(5458): Caused by: java.lang.SecurityException: Not allowed to start service Intent { cmp=com.mypackage/.MyService } without permission android.permission.BIND_INPUT_METHOD
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ApplicationContext.startService(ApplicationContext.java:765)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.content.ContextWrapper.startService(ContextWrapper.java:326)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at com.mypackage.MyActivity.onCreate(MyActivity.java:94)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-18 15:58:34.752: E/AndroidRuntime(5458):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
11-18 15:58:34.752: E/AndroidRuntime(5458):     ... 11 more

Any ideas?

Was it helpful?

Solution

You can't do this. The platform requires that input method services require the BIND_INPUT_METHOD permission, and no third party applications can get that permission. This is an important security mechanism to ensure that only the platform itself can interact with an input method service, and no applications can spoof the platform while the user is interacting with the input method.

This is described in the "Security" section here: http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html

If this is some other app's input method service, that is the end of the story, the only way to interact with it is through the formal IME architecture of the platform.

If this is your own app's input method service, there are many tricks you can use to interact with it since you are running in the same process as it. The easiest is just to have it set a global variable of the service object when it is created, which you can access from elsewhere in your app.

If you really need to actually put the service in the started state... well, you can't do that, because that is not how input methods work. You will need to make a second service that you start and coordinate between the two services. Again, these should all be running in the same process, so you can take advantage of that to directly call between them to do whatever interactions you want.

OTHER TIPS

You need to add the permission.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.my.package">
<application android:label="@string/ime_name">
    <service android:name="MyService">
        <intent-filter>
            <action android:name="android.view.InputMethod" />
        </intent-filter>
        <meta-data android:name="android.view.im" android:resource="@xml/method" />
    </service>
    <activity android:name=".MyKeyboard" android:theme="@style/Theme.Transparent">
    </activity>

    <uses-permission android:name="android.permission.BIND_INPUT_METHOD"/>
</application>

You are setting it wrong.

Another suggestion: You need both the android:permission in the service and the uses-permission in the application - outside the service - at the same time

In manifest: First: remove the dot btw my and package Next - if First doesn't help: put a dot in front of service name:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top