[NDK/JNI系列04] JNI接口方法表、基础API与异常API

简介: [NDK/JNI系列04] JNI接口方法表、基础API与异常API
  • 学习了如何在C++中调用Java的一些类和方法,例如System.currentTimeMillis(), Integer.parseInt(), String.substring()和ArrayList。
  • 学习了如何使用JNI函数来查找类、获取方法ID、调用方法、创建对象、传递参数和返回值。
  • 学习了如何使用JNI函数来检查、清除、打印和抛出Java异常。
  • 学习了如何使用命名空间、常量和辅助函数来组织和简化的C++代码。
  • 学习了如何在Kotlin中定义和调用原生方法,并使用System.loadLibrary()来加载本地库。

4.1 JNI接口方法表

  • JNI接口方法表是一个结构体指针,它包含了JNI提供的所有函数的指针。JNI接口方法表的类型是JNIEnv,它是一个二级指针,指向一个JNIEnv_结构体,该结构体只有一个成员,即指向JNI函数表的指针。
  • JNI接口方法表是线程相关的,每个线程都有自己的JNIEnv。在原生函数中,第一个参数就是JNIEnv,可以通过它调用JNI函数。例如:
JNIEXPORT void JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
    // 调用JNI函数
    jclass cls = (*env)->FindClass(env, "java/lang/String");
    // ...
}
  • 在C++中,JNIEnv被定义为一个类,它包含了一个指向JNI函数表的指针,并且为每个JNI函数提供了一个成员函数,可以直接调用。例如:
JNIEXPORT void JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
    // 调用JNI函数
    jclass cls = env->FindClass("java/lang/String");
    // ...
}
  • JNIEnv的类型是一个指向JNI接口方法表的指针,它的定义如下:
typedef const struct JNINativeInterface *JNIEnv;
struct JNINativeInterface {
    void *reserved0;
    void *reserved1;
    void *reserved2;
 
    void *reserved3;
    jint (JNICALL *GetVersion)(JNIEnv *env);
 
    jclass (JNICALL *DefineClass)
      (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
       jsize len);
    jclass (JNICALL *FindClass)
      (JNIEnv *env, const char *name);
 
    /* ... more functions ... */
};
  • JNI接口方法表中的函数可以分为以下几类:
  • 版本信息:GetVersion
  • 类操作:DefineClass, FindClass, GetSuperclass, IsAssignableFrom等
  • 异常处理:Throw, ThrowNew, ExceptionOccurred, ExceptionDescribe等
  • 全局引用操作:NewGlobalRef, DeleteGlobalRef等
  • 局部引用操作:NewLocalRef, DeleteLocalRef等
  • 弱全局引用操作:NewWeakGlobalRef, DeleteWeakGlobalRef等
  • 监视器操作:MonitorEnter, MonitorExit等
  • Java对象操作:AllocObject, NewObject等
  • 字段访问:GetFieldID, GetObjectField等
  • 方法调用:GetMethodID, CallObjectMethod等
  • 数组操作:NewArray, GetArrayLength等
  • 字符串操作:NewStringUTF, GetStringUTFChars等
  • 直接缓冲区操作:NewDirectByteBuffer, GetDirectBufferAddress等

4.2 JNI基础API的使用

  • JNI基础API是一些常用的JNI函数,它们可以实现以下功能:
  • 查找Java类、字段和方法的ID
  • 调用Java实例方法和静态方法
  • 获取和设置Java实例字段和静态字段的值
  • 创建Java对象和数组
  • 操作Java字符串和原始类型数组
  • 抛出和处理Java异常
  • JNI基础API的函数名都遵循一定的命名规则,例如:
  • FindClass: 查找一个Java类。
  • GetMethodID / GetStaticMethodID: 获取Java方法的ID。
  • CallMethod / CallStaticMethod: 调用Java方法。
  • GetFieldID / GetStaticFieldID: 获取Java字段的ID。
  • GetField / SetField: 获取或设置Java字段的值。
  • 其中,表示返回值或参数的类型,可以是以下之一:
  • Boolean: 布尔型
  • Byte: 字节型
  • Char: 字符型
  • Short: 短整型
  • Int: 整型
  • Long: 长整型
  • Float: 浮点型
  • Double: 双精度浮点型
  • Object: 对象型
  • Void: 空类型
  • 下面是一些JNI基础API的使用示例:
