Author Archives: Ben Lam

Android Genymotion Mock Location Google Play

To get Android Genymotion Mock Location Google Play fused location provider working in an emulator these are the necessary components and steps.  (For Genymotion 2.5.x emulator versions)

Download:

Steps

  1. Install these two zipped APK archive files by dragging the zip files directly onto your running Genymotion Emulator in order.  Start first with ARM Translation v1.1.  It will ask for confirmation.  Click OK.
    Install genymotion ARM Translation v1.1
  2. After the APK file is unpacked and installed, genymotion emulator will ask to restart.  To restart your genymotion emulator, in a command prompt on your computer, issue an emulator reboot command: adb reboot.  The emulator will reboot several times. For me: 4 times it will cycle before settling down and showing the home screen.
  3. Repeat with the Google Apps Play Store file (gapps-5.1-xxxxx) file –  drag and drop, confirm install, adb reboot.  This should only cycle off/on your emulator once, unlike the ARM Translation APK you installed earlier.
  4. Click on the Home button (center white circle with dots at bottom) and find Google Play Store.  Click it to start Google Play.  It may ask to update.  If so, update it.
    genymotion-playstore-installed
  5. Open Google Play. It will ask for a Google account.  Feel free to create a new one or use one you already have.  Supply its password.  Accept Terms of Service and Privacy Policy.  Google Play Services may pop up a dialog saying it has stopped.  Google Play setup will continue though.  Setup payment info if you like.  I didn’t and chose Remind me later.  After that you’ll be shown the Play Store home page.
    google_play_setup_account
  6. Google Play Store in Genymotion crashes repeatedly after install on a Genymotion emulator.  To fix the Google Play Store crashes on Genymotion emulator, open the Settings application in Android (gear icon), scroll down and click on Apps.  Click on Google Play Store.  Click on Clear Cache and Clear Data.  Click OK on any dialogs that come up.
    genymotion_settings
    settings_apps_downloaded
    settings_apps_clear_cache_clear_data

    1. Restart Google Play
    2. Accept Terms and Conditions again
    3. You may or may not have to log in again.  If you get an error regarding you must be logged in when trying to search for Maps, click on the three horizontal bars at the top left of the Google Play home screen to slide out the left tray and click My Account.  Log in if asked to do so.  For me it auto-logged me in from cached credentials.
      google_play_my_account
    4. Back in Google Play, text search for maps.  Google Play should not crash.
  7. Install Google Maps.
    google_play_store_google_maps
  8. In Google Play, find and install a mock location provider such as Mock Locations or Fake GPS.  Mock Locations (fake GPS path), which allows you to draw out a path which you can “drive” or “walk” at your desired speed between locations of your choice.  I find this quite useful when using GoogleApiClient fused provider where requestLocationUpdates is returning Location objects repeatedly over a period.  Very helpful when you’re testing Entering and Exiting GeoFences
    mock_location
  9. Don’t forgot to turn on High Accuracy mode in Settings -> Location -> Mode -> High accuracy, which allows GoogleAPIClient Location Services fused location provider to work properly.  I didn’t have much luck running Google Play Services Location Provider with GPS (Device) only Location setting.
    location_mode
  10. And finally Dev Tools (application on Genymotion) -> Developer Options -> Allow Mock Locations needs to be On.
    dev_options_app_icon_highlighted
    dev_options_mock_locations

 

Spring Boot SSL with Android Retrofit

To setup Spring Boot SSL with Android Retrofit connecting on HTTPS 443:

In Spring Boot

  1. <your project>/src/main/resources/application.properties – add the following values (not the “1.” which is just WordPress ordered list numbering)
    1. security.require-ssl=true
      server.port=8443
      server.ssl.key-store=src/main/resources/private/keystore
      server.ssl.key-store-password=changeit
      server.ssl.key-password=changeit
  2. create and add an SSL key to the location specified by server.ssl.key-store. Note: the SSL certificate file is actually named “keystore”.  That’s not a directory.
  3. Restart your Spring server and you should be able to make httpS connections on port 8443

In Android Retrofit

  • Add an OkHttp compile dependency to build.gradle

compile 'com.squareup.okhttp:okhttp:2.5.0'

  • Create a class that returns an OkHttp client that doesn’t validate trust certificates (written by Jules White of Vanderbuilt)


public class UnsafeHttpsClient {

public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {

@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};

// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance(“SSL”);
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});

return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

  • Update your Retrofit rest adapter with this unsafe OkHttp client

return new RestAdapter
.Builder()
.setEndpoint(server)
.setLogLevel(logLevel)
.setLog(new AndroidLog(debugTag))
.setConverter(new GsonConverter(myGsonDateAdapter()))
.setClient(new OkClient(UnsafeHttpsClient.getUnsafeOkHttpClient()))
.build()
.create(WebProxy.class);

In the above example,

  • WebProxy is the API interface class.
  • server is obviously the Spring server, should be https and at whatever port specified in Spring’s application.properties
  • debugTag is optional text to prefix Retrofit calls in Android’s console log
  • Converter is not required

