Android NDK开发之入门示例 用C++ 写一个能四则运算的计算器

简介: 这回用Android的NDK技术写一个计算器练练手,啥是Android的NDK开发?看看Google的介绍--传送门为啥要用NDK开发呢,NDK是用C++ 写的,运行效率特别高,在一些需要复杂计算的地方(例如游戏开发),还有就是Java代码反编译比较简单,很容易被反编译暴露源码,C++的反编译难度较大,涉及到加密的代码可以用C++来写。

这回用Android的NDK技术写一个计算器练练手,啥是Android的NDK开发?看看Google的介绍--传送门

为啥要用NDK开发呢,NDK是用C++ 写的,运行效率特别高,在一些需要复杂计算的地方(例如游戏开发),还有就是Java代码反编译比较简单,很容易被反编译暴露源码,C++的反编译难度较大,涉及到加密的代码可以用C++来写。当然用NDK开发也有缺点,C++代码上手比Java难,而且用C++后调试难度增加,所以是否要引入C++要权衡之后再决定。
我在暑假用C++写了一个能四则运算的小程序,现在想在Android端也写一个支持四则运算的计算器,要是再用Java重写一遍就太麻烦了,正好可以用这个练一练Android的NDK开发。
工欲善其事必先利其器,还么有配置好NDK开发环境的可以看我上一篇文章--传送门;
环境配好了,话不多说,开始撸代码吧。新建一个项目,

img_e2ba4fd07e03f05c57baaa9590e7ae73.png
新建项目.png

一定要把 Include C++ support 选中,然后 next,然后到选中Android版本,选择Activity的地方,都默认即可,一路 next
img_32424177bfc722f4b908a49c40a9be6f.png

到这还是默认就行,然后 finish,等项目创建成功后会看到熟悉的界面
img_39e4fc7e903298983791976f756c8fd4.png

和我们普通项目有点区别的地方是在 ActivityonCreate方法中会多出一段代码和一个方法

static {
        System.loadLibrary("native-lib");
    }
public native String stringFromJNI();

这段代码是用来加载C++生成的动态库,方法是一个本地方法,我理解为调用C++函数的方法。
先介绍到这,然后开始计算器界面的编写,这和普通的界面编写没有区别,就不多说了,上一个效果图吧

img_db617cd0831bcb0e6c8aed1163dfbea9.png
效果图

接下来就是Activity中的各种逻辑的编写,点击事件的处理,代码有点多,先不贴了,最后我会分享。
注意了,到这重点来了,要新建C++代码的源文件和头文件。在CPP文件夹上右键 New-> C++class,填写文件名-> OK
你会发现在CPP目录下没有刚才新建的文件,我靠,AS出BUG了吧。不要急,在导航栏的最下边找到CMakeLists.text,点开,在图上标注的地方添加代码
img_39bc9ede2d294f396762ccc5add9ddb7.png
CMakeLists.txt

src/main/cpp/native-lib.cpp 下面添加 src/main/cpp/×××××.cpp
××××是你的C++源文件的名。点击右上角的 Sync Now,等待同步完成。
这时你会发现CPP目录下有多了两个文件
img_2459806d8bd8b1ffb5efb00b85eb18a2.png
CPP

这时回到 MainActivity 中,把 public native String stringFromJNI();方法修改一下。改成这样 public native double stringFromC(String s);。为啥要改成这样呢,因为我们要做一个计算器,所有的按键逻辑和显示工作由Java代码完成,而计算工作由C++ 代码去做,Java层要传递一个字符串给C++层,然后C++层把计算结果返回给Java层,Java层来显示计算结果。所以要加一个 String类型的形参,把返回值改成double。这时会报错,然后按 Alt+回车 键AS会自动修改。现在来到 native-lib.cpp文件,把刚开始AS生产的函数删掉,只保留这一个函数

JNIEXPORT jdouble JNICALL
Java_com_bruce_counter_MainActivity_stringFromC(JNIEnv *env, jobject instance, jstring s_) {
    const char *s = env->GetStringUTFChars(s_, 0);

    // TODO

 //   env->ReleaseStringUTFChars(s_, s);
}

NIEXPORT jdouble JNICALL 是在 jni.h中定义的返回值类型,不清楚jni类型的可以看一下
如果有env->ReleaseStringUTFChars(s_, s);代码,把他删掉,用不到。
完成的native-lib.cpp代码