// 查找java.lang.String类
jclass stringClass = (*env)->FindClass(env, "java/lang/String");
 
// 获取java.lang.String类的构造方法ID,参数为字节数组和编码名称
jmethodID stringConstructor = (*env)->GetMethodID(env, stringClass, "<init>", "([BLjava/lang/String;)V");
 
// 获取java.lang.String类的length方法ID,无参数,返回值为整型
jmethodID stringLength = (*env)->GetMethodID(env, stringClass, "length", "()I");
 
// 创建一个字节数组对象,长度为10
jbyteArray byteArray = (*env)->NewByteArray(env, 10);
 
// 填充字节数组对象的内容为"Hello JNI"
jbyte buf[10] = {'H', 'e', 'l', 'l', 'o', ' ', 'J', 'N', 'I', '\0'};
(*env)->SetByteArrayRegion(env, byteArray, 0, 10, buf);
 
// 创建一个字符串对象,表示"UTF-8"编码
jstring encoding = (*env)->NewStringUTF(env, "UTF-8");
 
// 调用java.lang.String类的构造方法,创建一个字符串对象,内容为"Hello JNI"
jstring str = (*env)->NewObject(env, stringClass, stringConstructor, byteArray, encoding);
 
// 调用java.lang.String类的length方法,获取字符串的长度
jint len = (*env)->CallIntMethod(env, str, stringLength);
 
// 打印字符串的长度
printf("The length of the string is %d\n", len);

4.3 JNI异常API的使用

  • JNI异常API是一些用于处理Java异常的JNI函数,它们可以实现以下功能:
  • 检查是否发生了Java异常
  • 清除Java异常
  • 获取Java异常对象
  • 抛出Java异常
  • 抛出新的Java异常
  • JNI异常API的函数名都以Exception开头,例如:
  • ExceptionOccurred: 检查是否发生了Java异常。
  • ExceptionClear: 清除Java异常。
  • ExceptionDescribe: 打印Java异常的堆栈跟踪信息。
  • ExceptionGetCause: 获取Java异常的原因对象。
  • Throw: 抛出Java异常对象。
  • ThrowNew: 抛出新的Java异常。
  • 下面是一些JNI异常API的使用示例:
// 查找java.lang.Integer类
jclass integerClass = (*env)->FindClass(env, "java/lang/Integer");
 
// 获取java.lang.Integer类的parseInt方法ID,参数为字符串,返回值为整型
jmethodID parseInt = (*env)->GetStaticMethodID(env, integerClass, "parseInt", "(Ljava/lang/String;)I");
 
// 创建一个字符串对象,内容为"123"
jstring str = (*env)->NewStringUTF(env, "123");
 
// 调用java.lang.Integer类的parseInt方法,将字符串转换为整数
jint num = (*env)->CallStaticIntMethod(env, integerClass, parseInt, str);
 
// 检查是否发生了Java异常
jthrowable exception = (*env)->ExceptionOccurred(env);
if (exception != NULL) {
    // 清除Java异常
    (*env)->ExceptionClear(env);
 
    // 获取Java异常的原因对象
    jthrowable cause = (*env)->ExceptionGetCause(env, exception);
 
    // 打印Java异常的堆栈跟踪信息
    (*env)->ExceptionDescribe(env, exception);
 
    // 抛出新的Java异常,类型为java.lang.RuntimeException,信息为"JNI error"
    jclass runtimeExceptionClass = (*env)->FindClass(env, "java/lang/RuntimeException");
    (*env)->ThrowNew(env, runtimeExceptionClass, "JNI error");
}
else {
    // 打印转换后的整数
    printf("The number is %d\n", num);
}

