JNI編程筆記AndroidStudio3.0下的JNI編程

特別說明

當前博客平臺賬號已廢棄,如果有使用細節(jié)問題請前往我新博客平臺進行討論交流脂信。

個人博客平臺 HuRuWo的技術小站

文章首發(fā)于個人博客HuRuWo的技術小站,如果本文非vip用戶無法完全瀏覽或者圖片無法打開癣蟋,可前往個人博客文章地址查看文章并留言討論。

個人博客文章地址JNI編程筆記AndroidStudio3.0下的JNI編程

更多技術文章訪問本人博客HuRuWo的技術小站狰闪,包括 Electron從零開發(fā) Android 逆向 app 微信數(shù)據(jù)抓取 抖音數(shù)據(jù)抓取 閑魚數(shù)據(jù)抓取 小紅書數(shù)據(jù)抓取 其他軟件爬蟲 等技術文章

JNI介紹

官方介紹:

在編程領域疯搅,JNI (Java Native Interface,Java本地接口)是一種編程框架,使得Java虛擬機中的Java程序可以調(diào)用本地應用/或庫埋泵,也可以被其他程序調(diào)用幔欧。 本地程序一般是用其它語言(C、C++或匯編語言等)編寫的丽声,并且被編譯為基于本機硬件和操作系統(tǒng)的程序礁蔗。

總的來說呢,就是一個框架,可以使得java調(diào)用c/c++代碼恒序。在Android中谷歌提供了NDK工具瘦麸,用于移動下的JNI開發(fā)。

Android NDK 是一套允許您使用 C 和 C++ 等語言歧胁,以原生代碼實現(xiàn)部分應用的工具集滋饲。在開發(fā)某些類型的應用時,這有助于您重復使用以這些語言編寫的代碼庫

NDK下載和教程地址:https://developer.android.com/ndk/?hl=zh-cn

JNI對于Android安全的意義

做過逆向工程的小伙伴都知道喊巍。所謂的java層代碼是非常容易被解開的屠缭。即使加上混淆,加上簽名校驗什么的崭参,依然十分脆弱呵曹。而真正的大廠都會把真正的加密安全相關的信息放在so文件里面。

使用jni開發(fā)的so文件是一個二進制文件何暮,無法輕易被讀取奄喂。極大的增加破解難度。再配合加固等技術一般都能做到軟件的安全防護海洼。

使用AndroidStudio3.0進行JNI開發(fā)

這里強調(diào)AS3.0呢跨新,主要是在3.0之后的JNI編程和之前有很大的區(qū)別。

眾所周知,混合編譯需要一個配置文件來說明編譯的過程坏逢。在3.0之前使用的配置文件是makefile域帐。而在3.0之后官方直接默認了CMake.txt赘被。所以我們要習慣CMake文件的使用。

CMake介紹

CMake文件官網(wǎng)https://cmake.org/

官網(wǎng)首頁的介紹如下(谷歌翻譯):

CMake是一個開源的跨平臺工具系列肖揣,旨在構(gòu)建民假,測試和打包軟件。CMake用于使用簡單的平臺和獨立于編譯器的配置文件來控制軟件編譯過程龙优,并生成可在您選擇的編譯器環(huán)境中使用的本機makefile和工作空間羊异。CMake工具套件由Kitware創(chuàng)建,以滿足對ITK和VTK等開源項目的強大跨平臺構(gòu)建環(huán)境的需求陋率。

總之就是一個混合編譯配置文件球化,它有自己的語法包括版本秽晚。如果你想知道更多可以仔細的學習他的文檔瓦糟。

新建工程

新建安卓工程,點上Include C++ support

image.png

一路next到finish赴蝇,系統(tǒng)就會自動配置一個帶JNI的工程菩浙。

查看工程

實際上這個工程已經(jīng)是一個標準的JNI工程了,直接運行就可以了句伶。
不過在運行錢可以查看下工程目錄劲蜻,看看和平常的安卓工程有什么區(qū)別。

