[Android] Setting a quick instrumentation test environment with Espresso + JUnit + Mockito

1.- Gradle dependencies – global build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
} 

2.- Gradle dependencies – app/build.gradle

defaultConfig {
    applicationId "..."
    minSdkVersion 15
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}

dependencies { 
    // ... testCompile 'junit:junit:4.12' 
    androidTestCompile 'com.google.dexmaker:dexmaker:1.2' 
    androidTestCompile('com.google.dexmaker:dexmaker-mockito:1.2') { 
        exclude group: 'org.hamcrest', module: 'hamcrest-core' 
    }
    androidTestCompile 'com.android.support.test:runner:0.4.1' 
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'org.mockito:mockito-core:1.10.19' 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.1') 
    { 
        exclude group: 'javax.inject', module: 'javax.inject'
        exclude group: 'com.squareup', module: 'javawriter' 
    }
    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') 
    { 
        exclude module: 'support-annotations' 
        exclude module: 'recyclerview-v7' exclude module: 'support-v4' 
    }
    androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.1') 
    testCompile "org.mockito:mockito-core:1.9.5" 
    testCompile 'org.mockito:mockito-all:1.9.5' 
}

configurations.all { 
    resolutionStrategy.force 'com.android.support:support-annotations:23.0.1' 
}

3.- Sample test (androidTest/com/package/name folder)

@RunWith(AndroidJUnit4.class) @LargeTest
public class IssuesActivityTest {
    @Rule
    public IntentsTestRule<IssuesActivity> activityRule =
            new IntentsTestRule<>(IssuesActivity.class, true, false);

    @Test
    public void shouldDisplayToolbarOnStart() {
        startActivity();

        onView(withId(R.id.toolbar)).check(matches(isDisplayed()));
    }

    private IssuesActivity startActivity() {
        return activityRule.launchActivity(null);
    }
}

And that’s all folks

[Android] Sugar ORM is not creating tables on DB creation/migration

I was having this issue in two scenarios:

– Database creation from zero (app just installed)
– Database migration (for example from v2 to v3)

there were two tables that weren’t being created.

I discovered that they both had only one constructor, with parameters.
After adding an empty constructor, both tables were created.

public NotificationDBEntry() {
}

public ProjectDBEntry() {
}

So there are two choices to make it work:
– In classes with no constructor, it will work because the default one is the empty constructor
– In classes with a non-empty constructor, it is mandatory to add an empty constructor.

Hope this saves you time!

[Android] Configuring a quick test environment

In order to start writing tests for our app, one quick solution could be this one:

1.- Adding junit to our build.gradle file

dependencies{
...
testCompile 'junit:junit:4.12'
}

2.- Creating the test folder structure
This can be done with Android Studio, or directly in your file explorer (finder, nautilus, etc). Create the folder

your_app_folder/app/src/test/java/com/companyname/appname/

where the app’s package name would be com.companyname.appname (substitute by yours).

3.- Creating a sample test
Inside the recently created folder, create a file named ProjectTest.java and copy this content:

public class ProjectTest {
@Test
public void shouldCompare1To1() throws Exception {
assertEquals(1, 1);
}
}

4.- Running the tests in console
Go to terminal, move to your app’s folder and do

./gradlew test

If everything went fine, you should have a single test passing

[Android] Getting RAW JSON response with Retrofit2

The main thing that made me waste time when using Retrofit was that I could not see the JSON responses that my APIs were sending. I had to add a separate method to the RetrofitService that used a Response object instead of MyClass object.
This is much easier and comfortable in retrofit 2. Just add these lines:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LogJsonInterceptor());
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();

LogJsonInterceptor class:


public class LogJsonInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();

Response response = chain.proceed(request);
String rawJson = response.body().string();

Log.d(BuildConfig.APPLICATION_ID, String.format("raw JSON response is: %s", rawJson));

// Re-create the response before returning it because body can be read only once
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), rawJson)).build();
}
}

Here you can log your rawJson variable to display raw JSON message. Note that once body() has been called, the response has been consumed and becomes useless. You have to re-create it before returning it to another objects to consume.