4.3 完整例子

Chapter04.java

class Chapter04 : AppCompatActivity() {
    // 定义一些原生方法,用于调用测试函数
    external fun testSystemCurrentTimeMillis(): Long // 原生方法:测试System.currentTimeMillis()函数的调用
    external fun testIntegerParseInt(str: String): Int // 原生方法:测试Integer.parseInt()函数的调用
    external fun testStringSubstring(str: String, beginIndex: Int, endIndex: Int): String // 原生方法:测试String.substring()函数的调用
    external fun testArrayList(): Any // 原生方法:测试ArrayList的调用
    var TAG = "Chapter04"; // 定义TAG变量用于日志输出
 
    private lateinit var binding: Chapter04Binding
 
    // 在onCreate方法中调用原生方法,并打印结果
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.setTitle("Chapter04")
        binding = Chapter04Binding.inflate(layoutInflater)
        setContentView(binding.root)
 
        // Example of a call to a native method
        binding.sampleText.text = stringFromJNI() // 调用原生方法,返回字符串,并显示在UI中
 
        // 调用测试函数并打印结果
        val time = testSystemCurrentTimeMillis() // 调用原生方法获取当前时间戳
        Log.d(TAG, "当前时间为:$time")
 
        try {
            val num = testIntegerParseInt("123A") // 调用原生方法尝试将字符串解析为整数(故意触发错误)
            // val num = testIntegerParseInt("123") // 调用原生方法将字符串解析为整数(正确示例)
            Log.d(TAG, "解析得到的数字为:$num")
        } catch (e: Exception) {
            e.printStackTrace()
        }
 
        val result = testStringSubstring("Hello JNI", 0, 5) // 调用原生方法截取字符串的子串
        Log.d(TAG, "截取得到的子串为:$result")
 
        val firstElement = testArrayList() // 调用原生方法获取ArrayList的第一个元素
        Log.d(TAG, "ArrayList的第一个元素为:$firstElement")
    }
 
    /**
     * 一个由本应用程序打包的 'jnidemo' native库实现的原生方法。
     */
    external fun stringFromJNI(): String // 原生方法:获取一个字符串
 
    companion object {
        // 用于在应用程序启动时加载 'jnidemo' 库。
        init {
            System.loadLibrary("jnidemo")
        }
    }
}

chapter04.cpp

#include <jni.h>
#include <string>
 
using namespace chapter04; // 使用chapter04命名空间
 
// 定义一些常量,表示类名和方法签名
const char* SYSTEM_CLASS = "java/lang/System";
const char* INTEGER_CLASS = "java/lang/Integer";
const char* STRING_CLASS = "java/lang/String";
const char* ARRAYLIST_CLASS = "java/util/ArrayList";
 
const char* LONG_RETURN_VOID_ARG = "()J";
const char* INT_RETURN_STRING_ARG = "(Ljava/lang/String;)I";
const char* STRING_RETURN_INT_INT_ARG = "(II)Ljava/lang/String;";
const char* VOID_RETURN_VOID_ARG = "()V";
const char* BOOLEAN_RETURN_VOID_ARG = "()Z";
const char* BOOLEAN_RETURN_OBJECT_ARG = "(Ljava/lang/Object;)Z"; // 定义这个常量
const char* VOID_RETURN_OBJECT_ARG = "(Ljava/lang/Object;)V";
const char* OBJECT_RETURN_INT_ARG = "(I)Ljava/lang/Object;";
 
// 定义一个辅助函数,用于检查并打印JNI异常
void checkAndPrintException(JNIEnv *env) {
    jthrowable exception = env->ExceptionOccurred(); // 检查是否发生了Java异常
    if (exception != NULL) {
        env->ExceptionDescribe(); // 打印Java异常的堆栈跟踪信息
    }
}
 
// 定义一个测试函数,用于调用Java的System.currentTimeMillis()方法
jlong testSystemCurrentTimeMillis(JNIEnv *env) {
    // 查找System类
    jclass systemClass = env->FindClass(SYSTEM_CLASS);
    checkAndPrintException(env);
 
    // 获取currentTimeMillis方法的ID
    jmethodID currentTimeMillisMethod = env->GetStaticMethodID(systemClass, "currentTimeMillis", LONG_RETURN_VOID_ARG);
    checkAndPrintException(env);
 
    // 调用currentTimeMillis方法,获取当前时间的毫秒数
    jlong time = env->CallStaticLongMethod(systemClass, currentTimeMillisMethod);
    checkAndPrintException(env);
 
    // 返回时间值
    return time;
}
 
// 定义一个测试函数,用于调用Java的Integer.parseInt()方法
jint testIntegerParseInt(JNIEnv *env, jstring str) {
    // 查找Integer类
    jclass integerClass = env->FindClass(INTEGER_CLASS);
    checkAndPrintException(env);
 
    // 获取parseInt方法的ID
    jmethodID parseIntMethod = env->GetStaticMethodID(integerClass, "parseInt", INT_RETURN_STRING_ARG);
    checkAndPrintException(env);
 
    // 调用parseInt方法,将字符串转换为整数
    jint num = env->CallStaticIntMethod(integerClass, parseIntMethod, str);
    checkAndPrintException(env);
 
    // 检查是否发生了Java异常
    jthrowable exception = env->ExceptionOccurred();
    if (exception != NULL) {
        // 清除Java异常
        env->ExceptionClear();
 
        // 获取Java异常的原因对象(如果API版本低于24,注释掉这一行)
        // jthrowable cause = env->ExceptionGetCause(exception);
 
        // 打印Java异常的堆栈跟踪信息
        env->ExceptionDescribe(); // 修改函数调用,不传入任何参数
        checkAndPrintException(env);
 
        // 抛出新的Java异常,类型为java.lang.RuntimeException,信息为"JNI error"
        jclass runtimeExceptionClass = env->FindClass("java/lang/RuntimeException");
        env->ThrowNew(runtimeExceptionClass, "JNI error 》 testIntegerParseInt");
    }
 
    // 返回转换后的整数
    return num;
}
 
 
// 定义一个测试函数,用于调用Java的String.substring()方法
jstring testStringSubstring(JNIEnv *env, jstring str, jint beginIndex, jint endIndex) {
    // 查找String类
    jclass stringClass = env->FindClass(STRING_CLASS);
    checkAndPrintException(env);
 
    // 获取substring方法的ID
    jmethodID substringMethod = env->GetMethodID(stringClass, "substring", STRING_RETURN_INT_INT_ARG);
    checkAndPrintException(env);
 
    // 调用substring方法,截取字符串的一部分
    jstring result = (jstring) env->CallObjectMethod(str, substringMethod, beginIndex, endIndex);
    checkAndPrintException(env);
 
    // 检查是否发生了Java异常
    jthrowable exception = env->ExceptionOccurred();
    if (exception != NULL) {
        // 清除Java异常
        env->ExceptionClear();
 
        // 返回空字符串
        result = env->NewStringUTF("");
    }
 
    // 返回截取后的字符串
    return result;
}
 
