android ndk-build 編譯靜態庫libxx.a 以及Android studio openssl 靜態庫配置(cmake)

來源:互聯網
上載者:User

標籤:ted   images   default   add   直接   sig   string   定義   tip   

android ndk-build 編譯靜態庫libxx.a

需求情境:

目前有安卓編碼好的現在的openssl的兩個.a,我們需要調用openssl的函數,並把功能再封裝成.a;

這樣使用時,在android studio jni項目 cmake 裡面,需要先引用openssl的.a再引用 上面封裝的.a;

如果使用so,那麼,直接在android studio jni項目的 cpp裡面直接調用openssl的方法,對外提供jni java介面,打包成so即可;

 

先來說用ndk-build 打包 libxx.a吧,並在打包的時候引用openssl的靜態庫.a

1. 首先目前的目錄下準備好 編碼好的openssl靜態庫,如示,安卓平台的

   

2. 測試使用的源檔案,我這裡在.h聲明一個封裝的方法 ssl_sha,並且在.c 實現裡面,調用 openssl 的SHA256介面;如下 

  加 #ifdef __cplusplus 是為了在jni調用時,cpp裡面出現未定義的錯誤,如下 ssl_hash.h

#ifndef ssl_hash_h#define ssl_hash_h# ifdef  __cplusplusextern "C" {#endif#include <stdio.h>/* * openssl sha256 * */int ssl_sha256(const char *in_data,int in_len,char *out_hash);# ifdef  __cplusplus}# endif#endif /* ssl_hash_h */

 

 如下 ssl_hash.c 實現檔案

#include "ssl_hash.h"#include "openssl/sha.h"int ssl_sha256(const char *in_data,int in_len,char *out_hash){    if (!in_data) {        return -100;    }        if (!SHA256((const unsigned char *)in_data, in_len, (unsigned char *)out_hash)) {        return -1001;    }    return 1;}

同樣這兩檔案也要放在 .mk的同一目錄;

3. 開始編寫 Android.mk,Application.mk, 如下樣本

#Android.mk檔案LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#編碼後產生的.a的名稱LOCAL_MODULE    := sslhash #要編碼的源檔案c或cppLOCAL_SRC_FILES := ssl_hash.c#依賴的靜態庫.a,若要使用動態庫使用LOCAL_SHARED_LIBRARIES .soLOCAL_STATIC_LIBRARIES := libs/${TARGET_ARCH_ABI}/lib/libssl.a libs/${TARGET_ARCH_ABI}/lib/libcrypto.a#依賴的靜態庫的標頭檔LOCAL_C_INCLUDES := libs/${TARGET_ARCH_ABI}/include#最後產生靜態庫include $(BUILD_STATIC_LIBRARY)
#Application.mk 這裡測試,只編譯出x86的APP_ABI := x86

4. 所有檔案都準備好之後如示:

 

5. 調用ndk-build 開始編譯

~/Library/Android/sdk/ndk-bundle/ndk-build NDK_PROJECT_PATH=./ NDK_LIBS_OUT=./ APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk

 

6. 成功之後會在目前的目錄下產生 obj目錄,裡麵包含產生的 靜態庫libxx.a

   

 

7. 編譯好之後,下面需要在Android studio 中測試;用as 建立一個jni項目;

8.在工程build.gradle(Module:app) 裡面添加 libs目錄 (Android 視圖)

    externalNativeBuild {        cmake {            path "CMakeLists.txt"        }    }    sourceSets {        main {            jniLibs.srcDirs = [‘libs‘]        }    }

  並且在指定測試只編譯 x86

externalNativeBuild {            cmake {                cppFlags ""                abiFilters "x86"            }        }        ndk{            abiFilters "x86"        }

9. 將之前libs目錄的openssl庫全部copy到 工程 jnilibs目錄 (Android 視圖)

   並把產生的libsslhash.a放到 x86/lib下

   並把ssl_hash.h標頭檔放到x86/include下

   放到哪都行,需要在cmake裡面指定引用好

   

10. 開啟CmakeList.txt 配置openssl靜態庫的引用,以及配置引用產生的libsslhash.a

如下完善的cmakelist

