-
This section outlines the necessary steps to write a simple native "Hello World!" JNI-enabled Android application.
-
This section assumes you have read and followed the steps in Compiling C/C++ code directly from Android Studio
-
Create a new Android Studio project. To do so, select
File -> New -> New Project.-
Give the application a name. For example:
HelloWorldJni. -
Set the "Company Domain" entry to be
example.com, so that the application package name becomescom.example.helloworldjni. -
Select
Blank Activityin the "Add an activity to Mobile" step. This activity will become your application's "main" activity, and is appropriately namedMainActivity.javawith layout fileactivity_main.xml.
-
-
In
activity_main.xml, change the defaultTextViewto have anandroid:idwith no defaultandroid:text. The layout file should look like the following:<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
-
In
MainActivity.java, for the sake of simplicity, remove any override methods except foronCreate(Bundle). In astaticblock inside the class (usually at the top, by convention), add the lineSystem.loadLibrary("helloWorldJni"). This will link the native module with namehelloWorldJniwith theMainActivityclass at runtime, which we will write later. YourMainActivityclass should look like the following:public class MainActivity extends AppCompatActivity { static { System.loadLibrary("helloWorldJni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
-
Now, in the
onCreate(Bundle)method, initialize theTextViewfrom the layout file. We will then set aStringonto it, which will be returned by a native JNI method. To do this, declare anativemethod (usually at the bottom, also by convention) calledgetNativeString(). This is needed since the compiler still needs to know that such method exists. Then, on theTextView, call its member methodsetText(String), and pass in the return value ofgetNativeString(). YourMainActivityclass should look like the following:public class MainActivity extends AppCompatActivity { static { System.loadLibrary("helloWorldJni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.text_view); textView.setText(getNativeString()); } private native String getNativeString(); }
-
It's time to write the native method
getNativeString()you called above. To do this, create a C++ source file namedHelloWorldJni.cppundersrc/main/java/jniwith the following contents.#include <jni.h> extern "C" JNIEXPORT jstring JNICALL Java_com_example_helloworldjni_MainActivity_getNativeString( JNIEnv *env, jobject obj) { return env->NewStringUTF("Hello World! From native code!"); }
There are several points to note about this file:
-
extern "C": Statement to make C++ function names have C linkage. To support function overloading, C++ compilers mangle function names, which means C++ function names are not the same as in C. Withoutextern "C", your native functions' signatures will not match their declarations in Java (at runtime). Long story short, you need this statement for every method if you are writing native C++ and not C. -
Method signature: JNI functions need to be named in the following manner:
JNIEXPORT <RETURN_TYPE> JNICALL Java_<PACKAGE_NAME>_<JAVA_CLASS>_<METHOD_NAME>( JNIEnv *env, jobject obj, <METHOD_PARAMETERS>...) { ... }-
JNIEXPORT: Contains compiler directives required to ensure the function is exported properly. -
<RETURN_TYPE>: Return type of the JNI method, usually a native version of a Java type. For example, in the method you just wrote above, you are returning ajstring, which is the native equivalent ofStringin Java. -
JNICALL: Contains compiler directives required to ensure the function is treated with the proper JNI calling convention. -
<JAVA_CLASS>: The connecting Java class this function is tied to. In our example, this would beMainActivity, since that's the Java class that will use this function. -
<PACKAGE_NAME>: The package name where the previously defined<JAVA_CLASS>resides in. Replace dots (.) with underscores (_). -
<METHOD_NAME>: This name should be the same as the one you declare inside the connecting<JAVA_CLASS>. In our example, we declared thenativemethodgetNativeString(). In this case,<METHOD_NAME>should also begetNativeString(). -
JNIEnv *env: Pointer to a structure (a function table, to be exact) storing all JNI helper function pointers, including the one we call in our example,NewStringUTF(string). To be able to use these functions, you will need to#include <jni.h>. -
jobject obj: Java object corresponding to the connecting<JAVA_CLASS>. -
<METHOD_PARAMETERS>...: Comma delimited list of input arguments the native method is supposed to take. In our example, we do not have any input arguments for ourgetNativeString()function, and is hence left blank.
-
-
-
Ensure that your
Android.mkfile has correct entries forLOCAL_MODULEandLOCAL_SRC_FILES:LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := helloWorldJni LOCAL_SRC_FILES := HelloWorldJni.cpp include $(BUILD_SHARED_LIBRARY)
And that's it! You should be able to run your app onto a device/emulator as usual.
do you know how to arrange my native methods to group all together inside my java classes?

Im already tried regions, section rule, but android studio arrangement dont understand native keyword