We are seeing an issue where one of our intent services is unexpectedly retrieving a null
String extra for some of our users. We haven't been able to reproduce this, and we don't know if it is random or consistent on an affected user's device. There doesn't seem to be a correlation between affected users and device type or Android version.
I am extending IntentService
and implementing the handleIntent
method like this:
@Override
public void handleIntent(Intent intent) {
String action = intent.getAction();
if (action.Equals(ACTION_MARK_UNREAD)) {
String messageKey = intent.getStringExtra(EXTRA_MESSAGE_KEY);
// messageKey is null for some users
}
}
With fields:
public static final String ACTION_MARK_UNREAD = "com.myapp.action.MARK_UNREAD";
public static final String EXTRA_MESSAGE_KEY = "extraMessageKey";
In a fragment, we start this service in rapid succession 6 times:
for (int i = 0; i < 6; i++) {
Intent i = new Intent(MyIntentService.ACTION_MARK_UNREAD);
i = i.setClass(mContext, MyIntentService.class);
i.putExtra(MyIntentService.EXTRA_MESSAGE_KEY, i.toString());
mContext.startService(i);
}
Any ideas why the service would retrieve null
for the messageKey
extra?
We have other areas in the app that start this same service, and we can't identify which one it comes from when this situation happens. However, from looking at logs, it seems to be from this fragment that I mentioned. Logs show that the client timestamp when null
happens is several seconds after the previous occurrence. This could be because the service queue is slow to move, or my assumption could be wrong.
The Service will only run in one instance.
IntentService is an extension of the Service component class that handles asynchronous requests (expressed as Intent s) on demand. Clients send requests through Context.
IntentService runs outside the application in a background process, so the process would run even if your application is closed. Google now recommends using the JobIntentService, which is included as part of the support library. On pre-Android O devices, a normal IntentService will be dispatched in the background.
IntentService is deprecated in Android-R / Android-11.
My first guess is the compiler issue that many other commented about and I figure some other errors on your examples like Equals
with upper E for example.
But considering your code as an example just, I tested a lot this approach and the first thing that I concludes is no matter if your calls are inside a Fragment
or Activity
due the Context
of Fragment
is the same of parent Activity
.
Reading the IntentService
documentation we can read that:
All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.
Here: http://developer.android.com/reference/android/app/IntentService.html
So we can conclude that all your X requests will be processed enqueued one by one.
Another part at Android documentation about IntentService we can read that:
Because most started services don't need to handle multiple requests simultaneously (which can actually be a dangerous multi-threading scenario), it's probably best if you implement your service using the IntentService class.
Here: http://developer.android.com/guide/components/services.html#ExtendingIntentService
So with that information you can think if IntentService
has been the approach that you need. Right?
Here you can learn how extends just a Service
: http://developer.android.com/guide/components/services.html#ExtendingService
Finishing, below I'm pasting the code that I made to test your approach.
Main Activity
class MainActivity
.
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for (int i = 0; i < 10; i++) {
Intent intent = new Intent(MyIntentService.MY_ACTION);
intent.setClass(this, MyIntentService.class);
intent.putExtra(MyIntentService.EXTRA, UUID.randomUUID().toString());
startService(intent);
}
}
}
The IntentService
MyIntentService
.
public class MyIntentService extends IntentService {
public static final String MY_ACTION = "my.app.namespace.action.myaction";
public static final String EXTRA = "my_extra";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
String action = intent.getAction();
if (action.equals(MY_ACTION)) {
String messageKey = intent.getStringExtra(EXTRA);
Log.i(EXTRA, messageKey);
}
}
}
And the output Log
.
my_extra﹕ b6faeb0a-29fa-442b-b87e-9c7a5f8c35d7
my_extra﹕ 88076250-d455-4084-af5f-c560ba6d5570
my_extra﹕ 21339466-25ab-4aaa-aadd-344555c4c2df
my_extra﹕ 2f935a93-465b-4648-a3cc-60f0c9cc67a4
my_extra﹕ 128653d1-d6af-499f-8725-78158e2e7190
my_extra﹕ e453ae7b-e21a-41fe-bf9c-f45ccfd13edf
my_extra﹕ 2e3fc6aa-e425-41dd-a584-8ab056fb906d
my_extra﹕ a8d90d53-c6cd-4d15-84f9-4064d6972de9
my_extra﹕ 721dd17b-b977-4029-ada3-5999f0eb36e7
my_extra﹕ e83d3277-adc8-47a8-a246-6cd7f6f2735d
Will you try?
for (int y = 0; y < 6; y++) {
Intent i = new Intent(MyIntentService.ACTION_MARK_UNREAD);
i = i.setClass(mContext, MyIntentService.class);
i.putExtra(MyIntentService.EXTRA_MESSAGE_KEY, y.toString());
mContext.startService(i);
}
Could be a compiler issue...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With