Android Studio 简单生成so文件并调用「建议收藏」

Android Studio 简单生成so文件并调用「建议收藏」平台:windowsIDE:AndroidStudio下载好ndk:下载地址https://developer.android.com/ndk/downloads/index.html第1步:新建一个AndroidStudio工程JniHelloWorld。新建一个MyJni.java文件。MyJni.javapublicclassMyJni

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

注意:可以直接翻到后面的## 2021年新增部分看起了,当然前面看看也挺好,哈哈。

平台:windows
IDE :Android Studio
下载好ndk:下载地址 https://developer.android.com/ndk/downloads/index.html

第1步:新建一个Android Studio 工程 JniHelloWorld。新建一个MyJni.java文件。
这里写图片描述

MyJni.java

public class MyJni { 
   

    static { 
   
        System.loadLibrary("MyJni");
    }

    public native static String getString();
}

第2步:然后点击一下 make project 会在app的build目录下面生成.class文件。
这里写图片描述

第3步,在app/src/main文件夹下新建一个jni文件夹,然后打开Android Studio的终端,cd到这个目录,然后输入下面的指令

javah -jni -classpath D:\github\JniHelloWorld\app\build\intermediates\classes\debug com.brotherd.jnihelloworld.MyJni

就会在这个jni文件夹下生成一个.h文件,com_brotherd_jnihelloworld_MyJni.h,文件内容如下。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_brotherd_jnihelloworld_MyJni */

#ifndef _Included_com_brotherd_jnihelloworld_MyJni
#define _Included_com_brotherd_jnihelloworld_MyJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_brotherd_jnihelloworld_MyJni
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_brotherd_jnihelloworld_MyJni_getString
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

scr/main/jni目录下新建一个c/c++source file ,取名test.c 实现上面.h文件中的方法。

#include "jni.h"
#include "com_brotherd_jnihelloworld_MyJni.h"

JNIEXPORT jstring JNICALL Java_com_brotherd_jnihelloworld_MyJni_getString
  (JNIEnv *env, jclass jz){

  return (*env)->NewStringUTF(env,"this is the first time for me to use jni");

  }

接着在jni文件夹下新建Android.mk和Application.mk文件。
Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := MyJni
LOCAL_SRC_FILES := Test.c
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_ABI := all

第4步,关联下载好的ndk包,我的解压好的路径是C:\android-ndk-r14b
这里写图片描述

然后在终端进入到jni目录,输入指令 ndk-build,就会生成相应的so文件。

这里写图片描述

第5步,调用so文件。
在app的bulid文件中加入如下代码,然后build project

android {
    ...
    sourceSets {
        main() {
            jniLibs.srcDirs = ['src/main/libs']
            jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
        }
    }
}

在MainActivity中调用

public class MainActivity extends AppCompatActivity { 
   

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) { 
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);
        textView.setText(MyJni.getString());
    }
}

运行效果图

这里写图片描述

2021年新增

使用CMake

平台:mac
IDE :Android Studio 4.2.1

首先确保已经安装了CMake工具,没有安装的安装一下。
CMake

然后新建一个项目,选择Native C++,点击Next
创建Native C++项目
输入项目名称,JniHelloWorld1,语言这里选择了Kotlin。Next
在这里插入图片描述
C++我们选择 Toolchain Default 这一项就可以,然后点击finish。
在这里插入图片描述
创建好的项目结构如下所示:

在这里插入图片描述

我们可以看到这里有一个cpp文件夹,文件夹下面有两个文件。我们先运行看一下效果。

在这里插入图片描述

创建项目时,默认的MainActivity

package com.example.jnihellowrold1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import com.example.jnihellowrold1.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() { 
   

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) { 
   
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 调用一个native方法来获取字符串。
        binding.sampleText.text = stringFromJNI()
    }

    /** * native方法,由 'native-lib' 这个native库来实现。native-lib会打包到应用中。 */
    external fun stringFromJNI(): String

    companion object { 
   
        // 静态方法,在加载MainActivity类的时候,会加载'native-lib'库。
        init { 
   
            System.loadLibrary("native-lib")
        }
    }
}

我们在build文件夹下可以看到生成的so文件。有趣的是真正生成的so的命名是libnative-lib.so

在这里插入图片描述

我们看下native-lib.cpp文件。

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

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnihellowrold1_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) { 
   
    std::string hello = "Hello from C++";
    //返回一个字符串 Hello from C++
    return env->NewStringUTF(hello.c_str());
}

我们什么都没有做,我们就生成了libnative-lib.so文件并实现了调用native方法,这一切是谁帮我们做的呢?显然是CMake了。我们看一下CMakeLists.txt这个文件里面的内容。

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

# 设置用来构建native library所需CMake的最小版本。

cmake_minimum_required(VERSION 3.10.2)

# 声明项目名称。

project("jnihellowrold1")

# 创建并命名库,将库设置为静态的或者共享的,并提供源代码文件的相对路径。
# 你可以定义多个库,CMake会为你构建它们。
# Gradle会自动将共享库打包到你的apk里面。

add_library( # 设置库的名称
             native-lib

             # 将库设置为共享的
             SHARED

             # 提供源代码文件(可以是多个文件)的相对路径。
             native-lib.cpp )

# 搜索指定的预构建库并将其路径存储为变量。
# 因为CMake会在搜索路径上默认包含系统库,你只需要指定你想添加的公共的NDK库。
# 在完成构建之前CMake会验证这些库是否存在。

find_library( # 设置路径变量的名称。
              log-lib

              # 指定你想让CMake定位的NDK库的名称。
              log )

# 指定CMake应该链接到目标库的库。
# 你可以链接多个库,例如你在这个构建脚本中定义的库,预编译的三方库,或者系统库。

target_link_libraries( # 指定目标库
                       native-lib

                       # 将目标库链接到NDK中包含的日志库。
                       ${ 
   log-lib} )

那么CMakeLists.txt是怎么执行的呢,显然是在gradle.build文件中。

app/build.gradle文件精简版

//...
android { 
   
    compileSdkVersion 30

    defaultConfig { 
   
        applicationId "com.example.jnihellowrold1"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        //注释1处,
        externalNativeBuild { 
   
            cmake { 
   
                cppFlags ''
            }
        }
    }

    //...
    //注释2处,指定cmake文件所在的路径
    externalNativeBuild { 
   
        cmake { 
   
            path file('src/main/cpp/CMakeLists.txt')
            version '3.10.2'
        }
    }
}

参考链接:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191740.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 局域网文件传输方式分析

    局域网文件传输方式分析一、概述在C/S结构的软件开发过程中通常被限于局域网范围内, 常常会遇到需要传输数据文件、音视频文件、升级文件到服务器端或者客户端。每个工作站点都是通过交换机或者集线器、路由器等设备相互连接在一起。由于需要传输的站点数量、局域网环境、OS系统的不同,传输上的性能上也有很大的区别, 传输方式也是多种多样的,比如常见的局域网共享传输、基于FTP协议传输、点对点传输等方式。不同的网络操作系统(NOS

  • python如何使用for循环_Python 中for循环的应用

    python如何使用for循环_Python 中for循环的应用1.for…in循环循环,遍历,迭代都是指把容器中的数据一个一个获取出来lst=[1,2,3,4,5]i=0whilei<len(lst): print(lst[i]) i+=1 #无法用while它的索引下标获取集合其中的值;setvar={“a”,”b”,”c”}for..in..应用而生语法:for变量in可迭代对象: code…可迭代对象(通常用到的是:容器类型数据,range对象,迭代器)2

  • java和c 就业,c++和java的区别和就业前景

    java和c 就业,c++和java的区别和就业前景c++和java都是当下最热门的编程语言,二者各有各的优势。java与c++都是面向对象的语言,但java晚于c++发布,部分语法和思想也参考了c++,只是java没有头文件、指针、运算符重载、虚基类等等,算是c++语言的“纯净版”。c++和java的主要区别1、指针java语言让编程者无法找到指针来直接访问内存无指针,并且增添了自动的内存管理功能,从而有效地防止了c/c++语言中指针操作失误,…

  • 滚动条的scroll属性(怎么修改滚动条样式)

    http://www.dengjie.com/temp/scroller.swfIE下的滚动条样式IE是最早提供滚动条的样式支持,好多年了,但是其它浏览器一直没有支持,IE独孤求败了。这些样式规则很简单:scrollbar-arrow-color:color;/*三角箭头的颜色*/scrollbar-face-color:color;/*立体滚动条的颜色(包

  • VSCode设置中文语言显示

    VSCode设置中文语言显示 Vscode是一款开源的跨平台编辑器。默认情况下,vscode使用的语言为英文(us),如何将其显示语言修改成中文了?1)打开vscode工具;2)使用快捷键组合【Ctrl+Shift+p】,在搜索框中输入“configuredisplaylanguage”,点击确定后;3)修改locale.json文件下的属性“locale”为“zh-CN”;4)重启vscode工具;…

  • git修改gitignore不生效_github ignore

    git修改gitignore不生效_github ignore前言我在项目中采用Github代码托管仓库,由于部分项目文件,比如数据库文件不需要上传到网上,需要配置.gitignore文件,也就可以忽略版本控制,意思就是不上传它们。但是有一些文件一开始是期望忽略的,后来还是希望加入版本控制,上传到网上。不过直接从.gitignore文件中把它们移出来并不能解决问题,这些文件还是无法上传。百度的解决方式都大同小异,但是都有一个…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号