最近项目中要用到一些同屏操作,起初的方案是不断记录坐标,上传坐标,来达到画笔的同屏。但实际演示的时候效果并不好,于是我在想可不可以像视频录制一样直接调用底层,体验永远是程序质量的第一标准,不能因为自己的能力限制所妥协。但问题接踵而至,因为jvm的跨平台的特性,注定导致java跟底层几乎没什么联系。但是java能调用c方法,通过JNI的方式。在android程序中要想调用c方法,就要用到NDK,平常JNI和NDK说的很溜,其实我也不知道JNI与NDK的区别:
1.JNI与NDK的定义:
JNI:
Java Native Interface(Java 本地接口)
方便Java调用C,C++等本地代码所封装的一层接口
NDK:
Android 提供的一个工具集合(native develop kits),这套工具集允许你为android使用c或c++代码,并提供众多的平台库让你管理原生的activity和物理设备组件
通过NDK可以在android中更加方便的通过JNI来访问本地代码
交叉编译的工具链:在一个平台下,编译出来在另一个平台下可以执行的代码
.c 与 .java
1.编译:把源代码编译成一个低级语言,
2.链接:根据具体平台的特性,链接成一个二进制可执行的程序
工作环境()
应该是一个android程序员想要调用c方法,他要写成native方法,然后把nativie方法弄成头文件,
c程序员根据头文件里的方法,对其中的方法做实现,然后给android程序员再弄成so文件,弄成文件就简单了,开发过百度地图的都知道,建立jniLibs,将so文件放入,调用方法,实现功能。
运行环境:
as2.3.1
window64
ndk:android-ndk-r13b
NDK比较古老的使用方式:使用ndk-build命令
之前eclipse上使用ndk,或者ndk更早版本的时候,在官方的ndk目录里有ndk-build的文件,可惜只能在linux环境下运行,估计还要下cygwin模拟linux环境还要配置环境变量,而现在比较高的版本的ndk文件目录下有ndk-build.cmd文件,方便里我们可以直接在Android studo的Terminal控制台下直接编译成so库。
前言:
1.运行环境很重要,本人实验了一下午,发现低版本的ndk害死人,老是出Error:Execution failed for task ':app:compileDebugNdk'.这个错误,纠结代码半天,其实压根跟代码没啥关系
2.32位的系统androidstudio用不了cmake
3.android_studio看不了.mk文件
操作流程:
1.配置NDK与环境变量
配置ndk的环境变量跟配置jdk的环境变量差不多,自行百度
2.建立项目声明native方法
package com.wyt.hcy.libjpegandroid;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("Hello");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv= (TextView) findViewById(R.id.tv);
tv.setText(helloFromC());
}
public native String helloFromC();
}
3.形成头文件
在studio terminal中输入指令,切换到项目的目录,并输入javah 包名.
MainActivity
刷新就会看到产生的头文件
点开这个头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_wyt_hcy_libjpegandroid_MainActivity */
#ifndef _Included_com_wyt_hcy_libjpegandroid_MainActivity
#define _Included_com_wyt_hcy_libjpegandroid_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_wyt_hcy_libjpegandroid_MainActivity
* Method: helloFromC
* Signature: ()Ljava/lang/String;
*/
/**
* 函数名的格式Java_包名_类名_方法
* JNIEnv:表示一个指向JNi环境的指针
* jobject:表示java中的this
* JNICALL,JNIEXPORT:表示JNi定义的宏
*/
JNIEXPORT jstring JNICALL Java_com_wyt_hcy_libjpegandroid_MainActivity_helloFromC
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
4.根据头文件实现方法
建立jni文件夹,选择main目录右键,new/folder/jnifolder
将头文件剪切到jni目录下
这里以c语言为例,在jni目录下建立Hello.c文件,要引入头文件
#include<stdio.h>
#include<jni.h>
#include "com_wyt_hcy_libjpegandroid_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_wyt_hcy_libjpegandroid_MainActivity_helloFromC(JNIEnv *env, jobject obj)
{
return (*(*env)).NewStringUTF(env, "HelloWorldFromC");
}
5.编成so库
A。在jni目录下建立Android.mk文件(此文件名称固定:交叉编译器在编译c或者c++语言所依赖的配置文件符合linux下makefile的语法ziji),文件名字固定(不知道为什么),as是能建立.mk文件的,但打不开。
这里我用subnlite text打开它,在android.mk里输入
LOCAL_PATH := ${call my-dir}
include ${CLEAR_VARS}
LOCAL_MODULE :=Hello
LOCAL_SRC_FILES :=Hello.c
include ${BUILD_SHARED_LIBRARY}
LOCAL_PATH := ${call my-dir} 获取当前Android.mk文件的路径
include ${CLEAR_VARS} 变量的初始化但不会初始化LOCAL_PATH
LOCAL_MODULE :=Hello libHello.so 表示模块名称,即:MainActivity静态代码块填写的
LOCAL_SRC_FILES : 表示参与编译的源文件
B。在项目的gradle.properties里配置:
android.useDeprecatedNdk=true
C。最后在module的build.grade里输入:(一定要在android里的 defaultConfig代码块里写: )
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.wyt.hcy.libjpegandroid"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "Hello"
// abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
}
在Terninal控制台里输入ndk-build成功就会返回
编译成功的话:在jni同级目录下会多了个libs目录,还能看到libHello.so
然后clean,运行就会看到textview调用了c代码
运行中出错:Error:Execution failed for task ':app:compileDebugNdk'.
个人觉得不应该向其他人说的添加一个空的c文件就能解决的:
1.看看您
在项目的gradle.properties里配置:
2.看看项目的gradle里有没有设置ndk,或者当前项目的ndk版本是否跟你环境变量的版本一致
ndk-build clean 该命令可以删除编译的缓存
下面我们进行更深层次的探索
1.什么是cmake
一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果您只计划使用 ndk-build,则不需要此组件。
2.什么是LLDB
一种调试程序,Android Studio 使用它来调试原生代码。
//最近我一直想使用libjpeg-turbo这个开源库,但我一直没找到如何将这个开源库编译成android的版本的方法,一开始我看教程上说,只要把开源库里的c文件得名字都放进Android.mk文件里just like:
我展示too young,以为直接编译能成功结果问题太多
jinclude.h:23:10: fatal error: 'jconfig.h' file not found
jpeglib.h:69:9: error: unknown type name 'JSAMPLE'
结果我就傻眼了,百度这些问题,压根没找到有用的,由于自己c语言早已忘得一干二净
于是我今天又找了个项目:项目下载链接
只要将文件复制到项目的jni目录下:打开as 控制台输入:
ndk-build APP_ABI=armeabi-v7a,armeabi虽然有些警告,但直接编译成功了
转载请注明原文地址: https://ju.6miu.com/read-666134.html