Android Studio 进行NDK开发,实现JNI,以及编写C++与Java交互(Java调用本地函数)并编译出本地so动态库

这篇具有很好参考价值的文章主要介绍了Android Studio 进行NDK开发,实现JNI,以及编写C++与Java交互(Java调用本地函数)并编译出本地so动态库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.首先认识一下NDK。

(1)什么是NDK?
NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

(2)为什么使用NDK?
1)代码的保护:由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
2)可以方便地使用现存的开源库:大部分现存的开源库都是用C/C++代码编写的。
3)提高程序的执行效率:将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
4)便于移植:用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

(3)什么是JNI?
JNI全称为:Java Native Interface。JNI是本地编程接口,它使得在 Java 虚拟机内部运行的 Java代码能够与用其它语言(如 C、C++)编写的代码进行交互。

(4)为什么使用JNI?
JNI的目的是使java方法能够调用C/C++实现的一些函数。

(5)安卓中的so文件是什么?
Android中用到的so文件是一个C/C++的函数库。在android的JNI中,要先将相应的C/C++打包成so库,然后导入到lib文件夹中供java调用。

2.Android Studio 配置NDK(使用Android Studio 4.2.2之后的稳定版本)

(1) 步骤一:点击红圈处(这是Mac配置流程,Windows对应的按钮是Settings),如下图一

ndk编译jni,java,android studio,c++

(2)步骤二:下载下图一中第3步红圈中的一个NDK和一个CMake,下载成功后如下图一所示(建议下载前先配置Android Studio 国内镜像代理,详见:Android Studio 国内镜像代理设置(如果设置之后还是远程仓库下载失败,请仔细阅读其内容就可以解决了)_android studio 镜像_ErwinNakajima的博客-CSDN博客)。

ndk编译jni,java,android studio,c++

3.开始开发,在main文件夹下面创建一个cpp文件夹,如下图一和下圖二,然后在cpp文件夹下创建native-lib.cpp、return-data.cpp和CMakeLists.txt,然后添加具体内容;

ndk编译jni,java,android studio,c++

ndk编译jni,java,android studio,c++

native-lib.cpp文件的内容;

//
// Created by ErwinNakashima on 2022/12/24.
//
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <string>

static jclass contextClass;
static jclass signatureClass;
static jclass packageNameClass;
static jclass packageInfoClass;

