解決Service Intent must be explicit 崩潰問題

解決Service Intent must be explicit 崩潰問題

Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.wang.ordermanager.OrderService }

今天在寫一個app間通信的功能時,出現了些小問題,客戶端通過aidl綁定服務端的服務,結果在client端應用啓動時出現了崩潰,最初代碼是這樣寫的:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    Intent intent = new Intent("com.example.wang.ordermanager.OrderService");
    bindService(intent, conn, Context.BIND_AUTO_CREATE);
}

錯誤log如下:

04-15 02:26:19.114 1747-1747/? E/uncaughtException: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.wang.client/com.example.wang.client.MainActivity}: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.wang.ordermanager.OrderService }
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2444)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2504)
        at android.app.ActivityThread.access$900(ActivityThread.java:165)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:150)
        at android.app.ActivityThread.main(ActivityThread.java:5546)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
     Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.wang.ordermanager.OrderService }
        at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1366)
        at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1465)
        at android.app.ContextImpl.bindService(ContextImpl.java:1443)
        at android.content.ContextWrapper.bindService(ContextWrapper.java:604)
        at com.example.wang.client.MainActivity.onCreate(MainActivity.java:68)
        at android.app.Activity.performCreate(Activity.java:6367)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2504) 
        at android.app.ActivityThread.access$900(ActivityThread.java:165) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:150) 
        at android.app.ActivityThread.main(ActivityThread.java:5546) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684) 

跟了一下源碼,發現在ContextImpl中有如下的判斷:

@Override
public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
            Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
    ...
    validateServiceIntent(service);
    ...
}

private void validateServiceIntent(Intent service) {
    if (service.getComponent() == null && service.getPackage() == null) {
        if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
            IllegalArgumentException ex = new IllegalArgumentException(
                        "Service Intent must be explicit: " + service);
            throw ex;
        } else {
            Log.w(TAG, "Implicit intents with startService are not safe: " + service
                    + " " + Debug.getCallers(2, 3));
        }
    }
}

由此可見,在Android5.0中增加了對intent的判斷,因爲intent是通過設置action得到的,因此沒有Component對象的實例,也沒有包名,故而報錯。原因找到,增加了一個設置包名的步驟,而且需要是App的包名,而不是Service類所在包的包名,即可順利解決,代碼如下:

Intent intent = new Intent("com.example.wang.ordermanager.OrderService");
        intent.setPackage("com.example.wang.ordermanager");
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章