// 定义一个测试函数,用于创建一个Java的ArrayList对象,并向其中添加一些元素,然后获取其中的第一个元素
jobject testArrayList(JNIEnv *env) {
    // 查找ArrayList类
    jclass arrayListClass = env->FindClass(ARRAYLIST_CLASS);
    checkAndPrintException(env);
 
    // 获取ArrayList类的构造方法ID,无参数,返回值为void
    jmethodID arrayListConstructor = env->GetMethodID(arrayListClass, "<init>", VOID_RETURN_VOID_ARG);
    checkAndPrintException(env);
 
    // 获取ArrayList类的add方法ID,参数为对象,返回值为布尔型
    jmethodID arrayListAdd = env->GetMethodID(arrayListClass, "add", BOOLEAN_RETURN_OBJECT_ARG);
    checkAndPrintException(env);
 
    // 获取ArrayList类的get方法ID,参数为整型,返回值为对象
    jmethodID arrayListGet = env->GetMethodID(arrayListClass, "get", OBJECT_RETURN_INT_ARG);
    checkAndPrintException(env);
 
    // 创建一个ArrayList对象
    jobject arrayList = env->NewObject(arrayListClass, arrayListConstructor);
    checkAndPrintException(env);
 
    // 创建一些字符串对象,并向ArrayList中添加
    jstring str1 = env->NewStringUTF("Hello");
    jstring str2 = env->NewStringUTF("JNI");
    jstring str3 = env->NewStringUTF("World");
    env->CallBooleanMethod(arrayList, arrayListAdd, str1);
    env->CallBooleanMethod(arrayList, arrayListAdd, str2);
    env->CallBooleanMethod(arrayList, arrayListAdd, str3);
    checkAndPrintException(env);
 
    // 获取ArrayList中的第一个元素
    jobject firstElement = env->CallObjectMethod(arrayList, arrayListGet, 0);
    checkAndPrintException(env);
 
    // 返回第一个元素
    return firstElement;
}
 