Other tools that might help debug

  • Postman – if you can make an https/8443 GET request to your Spring server, you know Spring is setup properly

Android Studio Permanently Change Debug Configuration for Working Directory $MODULE_DIR$ and app:assembleDebugUnitTest

On Mac OS X, Android Studio’s default debug Unit Test build configuration generally doesn’t run with default settings complaining that:

AndroidManifest.xml not found or not a file; it should point to your project’s AndroidManifest.xml

To fix this error you need to edit your debug configuration to set Working Directory as $MODULE_DIR$ and it makes builds faster to set Before Launch as gradle :app:assembleDebugUnitTest

To set these Debug build configuration settings permanently go to Android Studio Menu -> Run -> Edit Configurations… -> click on the little wrench and cog icon to Edit Defaults, JUnit should be selected if you’re currently on a Unit Test and change the working Directory to $MODULE_DIR$ and Before Launch: Gradle-aware Make and choosing :app:assembleDebugUnitTest. Remove the plain-jane “Make” from the list as well.

android-studio-menu-edit-configurations
android-studio-debug-edit-configuration-screen

Android AsyncTask return result

To get Android AsyncTask to return a result use a callback method (Observer pattern) by following these steps.

  1. Define a constructor for our async class which extends AsyncTask (we’re required to subclass/extend AsyncTask for use). Let’s call our AsyncTask class MyAsyncTask.
  2. Constructor parameter takes a class which will handle the AsyncTask result.  Usually an Activity or Fragment, but could be a Robolectric Unit Test class for example.
  3. Declare a member variable/private field to hold the handling Activity/Fragment/Test. We’ll call it ResultListener.  The constructor will assign its parameter input to this member variable.
  4. Declare an Interface within  MyAsyncTask. Let’s call it ResultListener
  5. ResultListener defines a single method that our handling class must implement.  Let’s name the method handleAsyncResult and in this case it’s going to take a single boolean as an input parameter.
  6. In onPostExecute, call our listener class handler method, supplying a value to the input parameter as appropriate for the outcome of doInBackground.

Here’s a concrete example of an Android AsyncTask returning a result:

 

public class MyAsyncTask<T> extends AsyncTask<T, Void, Boolean> {
    private final String TAG = this.getClass().getName();
    ResultListener listener;

    public interface ResultListener {
        void handleAsyncResult(boolean result);
    }

    WebProxy proxy;

    public MyAsyncTask(ResultListener listener) {
        this.listener = listener;
    }

    @Override
    protected Boolean doInBackground(T... params) {
        // do interesting long running things here, Network, database, etc.
        Log.i(TAG, String.format("doInBack: sending %s via Retrofit", params.getClass().getName()));
        return true;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        listener.handleAsyncResult(success);
    }
}

As a bonus this AsyncTask uses a Type parameter <T> as input, so it can handle different input types for the AsyncTask.execute(input). This will make your AsyncTask more reusable and easy to extend for future use.

When MyAsyncTask completes doInBackground, it will pass a boolean to onPostExecute which we’re going to send along to our handling class through listener.handleAsyncResult(success).

Within our handling class (supplied to our AsyncTask constructor) we’ll need to do two things:

  1. Make our class implement our Interface by adding  “implements MyAsyncTask.ResultListener” after the class name.
  2. Define a method within our handling class with a signature that matches MyAsyncTask.ResultListener.

Here’s an example for our implementing class:

public class Test implements MyAsyncTask.ResultListener {
private boolean asyncResult;

@Override
public void handleAsyncResult(boolean result) {
    asyncResult = result;
}


@Test
public void firstAsyncTest() throws Exception {
    MyAsyncTask<Checkin> myTask = new MyAsyncTask<>(this);
    myTask.execute(someArrayOfTypeT);
    assertThat(asyncResult).isTrue();
}

}

Retrofit error 415 400 object with Date field Fix @JsonFormat annotation

Retrofit error 415 or error 400 on an object with a Date field can be fixed by using @JsonFormat annotation with the proper date pattern format specified in the annotation.

java.util.Date toString() (for my locale/region) returns a string date format of MMM dd, yyyy hh:mm:ss aa

Example: Oct 22, 2015 11:09:55 PM

For Retrofit / Jackson to serialize / deserialize a date (java.util.Date) properly, you must annotate your Date fields with the corresponding date pattern:

@JsonFormat(shape= JsonFormat.Shape.STRING, pattern = "MMM dd, yyyy hh:mm:ss aa")

