Android逆向基础知识之NDK开发篇

Android NDK,即Android Native Development Kit。
众所周知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序。
NDK包括了:

  1. 从C / C++生成原生代码库所需要的工具和build files。
  2. 将一致的原生库嵌入可以在Android设备上部署的应用程序包文件(application packages files ,即.apk文件)中。

那为什么要用到NDK呢?原因如下:
1. 代码的保护,由于apk的java层代码很容易被反编译,而C/C++库被反编译的难度较大。
2. 在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。
3. 便于移植,用C/C++写的库可以方便在其他的嵌入式平台上再次使用。
本文主要介绍利用Android Studio进行Android NDK开发。
官方说明:http://tools.android.com/tech-docs/new-build-system/gradle-experimental

笔者用的是Android Studio2.3版本进行开发。
每一个不同版本的 experimental plugin都对应了特定版本的 Gradle 。
此时为2017年4月11日,最新对应列表如下:

Plugin VersionGradle Version
0.1.02.5
0.2.02.5
0.3.0-alpha32.6
0.4.02.8
0.6.0-alpha12.8
0.6.0-alpha52.10
0.7.0-alpha12.10
0.7.02.10
0.7.32.14.1

需要修改的文件结构如下:
├── app/

│——├── app.iml

│—— |── build.gradle

│——└── src/

├── build.gradle

├── gradle/

│——└── wrapper/

│ ——├── gradle-wrapper.jar

│ ——└── gradle-wrapper.properties

├── gradle.properties

├── gradlew*

├── gradlew.bat

├── local.properties

├── MyApplication.iml

└── settings.gradle

./gradle/wrapper/gradle-wrapper.properties
每一个新的plugin 版本都会支持一个特定版本的Gradle
如:
‘#’Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-2.14.1-all.zip
./build.gradle
将plugin的路径由”com.android.tools.build:gradle.
“改为”com.android.tools.build:gradle-experimental ”
如:
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
jcenter()
}
dependencies {
classpath “com.android.tools.build:gradle-experimental:0.7.3”

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

}

allprojects {
repositories {
jcenter()
}
}
./app/build.gradle
具体修改如下:
apply plugin: “com.android.model .application”

model {
android {
compileSdkVersion 23
buildToolsVersion “23.0.2”
defaultConfig {
applicationId “com.example.user.myapplication”
minSdkVersion.apiLevel 15
targetSdkVersion.apiLevel 22
versionCode 1
versionName “1.0”

}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file(“proguard-rules.pro”))
}
}
ndk{
moduleName “mainactivity”
}

dependencies {
compile fileTree(dir: “libs”, include: [“*.jar”])
compile “com.android.support:appcompat-v7:22.2.0”
//testCompile ‘junit:junit:4.12’
}
最后在以下目录new一个jni目录文件夹:
这里写图片描述
再在./app/build.gradle添加以下代码:
android {
。。。
ndk{
moduleName “mainactivity”
}
}

声明在jni文件夹中生成mainactivity.c文件。
然后sync now!得到c文件:
这里写图片描述
接下来我们就可以编写Native原生程序了。
先在MainActivity.java中添加方法:

public static native String Hello1(); //静态无参native函数
public native String Hello1(int i);//非静态有参native函数

利用Android Studio自带的功能自动在mainactivity.c中创建对应的C函数并修改得:

#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_example_alen_hellonative_MainActivity_Hello1(JNIEnv *env, jclass type) {

    // TODO
    return (*env)->NewStringUTF(env,"Hello Hello1");

}

JNIEXPORT jstring JNICALL
Java_com_example_alen_hellonative_MainActivity_Hello2(JNIEnv *env, jobject instance, jint a) {

    // TODO

    return (*env)->NewStringUTF(env, "Hello Hello2");
}

而c函数受Java方法的影响:
1. Java方法的类型,如返回值,静态或非静态,将影响c函数的形参;
2. c函数的函数名对应Java方法的路径;
3. Java方法的形参将影响对应c函数的形参;

然后利用Button控件分别调用Hello1()与Hello2()。
activity_main.xml

<Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Button1"
        android:text="Hello1"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Button2"
        android:text="Hello2"/>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button hello1;
    private Button hello2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        hello1 = (Button)findViewById(R.id.Button1);
        hello2 = (Button)findViewById(R.id.Button2);
        hello1.setOnClickListener(this);
        hello2.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.Button1:
                Log.d("jk7aLen", Hello1());
                break;
            case R.id.Button2:
                Log.d("jk7aLen",Hello2(2));
                break;
            default:
                break;
        }
    }
    public static native String Hello1();
    public native String Hello2(int a);
}

运行后发现下面错误
com.DefiantDev.SkiSafari:bdservice_v1 E/socket: Native library not found! Please copy libbdpush_V2_2.so into your project!
解决:在MainActivity.java添加相应的Library即可:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    static {
        System.loadLibrary("mainactivity");
    }
    ...
    ...
}

其中“mainactivity”对应
ndk{
moduleName “mainactivity”
}
运行后在Logcat中显示得:
这里写图片描述
即调用成功

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发中,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio中进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本中,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其中选中相应的工具进行导入。 在项目的build.gradle文件中,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其中,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main中还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹中编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio中进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值