[Android SDK] A little clarification when using JakeWharton’s ButterKnife

Inside your Activity, respect this order:

@Inject(R.id.textView)
TextView injectedTextView;

protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ButterKnife.inject(this);
    injectedTextView.setText(“whatever”);
    ...
}

Method ButterKnife.inject(context) must be called after setContentView(…), or else you won’t be able to use injectedView.

Thanks JakeWharton for the excellent lib!

Advertisement

[Android SDK] Useful keyboard shortcuts for Android Studio

The ones I use most:

While developing

Alt+enter over class in code (.java): Quick assistance (import class, override methods, etc)
Alt+enter over string in code (.java): Extract string resource (include in res/values/strings.xml)
Alt+enter over string in resource file (.xml): Extract string resource (same as previous)

Shift+Cmd+F9: Make module (only current module)
Shift+Cmd+UP: Move this line UP (in .java)
Shift+Cmd+DOWN: Move this line DOWN (in .java)

Ctrl+R (aka ^ R): Run
Ctrl+Alt+D: Debug
Ctrl+Alt+I: Auto-indent code

Cmd+Backspace: Remove current line (VERY USEFUL)
Cmd+D: Duplicate current line (VERY USEFUL)

Cmd+F9: Make project  (all modules, app, wear, glass..)

When debugging:

F8: Step over
Cmd+Alt+R: Continue execution (what a weird shortcut this one)

I’ll keep completing it everytime I find a really useful one. Feel free to post your own in comments!

[iOS SDK] ITMS-4238: Redundant Binary Upload when submitting to App Store

Most common scenario for that error:

  • An App version (say, 1.4) has been submitted, and rejected by Apple review team
  • Errors are corrected, and App is resubmitted
  • Xcode organizer comes with ITMS-4238

Solution:

In Xcode, click on Project root, then on main target, and then go to “General” tab.

In the “Build” field, write a subversion of the current version (e.g. 1.4.1). Leave the “Version” field as it was, it has to match the release being submitted in the iTunes Connect panel.

Captura de pantalla 2015-01-21 a la(s) 17.51.44

To check that everything’s fine, right-click on the info.plist file, and open it as source code. CFBundleVersion should match the new build (1.4.1), but CFBundleShortVersionString should be the same one in App Store (1.4). Upload the binary.

Once uploaded, wait a few minutes, login into iTunes Connect, and select the recently submitted binary

Captura de pantalla 2015-01-21 a la(s) 18.21.52Then Save changes. Don’t forget to explain the Review team the changes you’ve made in 1.4.1 before sending it for review!

Thanks to this SO question for confirming I was on the right path 😉

[Android SDK] importing PullToRefresh to Gradle, for using in Android Studio

com.handmark.PullToRefresh is an excellent library. A pity it’s no longer being maintained, and has no gradle dependency.

Luckily, we can import the libproject “as it is” and compile it using Gradle. These are the steps.

1.- First of all, you need to download the libproject clicking on the “download ZIP” button found in the project’s GitHub site.

2.- Create an empty Android Studio project, let’s name it “PrjLibDeps”. Make sure it compiles succesfully and shows the “Hello World, PrjLibDeps” text before going to next step.

3.- In the project’s root folder, create a folder called “libs”, and place the “pulltorefresh” folder inside. The structure must remain as follows:

PrjLibdeps
|   settings.gradle
|   build.gradle
|   libs
      |    pulltorefresh
                 | src, res, LICENSE, pom.xml...
|  app/
    |   build.gradle
    |   src
| ...

4.- Now, inside “pulltorefresh” folder, create a file named “build.gradle”. If there is one, replace it. Copy and paste this dummy content we’re going to change later:

apply plugin: 'com.android.library'

dependencies {
   compile 'com.android.support:support-v4:21.0.3'
}

android {
   compileSdkVersion 20
   buildToolsVersion "20.0.0"

 defaultConfig {
   minSdkVersion 9
   targetSdkVersion 20
 }

 sourceSets {
   main {
     manifest.srcFile 'AndroidManifest.xml'
     java.srcDirs = ['src']
     res.srcDirs = ['res']
     }
   }
}