/**
    之前生成好的签名字符串
*/
const char *SIGN_RELEASE = "308203b130820299a00302010202045fa239d4300d06092a864886f70d01010b0500308188310c300a06035504061303555341311c301a060355040813135374617465206f662043616c69666f726e69613112301006035504071309437570657274696e6f310e300c060355040a13056170706c65310e300c060355040b13056170706c653126302406035504030c1d72786a617661325f616e645f726574726f666974325f72656c65617365301e170d3232313232313133333232365a170d3437313231353133333232365a308188310c300a06035504061303555341311c301a060355040813135374617465206f662043616c69666f726e69613112301006035504071309437570657274696e6f310e300c060355040a13056170706c65310e300c060355040b13056170706c653126302406035504030c1d72786a617661325f616e645f726574726f666974325f72656c6561736530820122300d06092a864886f70d01010105000382010f003082010a02820101009f09581713e084950d06b016bf86063343864fe59952c335f3bb44e14ed67686749dcd372f075d2d74757c18dff9082941cbc7c83c60c3ad51d69ca503826775b2b703a6c347d70b8364b5f140cf7e1025590c8dcfa1469d2b5af242323b6c7bcddf92fb44aaa82a7c735597112964432fc16bb6dbf360f2a44d0e9e9722295b070582ea72310c674aed8ef8aa24ec06e972edafcae51d93c7370cfbc3e804fda3cc6f22ec89f98dac2ceb5607ef564fd3151091d2e0c142b984a21c61bc63b75e0bdc931dca1a9cc76f1ee326d59ef6edeb1d5dd07dd12fa32e55de3572784e8adc67388d643b310560f77e75ec944e00e6ae62d283c90c89eae5ce71747a9f0203010001a321301f301d0603551d0e041604147387f3952464b66ce5bb906d56845bc4410d8bc1300d06092a864886f70d01010b050003820101003ca9530822c2f272bcfb94dc2552045db8d4038385fbac917e08266f6f47b00ba36a735fc62da0c2d4bbe8fcfaec0d87c7c6223c257a22240f69057f954d90fda7c7dfe4daa2f3fa482aa1a35b56c1220b449115a670324408ae9f4f6dfa3af40b9c55275c27785bcfeb1337c7228ca2deac5c9e5b4fabd33e77f3fab0c18df0facfd23980a037907acd215c11a450d98789f002081379a688686b23b3aec1fbf4e3bf1db0e34daac5140e60ad412c11c1717c3befb83ca5878d1f5b199f6f4fee89591c9dbcec13a340c7aa817ab4d68b19598f57e60b08e950ba2843d5400b576511d8b4a0ac45accf92d5c82f0d9afc11bce5c2d58ae4f3f8e9da604e83c7";
const char *SIGN_DEBUG = "308202e4308201cc020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3231303830363136353432345a180f32303531303733303136353432345a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a02820101008b2616bebb0dd79ea6e0688ce89e5ae221e3132ee9b6cc96514119557f0be3e79371e22c3c91250988a833942714ae562e8a86d6fff4290cb7b7bf718aeacd480d2cffe38c9787218e6391e562843b95dd26642b24e2106694501f0fe39186bf5fcc5c3cca91b9d86c113ffb0acf6e0e6ac9a4cda01110c5f18729d8f2f091b9fb604595a492ddcad6ae71dd190672cd8a675483563d5a734f9ec040890456ee02a32b61ccfc61811c8311b61eb90ffb15fae0db04f52c562b3713781fd772331619a4670065ed574e96da2cf47e7c4b29af30d5bbc1e271f23f3ea33b1085bb228e44d948d1f2adb0c71ee1c2652fe5b554d5e8e430c68f35b090f7d6dccbb10203010001300d06092a864886f70d010105050003820101004f1fd6247b615c2216e23eb8fe38e20282e9d5742b9485fec941fa541c97203eb60e3419fd6742d50bd2d60274d8489d1c03ab87f604aa2632aebdb2c7cc46e42f9f6dfec32155cca601fcf4abb3724068ccda637aa11c22d361afe9ec91b0d15209a9121c849aef791ceb670052e943891c34c0d380947f442ff93a93e8c6ac594d003f40ee0880dd0a0742ad1aa5c18f692b6480c3cf3baf42f5bacd8f31e811e88e98c187da52d4ed74aeaadb5f5f2c8b99c63612ce5abf4532151bcc4f3cab9b320c12b5c5e2c7fb6a69e72d6d1acdb43415dcecf9737ed124f28850d9e691cdb03a17c6c62a51fbd5c460067f3f890df085c4a849c05b061062d2aab16c";

std::string hello = "(*^__^*) 嘻嘻……~Hello from C++ 特朗普的头发是黄色的";

/*
    根据context对象,获取签名字符串
*/
const char *getSignString(JNIEnv *env, jobject contextObject) {
    jmethodID getPackageManagerId = (env)->GetMethodID(contextClass, "getPackageManager",
                                                       "()Landroid/content/pm/PackageManager;");
    jmethodID getPackageNameId = (env)->GetMethodID(contextClass, "getPackageName",
                                                    "()Ljava/lang/String;");
    jmethodID signToStringId = (env)->GetMethodID(signatureClass, "toCharsString",
                                                  "()Ljava/lang/String;");
    jmethodID getPackageInfoId = (env)->GetMethodID(packageNameClass, "getPackageInfo",
                                                    "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jobject packageManagerObject = (env)->CallObjectMethod(contextObject, getPackageManagerId);
    jstring packNameString = (jstring) (env)->CallObjectMethod(contextObject, getPackageNameId);
    jobject packageInfoObject = (env)->CallObjectMethod(packageManagerObject, getPackageInfoId,
                                                        packNameString, 64);
    jfieldID signaturefieldID = (env)->GetFieldID(packageInfoClass, "signatures",
                                                  "[Landroid/content/pm/Signature;");
    jobjectArray signatureArray = (jobjectArray) (env)->GetObjectField(packageInfoObject,
                                                                       signaturefieldID);
    jobject signatureObject = (env)->GetObjectArrayElement(signatureArray, 0);
    return (env)->GetStringUTFChars(
            (jstring) (env)->CallObjectMethod(signatureObject, signToStringId), 0);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_phone_library_1common_JavaGetData_nativeGetString(JNIEnv *env, jclass clazz,
                                                           jobject context, jboolean is_release) {
    const char *signStrng = getSignString(env, context);
    bool isRelease = is_release;
    const char *SIGN;
    if (isRelease) {
        SIGN = SIGN_RELEASE;
    } else {
        SIGN = SIGN_DEBUG;
    }
    if (strcmp(signStrng, SIGN) == 0)//签名一致  返回合法的 api key,否则返回错误
    {
        return (env)->NewStringUTF(hello.c_str());
    } else {
        return (env)->NewStringUTF("error");
    }
}

//bool toCppBool(jboolean value) {
//    return value == JNI_TRUE;
//}

/**
    利用OnLoad钩子,初始化需要用到的Class类.
*/
JNIEXPORT jint

JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {

    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK)
        return result;

    contextClass = (jclass) env->NewGlobalRef((env)->FindClass("android/content/Context"));
    signatureClass = (jclass) env->NewGlobalRef((env)->FindClass("android/content/pm/Signature"));
    packageNameClass = (jclass) env->NewGlobalRef(
            (env)->FindClass("android/content/pm/PackageManager"));
    packageInfoClass = (jclass) env->NewGlobalRef(
            (env)->FindClass("android/content/pm/PackageInfo"));

    return JNI_VERSION_1_4;
}

return-data.cpp文件的内容;

#include <jni.h>
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

static jclass contextClass;
static jclass signatureClass;
static jclass packageNameClass;
static jclass packageInfoClass;

/**
    之前生成好的签名字符串
*/
const char *SIGN_RELEASE = "308203b130820299a00302010202045fa239d4300d06092a864886f70d01010b0500308188310c300a06035504061303555341311c301a060355040813135374617465206f662043616c69666f726e69613112301006035504071309437570657274696e6f310e300c060355040a13056170706c65310e300c060355040b13056170706c653126302406035504030c1d72786a617661325f616e645f726574726f666974325f72656c65617365301e170d3232313232313133333232365a170d3437313231353133333232365a308188310c300a06035504061303555341311c301a060355040813135374617465206f662043616c69666f726e69613112301006035504071309437570657274696e6f310e300c060355040a13056170706c65310e300c060355040b13056170706c653126302406035504030c1d72786a617661325f616e645f726574726f666974325f72656c6561736530820122300d06092a864886f70d01010105000382010f003082010a02820101009f09581713e084950d06b016bf86063343864fe59952c335f3bb44e14ed67686749dcd372f075d2d74757c18dff9082941cbc7c83c60c3ad51d69ca503826775b2b703a6c347d70b8364b5f140cf7e1025590c8dcfa1469d2b5af242323b6c7bcddf92fb44aaa82a7c735597112964432fc16bb6dbf360f2a44d0e9e9722295b070582ea72310c674aed8ef8aa24ec06e972edafcae51d93c7370cfbc3e804fda3cc6f22ec89f98dac2ceb5607ef564fd3151091d2e0c142b984a21c61bc63b75e0bdc931dca1a9cc76f1ee326d59ef6edeb1d5dd07dd12fa32e55de3572784e8adc67388d643b310560f77e75ec944e00e6ae62d283c90c89eae5ce71747a9f0203010001a321301f301d0603551d0e041604147387f3952464b66ce5bb906d56845bc4410d8bc1300d06092a864886f70d01010b050003820101003ca9530822c2f272bcfb94dc2552045db8d4038385fbac917e08266f6f47b00ba36a735fc62da0c2d4bbe8fcfaec0d87c7c6223c257a22240f69057f954d90fda7c7dfe4daa2f3fa482aa1a35b56c1220b449115a670324408ae9f4f6dfa3af40b9c55275c27785bcfeb1337c7228ca2deac5c9e5b4fabd33e77f3fab0c18df0facfd23980a037907acd215c11a450d98789f002081379a688686b23b3aec1fbf4e3bf1db0e34daac5140e60ad412c11c1717c3befb83ca5878d1f5b199f6f4fee89591c9dbcec13a340c7aa817ab4d68b19598f57e60b08e950ba2843d5400b576511d8b4a0ac45accf92d5c82f0d9afc11bce5c2d58ae4f3f8e9da604e83c7";
const char *SIGN_DEBUG = "308202e4308201cc020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b30090603550406130255533020170d3231303830363136353432345a180f32303531303733303136353432345a30373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b300906035504061302555330820122300d06092a864886f70d01010105000382010f003082010a02820101008b2616bebb0dd79ea6e0688ce89e5ae221e3132ee9b6cc96514119557f0be3e79371e22c3c91250988a833942714ae562e8a86d6fff4290cb7b7bf718aeacd480d2cffe38c9787218e6391e562843b95dd26642b24e2106694501f0fe39186bf5fcc5c3cca91b9d86c113ffb0acf6e0e6ac9a4cda01110c5f18729d8f2f091b9fb604595a492ddcad6ae71dd190672cd8a675483563d5a734f9ec040890456ee02a32b61ccfc61811c8311b61eb90ffb15fae0db04f52c562b3713781fd772331619a4670065ed574e96da2cf47e7c4b29af30d5bbc1e271f23f3ea33b1085bb228e44d948d1f2adb0c71ee1c2652fe5b554d5e8e430c68f35b090f7d6dccbb10203010001300d06092a864886f70d010105050003820101004f1fd6247b615c2216e23eb8fe38e20282e9d5742b9485fec941fa541c97203eb60e3419fd6742d50bd2d60274d8489d1c03ab87f604aa2632aebdb2c7cc46e42f9f6dfec32155cca601fcf4abb3724068ccda637aa11c22d361afe9ec91b0d15209a9121c849aef791ceb670052e943891c34c0d380947f442ff93a93e8c6ac594d003f40ee0880dd0a0742ad1aa5c18f692b6480c3cf3baf42f5bacd8f31e811e88e98c187da52d4ed74aeaadb5f5f2c8b99c63612ce5abf4532151bcc4f3cab9b320c12b5c5e2c7fb6a69e72d6d1acdb43415dcecf9737ed124f28850d9e691cdb03a17c6c62a51fbd5c460067f3f890df085c4a849c05b061062d2aab16c";

const char *aesKey = "rxjava_and_re_ro";
const char *databaseEncryptKey = "Aa123456";

/*
    根据context对象,获取签名字符串
*/
const char *getSignString(JNIEnv *env, jobject contextObject) {
    jmethodID getPackageManagerId = (env)->GetMethodID(contextClass, "getPackageManager",
                                                       "()Landroid/content/pm/PackageManager;");
    jmethodID getPackageNameId = (env)->GetMethodID(contextClass, "getPackageName",
                                                    "()Ljava/lang/String;");
    jmethodID signToStringId = (env)->GetMethodID(signatureClass, "toCharsString",
                                                  "()Ljava/lang/String;");
    jmethodID getPackageInfoId = (env)->GetMethodID(packageNameClass, "getPackageInfo",
                                                    "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jobject packageManagerObject = (env)->CallObjectMethod(contextObject, getPackageManagerId);
    jstring packNameString = (jstring) (env)->CallObjectMethod(contextObject, getPackageNameId);
    jobject packageInfoObject = (env)->CallObjectMethod(packageManagerObject, getPackageInfoId,
                                                        packNameString, 64);
    jfieldID signaturefieldID = (env)->GetFieldID(packageInfoClass, "signatures",
                                                  "[Landroid/content/pm/Signature;");
    jobjectArray signatureArray = (jobjectArray) (env)->GetObjectField(packageInfoObject,
                                                                       signaturefieldID);
    jobject signatureObject = (env)->GetObjectArrayElement(signatureArray, 0);
    return (env)->GetStringUTFChars(
            (jstring) (env)->CallObjectMethod(signatureObject, signToStringId), 0);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_phone_library_1common_JavaGetData_nativeAesKey(JNIEnv *env, jclass clazz, jobject context,
                                                        jboolean is_release) {
    const char *signStrng = getSignString(env, context);
    bool isRelease = is_release;
    const char *SIGN;
    if (isRelease) {
        SIGN = SIGN_RELEASE;
    } else {
        SIGN = SIGN_DEBUG;
    }
    if (strcmp(signStrng, SIGN) == 0)//签名一致  返回合法的 api key,否则返回错误
    {
        return (env)->NewStringUTF(aesKey);
    } else {
        return (env)->NewStringUTF("error");
    }
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_phone_library_1common_JavaGetData_nativeDatabaseEncryptKey(JNIEnv *env, jclass clazz,
                                                                    jobject context,
                                                                    jboolean is_release) {
    const char *signStrng = getSignString(env, context);
    bool isRelease = is_release;
    const char *SIGN;
    if (isRelease) {
        SIGN = SIGN_RELEASE;
    } else {
        SIGN = SIGN_DEBUG;
    }
    if (strcmp(signStrng, SIGN) == 0)//签名一致  返回合法的 api key,否则返回错误
    {
        return (env)->NewStringUTF(databaseEncryptKey);
    } else {
        return (env)->NewStringUTF("error");
    }
}

/**
    利用OnLoad钩子,初始化需要用到的Class类.
*/
JNIEXPORT jint

JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {

    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK)
        return result;

    contextClass = (jclass) env->NewGlobalRef((env)->FindClass("android/content/Context"));
    signatureClass = (jclass) env->NewGlobalRef((env)->FindClass("android/content/pm/Signature"));
    packageNameClass = (jclass) env->NewGlobalRef(
            (env)->FindClass("android/content/pm/PackageManager"));
    packageInfoClass = (jclass) env->NewGlobalRef(
            (env)->FindClass("android/content/pm/PackageInfo"));

    return JNI_VERSION_1_4;
}

#ifdef __cplusplus
}
#endif

CMakeLists.txt的內容。

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

#设置so库的输出路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI})

add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)
add_library( # Sets the name of the library.
        return-data

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        return-data.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib

        return-data

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

4.配置ndk,在module的build.gradle文件下的android下配置;

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    ndkVersion '16.1.4479499'
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.10.2'
        }
    }

module的build.gradle文件下的defaultConfig下配置;

ndk {
            //选择要添加的对应 cpu 类型的 .so 库。
            abiFilters 'armeabi-v7a', 'arm64-v8a'
//            abiFilters 'armeabi-v7a', 'arm64-v8a'
            // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
        }

項目的gradle.properties文件下配置,如下图一;

android.useDeprecatedNdk=true

ndk编译jni,java,android studio,c++

 項目的local.properties 文件下配置,如下图一。

ndk.dir=/Users/erwinnakashima/Library/Android/sdk/ndk/16.1.4479499

ndk编译jni,java,android studio,c++

 5.添加JavaGetData文件,JavaGetData文件内容;

package com.phone.library_common;

import android.content.Context;

public class JavaGetData {
    static {
        System.loadLibrary("return-data");
        System.loadLibrary("native-lib");
    }

    public static native String nativeAesKey(Context context, boolean isRelease);

    public static native String nativeDatabaseEncryptKey(Context context, boolean isRelease);

    public static native String nativeGetString(Context context, boolean isRelease);


}

在Application的onCreate方法中调用JavaGetData.nativeAesKey(),然后ReBuild Project。就会生成两个文件这几个so文件,如下图一,然后就能正常获取到C++文件(也就是cpp文件)中的数据了,还可以把so动态库提供给第三方使用,具体方式详见Android 项目调用第三方库so动态库_ErwinNakajima的博客-CSDN博客

