Android 5.0 (L) Service Intent must be explicit in Google analytics
If you're trying to use Google's Licensing mechanism, solution that worked for me:
// explicit Intent, safe
Intent serviceIntent = new Intent(ILicensingService.class.getName());
serviceIntent.setPackage("com.android.vending");
boolean bindResult = mContext.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
This is located in com/google/android/vending/licensing/LicenseChecker.java
. Do a search for "Base64.decode(
"
Edit:
Adding reference to Google Licensing java file that has to be patched:
com.google.android.vending.licensing.LicenseChecker.checkAccess(LicenseChecker.java:150)
patch:
new String(
- Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))),
+ Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")))
+ .setPackage("com.android.vending"), // this fix the 'IllegalArgumentException: Service Intent must be explicit'
this, // ServiceConnection.
Source: https://code.google.com/p/android/issues/detail?id=78505#c19
Since Android 5.0 (Lollipop) bindService() must always be called with an explicit intent. This was previously a recommendation, but since Lollipop it is enforced: java.lang.IllegalArgumentException: Service Intent must be explicit
is thrown every time a call to bindService()
is made using implicit intents.
The difference between implicit and explicit intents is that the latter specifies the component to start by name (the fully-qualified class name).
See the documentation about intent types here.
The issue you are having is due to not having upgraded to a newer version of the google libraries, which comply with Android's restrictions on implicit intents when binding a service on Android 5 Lollipop. To fix the issue, you can upgrade the library to a newer version if available, or update the library code yourself and build your project with the modified version.
If there's no suitable library upgrade in the general case, you need to modify the source code (in your case com.google.analytics.tracking.android.AnalyticsGmsCoreClient.connect()
) to call intent.setPackage(packageName)
before calling bindService()
where intent
is the first argument of the bindService()
call and packageName
is the name of the package containing the service the code is attempting to start (in your case "com.google.android.gms.analytics").
You can use this code as an example how to do this: Unity's updated version of the Google Licensing Library (LVL) which calls bindService with an explicit intent and does not result in IllegalArgumentException.
Yet another way to get around the problem is to rebuild your project and the google libraries using targetSDK no later than 19. This will make it run without crashing on Lollipop but is the less secure option and prevents you from using SDK functionality introduced in later versions (for Android 5).
Migration from Google Analytics v2 to v3 solve the problem for me.
I was just having this problem myself. The issue lies within your activity that is starting your service.
Basically, an explicit intent names the service directly in the intent when the service is started. See http://developer.android.com/guide/components/intents-filters.html for a more in-depth explanation.
Since, you don't have your activity code posted, I don't know how you're starting it now, but it should probably look something like this:
Intent startIntent = new Intent(this, ServiceToStart.class);
this.startService(startIntent); // or bindService(...)
I used this and it works great
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
//Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
//Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
//Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
//Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
//Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}