From 3492bb7744bd7b7a90eed6f839fdbb2582b447b6 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sat, 8 Sep 2012 19:16:28 +0200 Subject: [PATCH] Adds android example using jni. --- .gitignore | 9 ++ .../android/AndroidManifest.xml | 18 ++++ examples/cross_calculator/android/build.xml | 92 +++++++++++++++++++ .../cross_calculator/android/custom_rules.xml | 17 ++++ .../cross_calculator/android/jni/Android.mk | 32 +++++++ .../android/jni/backend-jni.c | 42 +++++++++ .../android/project.properties | 14 +++ examples/cross_calculator/android/readme.txt | 30 ++++++ .../android/res/values/strings.xml | 4 + .../android/scripts/jnibuild.sh | 22 +++++ .../android/scripts/nimbuild.sh | 34 +++++++ .../cross_calculator/android/scripts/tags.sh | 13 +++ .../crosscalculator/CrossCalculator.java | 46 ++++++++++ 13 files changed, 373 insertions(+) create mode 100644 examples/cross_calculator/android/AndroidManifest.xml create mode 100644 examples/cross_calculator/android/build.xml create mode 100644 examples/cross_calculator/android/custom_rules.xml create mode 100644 examples/cross_calculator/android/jni/Android.mk create mode 100644 examples/cross_calculator/android/jni/backend-jni.c create mode 100644 examples/cross_calculator/android/project.properties create mode 100644 examples/cross_calculator/android/readme.txt create mode 100644 examples/cross_calculator/android/res/values/strings.xml create mode 100755 examples/cross_calculator/android/scripts/jnibuild.sh create mode 100755 examples/cross_calculator/android/scripts/nimbuild.sh create mode 100755 examples/cross_calculator/android/scripts/tags.sh create mode 100644 examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java diff --git a/.gitignore b/.gitignore index 417de4ab65..af25077dce 100755 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,12 @@ xcuserdata/ # iOS specific absolute paths examples/cross_calculator/ios/resources/ui/*.m examples/cross_calculator/ios/tags + +# Android specific absolute paths. +examples/cross_calculator/android/bin/ +examples/cross_calculator/android/gen/ +examples/cross_calculator/android/jni/backend-jni.h +examples/cross_calculator/android/libs/ +examples/cross_calculator/android/local.properties +examples/cross_calculator/android/obj/ +examples/cross_calculator/android/tags diff --git a/examples/cross_calculator/android/AndroidManifest.xml b/examples/cross_calculator/android/AndroidManifest.xml new file mode 100644 index 0000000000..05b96fb503 --- /dev/null +++ b/examples/cross_calculator/android/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/examples/cross_calculator/android/build.xml b/examples/cross_calculator/android/build.xml new file mode 100644 index 0000000000..d7c88432a7 --- /dev/null +++ b/examples/cross_calculator/android/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cross_calculator/android/custom_rules.xml b/examples/cross_calculator/android/custom_rules.xml new file mode 100644 index 0000000000..91783a50e4 --- /dev/null +++ b/examples/cross_calculator/android/custom_rules.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/cross_calculator/android/jni/Android.mk b/examples/cross_calculator/android/jni/Android.mk new file mode 100644 index 0000000000..c1a0feac3a --- /dev/null +++ b/examples/cross_calculator/android/jni/Android.mk @@ -0,0 +1,32 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := nimrod +LOCAL_SRC_FILES := nimcache/backend.c nimcache/system.c +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/nimcache + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := backend-jni +LOCAL_SRC_FILES := backend-jni.c +LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog +LOCAL_STATIC_LIBRARIES := nimrod + +include $(BUILD_SHARED_LIBRARY) diff --git a/examples/cross_calculator/android/jni/backend-jni.c b/examples/cross_calculator/android/jni/backend-jni.c new file mode 100644 index 0000000000..3d65458ec8 --- /dev/null +++ b/examples/cross_calculator/android/jni/backend-jni.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include "backend-jni.h" +#include "backend.h" + +#define TAG "backend-jni.c" + +jint JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_myAdd + (JNIEnv *env, jobject thiz, jint a, jint b) +{ + char buf[256]; + const jint ret = myAdd(a, b); + // Using logging from inside the native bridge to log-debug. + sprintf(buf, "a %d + b %d = ret %d", a, b, ret); + __android_log_write(ANDROID_LOG_DEBUG, TAG, buf); + return ret; +} + +void JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_initNimMain + (JNIEnv *env, jclass thiz) +{ + NimMain(); + __android_log_write(ANDROID_LOG_DEBUG, TAG, "Nimrod initialised"); +} + +// vim:tabstop=2 shiftwidth=2 syntax=c diff --git a/examples/cross_calculator/android/project.properties b/examples/cross_calculator/android/project.properties new file mode 100644 index 0000000000..9fb894d9b4 --- /dev/null +++ b/examples/cross_calculator/android/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-3 diff --git a/examples/cross_calculator/android/readme.txt b/examples/cross_calculator/android/readme.txt new file mode 100644 index 0000000000..f8b16d4fcf --- /dev/null +++ b/examples/cross_calculator/android/readme.txt @@ -0,0 +1,30 @@ +In this directory you will find the Android platform cross-calculator sample. + +Due to the nature of Android being java and nimrod generating C code, the build +process is slightly more complex because jni code has to be written to bridge +both languages. In a distant future it may be possible for nimrod to generate +the whole jni bridge, but for the moment this is manual work. + +For the jni bridge to work first the java code is compiled with the nimrod code +just declared as a native method which will be resolved at runtime. The scripts +nimbuild.sh and jnibuild.sh are in charge of building the nimrod code and +generating the jni bridge from the java code respectively. Finally, the +ndk-build command from the android ndk tools has to be run to build the binary +libary which will be installed along the final apk. + +All these steps are wrapped in the ant build script through the customization +of the -post-compile rule. If you have the android ndk tools installed and you +modify scripts/nimbuild.sh to point to the directory where you have nimrod +installed on your system, you can simply run "ant debug" to build everything. + +Once the apk is built you can install it on your device or emulator with the +command "adb install bin/CrossCalculator-debug.apk". + +You can use this example as a starting point for your project or look at the +history of the github project at https://github.com/gradha/nimrod-on-android. +That repository documents the individual integration steps you would take for +any Android project (note it uses Eclipse rather than ant to build and +therefore the build process requires more manual fiddling). + +This example runs against the Android level 3 API, meaning devices from +Android 1.5 and above should be able to run the generated binary. diff --git a/examples/cross_calculator/android/res/values/strings.xml b/examples/cross_calculator/android/res/values/strings.xml new file mode 100644 index 0000000000..05cd3ac93c --- /dev/null +++ b/examples/cross_calculator/android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + CrossCalculator + diff --git a/examples/cross_calculator/android/scripts/jnibuild.sh b/examples/cross_calculator/android/scripts/jnibuild.sh new file mode 100755 index 0000000000..8b61f20f7c --- /dev/null +++ b/examples/cross_calculator/android/scripts/jnibuild.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Force errors to fail script. +set -e + +# If we are running from inside the scripts subdir, get out. +if [ ! -d src ] +then + cd .. +fi + +# Ok, are we out now? +if [ -d src ] +then + javah -classpath bin/classes \ + -o jni/backend-jni.h \ + com.github.nimrod.crosscalculator.CrossCalculator +else + echo "Uh oh, bin/classes directory not found?" + echo "Try compiling your java code, or opening in eclipse." + exit 1 +fi diff --git a/examples/cross_calculator/android/scripts/nimbuild.sh b/examples/cross_calculator/android/scripts/nimbuild.sh new file mode 100755 index 0000000000..97130b8dd6 --- /dev/null +++ b/examples/cross_calculator/android/scripts/nimbuild.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# Set this to the local or full path of your nimrod compiler +PATH_TO_NIMROD=~/project/nimrod/bin/nimrod +# Set this to the location of the nimbase.h file so +# the script can update it if it changes. +PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h + +# Force errors to fail script. +set -e + +# If we are running from inside the scripts subdir, get out. +if [ ! -d src ] +then + cd .. +fi + +DEST_NIMBASE=jni/nimcache/nimbase.h + +# Ok, are we out now? +if [ -d src ] +then + $PATH_TO_NIMROD c --noMain --app:lib \ + --nimcache:jni/nimcache --cpu:arm --os:linux \ + --compileOnly --header ../nimrod_backend/*.nim + if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ] + then + echo "Updating nimbase.h" + cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}" + fi +else + echo "Uh oh, src directory not found?" + exit 1 +fi diff --git a/examples/cross_calculator/android/scripts/tags.sh b/examples/cross_calculator/android/scripts/tags.sh new file mode 100755 index 0000000000..95507064f4 --- /dev/null +++ b/examples/cross_calculator/android/scripts/tags.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +if [ ! -d src ] +then + cd .. +fi + +if [ -d src ] +then + ~/bin/objctags -R \ + jni \ + src +fi diff --git a/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java b/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java new file mode 100644 index 0000000000..22a4b9d0c7 --- /dev/null +++ b/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java @@ -0,0 +1,46 @@ +package com.github.nimrod.crosscalculator; + +import android.app.Activity; +import android.widget.TextView; +import android.os.Bundle; + +public class CrossCalculator extends Activity +{ + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + /* Create a TextView and set its content. + * the text is retrieved by calling a native + * function. + */ + TextView tv = new TextView(this); + final int a = 4; + final int b = 18; + final int c = myAdd(a, b); + tv.setText("myAdd(" + a + ", " + b + ") = " + c); + setContentView(tv); + } + + /* A native method that is implemented by the + * 'backend-jni' native library, which is packaged + * with this application. Adds to integers. + */ + public native int myAdd(int a, int b); + + /* A native method used to initialise Nimrod. + */ + static public native void initNimMain(); + + /* this is used to load the 'backend-jni' library on application + * startup. The library has already been unpacked into + * /data/data/com.github.nimrod.backendjni/lib/libbackend-jni.so at + * installation time by the package manager. + */ + static { + System.loadLibrary("backend-jni"); + initNimMain(); + } +}