Android NDK小Demo講解

開發工具:Eclipses

要進行NDK開發,先配置好開發環境,分爲以下兩項:

1.Android NDK

        提供編譯腳本和工具.

2.Cygwin

        完成Linux環境下的交叉編譯,將C/C++的源代碼文件編譯成Android系統可調用的共享連接庫文件.

兩者我都打包放在這兒了:

鏈接:AndroidNDK及Cygwin 密碼:i8yy

環境搭建OK了,現在開始新建一個小Demo測試下:


如上圖,基本重要的幾個文件都用紅框標示出來了.

libs文件夾不用手動創建,是完成編譯後自動生成的,用Refresh刷新就出現在其中了.

先把界面和基本功能OK.

package com.example.androidndkdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AndroidNdkDemoActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_android_ndk_demo);
		
		final TextView displayLable = (TextView)findViewById(R.id.display);
		Button button = (Button)findViewById(R.id.add_btn);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				double randomDouble = Math.random();
				long x = Math.round(randomDouble * 100);
				randomDouble = Math.random();
				long y = Math.round(randomDouble * 100);
				
				//System.loadLibrary("add-module");   //動態加載鏈接庫
				long z = add(x, y);
				String msg = x + "+" + y + "=" +z;
				displayLable.setText(msg);
			}

		});
	}
	//public native long add(long x, long y);            //鏈接庫中函數的聲明
	
	public long add(long x, long y) {
		return x + y;
	}
}

也可以通過如下方式靜態加載鏈接庫

static{

    System.loadLibrary("add-module");

}

佈局文件如下

<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"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:id="@+id/display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/hello_world"
        android:textSize = "30dp" />
    
    <Button 
        android:id="@+id/add_btn"
        android:layout_below="@id/display"
        android:layout_alignLeft="@id/display"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="加法運算"

        />

</RelativeLayout>

然後創建Android.mk文件,內容如下:

LOCAL_PATH := $(call my-dir)            //my-dir表示Android.mk所在的jni目錄, LOCAL_PATH用來定義需要編譯的C/C++源碼的位置

include $(CLEAR_VARS)                    //表示清空所有以LOCAL_開頭的變量,但不包括第一行的LOCAL_PATH,因爲所有變量都是全局變量,所以每次使用前必須清空所有以前用過的變量


LOCAL_MODULE    := add-module            //用來聲明模塊名稱,名稱必須唯一且不能存在空格,如本例中最後生成的鏈接庫文件名爲libadd-module.so,如果使用以lib爲前綴的模塊名稱,則最後生成的.so文件不會再添加lib前綴
LOCAL_SRC_FILES := add-module.c          //表示編譯模塊所需要的C/C++文件

include $(BUILD_SHARED_LIBRARY)          //表示Android NDK編譯系統需要構建共享庫,如果把BUILD_SHARED_LIBRARY改爲BUILD_STATIC_LIBRARY則表示需要NDK編譯系統構建靜態庫.共享庫可以被Android工程中的Java代碼調用,並打包到apk文件中;靜態庫只能在生成共享庫的過程中被共享庫中的C/C++代碼所調用

然後建立C源碼文件

#include <jni.h>

jlong Java_com_example_androidndkdemo_AndroidNdkDemoActivity_add(JNIEnv * env, jobject this, jlong x, jlong y)
{
	return x + y;
}

jlong表示java長型整數,com_example_androidndkdemo_AndroidNdkDemoActivity_add表示包名_類名_函數名

最後一步,編譯共享庫模塊

首先啓動Cygwin,切換到Android NDK的主目錄下


輸入命令 export NDK=/cygdrive/d/android-ndk-r16b/

表示把右邊的路徑賦值給NDK變量

可以通過命令 echo $NDK 查看NDK的值

切換到Android項目的路徑下


輸入命令 $NDK/ndk-build

編譯成功的提示信息如下


然後再Eclipses的AndroidNdkDemo右鍵點擊Refresh就有libs文件夾了.

把AndroidNdkDemoActivity中java寫的add函數註釋掉,把原本註釋的兩處都取消註釋,運行app,看效果嘍.

我驗證是和用java寫的add函數一樣的效果,你要是什麼地方報錯了歡迎在評論區討論.

完整項目源碼在這兒:

AndroidNdkDemo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章