Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> AS下NDK開發(一),as下ndk開發

AS下NDK開發(一),as下ndk開發

編輯:關於android開發

AS下NDK開發(一),as下ndk開發


搗鼓了一天的NDK,總結下。

Eclipse下開發ndk好像挺麻煩的樣子,看書上要下載Cygwin,eclipse還要下載插件CDT。。而在AS上就方便多啦。下載android ndk。安裝,配置環境,即可。

NDK(android native develop kits ):android 本地開發工具集 ,這些工具幫助開發者快速開發C或C++動態庫,並自動將so和java文件打包成apk,可以把c/c++ ->編譯成一個 linux下可以執行的二進制文件 java代碼裡面就可以通過jni 調用執行二進制的文件.

JNI :java本地開發接口,JNI是一個協議這個協議用來溝通java代碼和外部的本地代碼(c/c++).通過這個協議,java代碼就可以調用外部的c/c++,代碼外部的c/c++代碼也可以調用java代碼。

JNI開發用途:Native code效率高,數學運算,實時渲染的游戲上,音視頻處理(極品飛車,opengl,ffmpeg等。

一、配置NDK環境

下載NDK,網上有很多,下載好之後,解壓即可。然後在AS中配置,依次點擊:File ->ProjectStructure:如圖:

配置好之後,會在項目下的local.properties文件裡自動添加:ndk.dir=D\:\\android-ndk-r10d   如果沒有就自己加上,我的是自動的。

二、建立app項目

  1.建立一個普通的android project

  2.聲明原生方法,必須加上native,告訴程序這是一個原生方法。在具體java代碼調用時,和調用java的其他方法一樣,直接調用就可以了。activity代碼:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class NDK extends Activity {

    static {
        System.loadLibrary("MyJni");//導入生成的鏈接庫文件
    }
    
    public native String getStringFromNative();//本地方法
    public native String getString_From_c();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ndk);
    }

    public void onClick(View view) {
        System.out.println(getString_From_c());
        Toast.makeText(this, getStringFromNative(), Toast.LENGTH_LONG).show();
    }
}

System.loadLibrary("MyJni");加載庫,需要注意的是加載的庫名即編譯生成的庫名,去掉前綴lib和後綴so。

然後make project一下,目的就是編譯成對應的class文件。然後根據生成的class文件,利用javah生成對應的 .h頭文件。

三、生成.h頭文件

1.AS中點擊view ->ToolsWindows->Terminal,
cd app\src\main,進入src\main\目錄下:
2.執行:
javah -d jni -classpath F:\android\sdk\platforms\android-23\android.jar;..\..\build\intermediates\classes\debug example.user.ndkdemo2.NDK
這個命令很長,分開慢慢來,javah是生成頭文件需要的工具,-d jni 在工程下生成jni目錄,到時會在這個目錄下建JNI開始的C/C++源文件的。
-classpath F:\android\sdk\platforms\android-23\android.jar 這個就是你SDK文件下android.jar所在的文件位置,找到後復制即可。
..\..\build\intermediates\classes\debug 這個路徑如圖所示:

example.user.ndkdemo2.NDK就是NDKclass的路徑名。

執行完這個命令後,會在main文件夾下自動生成jni目錄和.h頭文件。

可以打頭文件看看:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class example_user_ndkdemo2_NDK */

