OnHandleIntent()没有在IntentService中调用

我知道之前已经问过这个问题,但是我已经找到了我能找到的所有答案,但仍然无法解决问题。

问题是当BroadcastReceiver启动时,不会调用IntentService onHandleIntent()。 奇怪的是构造函数运行(我可以通过Log输出看到)。 这是我的代码:

NoLiSeA.class (此类包含启动我的服务的BroadcastReceiver)

public void toProcess(StatusBarNotification sbn) { LocalBroadcastManager.getInstance(this).registerReceiver(notificationForwarder, new IntentFilter("to_forward")); Intent intent = new Intent("to_forward"); intent.putExtra("sbn", sbn); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); Log.i("NoLiSe.TAG", "toProcess"); } private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i("NoLiSe.TAG", "BroadCastReceiver.onReceive"); Intent i = new Intent(context, CoreTwoA.class); i.putExtras(intent); startService(i); } } }; 

CoreTwoA.class (这是IntentService。onHandleIntent()没有被调用,因为我可以看到,因为控制台中没有日志文本。)

 public class CoreTwoA extends IntentService { private TextToSpeech mtts; public CoreTwoA() { super("TheCoreWorker"); Log.d("source", "exception", new Exception()); Log.i("CoreTwoA.TAG", "Constructor"); } @Override protected void onHandleIntent(Intent intent) { Log.i("CoreTwoA.TAG", "onHandleIntent"); } } 

AndroidManifest.xml中

    

UPDATE

因此,基于下面的讨论,我能够将问题缩小到BroadCastReceiver中的以下代码行:

 i.putExtra("sbn", sbn) 

如果我删除它,即添加没有额外的意图,那么我的IntentService中的onHandleIntent()方法确实运行。

