Day 19 : 20 July 2022 : Adding Support for Android

 My 100 Daze of Code

https://github.com/davidjwalling/100-days-of-code

#19 : Adding Support for Android

In this episode, we'll add Android to our list of supported platforms for the Ava program, its library, libava, and its test program, testava. I'm using Android Studio Chipmunk 2021.2.1 Patch 1, built on May 18, 2022. I'll test and debug using a physical device, a Samsung Galaxy S9, connected to my development laptop using a USB-C cable. Since all supported platforms reference the same code, I'll update the CMakeLists.txt file that Android Studio generates to reference Ava source modules in their current location within the repository.

Folder and File Hierarchy Updates

For Window and iOS, we created folders at the top level of the repository to hold platform-specific project files. We'll follow the same example here. We'll create and android folder in the repository and create the Android Studio project there.

Update to .gitignore

It is not necessary to include all Android Studio files in the repository. So, we'll edit our .gitignore file to exclude configuration specific to the local build.


Project Files

android/app/src/main/AndroidManifest.xml

We created the project with a package name of "com.davidjwalling.ava". And a label of "ava". One important line was added manually the AndroidManifest.xml file, which is highlight below. We added a permission called "android.permission.INTERNET". This allows our Android app to perform networking functions using the sockets API.

android/app/src/main/cpp/CMakeLists.txt 

Our Android project has its own CMakeLists.txt for now. This allows us to include the native-lib.cpp bridge file that defines the JAVA APIs that will call into our Ava library. To include our original source files and headers, we define a SRC_PATH variable that defines the relative path to our sources and reference that variable our Android project's CMakeLists.txt file. We do not need to make any changes to our overall CMakeLists.txt file. When we save changes to the Android project's CMakeLists.txt file, Android Studio will automatically update its project explorer window to show the selected or included files.

android/app/src/main/cpp/native-lib.cpp

Android Studio has created the native-lib.cpp file to define the Java Native Interface (JNI) routines that are used to access our C++ code in the Ava library. Note several features about this file:

1. We include the public API "idriver.h" so that we can call our IDriver::Start and Stop methods. The Start method will be called when the application receives the onCreate event. The Stop method will be called when the application receives the onDestroy event.

2. We define and set our logging path to "/data/data/com.davidjwalling.ava/files" since this path will be writable for us when the application runs. The default current working directory is not writable. So, we must call the logging API LogPath to set the logging path to avoid errors performing file I/O.

3. The stringFromJNI method is automatically generated by Android Studio when we created the project. We'll leave it in but change the message to "Hello from Day 19".

android/app/src/main/java/com/davidjwalling/ava/MainActivity.java

Lastly, our Android application's MainActivity.java file performs the load of our "ava" library, which Android Studio compiles from the sources in its CMakeLists.txt file, and implements logic for the onCreate and onDestroy events. We leave the code provided by default and simply add a call in onCreate to the JNI start routine. We implement an onDestroy event handler to call the JNI stop routine.

Debugging the Android App using a Physical Device

With our Samsung Galaxy S9 attached to our development laptop by USB-C cable, Android Studio detects the device. We give permission on the device itself to allow the debugger to run.

Set breakpoints at the calls to the IDriver::Start and Stop routines. Build the code and then click on the debugger icon. The application will build, be installed on the device and the debugger will run and attach to the application running on the device. The breakpoint set at the call to Driver::Start will be reached.

At this point, our sockets code to listen for a connection has not yet been run. So we can confirm that by using a browser on the development laptop to try and reach the IP address of our device on our Ava port (1143). This will fail to make a TCP connection.

Now, we'll continue the program to set the IDriver::Start method run and retry the HTTP address in our browser. Now the connection is accepted and our familiar HTTP body is returned.

If we reorient the device from portrait to landscape mode, interestingly, the onDestroy event is triggered and the breakpoint we set at the call to Driver::Stop is reached.

Continuing the program, the application first calls onCreate again and that breakpoint is reached. Continuing again, the text is reoriented and displays in landscape mode.

Note that if we stop our debugging in Android Studio, this only detaches the debugger from the app, which continues to run on the device.





Comments

Popular posts from this blog

Day 12 : 19 June 2022 : Adding Windows Service Logic

Day 5 : 12 June 2022 : CMake on Windows

Day 11: 18 June 2022 : Handling Program Arguments