/>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button"/>
``` MainActivity.java ``` public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textview = findViewById(R.id.textview);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textview.setText(JNIUtils.sayHelloFromJNI());
}
});
}
}
上面代码中的JNIUtils.sayHelloFromeJNI()就是我们在与MainActivity相同的包中新建JNIUtils类后在里面编写的native方法。如下所示:
可以看到我们上面的sayHelloFromJNI()方法显示的是警告红色。把鼠标放到上面,它会提示我们对应的JNI头文件没有查找到。那么接下来我们要做的就是去生成与这个sayHelloFromJNI()方法所对应的头文件。
4.生成头文件。快捷键alt + F12调出AS下的Terminal窗口,在Terminal命令行窗口中输入如下几条指令,回车:
前面两个cd命令没什么好说的,就是先进入当前项目的app目录下,然后再进入Java目录下。我们重点说一下最后一条命令:javah -d ../jni com.example.zhangxudong.jindemo.JNIUtils。首先,要生成Java类对应的头文件我们就必须要用到javah这个命令,其次-d表示生成一个目录,那生成一个什么样的目录,具体又在哪里去生成这个目录呢?后面的../jni告示了我们。../表示在当前目录的上一层目录,我们当前在Java目录下,那么它的上层目录就是main目录了。而jni就表示我们生成的目录的名称。所以整个../jni就表示在main目录下生成一个名为jni的目录。最后一个com.example.zhangxudong.jindemo.JNIUtils就是我们在上面新建的JNIUtils的完整类名了。执行完这几天指令后,刷新一下目录我们就可以在main目录下看到jni这个目录,并且在它里面生成了我们JNIUtils类所对应的头文件。进入头文件中,代码是如下这个样子:
/* DO NOT EDIT THIS FILE - it is machine generated /
#include <jni.h>
/ Header for class com_example_zhangxudong_jnidemo_JNIUtils */
#ifndef _Included_com_example_zhangxudong_jnidemo_JNIUtils
#define _Included_com_example_zhangxudong_jnidemo_JNIUtils
#ifdef __cplusplus
extern “C” {
#endif
/*
- Class: com_example_zhangxudong_jnidemo_JNIUtils
- Method: sayHelloFromJNI
- Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_zhangxudong_jnidemo_JNIUtils_sayHelloFromJNI
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
5.头文件生成以后,我们就需要编写我们的C/C++代码了。右键jni目录---->new--->C/C++ Source File
输入要新建的C/C++文件名称JNIHello,这里我们用C++来编写,所以Type为.cpp,如果你选择用C来编写,那么Type选为.c,点击ok。这里说一下,在我们进行NDK开发的时候,选择用C还是C++,在编写代码的时候除了C和C++基本的语法不同外,还是有许多不同地方需要注意。我们后续会慢慢介绍。这里先默认跟着我的步骤来。
JNIHello.cpp代码如下:
#include "com_example_zhangxudong_jnidemo_JNIUtils.h"
JNIEXPORT jstring JNICALL Java_com_example_zhangxudong_jnidemo_JNIUtils_sayHelloFromJNI
(JNIEnv *env, jclass jclass){
return env->NewStringUTF("Hello World From JNI!!!!!");
}
可以看到我们首先需要把原来生成的JNIUtlis对应的头文件引入进来,下面的代码基本都是从com_example_zhangxudong_jnidemo_JNIUtils.h中复制粘贴过来的一部分,然后稍加修改。修改的地方主要有sayHelloFromJNI的两个参数和里面的简单实现,参数方面就是加了env和jclass两个字段。函数里面的实现呢,就是简单的返回一个字符串“Hello World From JNI!!!!!”,至于为什么这么写,我会在下一篇文章进行讲解,大家现在就需要知道如果要在这里返回一个字符串就必须要通过env->NewStringUTF("xxxxxx");这行代码。
6.上面的搞定以后,我们需要在app的build.gradle中的defaultConfig中加入如下代码。它表示项目在编译时生成的动态库的名字。
最后,我们还需在JNIUitls中加载我们生成的动态库:
public class JNIUtils {
static {
System.loadLibrary(“JNIHello”);
}
public static native String sayHelloFromJNI();
}
我们把加载动态库的代码放到静态代码块中,就是表示在JNIUtils这个类在加载的时候就去加载我们的动态库。
7.经过上面的5步,关于如何在AS中进行简单的NDK所需要的步骤差不多就讲完了。不过还有最后一点需要注意。到这里我们基本就可以执行一下我们的项目了,现在运行一下项目试一试......不出意外的话项目是build不成功的,它会报如下的错误:
Error:Execution failed for task ‘:app:compileDebugNdk’.
Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio. Please switch to a supported build system.
Consider using CMake or ndk-build integration. For more information, go to:
https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile
学习福利
【Android 详细知识点思维脑图(技能树)】
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
CodeChina开源项目:《Android学习PDF+架构视频+面试文档+源码笔记》
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2/android_p7)**
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。