Android之Windows下生成動態庫so並打包到APK中

Android內核是Linux的,而linux的動態庫是*.so文件,那麼在windows要如何生成並打包到APK中呢?實現這一過程,大致需要以下幾個步驟:

1、搭建編譯環境

2、使用JNI生成相應的頭文件

3、編寫動態庫的實現

4、生成動態庫

5、編譯調用動態庫的代碼

6、動態庫打包到APK中

7、測試

下面就依據這些步驟一一進行實現。

1、搭建編譯環境

要生成*.so的動態庫文件,需要有交叉編譯的環境,這個可以在Linux下搭建,在windows下也同樣可以。在Windows下需要借助Sourcery CodeBench Lite Edition for ARM,這個可以直接到官網上下載(可能需要註冊帳號),這裡是地址https://sourcery.mentor.com/sgpp/lite/arm/portal/subscription?@template=lite,進入後選擇GNU/Linux,如下圖。

選擇Sourcery CodeBench Lite 2013.11-33,進入下面的頁面。

下載完後,直接安裝,按照提示一路下一步。安裝的路徑最好不要放在有空格或者含中文的路徑下,比如默認文件夾Program Files就是帶空格的,這樣的路徑有可能會影響命令的執行。我是安裝到D:\Sourcery_CodeBench_Lite_for_ARM_GNU_Linux。vcD4KPHA+sLLXsM3qs8m686OsvauwstewxL/CvM/CtcRiaW7J6NbDtb27t76zseTBv9bQo6y8tEQ6XFNvdXJjZXJ5X0NvZGVCZW5jaF9MaXRlX2Zvcl9BUk1fR05VX0xpbnV4XGJpbqGjPC9wPgo8cD48aW1nIHNyYz0=”/uploadfile/Collfiles/20140320/20140320084610145.jpg” alt=”\”>

設置瞭環境變量後,才能方便調用這些exe。

2、使用JNI生成相應的頭文件

(1)、在Eclipse中新建一個Android工程,命名為DynamicLibTest,名包為com.example.dlt,新建一個調用動態庫的類NativeJniAdder.java,代碼如下

package com.example.dlt;

import android.util.Log;

public class NativeJniAdder {
	static 
	{
		try {
			Log.i("JNI", "Trying to load libNativeJniAdder.so");
			System.loadLibrary("NativeJniAdder");
			
		} catch (UnsatisfiedLinkError ule) {
			Log.e("JNI", "WARNING:Gould not load libNativeJniAdder.so");
		}
	}
	
	public static native int calculate(int digit_1,int digit_2);
}

註:System.loadLibrary就是加載動態庫的代碼,動態庫隻寫lib和.so之間的名稱,這個與Windows下調用dll不太一樣。比如動態庫為libNativeJniAdder.so,那麼在loadLibrary時就是NativeJniAdder.

(2)、使用javah來生成頭文件(javah需要安裝JDK)。

在DynamicLibTest的工程下增加一個libcode文件夾,在該文件夾下添加一個生成頭文件的genHeader.bat,代碼如下:

javah -classpath ../src com.example.dlt.NativeJniAdder

執行該,將會生成一個com_example_dlt_NativeJniAdder.h的頭文件。

打開該頭文件會看到如下的代碼:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_example_dlt_NativeJniAdder */

#ifndef _Included_com_example_dlt_NativeJniAdder
#define _Included_com_example_dlt_NativeJniAdder
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_dlt_NativeJniAdder
 * Method:    calculate
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_dlt_NativeJniAdder_calculate
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

註:該頭文件的代碼不要去修改。

3、編寫動態庫的實現

依據生成的頭文件com_example_dlt_NativeJniAdder.h實現,代碼如下:

com_example_dlt_NativeJniAdder.c

#include "com_example_dlt_NativeJniAdder.h"

JNIEXPORT jint JNICALL Java_com_example_dlt_NativeJniAdder_calculate(JNIEnv *env,
		jclass c, jint digit_1, jint digit_2) {
	int sum=digit_1+digit_2;
	return sum;
}

4、生成動態庫

(1)、生成*.o的中間文件,編寫腳本compile.bat,內容如下

arm-none-linux-gnueabi-gcc -I D:\Java\jdk7\include -I D:\Java\jdk7\include\linux -fpic -nostdlib -c com_example_dlt_NativeJniAdder.c

註:

1)、需要安裝JDK,而且JDK建立安裝在無空格且不含中文的目錄下,我是安裝在:\Java下。執行該腳本後,將會生成com_example_dlt_NativeJniAdder.o。