#include <jni.h>
#include <string>
#include "Counter.h"
using std::string;
extern "C"
JNIEXPORT jdouble JNICALL
Java_com_bruce_counter_MainActivity_stringFromC(JNIEnv *env, jobject instance, jstring s_) {
    const char *s = env->GetStringUTFChars(s_, 0);

    // TODO
//    env->ReleaseStringUTFChars(s_, s);
    string str=s;
    delete s;
    Counter *c=new Counter();
    double d=c->coutn(str);
    delete c;
    return d;
}

指针 ‘s’ 指向的就是我们从Java层传过来的字符串,我们把他保存下来,然后delete s,听说不delete会内存泄露,还没求证,就先这样写吧。Counter类是负责计算的,调用Counter的countn函数,就能得到结果。
为啥要在native-lib.cpp中调用这些方法呢?我的理解native-lib相当于main函数,Java调用C++会先调用这个。好了,整个C++层代码基本完成了。
到Java中去调用吧。

displayStr=displayStr.replace("×","*").replace("÷","/");
screen.setText(stringFromC(displayStr)+"");//计算结束更新屏幕

先说一个遇到的坑,在Java中乘号用的'×',除号用的'÷',Java用的unicode编码,没有问题,但是C++默认用的是ASCII编码,不能使用’ב’÷‘,我们使用‘*’和‘/’代替,所以在传入字符串时要替换一下displayStr=displayStr.replace("×","*").replace("÷","/");
到这基本就好了,可以运行一下看看了。
发现写博客比写代码累多了,就先写到这吧,我已经把完整的demo上传到码云,需要的同学可以去下载。如果还有什么问题就贴在在评论区吧,一起学习。

目录
相关文章
|
21天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
12 0
|
1月前
|
存储 C++
【C++初阶】第三站:类和对象(中) -- 日期计算器
【C++初阶】第三站:类和对象(中) -- 日期计算器
|
1月前
|
XML 缓存 Android开发
Android开发,使用kotlin学习多媒体功能(详细)
Android开发,使用kotlin学习多媒体功能(详细)
96 0
|
1月前
|
设计模式 人工智能 开发工具
安卓应用开发:构建未来移动体验
【2月更文挑战第17天】 随着智能手机的普及和移动互联网技术的不断进步,安卓应用开发已成为一个热门领域。本文将深入探讨安卓平台的应用开发流程、关键技术以及未来发展趋势。通过分析安卓系统的架构、开发工具和框架,本文旨在为开发者提供全面的技术指导,帮助他们构建高效、创新的移动应用,以满足不断变化的市场需求。
18 1
|
1月前
|
机器学习/深度学习 调度 Android开发
安卓应用开发:打造高效通知管理系统
【2月更文挑战第14天】 在移动操作系统中,通知管理是影响用户体验的关键因素之一。本文将探讨如何在安卓平台上构建一个高效的通知管理系统,包括服务、频道和通知的优化策略。我们将讨论最新的安卓开发工具和技术,以及如何通过这些工具提高通知的可见性和用户互动性,同时确保不会对用户造成干扰。
33 1
|
12天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
14天前
|
Java Android开发
Android开发之使用OpenGL实现翻书动画
本文讲述了如何使用OpenGL实现更平滑、逼真的电子书翻页动画,以解决传统贝塞尔曲线方法存在的卡顿和阴影问题。作者分享了一个改造后的外国代码示例,提供了从前往后和从后往前的翻页效果动图。文章附带了`GlTurnActivity`的Java代码片段,展示如何加载和显示书籍图片。完整工程代码可在作者的GitHub找到:https://github.com/aqi00/note/tree/master/ExmOpenGL。
19 1
Android开发之使用OpenGL实现翻书动画
|
14天前
|
Android开发 开发者
Android开发之OpenGL的画笔工具GL10
这篇文章简述了OpenGL通过GL10进行三维图形绘制,强调颜色取值范围为0.0到1.0,背景和画笔颜色设置方法;介绍了三维坐标系及与之相关的旋转、平移和缩放操作;最后探讨了坐标矩阵变换,包括设置绘图区域、调整镜头参数和改变观测方位。示例代码展示了如何使用这些方法创建简单的三维立方体。
12 1
Android开发之OpenGL的画笔工具GL10
|
21天前
|
Android开发
Android开发小技巧:怎样在 textview 前面加上一个小图标。
Android开发小技巧:怎样在 textview 前面加上一个小图标。
10 0
|
21天前
|
Android开发
Android 开发 pickerview 自定义选择器
Android 开发 pickerview 自定义选择器
12 0

热门文章

最新文章