Android Jni学习笔记

昨天开通了博客园,记录我的学习生活.

今天又练习了一下Android用Jni调本地的c程序.将内容整理如下

1.新建工程,建立一个Activity,将有关Activity的代码全部注释起来,只留下native方法的申明.这一步的原因是,在生成java方法的c(c++)方法签名的时候避免一些包的缺少错误.

package com.jon.jnitest;

/*
import android.app.Activity;
import android.os.Bundle;
*/
 /**
  * Jni测试
  * @author LJH
  *
  */
public class JniTestActivity 
//extends Activity 
{
	/** Called when the activity is first created. */
	/*
	@Override
	
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		System.out.println("加法8+2="+add(8, 2));
		System.out.println("减法8-2="+sub(8,2));
		System.out.println("乘法8*2="+mul(8,2));
		System.out.println("除法8/2="+div(8, 2));
		System.out.println(sayHello());
	}
	
	static{
		System.loadLibrary("testjni");
	}
	*/
	public native int add(int a, int b);

	public native int sub(int a, int b);

	public native int mul(int a, int b);

	public native int div(int a, int b);
	
	public native String sayHello();
}

2.在命令行下编译此java文件.

javac编译

将生成的.class文件拷到bin\classes下覆盖原来的.class文件.

3.生成c(c++)的方法签名cd到项目的根目录:

javah

此时会在src目录生成一个.h的头文件,改成.c或.cpp的文件,实现里面的方法.

4.用c或c++实现申明的方法.

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

#ifndef _Included_com_jon_jnitest_JniTestActivity
#define _Included_com_jon_jnitest_JniTestActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jon_jnitest_JniTestActivity
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_jon_jnitest_JniTestActivity_add
  (JNIEnv * env, jobject obj, jint a, jint b)
	{
		return a+b;
	}

/*
 * Class:     com_jon_jnitest_JniTestActivity
 * Method:    sub
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_jon_jnitest_JniTestActivity_sub
  (JNIEnv * env, jobject obj, jint a, jint b)
	{
		return a-b;
	}

/*
 * Class:     com_jon_jnitest_JniTestActivity
 * Method:    mul
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_jon_jnitest_JniTestActivity_mul
  (JNIEnv * env, jobject obj, jint a, jint b)
	{
		return a*b;
	}
 
/*
 * Class:     com_jon_jnitest_JniTestActivity
 * Method:    div
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_jon_jnitest_JniTestActivity_div
  (JNIEnv * env, jobject obj, jint a, jint b)
	{
		return a/b;
	}

/*
 * Class:     com_jon_jnitest_JniTestActivity
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jon_jnitest_JniTestActivity_sayHello
  (JNIEnv * env, jobject obj)
	{
		jstring jstr ;
		char cstr[] = "Welcome to the world of Jni!";
		jstr = env->NewStringUTF(cstr);
		return jstr;
	}

#ifdef __cplusplus
}
#endif
#endif

5.在工程根目录新建一个jni的文件夹,将上面实现的c或c++文件拷到里面,并新建或从别处复制一个Android.mk文件:内容如下:

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := testjni
LOCAL_SRC_FILES := com_jon_jnitest_JniTestActivity.cpp
include $(BUILD_SHARED_LIBRARY)

在这其中,LOCAL_MODULE是本地模块,也就是以后会生成的库文件名,当然,生成的库文件名前面有一个lib的前缀:libtestjni.so.

LOCAL_SRC_FILES是cpp源文件.
6.cd到项目根目录,用Cygwin 执行ndk的命令:

目标文件

这样就在工程根目录下出现了libs和obj两个文件夹,其中我们需要的库文件就在libs里面.

7.回到我们的Activity里面,调用库里面的方法

        @Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		System.out.println("加法8+2=" + add(8, 2));
		System.out.println("减法8-2=" + sub(8, 2));
		System.out.println("乘法8*2=" + mul(8, 2));
		System.out.println("除法8/2=" + div(8, 2));
		System.out.println(sayHello());
	}

	static {
		System.loadLibrary("testjni");
	}

记得一定要System.loadLibrary("testjni"); 装载库进来.注意库的名称是和LOCAL_MODULE := testjni 一样.

8 需要注意的是:在c中,char[]转换成jstring是用(*env)->NewStringUTF(cstr);

而c++中用的是 env->NewStringUTF(cstr);

我最开始将前面的.h头文件重命令成.c文件实现后,进行编译会报一个错误,网上找资料也没有解决,将它贴出来:

参数不对

这是先前用c实现的方法,别的地方都是一样的,只是在

jstr = (*env)->NewStringUTF(cstr);

这里不一样,

但是如果将c实现的这一句知写成和c++实现的一样的话又会报另一个错误:

结构体错误

 

真是另人纠结,最后改成.cpp文件才对了.

第一次写,如果有不对的地方欢迎大家指点.共同进步,先谢过了哈!

记录点滴...

转载于:https://www.cnblogs.com/John2011/archive/2011/12/29/2306771.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值