I have always wanted to develop simple one page apps for android but have been put off by the whole IDE stuff (Eclipse/Android Studio). Personally, I like working with just command-line tools to make and compile programs the way I do for linux. Recently I came across a simple minimal app development environment at http://www.hanshq.net/command-line-android.html. which made me want to have a go at it. After a day of working on it, I put together a barebones/ minimal environment for developing and building simple android app with just terminal in MacOS. As with everything I do lately, the text editing is done with vim and output is built with just command-line tools; no GUI, no fancy stuff.
First step is to get the software development kit (sdk) and the necessary development tools. This can be done in MacOSX using homebrew by,
[code language=”bash”]
brew install android-sdk
sdkmanager "platform-tools" "build-tools;27.0.3;" "platforms;android21"
[/code]
We are going to use a example app called clicker which I made for my research to count pedestrians on sidewalk. It has a simple counter which can be increased by clicking anywhere on the screen. There are only three files which make the app, MainActivity.java which has the app logic, activity_main.xml which has the layout on the screen and AndroidManifest.xml which pulls the .java and .xml together to make the app. The folder structure is shown below and the sample files with the folder structure are attached here.
MainActivity.java
[code language=”java”]
package com.bala.clicker;
import android.app.Activity;
import android.app.ActionBar;
import android.view.View;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
ActionBar actionBar = getActionBar();
actionBar.hide();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text = (TextView)findViewById(R.id.my_text);
text.setText("0");
LinearLayout layout = (LinearLayout)findViewById(R.id.lay);
layout.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
TextView text = (TextView)findViewById(R.id.my_text);
int count = Integer.parseInt(text.getText().toString());
text.setText(Integer.toString(count+1));
}
});
}
}
[/code]
activity_main.xml
[code language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:id="@+id/lay">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/my_text"
android:textSize="65dp"
android:gravity="center"
/>
</LinearLayout>
[/code]
AndroidManifest.xml
[code language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bala.clicker"
versionCode="1"
versionName="0.1">
<uses-sdk android:minSdkVersion="21"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application android:label="Clicker">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
[/code]
Before we can build the app, we need to make the required directories for the temporary files generated in the process. we do that by, mkdir -p build/gen build/obj build/apk. We also need a signature to sign the final app with before it can be installed on a device. This is generated by the keytool, keytool -genkeypair -keystore keystore.jks -alias androidkey -validity 10000 -keyalg RSA -keysize 2048 -storepass android -keypass android. Finally, for creating the building script we need to know the location of the android-sdk. this can be done by find command looking for “build-tools” as shown below sudo find / -name “build-tools”. This path (“/usr/local/Caskroom/android-sdk/3859397″) is defined as SDK in our script and used in our build script below. This is kept as build.sh in the root directory,
[code language=”bash”]
#!/bin/bash
# Defining the environment variables
SDK=/usr/local/Caskroom/android-sdk/3859397
BUILD_TOOLS="${SDK}/build-tools/27.0.3"
PLATFORM="${SDK}/platforms/android-21"
# Building the packages
"${BUILD_TOOLS}/aapt" package -f -m -J build/gen/ -S res -M AndroidManifest.xml -I "${PLATFORM}/android.jar"
javac -source 1.7 -target 1.7 -bootclasspath "${JAVA_HOME}/jre/lib/rt.jar" -classpath "${PLATFORM}/android.jar" -d build/obj build/gen/com/bala/clicker/R.java java/com/bala/clicker/MainActivity.java
"${BUILD_TOOLS}/dx" –dex –output=build/apk/classes.dex build/obj/
"${BUILD_TOOLS}/aapt" package -f -M AndroidManifest.xml -S res/ -I "${PLATFORM}/android.jar" -F build/clicker.unsigned.apk build/apk/
"${BUILD_TOOLS}/zipalign" -f -p 4 build/clicker.unsigned.apk build/clicker.aligned.apk
"${BUILD_TOOLS}/apksigner" sign –ks keystore.jks –ks-key-alias androidkey –ks-pass pass:android –key-pass pass:android –out build/clicker.apk build/clicker.aligned.apk
# Sending the apk to phone and starting the app.
"${SDK}/platform-tools/adb" install -r "build/clicker.apk"
"${SDK}/platform-tools/adb" shell am start -n com.bala.clicker/.MainActivity
[/code]
finally we give execute privileges on the file to ourselves by “chmod u+x build.sh”, connect the phone to the Mac via usb and run the script by “./build.sh”. Thats it! the app should be now installed on the phone and started as shown below,