Android Studio 下利用c语言生成so文件并利用jni调用(二))

Android Studio 下利用jni生成编译C语言的so文件并调用的常见问题(二)

前言:
前几天记录了自己在AS下利用jni生成.so文件并调用的方法,成功的demo较为简单,不涉及过多头文件的开发,自己循着这个思路往下开发实时,遇到挺多问题,发现前一篇所提到的方法局限性太大,局限之处具体哪些请看接下来的问题描述。

平台环境与工具版本:
1、ubuntu18.04LTS
2、Android Studio Arctic For | 2020.3.1

赘述:
之前网络上的教程很多是在 eclipse 上开发,使用了最新Android Studio版本后,很少见到与自己相关的问题解决思路,所以一定注意版本不同很多语法已经变了,包括老版本Android Studio 和 eclipse 在jni开发时,使用javah xxx,但新版本AS用的是 javac -h xxx;当然你需要先在local.properties 里结合你自已ndk安装路径进行ndk.dir的配置。总之注意新旧版本的差异,遇到问题“考虑版本,非必要不死磕”!

问题(1)描述:

工程着涉及C的头文件<stdio.h> <string.h> ,在按住“Ctrl”点击鼠标左键时发现无法跳转,并出现了“cannot find declaration to go”的提示,如下图示,并且在使用两个头文件中的函数时发现确实是使用不了,提示“未定义”,那必然,跳转不过去你怎么找得到呢。

在这里插入图片描述

问题(1)解决思路一:

a. 首先百度了下,带着问题找了一些方法:江湖大佬们的解决办法都是重启、clear project、rebuild project, restart,对我当前的问题实在是没有帮助。你说你连库中的头文件都找不到,还怎么进行后续的编程,Android Arctic Fox更新到都无法在新建工程时都选择support C++了(除了Native C++方式构建project,“别抬杠哦”),这版本实在是不敢恭维。

b. 那就寻找下如何在建好的“普通工程(Empty Project)”中加入C++ support,遍历一圈,花了不少time,我没找到。于是想着上一篇,用empty project 构建生so,在Native C++ project中调用,难道逻辑不对?那难道应该Native C++ project 生成so ,在另外一个Native C++ project中调用,好,试试,就猜想这么干。