5.- Now replace compileSdkVersion, buildToolsVersion, minSdkVersion, and targetSdkVersion with values that are valid in your Android SDK installation. The easiest way is to set the same values found in app/build.gradle file.

6.- Now edit app/build.gradle, and add these dependencies.

dependencies {
   compile project(":PullToRefresh")
   // Leave the previous dependencies (if any) unmodified
}

7.- Edit settings.gradle, located in the project’s root directory. Add these lines

include ‘:app', ':PullToRefresh'
project (':PullToRefresh').projectDir = new File('libs/pulltorefresh')

8.- A yellow message saying “Gradle files have changed since las project sync …” might appear on the upper right. Click on “Sync now” to make gradle synchronize all resources.

9.- After gradle sync has finished, press CMD+F9 to Make the whole project. If you’ve done all steps correctly, you might get success 🙂 At least I could make it work with these exact steps. More import examples can be found at: SO question 1, SO question 2.

Let me know any issues.

Have a nice coding day!!

[Android SDK] Gradle dependency syntax

As we can read in gradle’s official documentation (chapter 8), the syntax used to name an external library that we want to include in our project’s build.gradle file, is the following:

app/build.gradle

dependencies {
    compile group: 'com.actionbarsherlock', name: 'actionbarsherlock', version: '4.4.0'
}

In this case, the library’s package name is com.actionbarsherlock.actionbarsherlock, and the version name (found in the libproject’s AndroidManifest.xml) is 4.4.0.

There is also a shortcut version of the syntax, separating <group_id>:<artifact_id>:<version>. Like this

dependencies {
    compile 'com.actionbarsherlock:actionbarsherlock:4.4.0'
}

Just searched that info on Google and costed me a couple of minutes to find it. There you got it, in the easiest format possible 🙂

Have a nice coding day!

[Android SDK] Installing Gradle in command-line shell (MacOS X)

Once we install Android Studio (or just gradle itself), it is very comfortable to have it added to our PATH, which makes us able to run commands like

gradle task1

from any Android project’s folder.

One way to do that is adding gradle’s path to our PATH variable. Under MacOS X, this is done with the following steps.

1.- In terminal:

export GRADLE_HOME=/Applications/Android\ Studio.app/Contents/gradle/gradle-2.2.1

*We assume we’re using the bundled Gradle that comes with Android Studio. You can place gradle anywhere else, like your /Users/user folder, and use this location. Example:

export GRADLE_HOME=/Users/jimmy/gradle-2.2.1

2.- Now, let’s have a look at our PATH variable. In terminal:

echo $PATH

It should look like:

/usr/bin:/bin:/usr/sbin: ... (more system folders separated by ":" )

To append gradle’s folder at the end of our path:

export PATH=$PATH:$GRADLE_HOME/bin

Now, execute “echo $PATH” again, and you should see gradle’s folder appended in the end, separated by a “:”.

If you were successful on step 2, you should now be able to execute:

gradle –version

And see an output like:

------------------------------------------------------------
Gradle 2.2.1
------------------------------------------------------------
Build time:   ...
Build number: none
Revision:     6fcb59c06f43a4e6b1bcb401f7686a8601a1fb4a
Groovy:       2.3.6
Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:          1.6.0_65 (Apple Inc. 20.65-b04-462)
OS:           Mac OS X 10.9 x86_64

Hope it helps!

[Android SDK] The project may be using a version of Gradle that does not contain the method… After updating Android Studio

I was using Android Studio 0.8.6, and after updating to 1.0, found this error:

The project <project_name> may be using a version of Gradle that does not contain the method […]

According to this SO answer, changing the method runProguard by minifyEnabled fixed the issue.

1.- Open all the build.gradle files available, on modules “mobile”, “wear”, and any other available.

2.- Change the code

buildTypes {
     release {
         runProguard false
         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
     }
}

with

buildTypes {
    release {
         minifyEnabled false
         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
     }
 }

The project should now compile and you should be able to run your old Apps.

Thanks to the authors of the SO answers 🙂

[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!

[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!