2.让Android应用程序访问C库
来源:互联网 发布:澳门mac专柜地址 编辑:程序博客网 时间:2024/06/06 09:59
1>. JNI接口
<1. HardControl.java
<1. 作用:声明native方法
<2. 第一步:声明native方法public static native int lcdCtrl(int which, int status);
public static native int ledOpen();
public static native void ledClose();<3. 第二步:加载C库
System.loadLibrary(“hardcontrol”);
<2. hardcontrol.c
<1. 作用:实现相对应的C函数
<2. 相关变量/* 定义一个本地JNI接口数组 */
<1. static const JNINativeMethod methods[] = {…}
/* 用于在被加载的第一时间: 1.获得运行环境 2.找到供应者 3.注册本地方法 */
<2. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
2>. JNI字段描述符
变量类型
<1. jintArray等, 相关博文
3>. 开始狗血的写代码
. 编译源码:
<1. java源码:直接使用Android Studio
<2. C源码:最终要得到.so库
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include/. 将.so文件放入工程
<1. 第一步:创建armeabi目录: 路径在\app\libs\下
<2. 第二步:修改build.gradle(module:app) 路径\app\src\build.gradle;
+ sourceSets {
main {
jniLibs.srcDirs = [‘libs’] //其实际作用是将libs设置为jni库文件的目录
}
}
[保证]:1.Android JNI层 HardControl.java : System.loadLibrary(“hardcontrol”); 库的名字一定要和HAL层的保持一致
2.Linux HAL层 hardcontrol.c : 编译出来的文件一定要保证,前缀为libxxx.so , 同时保证是放在创建好的armeabi目录中
同时里面的JNI_OnLoad() -> FindClass(env, “com/becauseican/hardlibrary/HardControl”); 在给出供应者目录的同时要保证附带了类的名字,区分大小写
同时JNINativeMethod methods[] 数组里面的注册函数,要保证与供应者所定义的函数名相同
4<. 错误汇总:
1.<运行报错:
dlopen failed: cannot locate symbol “__android_log_print” referenced by “libhardcontrol.so”…解决方法>:
在编译选项后: + /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so2.<运行报错:
No implementation found for int com.becauseican.hardlibrary.HardControl.ledOpen();解决方法>:
if ((*env)->RegisterNatives(env, cls, methods, (sizeof(methods) / sizeof(methods[0])) < 0))
语法问题!! : 请注意(sizeof(methods) / sizeof(methods[0])) < 0);
示例代码:
MainActivity.java – APP层
package com.becauseican.app_0001_leddemo;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.CheckBox;import android.widget.Toast;import java.util.concurrent.Future;import com.becauseican.hardlibrary.*;public class MainActivity extends Activity { private Button buttonLead = null; private boolean boolLead = false; private CheckBox checkBoxLed1 = null; private CheckBox checkBoxLed2 = null; private CheckBox checkBoxLed3 = null; private CheckBox checkBoxLed4 = null; /* 自己定义的类 */ class MyButtonListener implements View.OnClickListener { @Override public void onClick(View v) { boolLead = !boolLead; if (boolLead) { buttonLead.setText("Close All"); checkBoxLed1.setChecked(true); checkBoxLed2.setChecked(true); checkBoxLed3.setChecked(true); checkBoxLed4.setChecked(true); /* 全部点亮 */ for (int i = 0; i < 4; ++i) { HardControl.ledCtrl(i, 1); } }else { buttonLead.setText("Open All"); checkBoxLed1.setChecked(false); checkBoxLed2.setChecked(false); checkBoxLed3.setChecked(false); checkBoxLed4.setChecked(false); /* 全部熄灭 */ for (int i = 0; i < 4; ++i) { HardControl.ledCtrl(i, 0); } } } } public void onCheckboxClicked(View view) { // Is the view now checked? boolean checked = ((CheckBox) view).isChecked(); // Check which checkbox was clicked switch(view.getId()) { case R.id.CheckBoxLed4: if (checked) { Toast.makeText(getApplicationContext(), "CheckBoxLed4 on", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(3, 1); } // Put some meat on the sandwich else { Toast.makeText(getApplicationContext(), "CheckBoxLed4 off", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(3, 0); } // Remove the meat break; case R.id.CheckBoxLed3: if (checked) { Toast.makeText(getApplicationContext(), "CheckBoxLed3 on", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(2, 1); } // Cheese me else { Toast.makeText(getApplicationContext(), "CheckBoxLed3 off", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(2, 0); } // I'm lactose intolerant break; case R.id.CheckBoxLed2: if (checked) { Toast.makeText(getApplicationContext(), "CheckBoxLed2 on", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(1, 1); } // Put some meat on the sandwich else { Toast.makeText(getApplicationContext(), "CheckBoxLed2 off", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(1, 0); } // Remove the meat break; case R.id.CheckBoxLed1: if (checked) { Toast.makeText(getApplicationContext(), "CheckBoxLed1 on", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(0, 0); } // Put some meat on the sandwich else { Toast.makeText(getApplicationContext(), "CheckBoxLed1 off", Toast.LENGTH_SHORT).show(); HardControl.ledCtrl(0, 0); } // Remove the meat break; // TODO: Veggie sandwich } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); buttonLead = (Button) findViewById(R.id.ButtonLead); /* 实例化 HardControl 类对象*/ HardControl.ledOpen(); checkBoxLed1 = (CheckBox) findViewById(R.id.CheckBoxLed1); checkBoxLed2 = (CheckBox) findViewById(R.id.CheckBoxLed2); checkBoxLed3 = (CheckBox) findViewById(R.id.CheckBoxLed3); checkBoxLed4 = (CheckBox) findViewById(R.id.CheckBoxLed4);/* // 采用匿名类的方式 buttonLead.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ boolLead = !boolLead; if (boolLead) { buttonLead.setText("Close All"); }else { buttonLead.setText("Open All"); } } });*/ //使用自定义类的方式 buttonLead.setOnClickListener(new MyButtonListener()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); }}
HardControl.java – APP层
package com.becauseican.hardlibrary;public class HardControl { public static native int ledCtrl(int which, int status); public static native int ledOpen(); public static native void ledClose(); /* 静态构造块,所有的HardControl对象,只会执行一次 */ static { try { /* 加载C库 hardcontrol.so*/ System.loadLibrary("hardcontrol"); } catch (Exception e) { e.printStackTrace(); } }}
hardcontrol.c – JNI层
#include <jni.h> /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */#include <stdio.h>#include <stdlib.h>/* __android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledopen.. : fd"); */#include <android/log.h> /* liblog */#if 0typedef struct { char *name; /* Java里调用的函数名 */ char *signature; /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */ void *fnPtr; /* C语言实现的本地函数 */} JNINativeMethod;#endifjint ledOpen(JNIEnv *env, jobject cls){ //__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledopen.."); return 0;}void ledClose(JNIEnv *env, jobject cls) { __android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledClose.."); }jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status){ __android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledCtrl.. which = %d status = %d : ", which, status); return 0;}static const JNINativeMethod methods[] = { {"ledOpen", "()I", (void *)ledOpen}, /* ()I : 这个是JNI字段描述符 */ {"ledClose", "()V", (void *)ledClose}, {"ledCtrl", "(II)I", (void *)ledCtrl},};/* System.loadLibrary */JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; /* 1.获得运行环境 */ if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } /* 2.找到需要用到该文件的包:全路径 */ cls = (*env)->FindClass(env, "com/becauseican/hardlibrary/HardControl"); if (cls == NULL) { return JNI_ERR; } /* 3.注册native 方法 */ if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods) / sizeof(methods[0])) < 0) return JNI_ERR; /* 最终返回JNI接口版本 */ return JNI_VERSION_1_4;}
- 2.让Android应用程序访问C库
- 硬件访问服务2之让Android应用程序访问C库
- android应用程序jni访问C库
- Android应用程序资源访问
- Android 让应用程序窗口话
- Android应用程序请求root访问
- 授权android应用程序访问网络
- 让.Net 应用程序突破2G的内存访问限制
- 让.Net 应用程序突破2G的内存访问限制
- Linux下如何让普通应用程序通过socks5访问互联网.
- 如何让iOS应用程序访问到 dev下的设备
- Android应用程序访问linux驱动第四步:实现android应用程序
- 让Qt应用程序跑在Android上
- 让Qt应用程序跑在Android上
- 让Qt应用程序跑在Android上
- 让Qt应用程序跑在Android上
- 让Qt应用程序移植到Android上
- 让Qt应用程序跑在Android上
- IntelliJ IDEA的下载安装和破解
- java8 stream
- FFmpeg 视频解码,窗口显示
- 干货 | 彻底理解ANDROID BINDER通信架构(上)
- L1-005. 考试座位号
- 2.让Android应用程序访问C库
- 机器学习视频第二课(从伯努利到sigmoid函数)
- 快排、堆排序
- am335x 看门狗驱动&看门狗应用例程序。
- softReference
- LeetCode
- Win32 SOCKET之UDP
- HDU 6053 TrickGCD
- 框架学习系列 mybatis 第三篇 mybatis入门程序之工程项目的搭建