#ifndef _Included_example_user_ndkdemo2_NDK
#define _Included_example_user_ndkdemo2_NDK
#ifdef __cplusplus
extern "C" {
#endif
#undef example_user_ndkdemo2_NDK_BIND_ABOVE_CLIENT
#define example_user_ndkdemo2_NDK_BIND_ABOVE_CLIENT 8L
#undef example_user_ndkdemo2_NDK_BIND_ADJUST_WITH_ACTIVITY
#define example_user_ndkdemo2_NDK_BIND_ADJUST_WITH_ACTIVITY 128L
#undef example_user_ndkdemo2_NDK_BIND_ALLOW_OOM_MANAGEMENT
#define example_user_ndkdemo2_NDK_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef example_user_ndkdemo2_NDK_BIND_AUTO_CREATE
#define example_user_ndkdemo2_NDK_BIND_AUTO_CREATE 1L
#undef example_user_ndkdemo2_NDK_BIND_DEBUG_UNBIND
#define example_user_ndkdemo2_NDK_BIND_DEBUG_UNBIND 2L
#undef example_user_ndkdemo2_NDK_BIND_IMPORTANT
#define example_user_ndkdemo2_NDK_BIND_IMPORTANT 64L
#undef example_user_ndkdemo2_NDK_BIND_NOT_FOREGROUND
#define example_user_ndkdemo2_NDK_BIND_NOT_FOREGROUND 4L
#undef example_user_ndkdemo2_NDK_BIND_WAIVE_PRIORITY
#define example_user_ndkdemo2_NDK_BIND_WAIVE_PRIORITY 32L
#undef example_user_ndkdemo2_NDK_CONTEXT_IGNORE_SECURITY
#define example_user_ndkdemo2_NDK_CONTEXT_IGNORE_SECURITY 2L
#undef example_user_ndkdemo2_NDK_CONTEXT_INCLUDE_CODE
#define example_user_ndkdemo2_NDK_CONTEXT_INCLUDE_CODE 1L
#undef example_user_ndkdemo2_NDK_CONTEXT_RESTRICTED
#define example_user_ndkdemo2_NDK_CONTEXT_RESTRICTED 4L
#undef example_user_ndkdemo2_NDK_MODE_APPEND
#define example_user_ndkdemo2_NDK_MODE_APPEND 32768L
#undef example_user_ndkdemo2_NDK_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define example_user_ndkdemo2_NDK_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef example_user_ndkdemo2_NDK_MODE_MULTI_PROCESS
#define example_user_ndkdemo2_NDK_MODE_MULTI_PROCESS 4L
#undef example_user_ndkdemo2_NDK_MODE_PRIVATE
#define example_user_ndkdemo2_NDK_MODE_PRIVATE 0L
#undef example_user_ndkdemo2_NDK_MODE_WORLD_READABLE
#define example_user_ndkdemo2_NDK_MODE_WORLD_READABLE 1L
#undef example_user_ndkdemo2_NDK_MODE_WORLD_WRITEABLE
#define example_user_ndkdemo2_NDK_MODE_WORLD_WRITEABLE 2L
#undef example_user_ndkdemo2_NDK_DEFAULT_KEYS_DIALER
#define example_user_ndkdemo2_NDK_DEFAULT_KEYS_DIALER 1L
#undef example_user_ndkdemo2_NDK_DEFAULT_KEYS_DISABLE
#define example_user_ndkdemo2_NDK_DEFAULT_KEYS_DISABLE 0L
#undef example_user_ndkdemo2_NDK_DEFAULT_KEYS_SEARCH_GLOBAL
#define example_user_ndkdemo2_NDK_DEFAULT_KEYS_SEARCH_GLOBAL 4L
#undef example_user_ndkdemo2_NDK_DEFAULT_KEYS_SEARCH_LOCAL
#define example_user_ndkdemo2_NDK_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef example_user_ndkdemo2_NDK_DEFAULT_KEYS_SHORTCUT
#define example_user_ndkdemo2_NDK_DEFAULT_KEYS_SHORTCUT 2L
#undef example_user_ndkdemo2_NDK_RESULT_CANCELED
#define example_user_ndkdemo2_NDK_RESULT_CANCELED 0L
#undef example_user_ndkdemo2_NDK_RESULT_FIRST_USER
#define example_user_ndkdemo2_NDK_RESULT_FIRST_USER 1L
#undef example_user_ndkdemo2_NDK_RESULT_OK
#define example_user_ndkdemo2_NDK_RESULT_OK -1L
#undef example_user_ndkdemo2_NDK_MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS
#define example_user_ndkdemo2_NDK_MAX_NUM_PENDING_FRAGMENT_ACTIVITY_RESULTS 65534L
#undef example_user_ndkdemo2_NDK_HONEYCOMB
#define example_user_ndkdemo2_NDK_HONEYCOMB 11L
#undef example_user_ndkdemo2_NDK_MSG_REALLY_STOPPED
#define example_user_ndkdemo2_NDK_MSG_REALLY_STOPPED 1L
#undef example_user_ndkdemo2_NDK_MSG_RESUME_PENDING
#define example_user_ndkdemo2_NDK_MSG_RESUME_PENDING 2L
/*
 * Class:     example_user_ndkdemo2_NDK
 * Method:    getStringFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_example_user_ndkdemo2_NDK_getStringFromNative
  (JNIEnv *, jobject);

/*
 * Class:     example_user_ndkdemo2_NDK
 * Method:    getString_From_c
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_example_user_ndkdemo2_NDK_getString_1From_1c
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

這個文件中:JNIEXPORT jstring JNICALL Java_example_user_ndkdemo2_NDK_getStringFromNative(JNIEnv *, jobject);這是函數定義,Java_<packege_path>_<class_name>_<method_name>(JNIEnv *, jobject,<parameter_list>);

函數定義中這兩個參數:JNIEnv *, jobject是必須的,之後才是需要在函數調用時需要傳遞的參數,如:

Java_<packege_path>_<class_name>_<method_name>(JNIEnv *, jint value1,jint value2);//jint是什麼意思,在後邊說明。jint就是代表的Java裡的int類型。

四,創建C文件,實現native方法

在jni目錄下建立c文件:util.c是一個空文件,這是因為NDK在windows系統上的一個bug,沒有會出錯,你也可以不建,如果出錯再建也沒事。

c文件:

#include "example_user_ndkdemo2_NDK.h"
//#include <android/log.h>
//#define  LOG_TAG  "System.out"
//#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,  __VA_ARGS__)
//#define LOGINFO(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,  __VA_ARGS__)


JNIEXPORT jstring JNICALL Java_example_user_ndkdemo2_NDK_getStringFromNative
        (JNIEnv * env, jobject jobject){
   // LOGINFO("LOGINFO");
    return (*env)->NewStringUTF(env,"NDK 測試成功");
}

JNIEXPORT jstring JNICALL Java_example_user_ndkdemo2_NDK_getString_1From_1c
        (JNIEnv * env, jobject jobject){

    return  (*(*env)).NewStringUTF(env,"NDK 來自於C文件");

}
//
// Created by user on 2016/4/13.
//

最後還有配置一個地方:build.gradle文件的defaultConfig中加ndk

android.mk文件位置:

五、jni.h文件

在jni.h文件中,定義了本地的數據類型和對象的引用類型,編寫c代碼時要注意必須使用這些定義的數據類型和對象的引用類型

對象數據:





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved