安卓逆向6.Android Studio JNI 快速构建项目+动态注册+简易计算器

前面几篇文章演示的是比较原始的创建JNI项目的方法,旨在了解JNI项目构建原理!

但是构建项目效率很低,开发,调试都存在很大的效率低下问题。

本篇文章将演示利用Android Studio快速构建JNI项目。本篇文章要点:

a、利用Android Studio快速构建JNI项目

b、添加日志打印

c、Android Studio调试C/C++代码

d、JNI动态注册

e、简易计算器实现。

 

1.打开Android Studio新建Project,选中Native c++选项,此选项可以帮助开发人员快速创建JNI项目,免去手动配置等麻烦问题。

 

2.项目取名为JniDynamicRegTest,点击Next

 

3.使用默认C++标准,点击Finish

 

4.File->Settings->Android SDK->SDK Tools选项下,安装LLDB,NDK,CMake

 

 

5.File->Project Structure->SDK Location->Android NDK Location ,选择Default xxxx选项,从而配置完成NDK

 

 

6.为了验证上一步是否配置成功,需要来到local.properties,如果同时出现ndk.dir=xxx sdk.dir=xxx 证明配置成功

 

7.此时如果我们对native-lib.cpp进行编辑,可以看到出现了智能提示。就代表我们的环境配置没有问题了。

 

8.接下来我们添加日志打印输出,将下面代码添加到cpp文件头部,使用的时候直接调用就行,比如:LOGI("我是输出的日志信息");
#include <android/log.h>
#define LOG_TAG    "JniDebugLogger"
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

 

9.接下来我们在C/C++代码下断点,并点击Debug图标。看是否能正确断下。

 

10.注意,当出现如下界面时,千万别点击,只需要什么都不做,等几秒钟,断点断下就行。

 

 

11.接下来我们在MainActivity中定义4个Native方法,分别为 add sub mul div

 

12.在native-lib.cpp里实现MainActivity的方法,native-lib.cpp源码如下
#include <jni.h>
#include <string>

#include <android/log.h>
#define  LOG_TAG    "JniDebugLogger"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

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

jint NativeAdd(JNIEnv* env,jobject  obj,jint a,jint b)
{
    return a+b;
}

jint NativeSub(JNIEnv* env,jobject  obj,jint a,jint b)
{
    return a-b;
}
jint NativeMul(JNIEnv* env,jobject  obj,jint a,jint b)
{
    return a*b;
}
jint NativeDiv(JNIEnv* env,jobject  obj,jint a,jint b)
{
    return a/b;
}
JNINativeMethod jniNativeMethods[]
{
        {"add","(II)I",(void*)NativeAdd},
        {"sub","(II)I",(void*)NativeSub},
        {"mul","(II)I",(void*)NativeMul},
        {"div","(II)I",(void*)NativeDiv}
};

jint  RegistNativeMethods(JNIEnv* env)
{
    jclass _jclass=env->FindClass("com/crackme/jnidynamicregtest/MainActivity");
    if(env->RegisterNatives(_jclass,jniNativeMethods, sizeof(jniNativeMethods)/ sizeof(jniNativeMethods[0]))==JNI_OK)
    {

        return JNI_OK;
    }
    return  JNI_ERR;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* jniEnv=0;
    if(vm->GetEnv((void**)&jniEnv,JNI_VERSION_1_6)!=JNI_OK)
    {
        LOGE("GetEnv执行失败");
        return  JNI_ERR;
    }
    if(RegistNativeMethods(jniEnv)!=JNI_OK)
    {
        LOGE("RegistNativeMethods执行失败");
        return  JNI_ERR;
    }
    return  JNI_VERSION_1_6;
}

 

13.在MainActivity里添加测试代码,运行测试

 

 

14.运行测试Native层没有问题,接下来添加Java层代码并在界面增加控件,实现简单的计算器。MainActivity代码如下
package com.crackme.jnidynamicregtest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    public native int add(int a,int b);
    public native int sub(int a,int b);
    public native int mul(int a,int b);
    public native int div(int a,int b);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Example of a call to a native method

        Button btnAdd=(Button)findViewById(R.id.btnAdd);
        Button btnSub=(Button)findViewById(R.id.btnSub);
        Button btnMul=(Button)findViewById(R.id.btnMul);
        Button btnDiv=(Button)findViewById(R.id.btnDiv);
        View.OnClickListener ocl=  new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText editTextA=(EditText)findViewById(R.id.editTextA);
                int nA=Integer.parseInt(editTextA.getText().toString());
                EditText editTextB=(EditText)findViewById(R.id.editTextB);
                int nB=Integer.parseInt(editTextB.getText().toString());
                TextView tv = findViewById(R.id.sample_text);
                    switch (v.getId())
                    {
                        case R.id.btnAdd:
                            tv.setText(""+add(nA,nB));
                            break;
                        case R.id.btnSub:
                            tv.setText(""+sub(nA,nB));
                            break;
                        case R.id.btnMul:
                            tv.setText(""+mul(nA,nB));
                            break;
                        case R.id.btnDiv:
                            tv.setText(""+div(nA,nB));
                            break;
                    }
            }
        };
        btnAdd.setOnClickListener(ocl);
        btnSub.setOnClickListener(ocl);
        btnMul.setOnClickListener(ocl);
        btnDiv.setOnClickListener(ocl);


    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

 

15.activity_main.xml代码如下
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editTextB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="56dp"
        android:autofillHints=""
        android:ems="10"
        android:inputType="textPersonName"
        android:text="@string/ediB"
        app:layout_constraintStart_toStartOf="@+id/editTextA"
        app:layout_constraintTop_toBottomOf="@+id/editTextA" />

    <TextView
        android:id="@+id/sample_text"
        android:layout_width="92dp"
        android:layout_height="23dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.795" />

    <EditText
        android:id="@+id/editTextA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="91dp"
        android:autofillHints=""
        android:ems="10"
        android:inputType="textPersonName"
        android:text="@string/ediA"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnAdd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:text="@string/add"
        app:layout_constraintBaseline_toBaselineOf="@+id/btnSub"
        app:layout_constraintEnd_toStartOf="@+id/btnSub"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnSub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:layout_marginEnd="5dp"
        android:text="@string/sub"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/btnAdd"
        app:layout_constraintTop_toBottomOf="@+id/editTextB" />

    <Button
        android:id="@+id/btnDiv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="34dp"
        android:layout_marginEnd="5dp"
        android:text="@string/div"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/btnMul"
        app:layout_constraintTop_toBottomOf="@+id/btnSub" />

    <Button
        android:id="@+id/btnMul"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:text="@string/mul"
        app:layout_constraintBaseline_toBaselineOf="@+id/btnDiv"
        app:layout_constraintEnd_toStartOf="@+id/btnDiv"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

16.测试运行

 

源文件下载:

链接:https://pan.baidu.com/s/1KZrjlLP9OiThZdT-MYeJbA
提取码:qiol

 

posted @ 2020-04-18 14:23  凉游浅笔深画眉  阅读(842)  评论(0编辑  收藏  举报