Thanks to this article written by @riggaroo and this issue thread (and ofcourse uncle Jake) for making this possible.

Have a nice coding day !!! 🙂

P.D. I know that the article format is crap, but anyway you can copy and paste the code for your own purpose and it will work 😛

[Android] imeOptions not working on EditText (actionNext, actionDone)

Don’t forget to add

<item name=”android:inputType”>text</item>

or

<item name=”android:inputType”>textPassword</item>

to your EditText’s style

Directly on XML:

<EditText
style=”@style/PasswordEditText”
android:id=”@+id/login_et_password”
android:layout_below=”@+id/login_tv_password”
android:inputType=”text”
android:imeOptions=”actionDone”
/>

[Android SDK] Using variables from Gradle, in Java code

This is a pretty simple issue, but I’ve seen many questions and bad solutions about it.

An example of doing that could be:

file: app/build.gradle

android{
   buildTypes{
       release{
           buildConfigField "int", "SAMPLE_INT", "52"
           buildConfigField "boolean", "SAMPLE_BOOL", "true"
           buildConfigField "String", "SAMPLE_STR", "\"release_foo\""
       }
       debug{
           buildConfigField "int", "SAMPLE_INT", "55"
           buildConfigField "boolean", "SAMPLE_BOOL", "false"
           buildConfigField "String", "SAMPLE_STR", "\"debug_foo\""
       }
   }
}

file: MainActivity.java

@Override
 protected void onCreate(Bundle savedInstanceState){
     String gradleStr = BuildConfig.SAMPLE_STRING;
     int gradleInt = BuildConfig.SAMPLE_INT;
     boolean gradleBool = BuildConfig.SAMPLE_BOOL;
 }

As simple as that 🙂

hope it helps for you!

[Marmalade SDK] Warning: Using default deployment icon(s)

I just found this error when deploying my Marmalade App to Android.

As it’s explained on this thread, we need to supply a default generic icon, apart from the android-specific icon options (like android-icon-xhdpi).

For those using the hub, there is a solution in the previously mentioned thread. For those who, like me, still use .mkb files, this is how I’ve solved it.

deployments
{
["Default"]
icon='data/icons/icon96.png'

... rest of the mkb
}

Deploy tool is not complaining about this anymore 🙂

[Marmalade SDK] Compiling your extension for supporting iOS 64-bit

When deploying a Marmalade App to AARCH64 (iOS 64-bit support), it is also necessary to re-compile its native extensions.
Else, “ld” will ignore the whole extension and warn us about the fact.
In order to recompile the iOS extension, you are forced to use a Mac. This can be an impediment if you use Marmalade under Windows. The steps you basically need are

1.- Download and install Marmalade SDK for Mac
2.- If you are Windows user, release your license on Windows Marmalade Hub
3.- Activate your license in Mac Marmalade Hub
4.- Copy the whole extension’s folder from Windows to your mac
5.- Right-click on the extension’s .mkb for iphone (extensionName_iphone.mkb), select “Open with”. There will be two options: Mkb (default), and Mkb (7.4.3), choose the second one. Note that the numbers may change in future Marmalade versions
6.- A shell command-prompt will appear, and will attempt to compile the extension. Once completed, make sure that file
extensionName/lib/arm64/libExtName.a
is present. There should be also two folders with names finishing in _iphone_scons_aarch64 and _iphone_iphone_xcode. If that’s not the case, go to step 6b 🙂
6b.- [Optional] Open the extension Xcode project (it is located inside build_extName_iphone_iphone_xcode folder), go to Build settings, and select “Latest iOS SDK” (mine is 8.2 in this moment), and include “arm64” inside Valid architectures. This is explained in more depth in this document.
7.- Once process is complete, you can copy your extension folder back to your usual Marmalade installation (either under Windows or Mac), and recompile the whole App (including extension) to AARCH64 in iOS-fat mode. More info in the previous post 🙂

Sorry for the little mess going on here!! Hope it helps someone!!