Android Lollipop - 服务意图必须明确

时间:2015-03-02 15:12:24

标签: android android-intent service bluetooth android-5.0-lollipop

我对Lollipop和显式意图有(我肯定是一个简单的)问题。我已经构建了一个通过蓝牙连接与打印机通信的应用程序 - 这在Lollipop以下的任何地方都能正常工作。

我已经检查过各种其他答案和Android文档,但看不出他们创建显式意图的方式与我这样做的方式之间有任何区别。

logcat的错误如下:

03-02 14:35:43.471: E/AndroidRuntime(28094): FATAL EXCEPTION: main
03-02 14:35:43.471: E/AndroidRuntime(28094): Process: com.example.app, PID: 28094
03-02 14:35:43.471: E/AndroidRuntime(28094): java.lang.RuntimeException: Error receiving broadcast Intent { act=printing flg=0x10 (has extras) } in com.example.app.AppName$1@351d4863
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:969)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Handler.handleCallback(Handler.java:739)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Handler.dispatchMessage(Handler.java:95)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.os.Looper.loop(Looper.java:155)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ActivityThread.main(ActivityThread.java:5696)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at java.lang.reflect.Method.invoke(Native Method)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at java.lang.reflect.Method.invoke(Method.java:372)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
03-02 14:35:43.471: E/AndroidRuntime(28094): Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=printing flg=0x10 (has extras) }
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1786)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.stopServiceCommon(ContextImpl.java:1844)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.ContextImpl.stopService(ContextImpl.java:1805)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.content.ContextWrapper.stopService(ContextWrapper.java:520)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at com.example.app.AppName$1.onReceive(ExampleClass.java:530)
03-02 14:35:43.471: E/AndroidRuntime(28094):    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:950)
03-02 14:35:43.471: E/AndroidRuntime(28094):    
... 8 more

我从其他3个活动中调用此函数,因此将其放在自己的类中并通过执行以下操作调用它:

// In the activity I call it from
ExampleClass example = new Example(this);
example.print(); // Function in the example class

然后在这个打印功能中:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PRINT_ACTION);
ctx.registerReceiver(intentReciever, intentFilter); // Where ctx is the context                 
Intent i = new Intent(ctx, printerService.class);
i.putExtras(bundle);
ctx.startService(i); // Start the relevant service

android文档:

  

Intent downloadIntent = new Intent(this,DownloadService.class);   downloadIntent.setData(Uri.parse(fileUrl));   startService(downloadIntent);

setDataputExtras外,我看不出任何差异。

与上述(广播接收器)在同一类中:

private BroadcastReceiver intentReciever = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        context.unregisterReceiver(intentReciever);
        context.stopService(intent); // If I remove this, I get multiple returns, but if I leave it - it crashes :(
    }
};

在printerClass.class(intentService)文件中,我有:

Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ExampleClass.PRINT_ACTION);
broadcastIntent.putExtras(ReceivedBundle); // Put all the received data back in and send back!
getBaseContext().sendBroadcast(broadcastIntent);

对我而言,这看起来服务已经明确但显然不是!

这个问题似乎正处于回归之中,但我却迷失了它的不真实!任何对此的帮助都将受到大力赞赏。

1 个答案:

答案 0 :(得分:0)

您的onReceive()方法执行此操作:

public void onReceive(Context context, Intent intent) {
    context.unregisterReceiver(intentReciever);
    context.stopService(intent); // If I remove this, I get multiple returns, but if I leave it - it crashes :(
}

使用stopService()启动的Intent来调用BroadcastReceiver(广播Intent)。如果您查看创建广播Intent的代码,它看起来像这样:

Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ExampleClass.PRINT_ACTION);
broadcastIntent.putExtras(ReceivedBundle);

Intent只有一个ACTION和EXTRAS。它是隐式Intent,而非显式Intent

注意:这个"工作"在其他平台上,因为它根本没有实际停止Service。调用stopService()的代码无效,因为没有Service响应Intent

在Android 5上,由于服务隐式stopService()的安全性收紧,对Intent的调用引发了异常。