區(qū)別1:MainActivity.java的so文件導入和本地方法

image.png

引用so文件native-lib
調(diào)用本地方法stringFromJNI()
本地方法public native String stringFromJNI();

區(qū)別2:app build.gradle 文件配置
可以看到和平常的build.gradle有兩處不同

image.png

可以看到有兩個externalNativeBuild節(jié)點

defaultConfig內(nèi)部的externalNativeBuild節(jié)點用于配置cmake的配置
可選配置有下面這些文檔地址:

android {
    // Similar to other properties in the defaultConfig block, you can override
    // these properties for each product flavor you configure.
    defaultConfig {
        // This block is different from the one you use to link Gradle
        // to your CMake or ndk-build script.
        externalNativeBuild {
            // For ndk-build, instead use the ndkBuild block.
            cmake {
                // Passes optional arguments to CMake.
                arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"

                // Sets a flag to enable format macro constants for the C compiler.
                cFlags "-D__STDC_FORMAT_MACROS"

                // Sets optional flags for the C++ compiler.
                cppFlags "-fexceptions", "-frtti"

                // Specifies the library and executable targets from your CMake project
                // that Gradle should build.
                targets "libexample-one", "my-executible-demo"
            }
        }
    }
}

defaultConfig外部的externalNativeBuild節(jié)點用于配置cmake的文件地址考余,如果CMake.txt放在根目錄先嬉,配置如下:

android {
    externalNativeBuild {
        // Encapsulates your CMake build configurations.
        // For ndk-build, instead use the ndkBuild block.
        cmake {
            // Specifies a path to your CMake build script that's
            // relative to the build.gradle file.
            path "CMakeLists.txt"
        }
    }
}

區(qū)別3:main目錄下的cpp文件夾以及里面的native-lib.cpp文件
這個不解釋了,就是c層文件目錄了
代碼如下:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring

JNICALL
Java_com_huruwo_as3_1jni_1demo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

這里就是return 了一個字符串 ,具體這里怎么生成的我下一節(jié)講楚堤。

區(qū)別4:CMakeLists.txt文件

非常有意思這個文件疫蔓,我把內(nèi)容復制出來分析:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# 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.

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.

