第一个NDK程序

之前写了第一个JNI程序,有翻译了一篇NDK的入门教程,今天从头到尾自己写了一个。

环境:linux+ndk r6

开始之前:java和ndk的环境变量已经设置好

目标:一个简单的例子,从c中传给java int数组和字符串数组

开始:

新建一个项目,名称为FirstNDK

一个包是package com.linc.FirstNDK;放activity

另一个是package com.linc.lib;放lib文件,主要处理jni

布局:两个按钮+一个textview

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
	android:id="@+id/btnOne"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="int Array!"
/>
<TextView  
	android:id="@+id/Result"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Result:"
    />
<Button
	android:id="@+id/btnTwo"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="string Array!"
/>    
</LinearLayout>
package com.linc.lib包下新建一个类FirstLib

package com.linc.lib;


public class FirstLib {
	// Native implementation  
	static {  
	System.loadLibrary("FirstLib"); 
	}  
	
	//传递数组
	public static native int[] intMethod();
	//传递字符串数组
	public static native String[] stringMethod();
}
这里主要有两个本地方法,

下面用它生成jni的头文件:用终端来到项目bin目录(前提是FirstLib这个类已经编译完成),

[linc@localhost bin]$ javah -jni com.linc.lib.FirstLib
项目中新建一个jni目录,用来存放jni相关文件,并把刚刚生成的头文件放进去

[linc@localhost bin]$ mv com_linc_lib_FirstLib.h ../jni
在jni中新建一个c文件与上面的对应叫FirstLib.c,

#include "com_linc_lib_FirstLib.h"
const static int length=10;

//传递整型数组
JNIEXPORT jintArray JNICALL Java_com_linc_lib_FirstLib_intMethod
  (JNIEnv *env, jclass obj)
{
	jintArray array;//数组
	array=(*env)->NewIntArray(env,10);
	int i=1;
	for(;i<=10;++i)
	{
		(*env)->SetIntArrayRegion(env,array,i-1,1,&i);
	}

	//获取数组长度
	int len=(*env)->GetArrayLength(env,array);

	//获得数组中的所有元素
	jint* elems=(*env)->GetIntArrayElements(env,array,0);

	return array;
}

//字符串数组
JNIEXPORT jobjectArray JNICALL Java_com_linc_lib_FirstLib_stringMethod
  (JNIEnv *env, jclass obj)
{
	jclass class=(*env)->FindClass(env,"java/lang/String");
	jobjectArray string=(*env)->NewObjectArray(env,(jsize)length,
			class,0);
	jstring jstr;
	char* _char[]={"my ","name ","is ",
					"linc!!","正在","学习",
					"JNI","和","NDK","技术!"
					};
	int i=0;
	for(;i<length;++i)
	{
		jstr=(*env)->NewStringUTF(env,_char[i]);
		(*env)->SetObjectArrayElement(env,string,i,jstr);
	}

	return string;
}

在jni目录下新建一个mk文件,Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := FirstLib
LOCAL_SRC_FILES := FirstLib.c
include $(BUILD_SHARED_LIBRARY)

好,下面将其编译成共享库:回到项目目录

[linc@localhost FirstNDK]$ cd ..
[linc@localhost FirstNDK]$ ndk-build
Compile thumb  : FirstLib <= FirstLib.c
SharedLibrary  : libFirstLib.so
Install        : libFirstLib.so => libs/armeabi/libFirstLib.so

下面在activity中调用之:

package com.linc.FirstNDK;


import java.io.UnsupportedEncodingException;

import com.linc.lib.FirstLib;
import com.linc.lib.PersonalInfo;

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