(具体怎么到下图所示这一步,我上一篇blog就有具体步骤,链接:https://blog.csdn.net/zxl970921/article/details/119711760?spm=1001.2014.3001.5501)本篇仅从此处开始“赘述”
在这里插入图片描述
同时在Test.c 中依然无法跳转,如下图
在这里插入图片描述

从图里看到:本以为只要在Native C++ project 下就无条件support C++ ,结果上来.h文件就爆红,而C文件依然找不到头文,比普通工程构建的还“傻”,我曾经“一度多次一键删除”(沈腾飞驰人生:我曾经跨过山河大海…),又新建继续研究,真是个磨人的过程。突然我头上飞过一只“xxx”,“哎,那为啥AS自主生成的native.cpp里的头文件就能自动跳转自动补全呢?“没错,你(native-lib.cpp)是亲儿子””一探究竟了,那必然来到了CMakeList.txt里查看,果然这有你,如下图

在这里插入图片描述
图中可以看了add_library 下有native-lib.cpp,恰好,亲儿子就在这,那我就顺势加一个,当然需要注意路径了,不然怎么找得到;如下图

在这里插入图片描述

add_library( # Sets the name of the library.
        netjni1
        # Sets the library as a shared library.
        SHARED
        ${CMAKE_SOURCE_DIR}/../jni
        # Provides a relative path to your source file(s).
        ${CMAKE_SOURCE_DIR}/../jni/Test2.c
        ${CMAKE_SOURCE_DIR}/../jni/Test.c
        native-lib.cpp)

这里就结合自身工程C文件路径来添加就行了。

到这一步还有个关键操作: 点击 File下的 Sync project with Gradle files 这样一来CMakeLists.txt 才会开始“生效”。

这样再去你的C文件和.h文件下 查看添加头文件就可以自动跳转和补全了。

问题(1)解决思路二:

a. 发人深思,解决问题的关键之处在于在CMakeLists.txt中修改添加,那么我好奇Empty Project 新建的工程里按照我前一篇blog方法步骤中添加一下是不是就OK了呢?问题来了:Empty Project中哪来的CMakeLists.txt?反正我没找到,没有那么咱就造一个,多大点事!

实操开始:
new 一个 Native C++ 将其cpp下的CMakelist.txt copy 过来,在本project /main、目录下新建一个cpp文件如图 ,将复制来的 CMakelist.txt Paste 过来。

在这里插入图片描述

此时必然会有新的风暴:CMakelist.txt文件呈现灰色,即没有作用,what?因为你没有在cpp下的build.gradle下指明CMakelist.txt的位置,必然找不到也就没用了,将以下代码添加在 cpp下的build.gradle的dependencies上方位置:

   externalNativeBuild {
        cmake {
        #请结合你自己的CMakelist.txt 路径来修改
            path file('src/main/cpp/CMakeLists.txt')
            version '3.10.2'
        }
    }
    buildFeatures {
        viewBinding true
    }

如下图(不带点图,可能像我一样的新手有点不适应)
在这里插入图片描述

到这一步还有个关键操作再次闪亮登场:
点击 File下的 Sync project with Gradle files 这样一来build.gradle和CMakeLists.txt 才会开始“生效”。这个时候CMakeLists.txt 就不再是“全灰色状态”回过去在CMakeLists.txt文件中 对应工程名之类的进行修改,修改为与当前的相符合,这个不在赘述,重点依然是添加add_library内容同上,即将.c文件的路径写入进行。

add_library( # Sets the name of the library.
        jnibili
        # Sets the library as a shared library.
        SHARED
        # Provides a relative path to your source file(s).
        ${CMAKE_SOURCE_DIR}/../jni
        ${CMAKE_SOURCE_DIR}/../jni/Test.c
        )

如下图
在这里插入图片描述
点击 File下的 Sync project with Gradle files。(总之:修改这两个文件后都需要这一步)

后续就可以愉快的在C文件中继续掉发了,支持c相关跳转和补全。

问题(2)描述:
在jni目录下执行 javac -h jni java/com/example/netjni1/Net.java
错误: 找不到文件: java/com/example/netjni1/Net.java
用法: javac <选项> <源文件>
使用 --help 可列出可能的选项

这个命令我近期天天用天天出错,主要原因“马大哈系列”

a. 检查你当前terminal路径,需要与你执行的对应起来,否则找不到文件

b. ndk.dir在local.properties中设置正确了没。

c. 新版本已经不再是javah 了,已经被javac 吞并了,注意正确用法。

参考了以下博主们的分享让我有了解决思路,感谢!

博客链接:

https://www.jianshu.com/p/92daab193195
https://blog.csdn.net/Xiongjiayo/article/details/85340121?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-11.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-11.control

以及bilibili学习链接:

https://www.bilibili.com/video/BV1HJ411L756?p=314&spm_id_from=pageDriver
https://www.bilibili.com/video/BV1qW411L7oY?p=39&spm_id_from=pageDriver

声明:

属于本人“小白小白小小白”原创,如果转需请注明出处。对于大佬来说这教程很儿科,但对于新手可能还是有帮助,为了顺应像我一样的新手,需要赘述太多,请大白们莫要见笑。

END !

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android Studio 中使用 C 语言来收发短信,需要使用 Android NDK (Native Development Kit) 和 Android SMS Manager API。 以下是一个简单的示例代码,可以使用 C 语言来发送短信: ``` #include <jni.h> #include <android/log.h> #include <stdlib.h> #include <string.h> jstring Java_com_example_smsapp_MainActivity_sendSMS(JNIEnv* env, jobject obj, jstring phoneNumber, jstring message) { jclass smsManagerClass = (*env)->FindClass(env, "android/telephony/SmsManager"); jmethodID getDefaultMethod = (*env)->GetStaticMethodID(env, smsManagerClass, "getDefault", "()Landroid/telephony/SmsManager;"); jobject smsManager = (*env)->CallStaticObjectMethod(env, smsManagerClass, getDefaultMethod); const char* phoneNumberCStr = (*env)->GetStringUTFChars(env, phoneNumber, NULL); jstring destinationAddress = (*env)->NewStringUTF(env, phoneNumberCStr); const char* messageCStr = (*env)->GetStringUTFChars(env, message, NULL); jstring text = (*env)->NewStringUTF(env, messageCStr); jmethodID sendTextMessageMethod = (*env)->GetMethodID(env, smsManagerClass, "sendTextMessage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)V"); (*env)->CallVoidMethod(env, smsManager, sendTextMessageMethod, destinationAddress, NULL, text, NULL, NULL); (*env)->ReleaseStringUTFChars(env, phoneNumber, phoneNumberCStr); (*env)->ReleaseStringUTFChars(env, message, messageCStr); return (*env)->NewStringUTF(env, "SMS sent successfully!"); } ``` 在此示例代码中,`sendSMS` 函数是一个 JNI (Java Native Interface) 函数,可以从 Java 代码中调用。在此函数中,我们首先获取 `SmsManager` 的实例,然后将目标电话号码和消息转换为 C 字符串并创建相应的 Java 字符串对象。最后,我们调用 `sendTextMessage` 方法来发送短信。 在 Android Studio 中使用 NDK 编译此代码时,需要编写一个 CMake 或 ndk-build 脚本来指定编译器、链接库等设置。可以参考 Android NDK 文档来了解更多信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值