target_link_libraries( # Specifies the target library.
        native-lib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

通過里面的英文說明我們可以知道每一段文字的意義:

設置最小的CMake版本

# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)

設置生成so文件信息 源代碼地址

# 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.

add_library( # Sets the name of the library.
        native-lib  # 設置so文件名稱 也就是我們在mainactivity里面引用的名稱

        # Sets the library as a shared library.
        SHARED #設置為分享庫

        # Provides a relative path to your source file(s).
        src/main/cpp/native-lib.cpp) # 設置代碼的地址 有多少寫多少

導入一些而外的庫,比如這里的log庫(系統(tǒng)庫)

# 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)

把前面的所有庫連接起來 包括三方庫 so庫 系統(tǒng)庫

# 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.

target_link_libraries( # Specifies the target library.
        native-lib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

如何生成native-lib.cpp文件

步驟如下:

1.新建myJNI.java文件

代碼如下:

public class myJNI {

   //加載so文件
    static {
        System.loadLibrary("JniTest");
    }
    
    //調(diào)用c層方法
    public static native System sayHello();
}

2.利用javac 命令生成.class文件

轉(zhuǎn)到myJNI.java目錄下身冬,右鍵當前打開命令行:

image.png

會生成一個myJNI.class文件

image.png

3.javah命令生成.h頭文件

轉(zhuǎn)到java目錄下(即com同層目錄下)

命令如下: javah -jni 包名+文件名

image.png

生成新的.h文件

image.png

打開里面的內(nèi)容如下:

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

#ifndef _Included_com_huruwo_hellosoworld_myJNI
#define _Included_com_huruwo_hellosoworld_myJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_huruwo_hellosoworld_myJNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/System;
 */
JNIEXPORT jobject JNICALL Java_com_huruwo_hellosoworld_myJNI_sayHello
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

4.編寫c層代碼

新建文件夾jni衅胀,在main下與java同層級

image.png

新建main.c文件(這個命名可以隨意) 把之前生成的.h文件內(nèi)容拷貝過來

然后改動JNIEXPORT jobject JNICALL Java_com_huruwo_hellosoworld_myJNI_sayHello這個方法,讓其返回一段文字酥筝。

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

#ifndef _Included_com_huruwo_hellosoworld_myJNI
#define _Included_com_huruwo_hellosoworld_myJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_huruwo_hellosoworld_myJNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/System;
 */
JNIEXPORT jobject JNICALL Java_com_huruwo_hellosoworld_myJNI_sayHello
  (JNIEnv *, jclass){
  return (*env)->NewStringUTF(env,"hello 52pojie!");
  }

#ifdef __cplusplus
}
#endif
#endif

編譯工程 其他配置

為了節(jié)省空間,避免包太大滚躯。通常我們配置NDK 支持的CPU架構(gòu)。
百度一搜可能就會出現(xiàn)以下代碼:

ndk{
            moduleName "helloJni"http://*生成的so文件名嘿歌,必填
            abiFilters "armeabi", "armeabi-v7a", "x86" //配置輸出的abi體系結(jié)構(gòu)下的so庫掸掏,
        }

你興奮的復制上去,shit 報錯了宙帝。

image.png

顯然這些配置需要出現(xiàn)在CMake節(jié)點里面 就想這樣

externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
            }
        }

運行起來:

image.png

沒毛病哦老鐵丧凤,數(shù)據(jù)請求成功。

我們可以看到生成的so文件茄唐,build文件后解壓apk:

image.png

總結(jié)

本次了解了AS3.0的JNI基礎編程息裸,可以提高安全性蝇更。

一份參考資料奉上 http://wiki.jikexueyuan.com/project/jni-ndk-developer-guide/workflow.html

最后是項目地址:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呼盆,隨后出現(xiàn)的幾起案子年扩,更是在濱河造成了極大的恐慌,老刑警劉巖访圃,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厨幻,死亡現(xiàn)場離奇詭異,居然都是意外死亡腿时,警方通過查閱死者的電腦和手機况脆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來批糟,“玉大人格了,你說我怎么就攤上這事』斩Γ” “怎么了盛末?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長否淤。 經(jīng)常有香客問我悄但,道長,這世上最難降的妖魔是什么石抡? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任檐嚣,我火速辦了婚禮,結(jié)果婚禮上啰扛,老公的妹妹穿的比我還像新娘嚎京。我一直安慰自己,他們只是感情好侠讯,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布挖藏。 她就那樣靜靜地躺著,像睡著了一般厢漩。 火紅的嫁衣襯著肌膚如雪膜眠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天溜嗜,我揣著相機與錄音宵膨,去河邊找鬼。 笑死炸宵,一個胖子當著我的面吹牛辟躏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播土全,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼捎琐,長吁一口氣:“原來是場噩夢啊……” “哼会涎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瑞凑,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤末秃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后籽御,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體练慕,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年技掏,在試婚紗的時候發(fā)現(xiàn)自己被綠了铃将。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡哑梳,死狀恐怖劲阎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涧衙,我是刑警寧澤哪工,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布奥此,位于F島的核電站弧哎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏稚虎。R本人自食惡果不足惜撤嫩,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蠢终。 院中可真熱鬧序攘,春花似錦、人聲如沸寻拂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祭钉。三九已至瞄沙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慌核,已是汗流浹背距境。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垮卓,地道東北人垫桂。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像粟按,于是被迫代替她去往敵國和親诬滩。 傳聞我的和親對象是個殘疾皇子霹粥,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容