public class FirstNDK extends Activity {
	TextView textResult;  
	Button buttonOne;  
	Button buttonTwo;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        textResult = (TextView) findViewById(R.id.Result);  
        buttonOne = (Button) findViewById(R.id.btnOne);  
        buttonOne.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				int[] nums=FirstLib.intMethod();
				for(int i=0;i<nums.length;++i)
				{
					textResult.append("  "+nums[i]);
				}
			}
		}); 
        
        buttonTwo = (Button) findViewById(R.id.btnTwo);  
        buttonTwo.setOnClickListener(btnTwo_Click);
    }
    
    private OnClickListener btnTwo_Click = new OnClickListener()
    {
    	public void onClick(View v)
    	{    		
    		String[] string=FirstLib.stringMethod();
    		for(int i=0;i<string.length;++i)
    		{
    			try {
    				string[i]=new String(string[i].getBytes("gb2312"),"GBK");
    			} catch (UnsupportedEncodingException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			textResult.append("  "+string[i]);
    		}
    	}
    };
	
}
最后就可以运行看效果了!
ndk的使用,首先要具备jni的相关知识,在本blog中有相关记载。

希望大家用ndk来开发游戏时,玩的开心!


后记:

1.ndk 未找到。。。类的错误。
今天发现这个错误,主要是因为项目bin路径下还有一层classes。如下处理就可以了:

~/workspace/TestNDK/bin$ javah -classpath ./classes -d ./jni com.linc.lib.FirstLib


2.loadlibrary相关

Android.mk 可以这样写(摘自cocos2d-x中的demo):

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := game_shared

LOCAL_MODULE_FILENAME := libgame

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp \
                   ../../Classes/GameOverScene.cpp
                   
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes                   

LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static
            
include $(BUILD_SHARED_LIBRARY)

$(call import-module,CocosDenshion/android)
$(call import-module,cocos2dx)
LOCAL_MODULE 是game_shared,如果没有定义LOCAL_MODULE_FILENAME,那么编译出来的so就是libgame_shared.so,

而在java文件中load时就必须要

    static {
        System.loadLibrary("game_shared");
    }
有趣的是,定义LOCAL_MODULE_FILENAME为libgame后,编译出来的so当然是libgame.so了,而java中load “game”就可以了。

3.NDK r7之后直接对编译的支持

        在整理NDK r7的特性时,直接提供对编译的支持,在windows下就不用cygwin了。

        现在我已经使用r9b了,项目右键--->Android Tools--->Add Native Support...

你会发现帮你添加了jni的文件夹,并且项目属性中在Builders里面有多了两项,一个是CDT Builder,一个是Scanner Configuration Builder。

更贴心的,属性都为你设置好了,直接添加编辑你的C、C++代码吧。




  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
android-ndk-r18是Android软件开发工具包(NDK)的一个版本。NDK允许开发者使用C、C++和其他本地语言来开发Android应用程序。使用NDK,开发者可以编写高性能和可移植的代码,并与Java代码进行混合编程。 android-ndk-r18是NDK的第18个稳定版本。这个版本包含了一些新的特性和改进,以提升开发者的开发体验和应用性能。其中一些特性包括: 1. 支持新的架构:android-ndk-r18引入了对新的CPU架构的支持,如ARMv8、x86和x86_64。开发者可以利用这些新的架构特性来编写更高效的代码,并为不同的平台提供最佳的性能。 2. CMake支持:这个版本引入了对CMake构建系统的支持。CMake是一个流行的开源构建系统,它可以帮助开发者更轻松地管理和构建复杂的项目。使用CMake,开发者可以更快速地配置和构建他们的NDK项目。 3. OpenMP支持:android-ndk-r18增加了对OpenMP并行程序设计的支持。OpenMP是一种面向共享内存多线程编程的API,可以帮助开发者更容易地编写和管理多线程应用程序。 4. LLVM更新:这个版本的NDK使用了最新的LLVM编译器,提供了更好的代码优化和性能。 总的来说,android-ndk-r18是一个强大的工具包,可以帮助开发者更好地开发高性能和可移植的Android应用程序。通过支持新的架构、引入CMake和OpenMP支持以及使用最新的LLVM编译器,这个版本提供了更多的工具和功能,以满足开发者的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值