1. Add the android JNI interface to the android code tree
1.1 assume that the JNI interface to be tested is testnativeapi. Java, and add it to frameworks/base/CORE/JNI/testnativeapi. Java under the android code tree.
This native program is compiled into a jar package in Android and can be called by upper-layer Android Java applications.
In its static function, Android system. loadlibrary () is called to call the. So library of lower-level C ++, and loadlibrary () judges the type of. So library,
If the JNI library of C ++ is used, the jni_onload () function in the. So library is called to register the JNI interface. Native program to implement the bridge function from Java to C ++ code.
The code for testnativeapi. Java is as follows:
Package com. Me. test;
Import Android. util. log;
Public final class testnativeapi {
Static {
Try {
System. loadlibrary ("itest_jni ");
} Catch (unsatisfiedlinkerror e ){
Log. D ("itest_jni", "itest JNI library not found! ");
}
}
/**
* This class is uninstantiable.
*/
Private testnativeapi (){
// This space intentionally left blank.
}
Public native static int apifunction ();
}
1.2 modify the makefile (frameworks/base/CORE/JNI/Android. mk) of Android and compile testnativeapi. Java into jar by using the makefile function build_java_library.
# Build com. Me. Test. Jar
#===================================================== ==================================
Test_dirs: =/
./Test/Java/COM/ME/test
Test_src_files: = $ (call all-Java-files-under, $ (cm_dirs ))
#===== The library ============================================== ==========
Include $ (clear_vars)
Local_src_files: = $ (test_src_files)
Local_no_standard_libraries: = true
Local_java_libraries: = core framework
Local_module: = com. Me. Test
Include $ (build_java_library)
1.3 you also need to modify framework/base/data/etc/platform. XML to add.
<Library name = "com. Me. test"
File = "/system/framework/COM. Me. Test. Jar"/>
So that the jar package can be linked.
2. Then we can add the C ++ code to implement the JNI interface defined in step 1.
2.1 Add frameworks/base/CORE/JNI/testinternalapi. cpp to the android code tree. In this c ++ class, you can call the underlying C ++/C function control hardware.
Among them, the jni_onload () function is called when. So is loaded, and the test_testinterapi_func () function is the specific code run when the android upper-layer Java application calls JNI apifunction.
# Define log_tag "itest_jni"
# Include <utils/Misc. h>
# Include <utils/log. h>
# Include "JNI. H"
# Include "jnihelp. H"
# Include "android_runtime/androidruntime. H"
# Include "scm_dbus_utils.h"
# Define internalapi_pkg_name "com/ME/test/testnativeapi"
Using namespace android;
Static jint test_testinterapi_func (jnienv * ENV, jobject clazz)
{
Jint ret = (jint) 0;
Logd ("Call/" % S/"", _ function __);
Return ret;
}
/*
* JNI registration.
*/
Static jninativemethod gtestinterapimethods [] = {
{"Apifunction", "() I", (void *) test_testinterapi_func}
};
Int register_com_me_test_testinternalapinative (jnienv * env)
{
Return androidruntime: registernativemethods (ENV, internalapi_pkg_name, gtestinterapimethods, nelem (gtestinterapimethods ));
}
Jint jni_onload (JavaVM * Vm, void * Reserved)
{
Jnienv * Env = NULL;
Jint result =-1;
Logd ("testinteralapi JNI loaded ");
If (Vm-> getenv (void **) & ENV, jni_version_1_4 )! = Jni_ OK ){
LogE ("getenv failed ");
Goto bail;
}
Assert (ENV! = NULL );
If (register_com_me_test_testinternalapinative (ENV) <0 ){
LogE ("testinternalapi native registration failed ");
Goto bail;
}
Result = jni_version_1_4;
Bail:
Return result;
}
2.2 modify the makefile (frameworks/base/CORE/JNI/Android. mk) of Android and compile testinternalapi. cpp into. So by using the makefile function build_java_library.
Include $ (clear_vars)
Ifeq ($ (target_arch), arm)
Local_cflags + =-dpacked = "_ attribute _ (packed ))"
Else
Local_cflags + =-dpacked = ""
Endif
Local_src_files: =/
Testinternalapi. cpp
Local_c_includes + =/
$ (Jni_h_include)
Local_shared_libraries: =/
Libandroid_runtime/
Libnativehelper/
Libcutils/
Libutils/
Libdvm
Local_module: = libitest_jni
Include $ (build_shared_library)
Endif
3. recompile Android and install to generate JNI. So and jar packages.
/System/lib/libitest_jni.so
/System/framework/COM. Me. Test. Jar
4. To compile and debug Android JNI in eclipse, you need to install Android SDK and ADT
If Android 2.0.1/2.0.01 is used, configure adt-0.9.5.zip or up
4.1 to install the SDK, follow these steps:
Set "eclipse --> window --> prefrences --> Android --> SDK location" to Android SDK path
4.2 To install ADT, follow these steps:
Set "eclipse --> help> Software Updates... --> Add site dialog --> click Archive" to the downloaded ADT-0.9.5.zip
5. note that we want to test the implementation of JNI, that is, in step 2. so, we need to set the JNI interface, that is, testnativeapi in step 1. compile a jar package available for host eclipse in Java.
Eclipse-> file-> New-> project...-> JAVA Project
Add testnativeapi. Java to src/COM/ME/test/
Add the Android. jar in the SDK to the "build library path" of the project"
After compilation, generate the jar package, export-> JAVA-> jar-> com. Me. Test. Jar
6. finally, the android JUnit test project is established. By calling the jar package (JNI Interface) of Step 5 on the host, the communication is implemented through JNI generated by ADB and Step 2 on the target to achieve debug.
Eclipse-> file-> New-> project...-> Android test project
6.1 add internalapialltest. Java (this is common to all JUnit and can be copied directly)
Package com. Me. internalapitest;
Import JUnit. Framework. test;
Import JUnit. Framework. testsuite;
Import Android. Test. suitebuilder. testsuitebuilder;
/**
* A test suite containing all tests for my application.
*/
Public class internalapialltest extends testsuite {
Public Static Test Suite (){
Return new testsuitebuilder (alltests. Class). includeallpackagesunderhere (). Build ();
}
}
6.2 add internalapinativetest. Java (this is the actual test case)
Package com. Me. internalapitest;
Import JUnit. Framework. Assert;
Import COM/ME/test/testnativeapi;
Import Android. Test. instrumentationtestcase;
Public class internalapinativetestextends
Instrumentationtestcase {
Protected void setup () throws exception {
Super. Setup ();
}
Protected void teardown () throws exception {
Super. teardown ();
}
Public void testenablesystem () throws throwable {
Int result = internalapinativetest. apifunction (0 );
Assert. asserttrue (result = 0 );
}
}
6.3 modify the properties of the internalapinativetest project and add the com. Me. Test. Jar generated in step 5 to the Java build library path.
7. After all the code is added, debug is started.
7.1 log on to the android board and use the following method to make the adbd on the target board use the socket port instead of the default USB port.
# Rm/dev/android_adb
# Rm/dev/android_adb_enable
# Setprop persist. Service. ADB. Enable 1
# Setprop service. ADB. Root 1
# Setprop CTL. Stop adbd
# Setprop CTL. Start adbd
7.2. Because the host eclispe will also start the ADB server, which points to the android emulator, You need to first launch eclipse and first kill all ADB processes
# Ps aux | grep ADB | grep-V grep
# Kill-9 <adb_pid>
7.3. Enable ADB server again on the host,
# Export adbhost = <android_bb_ip_address>
# Export adb_trace = aDb
# ADB nodaemon Server
If the following information is displayed on the terminal, it indicates that the ADB server points to the android development board at this time.
...
Parse_banner: Device ::
Setting connection_state to cs_device
ADB: Online
...
At this time, you can log on to the android Development Board using the ADB shell in another terminal.
# Export adbhost = <android_bb_ip_address>
# ADB Shell
7.4. Set the android JUnit Environment
# Export adbhost = <android_bb_ip_address>
# <Eclispe_path>/eclipse
Choose "run --> RUN configuration --> Android JUnit test" and select "new launch configuration"
On the "test" tab, select "Run all tests in the selected project, or package" and "internalapinativetest"
On the "target" tab, select the "deployment target selection mode" option "Manual"
7.5. finally run JUnit test runner
In the ADB login terminal generated in step 7.3
# Logcat
In eclipse, select "Run --> Run as --> Android JUnit test" and use the configuration generated in step 7.4.
You can see that JUnit in eclipse displays the test results.
In addition, log information in frameworks/base/CORE/JNI/testinternalapi. cpp is printed on the android terminal running logcat.
For other information about Android JNI,
We can refer to this article http://android.wooyd.org/JNIExample/