Tuesday, March 20, 2018

Running your app on a physical device for Android

This applies to both Android Studios and NativeScript.

In Android Studios if you cannot see your device in the dialog when trying to run on physical device:


and in NativeScript after running the below command you get:

tns devices

Connected devices & emulators
Searching for devices...
iTunes is not installed. Install it on your system and run this command again.
Cannot find connected devices. Reconnect any connected devices, verify that your system recognizes them, and run this command again.

Try the following:
- Ensure your phone is plugged into the USB
- Enable devloper mode by going to Settings > About phone and tap Build number seven times.
- Enable USB debugging
- Open up the device manager and if there is an unknown ADB interface then:

- Download the Google USB drivers following the instructions here. The drivers should be located at android sdk\extras\google\usb_driver\
- In the device manager right click on the ADB Interface and choose update driver and choose to manually install it by navigating to  sdk\extras\google\usb_driver\
- Pick Android ADB Interface. If everything installs fine your device manager should contain the driver

- Your phone will then ask you to accept the RSA fingerprint from your computer. Click Ok and you should now be able to run your app on your physical device.

Nativescript application running on Android 7.0 throws SSLHandShakeException

The application I am creating has a back-end web API hosted with Node and Nginx. I used Let's Encrypt to create an SSL certificate. The application has a web and mobile front-end. The web side of things all worked fine on the desktop and on the mobile browser. The mobile native application is created with NativeScript.

While testing against an Android 7.0 device I kept getting errors and could not connect to the back-end web API. After discovering NativeScript Playground in particular this sample which I modified to make a call to my web API, I was able to see that the application was throwing a SSLHandShakeException.

javax.net.ssl.SSLHandShakeException: Handshake failed 
at ZoneAwareError at onRequestComplete 
at Object.onComplete 
Initially I thought the issue was due to using Let's Encrypt however after further digging and hunting I came across this StackOverFlow post which suggests "changing the nginx configuration by removing secp384r1 or replacing it with the default (prime256v1)". It turns out that this is a "known regression in Android 7.0, acknowledged by Google and fixed sometime before the release of Android 7.1.1".

To over come the problem I had to change my Nginx config to use:

ssl_ecdh_curve prime256v1;
instead of

ssl_ecdh_curve secp384r1;

Also to support previous version of Android you will need

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;