`
liujianguangaaa
  • 浏览: 235156 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

Android 远程调试 JNI 实现 ( Android JNI remote debugging )

阅读更多

1. 添加Android JNI 接口到Android 代码树
1.1 假定需要被测试Jni 接口是TestNativeApi.java, 将其添加到Android的代码树下 frameworks/base/core/jni/TestNativeApi.java
这个Native程序,在Android中被编译成jar包形式,可以被上层Android java应用调用。
而其static 函数中调用 android System.loadLibrary() 来调用下层C++ 的 .so 库,并且loadLibrary()会判断 .so库的类型,
如果是C++ 的jni库,则会调用 .so库中的 JNI_OnLoad()函数来注册jni interface. Native 程序 实现了 JAVA 到 C++ 代码的Bridge 功能。

TestNativeApi.java 的代码如下:
package com.me.test;
import android.util.Log;
public final class TestNativeApi {
static {
try {
System.loadLibrary("itest_jni");
} catch (UnsatisfiedLinkError e) {
Log.d("itest_jni", "itest jni library not found!");
}
}
/**
* This class is uninstantiable.
*/
private TestNativeApi() {
// This space intentionally left blank.
}
public native static int apiFunction();
}

1.2 修改Android 的Makefile(frameworks/base/core/jni/Android.mk), 通过Makefile 函数 BUILD_JAVA_LIBRARY 将TestNativeApi.java编译成jar.

# Build com.me.test.jar
# ============================================================

test_dirs := \
./test/java/com/me/test

test_src_files := $(call all-java-files-under,$(cm_dirs))

# ====  the library  =========================================
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(test_src_files)

LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core framework

LOCAL_MODULE := com.me.test

include $(BUILD_JAVA_LIBRARY) 

1.3 此外还需要修改 framework/base/data/etc/platform.xml 添加.

<library name= "com.me.test"

    file="/system/framework/com.me.test.jar" />

使得jar包能够被应用程序link到.


2.  接着我们可以添加C++ 代码,来具体实现 Step1 中 定义的 JNI interface 。

2.1  添加 frameworks/base/core/jni/TestInternalApi.cpp 到Android 代码树,在这个C++类中可以调用底层的 C++/C函数控制硬件等。

其中 JNI_OnLoad()函数在.so被load的时候调用, test_TestInterAPI_Func() 函数则是Android 上层JAVA应用调用JNI apiFunction() 的时候具体运行的代码.

#define LOG_TAG "itest_jni"
#include <utils/misc.h>
#include <utils/Log.h>
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "scm_dbus_utils.h"

#define INTERNALAPI_PKG_NAME                "com/me/test/TestNativeApi"

using namespace android;

static jint test_TestInterAPI_Func(JNIEnv* env, jobject clazz)
{
jint ret = (jint)0;

LOGD("call \"%s\"", __FUNCTION__);
return ret;
}

/*
* JNI registration.
*/

static JNINativeMethod gTestInterApiMethods[] = {
{ "apiFunction", "()I", (void *)test_TestInterAPI_Func }
};

int register_com_me_test_TestInternalApiNative(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env, INTERNALAPI_PKG_NAME, gTestInterApiMethods, NELEM(gTestInterApiMethods));
}

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;

LOGD("TestInteralApi JNI loaded");

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed");
goto bail;
}
assert(env != NULL);

if (register_com_me_test_TestInternalApiNative(env) < 0) {
LOGE("TestInternalApi native registration failed");
goto bail;
}

result = JNI_VERSION_1_4;

bail:
return result;
}

2.2 修改Android 的Makefile(frameworks/base/core/jni/Android.mk), 通过Makefile 函数 BUILD_JAVA_LIBRARY 将TestInternalApi.cpp编译成.so.

include $(CLEAR_VARS)

ifeq ($(TARGET_ARCH), arm)
LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
else
LOCAL_CFLAGS += -DPACKED=""
endif

LOCAL_SRC_FILES:= \
TestInternalApi.cpp

LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libnativehelper \
libcutils \
libutils \
libdvm

LOCAL_MODULE:= libitest_jni

include $(BUILD_SHARED_LIBRARY)

endif


3.  重新编译Android 并且 install, 生成JNI .so 和 jar 包
/system/lib/libitest_jni.so 
/system/framework/com.me.test.jar

4. 为了在Eclipse 中编译和调试Android JNI, 需要安装 Android SDK 和ADT
如果使用Android 2.0.1/2.0.01 ,需要安装ADT-0.9.5.zip or up
4.1 安装 SDK 可以通过下面步骤
Set "Eclipse-->Window-->Prefrences-->Android-->SDK Location" to Android SDK path
4.2 安装 ADT 可以通过下面步骤
Set "Eclipse-->Help > Software Updates..-->Add Site dialog-->click Archive" to the downloaded ADT-0.9.5.zip

5. 需要注意的是,因为我们是要测试JNI的实现,也就是Step2 中的.so,因此我们要将JNI Interface, 也就是Step1中的TestNativeApi.java 再编译一份Host Eclipse 可用的jar包
Eclipse -> File->New->Project...->JAVA Project
添加 TestNativeApi.java 到 src/com/me/test/
将 SDK 中的 android.jar 加入工程 的 “build library path”
编译成工后生成jar包, Export->java->jar ->com.me.test.jar

6. 最后是建立Android JUnit 测试工程,通过在Host上调用Step5的jar包(JNI Interface), 最终通过ADB 与Step2 生成的运行在Target 上JNI 实现通信来实现Debug.
Eclipse -> File->New->Project...->Android Test Project
6.1 添加 InternalApiAllTest.java  (这是所有JUnit 共通的,可以直接拷贝)
package com.me.internalapitest;

import junit.framework.Test;
import junit.framework.TestSuite;
import android.test.suitebuilder.TestSuiteBuilder;

/**
* A test suite containing all tests for my application.
*/
public class InternalApiAllTest extends TestSuite {
public static Test suite() {
return new TestSuiteBuilder(AllTests.class).includeAllPackagesUnderHere().build();
}
}
6.2 添加 InternalApiNativeTest.java (这是实际测试Case)
package com.me.internalapitest;

import junit.framework.Assert;

import com/me/test/TestNativeApi;

import android.test.InstrumentationTestCase;

public class InternalApiNativeTestextends
InstrumentationTestCase {

protected void setUp() throws Exception {
super.setUp();
}

protected void tearDown() throws Exception {
super.tearDown();
}

public void testEnableSystem() throws Throwable {
int result = InternalApiNativeTest.apiFunction(0);
Assert.assertTrue(result == 0);
}

}

6.3 修改 InternalApiNativeTest 工程属性 将Step 5中 生成的 com.me.test.jar 到 Java build library path


7 . 代码全部添加完毕,现在就开始Debug 了。
7.1 登陆 Android board, 通过下面方法使目标板上 adbd 使用socket 端口而不是默认的usb口
#rm /dev/android_adb
#rm /dev/android_adb_enable
#setprop persist.service.adb.enable 1
#setprop service.adb.root 1
#setprop ctl.stop adbd
#setprop ctl.start adbd

7.2. 因为 Host 端 Eclispe 也会启动ADB server, 而这个server 指向了Android Emulator, 所以需要先推出 Eclipse and 并先杀死所有 adb 进程
#ps aux | grep adb | grep -v grep
#kill -9 <ADB_PID>

7.3. 接着 在Host 上再次开启 ADB server,
#export ADBHOST=<ANDROID_BB_IP_ADDRESS>
#export ADB_TRACE=adb
#adb nodaemon server

如果在终端中看到下面的信息,就表明 这个时候 ADB server 指向了 Android 的开发板
...
parse_banner: device::
setting connection_state to CS_DEVICE
adb: online
...

这时候可以在另外一个终端中ADB Shell登陆到Android 开发板
#export ADBHOST=<ANDROID_BB_IP_ADDRESS>
#adb shell

7.4. 设置Android Junit 环境
#export ADBHOST=<ANDROID_BB_IP_ADDRESS>
#<ECLISPE_PATH>/eclipse

选择 "Run-->Run Configuration-->Android JUnit Test", 选择"New Launch configuration"
在 "Test" tab, 选中"run all tests in the selected project, or package" 和 "InternalApiNativeTest"
在 "Target" tab, 选中 "Deployment Target Selection Mode" 的选项 "Manual"

7.5. 最后运行 JUnit test runner
在Step 7.3 生成的 ADB登陆终端中
# logcat

再在eclipse 选中菜单 "Run-->Run as-->Android jUnit Test" and 并使用Step 7.4 中生成的配置。

就可以看到 Eclipse 中的JUnit 显示测试结果。
并且在运行logcat 的Android 终端,打印出了frameworks/base/core/jni/TestInternalApi.cpp 中log信息

For other information about android jni,

we can refer to this article http://android.wooyd.org/JNIExample/

分享到:
评论

相关推荐

    Android中JNI实现AES加密源代码

    综上所述,"Android中JNI实现AES加密源代码"涉及的知识点包括Android JNI的使用、AES加密算法的实现、NDK开发环境的配置、C/C++与Java的交互,以及数据安全和性能优化。通过这样的实现,开发者可以在Android应用中...

    Android JNI 断点调试C++

    本教程将聚焦于如何在Android环境中进行JNI的断点调试,特别是针对C++代码。 首先,我们需要理解Android NDK(Native Development Kit),它是Android开发的一部分,提供了一系列工具用于在Android应用中编写原生...

    serial_jni_largestgle_Androidjni_Android串口操作JNI代码_android_

    `serial_jni_largestgle_Androidjni_Android串口操作JNI代码_android_`这个项目就是关于如何使用JNI来实现Android设备的串口读写的示例。 首先,我们需要了解JNI的概念。JNI是Java平台提供的一种接口,允许Java代码...

    Android--JNI-Device.zip_Android jni_android_jni_jni android

    Android Studio提供了对JNI的调试支持,可以通过设置断点、查看变量值等来帮助调试。 9. **总结**:这个教程资料“Android--JNI-Device.zip”对于希望深入了解Android硬件驱动开发的开发者来说非常有价值,它将帮助...

    android通过JNI访问硬件LED

    综上所述,本项目展示了如何通过Android应用结合JNI技术,实现对硬件LED的控制,提供了一个从Java层到硬件层通信的实例。开发者可以通过学习和实践这个项目,深入了解Android系统的底层工作原理以及JNI的使用技巧。

    Android下AES加密算法的JNI实现(包含SO文件)

    在Android开发中,有时为了提高性能或利用C/C++库的优势,我们会选择使用JNI(Java Native Interface)来实现部分功能。本资源提供了一个具体的实例,即在Android环境下使用JNI实现AES(Advanced Encryption ...

    android下一个jni方式实现的音频播放

    本示例着重于使用JNI在Android系统中实现音频的播放功能,这是一个深入理解Android NDK(Native Development Kit)和音频处理的好教材。 首先,我们需要了解JNI的基本原理。JNI是Java平台的一部分,它提供了在Java...

    android studio 下jni学习

    在Android开发中,JNI常用于提升性能、调用系统库或者实现特定的硬件功能。本教程聚焦于在Android Studio环境下使用JNI进行学习,涵盖了基本数据类型转化、引用数据类型转化以及JSON格式数据类型的转化。 首先,...

    AndroidStudio加载jni

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与其他语言写的代码进行交互。JNI在很多场景下是必要的,比如优化性能、利用硬件特性、调用C/C++库或者与第三方库集成。Android ...

    Android通过JNI调用.so动态库

    通过 JNI,我们可以在 Android 项目中调用.so 动态库中的 C/C++ 方法,实现与 native 代码的交互。 首先,我们需要在 Eclipse 中创建一个 Android 项目,并在项目中创建一个 Java 类,例如 TestJNI.java。这个类中...

    Android 深入研究JNI详解

    对于Android应用程序来说,如果需要与C组件进行通信,就需要借助JNI来实现。通常情况下,原生代码会被打包成.so(共享对象)库的形式,并且可以通过`System.loadLibrary()`方法来加载这些库。例如,Android的多媒体...

    Androidstudio调用jni的示例

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,允许Java代码和其他语言写的代码进行交互。这个“Androidstudio调用jni的示例”是一个基础教程,旨在帮助初学者理解如何在Android Studio项目中...

    android--JNI.zip_android_android 驱动_jni_jni android

    5. **跨平台支持**:对于已经在其他平台上使用C/C++实现的功能,JNI使得这些代码可以在Android上复用。 要使用JNI,开发者首先需要创建一个Java类,声明native方法,并通过`System.loadLibrary()`加载对应的本地库...

    android上jni实现

    Android上的JNI实现主要涉及到Android应用开发中的本地化编程技术,JNI(Java Native Interface)是Java平台提供的一种标准接口,允许Java代码和其他语言写的代码进行交互。这个案例是为初学者设计的,旨在帮助理解...

    JniCallback.zip_Android jni_android_jni android_jni callback_jni

    “JniCallback.zip”中的“JniCallback”文件可能是一个示例项目,展示了如何在Android应用中实现JNI回调。这个项目可能包含了一个Java类,该类定义了回调接口,以及对应的本地代码实现,演示了如何在本地代码中...

    Androidapi.JNI.Net.Wifi

    本主题主要探讨的是如何通过JNI在Delphi XE FMX环境中实现对Android设备WiFi功能的操作。 首先,理解JNI的基本概念至关重要。JNI是Java平台的一部分,为Java应用程序提供了一个接口,使其能够调用本地(非Java)...

    Android下JNI和HAL技术

    在Android系统中,Java的应用层和框架层主要使用Java语言进行开发,而Android底层却是基于Linux的,这就需要一种机制来实现Java与C/C++的通信,JNI就是这种机制的实现。 JNI在Android系统中的应用非常广泛,尤其在...

    android-jni.zip_Android jni_android_jni_jni android

    Android NDK(Native Development Kit)是一套工具,提供了编译、构建、调试本地代码的功能,使得开发者可以在Android应用中使用JNI技术。 八、Android Studio与JNI集成 现代Android开发中,大部分开发者使用...

    Android使用JNI调用Python so解释器

    在这个特殊的场景中,我们讨论的是如何通过JNI在Android应用中调用Python解释器,这通常用于实现动态脚本执行或者利用Python丰富的库资源。 首先,我们需要理解Android的NDK(Native Development Kit),它是...

Global site tag (gtag.js) - Google Analytics