Android Studio使用JNI和NDK進行開發

想要學習一下在Android Studio中進行JNI的開發,文章挺多的,可是幾乎沒有一個完整的說明的,中間老是有一兩步漏掉。分享技術就應該完整的讓讀者學會,藏着掖着不是君子所爲。對於那些故意含糊過去的,我只想說Navie!html

轉載請註明出處 http://www.cnblogs.com/qiusuo/p/5656625.htmljava

正文android

JNI是JAVA標準平臺中的一個重要功能,它彌補了JAVA的與平臺無關這一重大優勢的不足,在JAVA實現跨平臺的同時,也能與其它語言(如C、C++)的動態庫進行交互,給其它語言發揮優點的機會。app

Android NDK(Native Development Kit )是一套工具集合,容許你用像C/C++語言那樣實現應用程序的一部分。ide

  1. 在使用NDK以前須要配置NDK和LLDB
    經過使用SDK Manager找到NDK和LLDB,進行安裝
  2. 按照通常方法,建立一個Android應用
    File - New - New Project工具

  3. 建立一個新的Java Class(與MainActivity一個目錄),類名爲JniDemo,其中有一個Native方法
    package com.example.angel.myapplication;
    
    /**
     * Created by Angel on 2016/7/8.
     */
    public class JniDemo {
        public native String getJniMessage();
    } 
  4. 編譯JniDemo.java這個帶有Native方法的類
    在命令提示符中,cd到文件所在目錄,執行javac JniDemo.java,能夠看到目錄中生成了對應的.class文件
  5. 生成對應的.h頭文件
    a) 在命令提示符中,cd到src/main/java文件夾中(內部的目錄結構是包名,例如個人包名是com.example.angel.myapplication,目錄結構爲/src/main/java/com/example/angel/myapplication)
    b) 執行javah com.example.angel.myapplication.JniDemo,會在當前目錄生成head file(.h)文件。
  6. 在Project樹形目錄下app - src - main,創建jni folder,並將head file放到裏邊
     
  7. 在jni文件夾中建立C/C++源文件,並include這個頭文件,實現其中的方法。
    #include "com_example_angel_myapplication_JniDemo.h"
    JNIEXPORT jstring JNICALL Java_com_example_angel_myapplication_JniDemo_getJniMessage
      (JNIEnv *, jobject)
    {
        return (*env)->NewStringUTF(env,"Jni Message: Hello World!");
    }
  8. build - Rebuild Project後,會出現一個錯誤。而且給出瞭解決方案:Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
    在gradle.properties中添加一行android.useDeprecatedNdk=true
  9. build - Rebuild Project後,又會出現warming,NDK option is not configured。按照提示,進行以下內容的添加:
    在app的build.gradle文件中,添加以下內容:
    android {
     sourceSets { main { jniLibs.srcDir 'src/main/jni' } }
    }

    而且自定義so庫的名稱學習

    android {
        ......
        defaultConfig {
            ......
     ndk { moduleName 'jnidemo'//自定義名稱
     }
        }
    }

    若是不這麼作的話,生成的庫文件名稱是[lib][module name].sogradle

  10. build - Rebuild Project,能夠看到生成了so文件
    在目錄:app - build - intermediates - ndk - debug - lib下
  11. 加載so文件。
    so文件加載一次即可以使用,通常狀況下,在靜態代碼段中進行加載
        static {
            System.loadLibrary("jnidemo");
        }
  12. 使用Native方法
    public class MainActivity extends AppCompatActivity {
        static {
            System.loadLibrary("jnidemo"); }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final JniDemo jniDemo = new JniDemo();
            TextView textView = (TextView) findViewById(R.id.text); textView.setText(jniDemo.getHelloWordText());
        }
    } 
  13. Native方法使用java代碼
    在Java代碼中,建立以下方法,用以在Native代碼中調用
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            sContext = getApplicationContext();
        }
        private static Context sContext;
        public static void showToast() {
            Toast.makeText(sContext, "此方法由Native方法調用", Toast.LENGTH_SHORT).show();
        }

    在Native代碼中,使用以下代碼進行調用ui

        //找到咱們要調用的方法,注意包名+類名
        jclass clazz = (*env)->FindClass(env,"com/example/angel/myapplication/MainActivity");
        //獲取某個靜態方法的ID
        //clazz 是咱們上面找到的類的字節碼文件
        //showToast 是clazz類中的方法名
        //"()V" 這個表示方法的簽名;()是方法的參數列表;V表示方法的返回類型;V -> void
        jmethodID id = (*env)->GetStaticMethodID(env,clazz, "showToast","()V");
        //最後調用這個方法,CallStaticVoidMethod(clazz,方法ID)
        (*env)->CallStaticVoidMethod(env,clazz,id);
相關文章
相關標籤/搜索