Pay special attention to the uppercase / lowercase lettering of each date part.  Two digit date of month must be LOWERCASE (i.e. “dd” not “DD”).  Otherwise it will be interpreted as a date of year which can be three digits.  (I was getting bizarre JSON serialization JSON deserialization results such as Oct 22 becoming Dec 362 by having the wrong case on my date part of the date format (i.e. “DD”.)

For the full list of date format parts that Jackson (fasterxml) uses see:

http://docs.oracle.com/javase/1.5.0/docs/api/java/text/SimpleDateFormat.html

H2 Web Console to In Memory Database – Spring Boot

To get an H2 Database Web Console accessing an in-memory database running on Spring Boot:

  1. Register H2’s WebServlet (with UrlMapping /console/*) to your Spring project in a Configuration annotated class. Restart your Application.
  2. Open a web page to http://localhost:8080/console/
  3. Be sure you’re accessing the correct database JDBC URL (default would be jdbc:h2:mem:testdb)

(Credit: Spring Framework Guru)

 

import org.h2.server.web.WebServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class H2ConsoleWebConfiguration {
 @Bean
 ServletRegistrationBean h2servletRegistration() {
 ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
 registrationBean.addUrlMappings("/console/*");
 return registrationBean;
 }
}

Robolectric reference

Robolectric Android testing Fragments and more

private ReminderManagerFragment startReminderManagerFragment() {
    final ReminderManagerFragment fragment = new ReminderManagerFragment();
    SupportFragmentTestUtil.startVisibleFragment(fragment);
    return fragment;
}

@Test
public void reminderManagerTest() throws Exception {
    // by default there should be 3 Reminder rows
    ReminderManagerFragment fragment = startReminderManagerFragment();
    assertThat(fragment).isNotNull();
    Button addButton = (Button) fragment.getView().findViewById(R.id.reminder_add_button);
    assertThat(addButton).isNotNull();

    List<Reminder> reminders = getReminders(TestValues.BillyUser);
    assertThat(reminders.size()).isEqualTo(3);

    // add a reminder, assert reminders = 4
    addButton.performClick();

    //assertThat(reminders.size()).isEqualTo(4);
    TimePickerFragment pickerFragment =
            (TimePickerFragment) fragment.getFragmentManager()
                    .findFragmentByTag(ReminderManagerFragment.TIME_DIALOG);
    assertThat(pickerFragment).isNotNull();

    reminders = getReminders(TestValues.BillyUser);
    assertThat(reminders.size()).isEqualTo(4);

    AlertDialog pickerDialog = (AlertDialog) pickerFragment.getDialog();

    assertThat(pickerDialog).isNotNull();
    assertThat(pickerDialog.getButton(AlertDialog.BUTTON_POSITIVE)).isNotNull();

    Button pickerOKButton = (Button) pickerDialog.getButton(AlertDialog.BUTTON_POSITIVE);
    pickerOKButton.performClick();

    // check that an alarm was set
    ShadowAlarmManager shadowAlarmManager = shadowOf(AlarmFactory.getAlarmManager(mCtx));
    // shadow AlarmManager should return 0 alarms
    List<ShadowAlarmManager.ScheduledAlarm> shadowAlarms = shadowAlarmManager.getScheduledAlarms();
    Log.i(TAG, "alarms currently set: " + shadowAlarms.size());
    assertThat(shadowAlarms.size()).isGreaterThan(0);

 

Try changing TimePicker Hour and Minutes and resubmit AlertDialog (TimePickerDialog), they key method being ((TimePickerDialog) pickerDialog).updateTime(hh,mm);

// try adding a second reminder & alarm
addButton.performClick();

pickerFragment =
        (TimePickerFragment) fragment.getFragmentManager()
                .findFragmentByTag(ReminderManagerFragment.TIME_DIALOG);

assertThat(pickerFragment).isNotNull();

reminders = getReminders(TestValues.BillyUser);
assertThat(reminders.size()).isEqualTo(5);

pickerDialog = (AlertDialog) pickerFragment.getDialog();


assertThat(pickerDialog).isNotNull();

((TimePickerDialog) pickerDialog).updateTime(18, 30);

pickerOKButton = (Button) pickerDialog.getButton(AlertDialog.BUTTON_POSITIVE);
pickerOKButton.performClick();

shadowAlarms = shadowAlarmManager.getScheduledAlarms();
for (ShadowAlarmManager.ScheduledAlarm sAlarm :
        shadowAlarms) {
    Log.i(TAG, Dates.getBasicDate(new Date(sAlarm.triggerAtTime)) + " " +
            sAlarm.operation.toString());
}
Log.i(TAG, "alarms currently set: " + shadowAlarms.size());
assertThat(shadowAlarms.size()).isGreaterThan(1);

More to come

Most efficient Mac browser Safari

Safari is the most efficient Mac browser using the least amount of battery power (amperage) compared to Firefox and Chrome on Apple MacBooks.  In a quick test of watching YouTube videos in browsers here’s how much battery/energy each browser used:

  • Safari: 1250 mA
  • Firefox: 1600mA
  • Chrome: 3600mA

Chrome is far and away the most power hungry web browser on Mac OS X, using nearly 3X the processing power and battery usage than Safari.

Obviously if you’re trying to maximize battery life on your MacBook, use Safari browser as its the most efficient.

To test this yourself, use the System Information application (Apple logo top right corner, About this Mac, More Info…, System Report, Power and look for the Amperage (mA) value).

Robotium reference

Enter text EditText / text field

solo.enterText((EditText) solo.getView(R.id.email_edittext), "baduser@gmail.com");

Click Button

solo.clickOnButton("Login");

Check for Toast Text Message

assertTrue(solo.waitForText(getActivity().getResources()
        .getString(R.string.msg_login_failed)));

 

 

More to come…