Use printf in Android JNI

本文介绍了一种在Android JNI中使用日志打印的方法。通过定义宏和链接库,可以在JNI代码中输出不同级别的日志信息到Android的logcat中,便于调试。

转载自:http://xms.eps.csie.ntut.edu.tw/xms/content/show.php?id=2752  作者: 張玉龍 (05-27 14:06)

Use printf in Android JNI

Problem:

        Android can debug by logcat. So Android JNI need it to debug. This method let JNI code can print something we need in logcat.

 

1.         Define LOG in c file

Add the following code in c file

#include <android/log.h>

#define LOG_TAG "D2mce-JNI"

#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)

#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)

 

2.         Add lib link in Android.mk

Add the following code in Android.mk

LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

 

3.         How to use

JNIEXPORT jint JNICALL Java_eps_d2mce_D2MCENative_logtest(JNIEnv* env, jobject thiz, jint x, jint y)

{

LOGD("test log in JNI, x is %d, y is %d\n",x,y);
return add(x,y);

}

要在 Android 应用程序中使用 C++ 实现 traceroute,可以使用以下步骤: 1. 创建一个 C++ 类,该类将实现 traceroute 功能。这个类可以使用第三方库,如 libnet、libpcap 和 libtrace,来实现 traceroute。 2. 将 C++ 代码编译成共享库(.so 文件)。 3. 在你的 Android 项目中添加共享库文件。 4. 在 Java 代码中调用 C++ 的 traceroute 方法。 以下是一个简单的示例: 1. 创建一个名为 Traceroute 的 C++ 类,该类将实现 traceroute 功能。 ```c++ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <netinet/ip_icmp.h> #include <sys/types.h> #include <time.h> #define PACKETSIZE 64 class Traceroute { public: Traceroute(const char* hostname); ~Traceroute(); void run(); private: const char* mHostname; int mTtl; int mSocket; struct sockaddr_in mDestAddr; char* mPacket; struct timeval mTimeout; fd_set mReadSet; struct timeval mStartTime; struct timeval mEndTime; struct timeval mTimeDiff; void sendPacket(int ttl); int receivePacket(int ttl); void printAddress(struct sockaddr_in addr); }; ``` 2. 实现 Traceroute 类的构造函数和析构函数。 ```c++ Traceroute::Traceroute(const char* hostname) { mHostname = hostname; mTtl = 1; mSocket = -1; mPacket = NULL; memset(&mDestAddr, 0, sizeof(struct sockaddr_in)); memset(&mTimeout, 0, sizeof(struct timeval)); memset(&mReadSet, 0, sizeof(fd_set)); memset(&mStartTime, 0, sizeof(struct timeval)); memset(&mEndTime, 0, sizeof(struct timeval)); memset(&mTimeDiff, 0, sizeof(struct timeval)); } Traceroute::~Traceroute() { if (mSocket != -1) { close(mSocket); } if (mPacket != NULL) { free(mPacket); } } ``` 3. 实现 Traceroute 类的 run 方法,该方法将实现 traceroute 功能。 ```c++ void Traceroute::run() { struct hostent* host; struct timeval timeout; int maxfd; int ret; int done = 0; // resolve hostname host = gethostbyname(mHostname); if (host == NULL) { printf("traceroute: unknown host %s\n", mHostname); return; } // create socket mSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (mSocket < 0) { printf("traceroute: cannot create socket: %s\n", strerror(errno)); return; } // set socket options setsockopt(mSocket, IPPROTO_IP, IP_TTL, &mTtl, sizeof(mTtl)); // set destination address mDestAddr.sin_family = AF_INET; mDestAddr.sin_port = 0; memcpy(&mDestAddr.sin_addr, host->h_addr, host->h_length); // allocate packet buffer mPacket = (char*)malloc(PACKETSIZE); if (mPacket == NULL) { printf("traceroute: out of memory\n"); return; } // set timeout timeout.tv_sec = 1; timeout.tv_usec = 0; // loop until done while (!done) { // send packet sendPacket(mTtl); // receive packet ret = receivePacket(mTtl); if (ret == 0) { // reached destination done = 1; } else if (ret == -1) { // error printf("traceroute: error receiving packet: %s\n", strerror(errno)); return; } else { // continue } // increase ttl mTtl++; // check if max ttl reached if (mTtl > 30) { printf("traceroute: max ttl reached\n"); break; } } } ``` 4. 实现 Traceroute 类的 sendPacket 和 receivePacket 方法。 ```c++ void Traceroute::sendPacket(int ttl) { struct icmp* icmp; int len; // set packet data icmp = (struct icmp*)mPacket; icmp->icmp_type = ICMP_ECHO; icmp->icmp_code = 0; icmp->icmp_id = getpid(); icmp->icmp_seq = ttl; memset(icmp->icmp_data, 0xa5, PACKETSIZE - sizeof(struct icmp)); // set packet length len = sizeof(struct icmp) + PACKETSIZE - sizeof(struct icmp); // send packet gettimeofday(&mStartTime, NULL); if (sendto(mSocket, mPacket, len, 0, (struct sockaddr*)&mDestAddr, sizeof(struct sockaddr_in)) <= 0) { printf("traceroute: error sending packet: %s\n", strerror(errno)); return; } } int Traceroute::receivePacket(int ttl) { struct sockaddr_in addr; socklen_t addrlen; struct ip* ip; struct icmp* icmp; int len; int ret; // set timeout mTimeout.tv_sec = 1; mTimeout.tv_usec = 0; // clear read set FD_ZERO(&mReadSet); FD_SET(mSocket, &mReadSet); // select ret = select(mSocket + 1, &mReadSet, NULL, NULL, &mTimeout); if (ret == 0) { // timeout printf("%2d * *\n", ttl); return 1; } else if (ret < 0) { // error return -1; } // receive packet addrlen = sizeof(struct sockaddr_in); len = recvfrom(mSocket, mPacket, PACKETSIZE, 0, (struct sockaddr*)&addr, &addrlen); if (len < 0) { printf("traceroute: error receiving packet: %s\n", strerror(errno)); return -1; } // check packet length ip = (struct ip*)mPacket; if (len < (int)(ip->ip_hl * 4 + sizeof(struct icmp))) { printf("traceroute: packet too short\n"); return -1; } // check packet type icmp = (struct icmp*)(mPacket + ip->ip_hl * 4); if (icmp->icmp_type == ICMP_ECHOREPLY) { // received reply gettimeofday(&mEndTime, NULL); timersub(&mEndTime, &mStartTime, &mTimeDiff); printf("%2d ", ttl); printAddress(addr); printf(" %.3f ms\n", mTimeDiff.tv_sec * 1000.0 + mTimeDiff.tv_usec / 1000.0); return 0; } else if (icmp->icmp_type == ICMP_TIME_EXCEEDED) { // received time exceeded printf("%2d ", ttl); printAddress(addr); printf(" *\n"); return 1; } else { // received unknown packet printf("traceroute: unknown packet type: %d\n", icmp->icmp_type); return -1; } } ``` 5. 在 Java 代码中调用 C++ 的 traceroute 方法。 ```java public class MainActivity extends AppCompatActivity { static { System.loadLibrary("traceroute"); } private static final String HOSTNAME = "www.google.com"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Traceroute traceroute = new Traceroute(HOSTNAME); traceroute.run(); } } ``` 注意,为了在 Android 应用程序中使用 C++,需要使用 Android NDK。在你的 Android 项目中添加一个名为 jni 的文件夹,并在其中创建一个名为 Android.mk 的文件和一个名为 traceroute.cpp 的文件。Android.mk 文件应该包含以下内容: ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := traceroute LOCAL_SRC_FILES := traceroute.cpp include $(BUILD_SHARED_LIBRARY) ``` 然后,可以使用 ndk-build 命令编译 C++ 代码,并将生成的共享库文件添加到 Android 项目中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值