extern "C" JNIEXPORT jstring JNICALL
Java_com_ln28_jnidemo_Chapter04_stringFromJNI( // 修改函数名前缀,与Chapter04.kt中对应
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
 
extern "C" JNIEXPORT jlong JNICALL
Java_com_ln28_jnidemo_Chapter04_testSystemCurrentTimeMillis( // 修改函数名前缀,与Chapter04.kt中对应
        JNIEnv* env,
        jobject /* this */) {
    return testSystemCurrentTimeMillis(env);
}
 
extern "C" JNIEXPORT jint JNICALL
Java_com_ln28_jnidemo_Chapter04_testIntegerParseInt( // 修改函数名前缀,与Chapter04.kt中对应
        JNIEnv* env,
        jobject /* this */,
        jstring str) {
    return testIntegerParseInt(env, str);
}
 
extern "C" JNIEXPORT jstring JNICALL
Java_com_ln28_jnidemo_Chapter04_testStringSubstring( // 修改函数名前缀,与Chapter04.kt中对应
        JNIEnv* env,
        jobject /* this */,
        jstring str,
        jint beginIndex,
        jint endIndex) {
    return testStringSubstring(env, str, beginIndex, endIndex);
}
 
extern "C" JNIEXPORT jobject JNICALL
Java_com_ln28_jnidemo_Chapter04_testArrayList( // 修改函数名前缀,与Chapter04.kt中对应
        JNIEnv* env,
        jobject /* this */) {
    return testArrayList(env);
}

异常打印:

java.lang.NumberFormatException: For input string: "123A"
java.lang.RuntimeException: JNI error 》 testIntegerParseInt
异常被捕获,程序没有崩溃。

4.4 疑问和问题解答

JNI接口方法表:

  1. JNI接口方法表是什么?它的作用是什么?
    JNI接口方法表是一个结构体,其中包含了所有可用的JNI函数的指针。可以通过在C/C++代码中使用JNIEnv指针来调用这些函数。这个结构体为提供了一个与Java交互的接口,如访问和修改Java对象的字段,调用Java方法,处理Java异常等。
  2. 如何使用JNI接口方法表?
    在C/C++代码中,可以通过JNIEnv指针来访问JNI接口方法表中的函数。例如,可以使用(*env)->GetObjectField(env, obj, fieldID)来访问一个Java对象的字段。
  3. JNI接口方法表中的函数有哪些?我需要了解所有的函数吗?
    JNI接口方法表中包含了大约100多个函数,这些函数提供了丰富的功能,如创建Java对象,访问和修改Java对象的字段,调用Java方法,抛出和处理Java异常等。不需要了解所有的函数,只需要掌握常用的一些函数就可以了。
  4. 有没有一个示例展示如何使用JNI接口方法表的某个函数?
    当然,例如,下面的代码展示了如何使用JNI接口方法表的GetObjectField函数和SetIntField函数来访问和修改Java对象的字段:
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fieldID = (*env)->GetFieldID(env, cls, "intValue", "I");
jint value = (*env)->GetIntField(env, obj, fieldID);
value++;
(*env)->SetIntField(env, obj, fieldID, value);

       5.我是否可以修改JNI接口方法表?

不,不能修改JNI接口方法表。这个结构体是由JNI环境提供的,只能通过JNIEnv指针来访问它,不能修改它。

JNI基础API:

  1. JNI基础API包含哪些函数?
    JNI基础API包含了许多函数,如创建Java对象,访问和修改Java对象的字段,调用Java方法,抛出和处理Java异常等。一些常用的函数包括NewObjectGetObjectClassGetFieldIDGetObjectFieldSetObjectFieldCallVoidMethod等。
  2. JNI基础API的主要作用是什么?
    JNI基础API的主要作用是提供一个接口,让可以在C/C++代码中与Java交互。可以通过JNI基础API来创建Java对象,访问和修改Java对象的字段,调用Java方法,抛出和处理Java异常等。
  3. 如何使用JNI基础API访问和修改Java对象的字段?
    可以使用GetFieldID函数来获取一个字段的ID,然后使用Get<Type>FieldSet<Type>Field函数来访问和修改该字段。例如:

jclass cls = (*env)->GetObjectClass(env, obj);

jfieldID fieldID = (*env)->GetFieldID(env, cls, "intValue", "I");

jint value = (*env)->GetIntField(env, obj, fieldID);

value++;

(*env)->SetIntField(env, obj, fieldID, value);

       4.如何使用JNI基础API调用Java方法

可以使用GetMethodID或者GetStaticMethodID函数来获取一个方法的ID,然后使用Call<Type>Method或者CallStatic<Type>Method函数来调用该方法。例如:

jclass cls = (*env)->GetObjectClass(env, obj);

jmethodID mid = (*env)->GetMethodID(env, cls, "print", "(I)V");

(*env)->CallVoidMethod(env, obj, mid, 123);

       5.如何创建和处理Java对象?

可以使用NewObject函数来创建一个新的Java对象,然后使用各种Get<Type>FieldSet<Type>Field函数来访问和修改其字段。如果需要处理Java对象的数组,可以使用NewObjectArrayGetObjectArrayElementSetObjectArrayElement等函数。

JNI异常API:

  1. JNI异常API是用来做什么的?
    JNI异常API用于在native代码中抛出和处理Java异常。当在C/C++代码中调用Java方法时,可能会发生Java异常,可以使用JNI异常API来检查和处理这些异常。2
  2. 如果在native方法中发生了Java异常,我应该如何处理?可以使用ExceptionOccurred函数来检查是否发生了异常,然后使用ExceptionDescribe函数来打印异常的堆栈轨迹,使用ExceptionClear函数来清除异常。如果想在native代码中处理异常,可以使用ThrowNew函数来抛出一个新的异常。
jmethodID mid = (*env)->GetMethodID(env, cls, "method", "()V");
if ((*env)->ExceptionOccurred(env)) {
    (*env)->ExceptionDescribe(env);
    (*env)->ExceptionClear(env);
    return;
}

       3.我应该如何使用JNI异常API抛出一个新的Java异常

可以使用ThrowNew函数来抛出一个新的Java异常。需要指定异常类和异常信息。

jclass exCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
if (exCls != NULL) {
    (*env)->ThrowNew(env, exCls, "Illegal argument");
}

       4.JNI异常API中的ExceptionCheckExceptionOccurred有什么区别?

ExceptionCheckExceptionOccurred函数都可以用来检查是否发生了Java异常,但是ExceptionCheck函数不会清除异常状态,而ExceptionOccurred函数会返回一个异常对象并清除异常状态。

       5。如果我忽略了一个Java异常(没有清除或者抛出),会发生什么?

如果在native方法中忽略了一个Java异常,这个方法将会立即返回,不会执行后面的代码。如果这个native方法是由Java调用的,Java将会收到这个异常。所以,如果不打算处理Java异常,应该至少使用ExceptionDescribe函数来打印异常的堆栈轨迹,然后使用ExceptionClear函数来清除异常,避免影响后续代码的执行。

(1) JNI 提示 | Android NDK | Android Developers - Android 开发者. JNI 提示  |  Android NDK  |  Android Developers.

(2) NDK系列:JNI基础 - 掘金. NDK系列:JNI基础 - 掘金.

相关文章
|
10天前
|
人工智能 自然语言处理 API
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
谷歌推出的Multimodal Live API是一个支持多模态交互、低延迟实时互动的AI接口,能够处理文本、音频和视频输入,提供自然流畅的对话体验,适用于多种应用场景。
59 3
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
|
5天前
|
前端开发 API 数据库
Next 编写接口api
Next 编写接口api
|
12天前
|
XML JSON 缓存
阿里巴巴商品详情数据接口(alibaba.item_get) 丨阿里巴巴 API 实时接口指南
阿里巴巴商品详情数据接口(alibaba.item_get)允许商家通过API获取商品的详细信息,包括标题、描述、价格、销量、评价等。主要参数为商品ID(num_iid),支持多种返回数据格式,如json、xml等,便于开发者根据需求选择。使用前需注册并获得App Key与App Secret,注意遵守使用规范。
|
10天前
|
JSON API 开发者
淘宝买家秀数据接口(taobao.item_review_show)丨淘宝 API 实时接口指南
淘宝买家秀数据接口(taobao.item_review_show)可获取买家上传的图片、视频、评论等“买家秀”内容,为潜在买家提供真实参考,帮助商家优化产品和营销策略。使用前需注册开发者账号,构建请求URL并发送GET请求,解析响应数据。调用时需遵守平台规定,保护用户隐私,确保内容真实性。
|
11天前
|
搜索推荐 数据挖掘 API
淘宝天猫商品评论数据接口丨淘宝 API 实时接口指南
淘宝天猫商品评论数据接口(Taobao.item_review)提供全面的评论信息,包括文字、图片、视频评论、评分、追评等,支持实时更新和高效筛选。用户可基于此接口进行数据分析,支持情感分析、用户画像构建等,同时确保数据使用的合规性和安全性。使用步骤包括注册开发者账号、创建应用获取 API 密钥、发送 API 请求并解析返回数据。适用于电商商家、市场分析人员和消费者。
|
21天前
|
JSON API 开发工具
淘宝实时 API 接口丨淘宝商品详情接口(Taobao.item_get)
淘宝商品详情接口(Taobao.item_get)允许开发者获取商品的详细信息,包括基本信息、描述、卖家资料、图片、属性及销售情况等。开发者需注册账号、创建应用并获取API密钥,通过构建请求获取JSON格式数据,注意遵守平台规则,合理使用接口,确保数据准确性和时效性。
|
22天前
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
94 5
|
21天前
|
JSON 缓存 监控
淘宝商品详情接口(Taobao.item_get)丨淘宝API接口指南
淘宝商品详情接口(Taobao.item_get)允许开发者通过HTTP GET方法获取淘宝商品的详细信息,包括商品ID、价格、库存等。请求需包含key、secret、num_iid等必选参数,支持缓存及多种返回格式。此接口广泛应用于电商数据分析、商品选品、价格监控等领域,提升商家运营效率。
|
25天前
|
JSON 搜索推荐 API
LAZADA关键词搜索API接口的获取与应用
Lazada作为东南亚领先的电商平台,为满足开发者和商户需求,开放了关键词搜索API接口。本文详细介绍该接口的获取与应用,助力提升电商业务效率。接口支持关键词搜索、指定搜索范围和排序方式,提供精准、灵活且全面的数据支持,促进电商应用和服务的优化与创新。
25 3
|
1月前
|
JSON API 数据库
电商拍立淘按图搜索API接口,数据格式示例
电商拍立淘按图搜索API接口系列为电商平台和购物应用提供了强大的图像搜索功能,以下是其文档说明的详细参考

热门文章

最新文章