ndk编译jni,java,android studio,c++

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:原本是RxJava2 和Retrofit2 项目,现已更新使用Kotlin+RxJava2+Retrofit2+MVP架构+组件化和
Kotlin+Retrofit2+协程+MVVM架构+组件化, 添加自动管理token 功能,添加RxJava2 生命周期管理,集成极光推送、阿里云Oss对象存储和高德地图定位功能。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2


 文章来源地址https://www.toymoban.com/news/detail-671583.html

到了这里,关于Android Studio 进行NDK开发,实现JNI,以及编写C++与Java交互(Java调用本地函数)并编译出本地so动态库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【环境配置】Android-Studio-OpenCV-JNI以及常见错误 ( 持续更新 )

    最近一个项目要编译深度学习的库,需要用到 opencv 和 JNI,本文档用于记录环境配置中遇到的常见错误以及解决方案 解决办法: 删除文件 .idea/gradle.xml 和 .idea/workspace.xml , 重新编译; 解决办法:Invalid Gradle JDK configuration found 原因是NDK版本过高,跟当前的AndroidStudio版本不匹配

    2024年02月11日
    浏览(45)
  • Android Studio中使用cmake开发JNI实战

    JNI学习大纲 一、JNI编程入门 二、Android Studio中使用cmake开发JNI实战 第一章节我们介绍了JNI的开发步骤,那这一章节我们就开始在Android Studio中实战一下吧,Let\\\'s Start。 AS中菜单栏选择ToolsSDK Manager 在Android SDK中选择SDK Tools,安装CMake和NDK。 在项目工程下的src/main创建cpp目录,编

    2024年02月14日
    浏览(56)
  • 安卓Android Studio JNI开发问题澄清与汇总

    AndroidBitmap_lockPixels和AndroidBitmap_unlockPixels的底层逻辑就是在处理bitmap中的数据的时候,把内存锁定,防止像素缓存被改变导致数据变化。 这篇文章有具体介绍相关的机制 下面是Bitmap操作的示例代码: Java端代码: 使用时,可以直接调用NativeUtils中的processImage方法即可。当然,

    2023年04月09日
    浏览(58)
  • Android NDK开发详解之编写C/C++代码中的Android SDK 版本属性)

    本部分将讨论如何使用 NDK 提供的库。 注意:有关导入预构建库(未包含在 NDK 中的库)的指南已移至各个构建系统的相关部分。请根据您的项目需求参阅 CMake 或 ndk-build 指南。 文中说明了 NDK 提供的 C ++ 运行时,并介绍了 NDK 提供的其他库(例如 OpenGL ES 和 OpenSL ES)以及支持

    2024年02月07日
    浏览(52)
  • Android JNI系列详解之ndk-build工具的使用

    一、Android项目中使用ndk-build工具编译库文件 之前介绍过CMake编译工具的使用,今天介绍一种ndk自带的编译工具ndk-build的使用。 ndk-build目前主要有两种配置使用方式:  如上图所示,第一种方式是Android.mk+Application.mk+gradle的方式生成库文件;第二种方式是Android.mk+Application.mk+命

    2024年02月10日
    浏览(35)
  • Android JNI系列详解之CMake和ndk-build编译工具介绍

    一、前提 CMake和ndk-build只是编译工具,本次主要介绍ndk-build和CMake的区别,下节课介绍他们的使用。 二、CMake工具介绍 CMake:cross platform make,是跨平台的编译工具 CMake是在AndroidStudio2.2之后引入(目前默认的NDK编译工具),使用时配合CMakeList.txt和gradle。 对C++的配置: 默认配置

    2024年02月12日
    浏览(35)
  • 【Android -- JNI 和 NDK】Java 和 C/C++ 之间传递参数和返回值

    本文主要介绍 JNI 的数据传递上,即 Java 如何传递对象给 C++; 而 C++ 又如何将数据封装成 Java 所需的对象。 1. 基本数据类型 传递 java 的基本类型是非常简单而直接的,一个 jxxx 之类的类型已经定义在本地系统中了,比如: jint, jbyte, jshort, jlong, jfloat, jdouble, jchar 和 jboolean 分别

    2024年02月09日
    浏览(38)
  • Android studio配置OpenCV的JNI接口,实现C++代码编程

    目录 一、下载OpenCV-android-sdk 二、新建项目 三、导入OpenCV包  四、配置OpenCV的JNI接口,拷贝OpenCV所需的头文件和库文件 五、修改Cmake文件  六、配置app的build.gradle文件  七、测试 OpenCV官网地址:https://opencv.org/  点击Library--Releases,下载Android版本,解压得到 OpenCV-android-sdk文件

    2024年02月10日
    浏览(49)
  • Android串口开发之使用JNI实现ANDROID和串口通信

    导语:Android串口通信在物联网、智能家居等领域具有广泛的应用。本文将详细介绍如何使用JNI技术实现Android设备与串口的通信,包括串口的打开、设置参数和读写数据等过程。 在开始介绍Android串口开发之前,我们需要了解以下几个概念: JNI:JNI(Java Native Interface)是一种

    2024年02月07日
    浏览(47)
  • 【移动开发学习】 Android Studio 编写一个简单的微信界面

    Android Studio简单还原微信ui 目标 实现3-4个tab的切换效果 技术需求 activity, xml, fragment, recyclerview 成果展示 其中联系人界面通过recyclerview实现了可以滑动列表           仓库地址 https://github.com/SmileEX/wecaht.git 实现过程 主要ui 第一步我们首先把微信的ui主体做出来,即这三个部分

    2024年02月08日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包