2)、windows下安裝jdk,在include下會有一個win32的文件夾,這裡需要用到liunx的文件夾(該文件夾是在linux下安裝jdk產生的),該文件夾可以從liunx下復制過來。或者建一個liunx文件夾,在下面增加jawt_md.h和jni_md.h文件,其內容如下:

jawt_md.h

/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_

#include 
#include 
#include 
#include "jawt.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * X11-specific declarations for AWT native interface.
 * See notes in jawt.h for an example of use.
 */
typedef struct jawt_X11DrawingSurfaceInfo {
    Drawable drawable;
    Display* display;
    VisualID visualID;
    Colormap colormapID;
    int depth;
    /*
     * Since 1.4
     * Returns a pixel value from a set of RGB values.
     * This is useful for paletted color (256 color) modes.
     */
    int (JNICALL *GetAWTColor)(JAWT_DrawingSurface* ds,
        int r, int g, int b);
} JAWT_X11DrawingSurfaceInfo;

#ifdef __cplusplus
}
#endif

#endif /* !_JAVASOFT_JAWT_MD_H_ */

jni_md.h

/*
 * %W% %E%
 *
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_

#define JNIEXPORT 
#define JNIIMPORT
#define JNICALL

typedef int jint;
#ifdef _LP64 /* 64-bit Solaris */
typedef long jlong;
#else
typedef long long jlong;
#endif

typedef signed char jbyte;

#endif /* !_JAVASOFT_JNI_MD_H_ */

(2)、檢驗*.o文件

cmd中定位到com_example_dlt_NativeJniAdder.o所在的目錄,然後輸入

arm-none-linux-gnueabi-ld com_example_dlt_NativeJniAdder.o

這時會看到如下圖的畫面,提示警告。如果提示有error的,說明編譯出問題瞭。

(3)、生成*.so的中間文件,編寫腳本genSo.bat,內容如下

arm-none-linux-gnueabi-ld -T D:\Sourcery_CodeBench_Lite_for_ARM_GNU_Linux\arm-none-linux-gnueabi\lib\ldscripts\armelf_linux_eabi.xsc -shared -o ..\libs\armeabi\libNativeJniAdder.so com_example_dlt_NativeJniAdder.o

註:

1)、D:\Sourcery_CodeBench_Lite_for_ARM_GNU_Linux是Sourcery_CodeBench_Lite_for_ARM_GNU_Linux的安裝路徑,需依據實際的安裝路徑進行修改。

2)、在DynamicLibTest工程下的libs文件夾下增加armeabi文件夾,如果libs沒有,可以自行增加。

3)、生成的動態庫文件的名字必須是以lib開頭、以.so作為後綴的,如libNativeJniAdder.so。否則放到Android中將會識別不瞭。

執行腳本後,將會在armeabi文件夾下生成一個libNativeJniAdder.so的動態庫文件,見下圖。


5、編譯調用動態庫的代碼

在DynamicTest工程的MainActivity.java中調用動態庫。

package com.example.dlt;

import android.app.Activity;
import android.os.Bundle;

import com.example.sumcalculator.R;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_activity);

		int digit_1 = 8, digit_2 = 9;
		int sum = NativeJniAdder.calculate(digit_1, digit_2);

		setTitle("[" + sum + "]");
	}

}

6、動態庫打包到APK中

將*.so的動態庫文件打包到APK中時,如果是在eclipse環境中,必須要在工程下的libs文件夾下增加一個armeabi文件夾(eabi:Embedded application binary interface, 即嵌入式應用二進制接口),然後正常編譯生成apk即可。

在編譯生成apk後,可以將apk解開,然後可以看到在lib文件夾下會有一個armeabi的文件夾,裡面含有我們打包進去的動態庫文件。

註:也可以通過adb push *.so \system\lib的方式,將*.so放到system\lib下,以供調用。但是這個過程,並不是所有手機都可以的。比如小米就不行,會被擋掉。如果使用這個命令來做,還有可能會出現only read file system的錯誤,這時可以先執行adb remount,然後再adb push *.so \system\lib。adb remount這個命令在小米中同樣會被擋掉。

所以要怎麼用,需自行斟酌。

7、測試

將apk安裝到手機中,然後執行。在代碼中我們執行的是8+9,所以預期的結果是[17]。測試結果如下圖。

<img src="/wp-content/images1/20181210/20140320084611150107.jpg" alt="n塊?莓垵Z)藎源碼下載

發佈留言