cmake_minimum_required(VERSION 3.4.1)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")#這裡配置指定目錄libsset(OpenSSL_DIR ${CMAKE_SOURCE_DIR}/libs)# Creates and names a library, sets it as either STATIC# or SHARED, and provides the relative paths to its source code.# You can define multiple libraries, and CMake builds them for you.# Gradle automatically packages shared libraries with your APK.#這裡引用三個靜態.a, ssl,sslhash,cryptoadd_library(crypto STATIC IMPORTED)add_library(ssl STATIC IMPORTED)add_library(sslhash STATIC IMPORTED)# 這裡載入,並且找到相應的 libxxx.aset_target_properties( # Specifies the target library.                       crypto                       # Specifies the parameter you want to define.                       PROPERTIES IMPORTED_LOCATION                       # Provides the path to the library you want to import.                       ${OpenSSL_DIR}/${ANDROID_ABI}/lib/libcrypto.a )set_target_properties( # Specifies the target library.                       ssl                       # Specifies the parameter you want to define.                       PROPERTIES IMPORTED_LOCATION                       # Provides the path to the library you want to import.                       ${OpenSSL_DIR}/${ANDROID_ABI}/lib/libssl.a ) set_target_properties( # Specifies the target library.                        sslhash                        # Specifies the parameter you want to define.                        PROPERTIES IMPORTED_LOCATION                        # Provides the path to the library you want to import.                        ${OpenSSL_DIR}/${ANDROID_ABI}/lib/libsslhash.a)add_library( # Sets the name of the library.             native-lib             # Sets the library as a shared library.             SHARED             # Provides a relative path to your source file(s).             src/main/cpp/native-lib.cpp )# Searches for a specified prebuilt library and stores the path as a# variable. Because CMake includes system libraries in the search path by# default, you only need to specify the name of the public NDK library# you want to add. CMake verifies that the library exists before# completing its build.find_library( # Sets the name of the path variable.              log-lib              # Specifies the name of the NDK library that              # you want CMake to locate.              log )# Specifies libraries CMake should link to your target library. You# can link multiple libraries, such as libraries you define in this# build script, prebuilt third-party libraries, or system libraries.#這裡openssl需要 zlib庫,載入系統的find_library( z-lib z )#這裡指定一下咱的標頭檔目錄,openssl標頭檔,以及咱封裝的ssl_hash.h標頭檔include_directories( ${OpenSSL_DIR}/${ANDROID_ABI}/include                     ${OpenSSL_DIR}/${ANDROID_ABI}/)#最後一步串連,這裡注意,一定要把sslhash,咱封裝的這個.a放到ssl,crypto的前面,不然報錯說方法未定義,可能因為sslhash引用了openssl的東西,target_link_libraries( # Specifies the target library.                       native-lib                       # Links the target library to the log library                       # included in the NDK.                        sslhash                        ssl                        crypto                        ${log-lib}                        ${z-lib})

 

11. 配置完成,如果編譯不出問題就可以寫jni調用測試了;

   在 MainActitity.java裡面,添加一下jni方法  

    public native String stringFromJNI();    //添加的測試方法    public native int sslsha(byte[] indata,int inlen,byte[] outhash);

12. 在native-lib.cpp 裡面實現jni方法

#include "ssl_hash.h"extern "C"JNIEXPORT jint JNICALLJava_androidapp_cocoajin_com_tjni_MainActivity_sslsha(JNIEnv *env, jobject instance,                                                      jbyteArray indata_, jint inlen,                                                      jbyteArray outhash_) {    jbyte *indata = env->GetByteArrayElements(indata_, NULL);    jbyte *outhash = env->GetByteArrayElements(outhash_, NULL);    int ret = ssl_sha256((const char *)indata,inlen,(char *)outhash);    env->ReleaseByteArrayElements(indata_, indata, 0);    env->ReleaseByteArrayElements(outhash_, outhash, 0);    return ret;}//預設系統的extern "C"JNIEXPORT jstring JNICALLJava_androidapp_cocoajin_com_tjni_MainActivity_stringFromJNI(        JNIEnv *env,        jobject /* this */) {    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}

 

13. 最後調用 ,這裡把byte[] 轉成了hexString顯示在了app上

        // Example of a call to a native method        TextView tv = (TextView) findViewById(R.id.sample_text);        String he = "hello";        byte[] habb = new byte[32];        sslsha(he.getBytes(),he.length(),habb);        tv.setText(ByteHexUtil.bytesToHexString(habb));

 

14. 執行結果,以及驗證結果

 

15: 參考資料與 工程下載

 

android ndk-build 編譯靜態庫libxx.a 以及Android studio openssl 靜態庫配置(cmake)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.