[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基础 - 掘金.

目录
打赏
0
0
0
0
74
分享
相关文章
速卖通商品详情接口(速卖通API系列)
速卖通(AliExpress)是阿里巴巴旗下的跨境电商平台,提供丰富的商品数据。通过速卖通开放平台(AliExpress Open API),开发者可获取商品详情、订单管理等数据。主要功能包括商品搜索、商品详情、订单管理和数据报告。商品详情接口aliexpress.affiliate.productdetail.get用于获取商品标题、价格、图片等详细信息。开发者需注册账号并创建应用以获取App Key和App Secret,使用PHP等语言调用API。该接口支持多种请求参数和返回字段,方便集成到各类电商应用中。
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
52 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
亚马逊商品详情接口(亚马逊 API 系列)
亚马逊作为全球最大的电商平台之一,提供了丰富的商品资源。开发者和电商从业者可通过亚马逊商品详情接口获取商品的描述、价格、评论、排名等数据,对市场分析、竞品研究、价格监控及业务优化具有重要价值。接口基于MWS服务,支持HTTP/HTTPS协议,需注册并获得API权限。Python示例展示了如何使用mws库调用接口获取商品详情。应用场景包括价格监控、市场调研、智能选品、用户推荐和库存管理等,助力电商运营和决策。
84 23
lazada商品详情接口 (lazada API系列)
Lazada 是东南亚知名电商平台,提供海量商品资源。通过其商品详情接口,开发者和商家可获取商品标题、价格、库存、描述、图片、用户评价等详细信息,助力市场竞争分析、商品优化及库存管理。接口采用 HTTP GET 请求,返回 JSON 格式的响应数据,支持 Python 等语言调用。应用场景包括竞品分析、价格趋势研究、用户评价分析及电商应用开发,为企业决策和用户体验提升提供有力支持。
79 21
eBay商品详情接口(ebay API系列)
eBay 商品详情接口是电商从业者、开发者和数据分析师获取商品详细信息的重要工具,涵盖标题、价格、库存、卖家信息等。使用前需在 eBay 开发者平台注册并获取 API 凭证,通过 HTTP GET 请求调用接口,返回 JSON 格式数据。Python 示例代码展示了如何发送请求并解析响应,确保合法合规使用数据。
51 12
阿里巴巴商品详情接口(阿里巴巴 API 系列)
在电商开发中,获取阿里巴巴商品详情信息对数据分析、竞品研究等至关重要。通过调用其商品详情接口,开发者可获取标题、价格、图片、描述等数据,满足多种业务需求。接口采用HTTPS协议,支持GET/POST请求,返回JSON格式数据。示例代码展示了如何使用Python的requests库进行接口请求,需传递商品ID和访问令牌。实际应用时,请依据官方文档调整参数并确保安全性。
49 10
速卖通商品列表接口(以 AliExpress Affiliate 商品查询 API 为例)
以下是使用 Python 调用速卖通商品列表接口(以 AliExpress Affiliate 商品查询 API 为例)的代码示例。该示例包含准备基础参数、生成签名、发送请求和处理响应等关键步骤,并附有详细注释说明。代码展示了如何通过公共参数和业务参数构建请求,使用 HMAC-SHA256 加密生成签名,确保请求的安全性。最后,解析 JSON 响应并输出商品信息。此接口适用于商品监控、数据采集与分析及商品推荐等场景。注意需通过 OAuth2.0 获取 `access_token`,并根据官方文档调整参数和频率限制。
淘宝拍立淘按图搜索API接口系列概述
淘宝拍立淘按图搜索API接口允许用户通过上传图片或拍摄实物来搜索相似或相同的商品。这一功能主要依赖于图像识别技术,系统会对上传的图片进行分析和处理,提取出商品的特征信息,并在淘宝的商品数据库中进行匹配搜索,最终返回与上传图片相似或相同的商品列表。
速卖通商品列表接口(速卖通API系列)
速卖通提供商品列表API,开发者可通过关键词、类目、价格范围等条件获取商品标题、价格、销量等基本信息。使用前需注册开发者账号、创建应用并授权获取access_token。Python示例代码展示了如何调用接口,返回JSON格式数据,包含商品列表、总数、页码等信息。应用场景包括商品监控、数据分析和个性化推荐。注意API会更新,请参考官方文档。
淘宝商品评论数据API接口详解及JSON示例返回
淘宝商品评论数据API接口是淘宝开放平台提供的一项服务,旨在帮助开发者通过编程方式获取淘宝商品的评论数据。这些数据包括评论内容、评论时间、评论者信息、评分等,对于电商分析、用户行为研究、竞品分析等领域都具有极高的价值。

热门文章

最新文章