如果包含它,则onHandleIntent()不会运行,并且我的IntentService的构造函数中的Log.d()将以下内容写入logcat

 06-10 19:40:35.355 25094-25094/com.dezainapps.myapp D/source: exception java.lang.Exception at com.dezainapps.myapp.CoreTwoA.(CoreTwoA.java:20) at java.lang.Class.newInstance(Native Method) at android.app.ActivityThread.handleCreateService(ActivityThread.java:2859) at android.app.ActivityThread.-wrap4(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 06-10 19:40:35.355 25094-25094/com.dezainapps.myapp I/CoreTwoA.TAG: Constructor 

为什么通过Intent将实现Parcelable的StatusBarNotification对象传递给IntentService的任何想法都不起作用? 奇怪的是,通过intent(参见代码)从我的toProcess()方法广播相同的StatusBarNotfication sbn对象确实有效。

我和OP有同样的问题。

问题是我通过启动IntentServiceIntent传递了一个巨大的ArrayList (大约4000个Parcelable元素)。 诊断非常困难,因为它在客户的设备上“默默地”失败,因此我没有得到ACRA错误报告。

无论如何,我使用了一个快速而肮脏的技巧来解决问题 – 基本上将ArrayList存储在我用于设置/获取ArrayList的静态元素中,而不是尝试通过Intent传递它。

在进一步调查(对其他设备进行一些测试)时,我发现抛出了TransactionTooLargeException 。 这里有更多的讨论 。

如果有人想要复制,这是我的测试代码:

测试代码

如果要使其工作,请将4000值更改为更小的值。

 ArrayList testArrayList = new ArrayList<>(); for (int i = 0; i < 4000; i++) { testArrayList.add(new ParcelableNameValuePair("name" + i, "value" + i)); } TestIntentService.startAction(AdminHomeActivity.this, testArrayList); 

TestIntentService.java

 public class TestIntentService extends IntentService { private static final String LOG_TAG = TestIntentService.class.getSimpleName(); private static final String TEST_ACTION = "com.example.action.FOO"; private static final String EXTRA_PARAM1 = "com.example.extra.PARAM1"; private static final String EXTRA_PARAM2 = "com.example.extra.PARAM2"; public TestIntentService() { super("TestIntentService"); } public static void startAction(Context context, ArrayList testArrayList) { Log.d(LOG_TAG, "1. startAction()"); Utilities.makeToast(context, "1. startAction()"); try { int arrayListSize = (testArrayList == null) ? -1 : testArrayList.size(); Log.d(LOG_TAG, "2. arrayListSize: " + arrayListSize); Utilities.makeToast(context, "2. arrayListSize: " + arrayListSize); Intent intent = new Intent(context, TestIntentService.class); intent.setAction(TEST_ACTION); //intent.putExtra(EXTRA_PARAM1, testArrayList); intent.putParcelableArrayListExtra(EXTRA_PARAM2, testArrayList); /** * This line should result in a call to onHandleIntent() but, if we're sending a huge ArrayList, it doesn't... */ context.startService(intent); } catch(Exception e) { Log.e(LOG_TAG, "Exception starting service", e); Utilities.makeToast(context, "Exception starting service: " + e); } } @Override protected void onHandleIntent(Intent intent) { Log.d(LOG_TAG, "3. onHandleIntent()"); Utilities.makeToast(getApplicationContext(), "3. onHandleIntent()"); try { if (intent != null) { final String action = intent.getAction(); if (TEST_ACTION.equals(action)) { ArrayList testArrayList = intent.getParcelableArrayListExtra(EXTRA_PARAM1); int testArrayListSize = (testArrayList == null) ? -1 : testArrayList.size(); Log.d(LOG_TAG, "4. testArrayListSize: " + testArrayListSize); Utilities.makeToast(getApplicationContext(), "4. testArrayListSize: " + testArrayListSize); ArrayList testArrayList2 = intent.getParcelableArrayListExtra(EXTRA_PARAM2); int testArrayList2Size = (testArrayList2 == null) ? -1 : testArrayList2.size(); Log.d(LOG_TAG, "5. testArrayList2Size: " + testArrayList2Size); Utilities.makeToast(getApplicationContext(), "5. testArrayList2Size: " + testArrayList2Size); } } } catch(Exception e) { Log.e(LOG_TAG, "Exception handling service intent", e); Utilities.makeToast(getApplicationContext(), "Exception handling service intent: " + e); } } } 

ParcelableNameValuePair.java

 public class ParcelableNameValuePair implements Parcelable { private String name, value; public ParcelableNameValuePair(String name, String value) { this.name = name; this.value = value; } public String getName() { return name; } public String getValue() { return value; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeString(name); out.writeString(value); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public ParcelableNameValuePair createFromParcel(Parcel in) { return new ParcelableNameValuePair(in); } public ParcelableNameValuePair[] newArray(int size) { return new ParcelableNameValuePair[size]; } }; private ParcelableNameValuePair(Parcel in) { name = in.readString(); value = in.readString(); } } 

就像我说的,我使用了一个快速而肮脏的解决方案来解决这个问题。 我认为更好的解决方案是让app将ArrayList写入文件系统,然后通过Intent将对该文件的引用(例如,文件名/路径)传递给IntentService ,然后让IntentService检索文件内容并转换它回到了ArrayList

IntentService完成该文件时,它应该删除它或通过本地广播将指令传递回应用程序以删除它创建的文件(传回提供给它的相同文件引用)。

您是否尝试过使用context.startService(intent);?

当你在这样的广播接收器中时,你没有自己的上下文来引用我相信你需要使用传递给onRecieve方法的那个。

用这个:

 private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i("NoLiSe.TAG", "BroadCastReceiver.onReceive"); Intent i = new Intent(context, CoreTwoA.class); i.putExtra("intent",intent); context.startService(i); } } 

};

使用以下代码:

 private BroadcastReceiver notificationForwarder = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.e("NoLiSe.TAG", "BroadCastReceiver.onReceive"); Intent i = new Intent(context, CoreTwoA.class); i.putExtra("sbn",intent.getParcelableExtra("sbn")); startService(i); } }; 

您错误地使用了i.putExtras(intent); 我删除并添加了通过putExtra发送StatusBarNotification对象的其他方式。

我测试了这段代码并调用了onHandleIntent