jni生成so動態庫,a靜態庫,傳遞中文字符串

本項目是生成靜態庫libA.a,用libA.a生成libB.a,再用libA.a和libB.a一起生成libC.so動態庫。

1.新建一個安卓項目,添加文件夾jni,在jni下添加cpp或者c文件,此cpp或c文件就是用來生成so的源文件。

2.要生成靜態庫libA.a,要有Android.mk文件和Application.mk,直接在jni目錄下添加即可。

Android.mk內容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := A//生成的靜態庫的名字,即libA.a中的A
LOCAL_SRC_FILES :=  //需要的源文件,依次列開,用空格或tab隔開

include $(BUILD_STATIC_LIBRARY)//生成靜態庫

Application.mk內容如下:

APP_MODULES :=A//表明生成靜態庫的名字

3.用靜態庫libA.a生成libB.a,直接在jni目錄下添加Android.mk和Application.mk文件。

Android.mk內容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS) 
LOCAL_MODULE    := A 
LOCAL_SRC_FILES := libA.a 
include $(PREBUILT_STATIC_LIBRARY) //連接方式是靜態的
include $(CLEAR_VARS)

LOCAL_MODULE    := B//生成的靜態庫的名字
LOCAL_STATIC_LIBRARIES := A//需要的靜態庫
LOCAL_SRC_FILES := //需要的源文件 

include $(BUILD_STATIC_LIBRARY)//生成靜態庫

Application.mk的內容和2中的一樣。

4.用靜態庫libA.a和libB.a生成libC.so動態庫

只需要Android.mk即可,內容如下:

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=A B
LOCAL_SRC_FILES :=libA.a libB.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -lm -llog//在c文件中打log
LOCAL_MODULE :=C//生成的動態庫的名字
LOCAL_STATIC_LIBRARIES :=A B//依賴的靜態庫名字
LOCAL_SRC_FILES:=//所需的源文件
include $(BUILD_SHARED_LIBRARY)
5.生成的動態庫在本項目中使用,或者在別的項目中調用。

src中的java文件如何調用:

/*
 * 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.
 */
package com.example.hellojni;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Hashtable;

import org.apache.http.util.ByteArrayBuffer;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
import android.os.Environment;
//import com.android.ide.eclipse.ndk.*;
public class HelloJni extends Activity
{
	  public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
<span style="white-space:pre">	</span>}
    static {
        System.loadLibrary("decode");//加載動態庫,動態庫要放在bin\ndk\local\armeabi目錄下
    }
}

6.在windows命令行進入項目的bin\classes路徑下,執行javah -d jni com.example.hellojni.HelloJni,前3個單詞是包的名字,後一個單詞是類名字。

會生成一個頭文件,放在jni目錄下

7.源文件的接口必須按照如下接口:

jbyteArray Java_com_example_hellojni_HelloJni_fun( JNIEnv* env,
                                                  jobject thiz,jstring imagefile)

com_example_hellojni是包名

HelloJni是類名

fun是方法名

8.從java傳入字符串給c

const char* jcstr = (const char *)(*env)->GetStringUTFChars(env,imagefile, 0 );//返回指向字符串的 UTF-8 字符數組的指針
		//LOGI("%s","MYLOG:BBB");
		int length=0;
		length= (*env)->GetStringUTFLength(env,imagefile)+1;//以字節爲單位返回字符串的 UTF-8 長度
		LOGI("%d",length);
		char* rtn = (char*)malloc( length );
		memcpy(rtn,jcstr,length);
		//char* rtn = (char*)malloc( 33 );
		//memcpy(rtn,jcstr,33);
		char *aaa = rtn;
		 (*env)->ReleaseStringUTFChars(env, imagefile, jcstr);//通知虛擬機平臺相關代碼無需再訪問 utf
		

9.如果返回一個自己定義的中文字符串,那麼在java中接受是沒有問題的,但是我的項目提供的字符串是帶中文的而且不知道是什麼格式的,和自己定義的字符串不一樣,所以最終決定返回byte數組,在java中轉換爲中文字符串 ,

unsigned char result[1000] = {0};
	memset(result,0,1000);
						//	unsigned char test[] = "adfadf35345你說什麼";
			len = strlen(result);
			LOGI("len::");
			LOGI("%d",len);
			jbyteArray data = (*env)->NewByteArray(env,len);// 我這裏是byte型數組 1024是數組長度
			jbyte* pbuf = (jbyte*)malloc(len);
			memcpy(pbuf, result, len);

			(*env)->SetByteArrayRegion(env,data, 0, len, pbuf);
			LOGI("%s",data);
			free(pbuf);
			return data;

在java中

 String str2 = "";
      try {
		str2 = new String(res,"GBK");
	} catch (UnsupportedEncodingException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

即可

ps:c和java的文件環境都是utf-8格式的


10.在c文件打log:

#include <android/log.h>

#define LOG_TAG "logfromc"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

在Android.mk中加入一句:

include $(CLEAR_VARS)//此句下邊
LOCAL_LDLIBS := -lm -llog





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