[Android SDK] java.lang.IllegalArgumentException: Service Intent must be explicit – on Android 5.0 Lollipop

[Refloated post from 2014, treasure from the past]

I just noticed that one of my Apps is getting continous crash reports on Google Play. The crashes are related to IAPs (In-App Purchases, Billing library), exactly on this line:

Intent serviceIntent = new Intent(“com.android.vending.billing.InAppBillingService.BIND”);
mContext.bindService(explicitIntent, mServiceConnection, Context.BIND_AUTO_CREATE);

According to this SO question, there are two possible solutions:

1.- Turning the implicit intent (the serviceIntent var above) into an explicit intent

1.1.- Copy this code for createExplicitFromImplicitIntent() method found in android-develop blog:

/***
* Android L (lollipop, API 21) introduced a new problem when trying to invoke implicit intent,
* "java.lang.IllegalArgumentException: Service Intent must be explicit"
*
* If you are using an implicit intent, and know only 1 target would answer this intent,
* This method will help you turn the implicit intent into the explicit form.
*
* Inspired from SO answer: http://stackoverflow.com/a/26318757/1446466
* @param context
* @param implicitIntent - The original implicit intent
* @return Explicit Intent created from the implicit original intent
*/
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List 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;
}

1.2.- Add this line to your IabHelper implementation:

Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
Intent explicitIntent = createExplicitFromImplicitIntent(mContext, serviceIntent);
mContext.bindService(explicitIntent, mServiceConnection, Context.BIND_AUTO_CREATE);

2.- Setting the intent’s package name

Add this line

serviceIntent.setPackage("com.android.vending");

Choose the one of your preference, then re-submit your app to Google Play. This should fix the crash reports!

Thanks to the authors of both solutions. Have a nice coding day!

Advertisements

[iOS SDK] Changing TabBar order in a storyboard

In a storyboard-based app containing an UITabBarController with various ViewControllers as tabs, the need of changing the tab’s order is very frequent due to changes in the App’s requirements.

There are various ways of doing that. In my opinion, the most elegant one is doing the steps above:

1.- Open Xcode, open the current project. In the project structure (left menu), right click on the desired .storyboard file. Select “Open as > Source code”
2.- Inside the enormous XML file, find a tag with a tag inside it. The Find command (CMD+F) might be helpful.
3.- You might have several tags with attributes “destination”,”kind”,”relationship” and “id”; One on each line. Change the lines to the order of your preference (for example, the fourth becomes the first, the second is swapped with the third, etc). Useful keyboard shortcuts: ALT+arrow_up, ALT+arrow_down.
4.- Save (CMD+S) the file, again right click on the .storyboard and select “Open as > Interface Builder”. You might see your tabs in the desired order 🙂

Another useful thing: Inside the tag (could be also , or another derived class), you can set the “title” attribute. This value will be the text displayed as the tab name. More info in this SO question

Have a nice coding day!