2019独角兽企业重金招聘Python工程师标准>>>
开发工具: Eclipse
开发语言: Java和c++
Pcduino跑Android系统让我兴奋了很长时间,也由此幻想了很多有趣的应用。例如 结合Yeelink做远程加电控制;结合微信开放接口与传感器向好友推送信息等等。 当然这些有趣的应用都离不开PCDUINO硬件的操作。那么在Android系统下怎么来操作硬件呢?我想大概有以下几种方式:
1、利用Arduino 库自己写c++程序然后编译成可执行文件,然后把可执行文件拷到PCDUINO中,添加权限,在模拟中端里运行可执行文件。
优点:Arduino库函数完善,非常容易操作。
缺点:貌似和Android开发的应用不能完美的结合。
2、利用Android 的Jni编程,直接驱动GPIO。
优点:开发工具简单,利用Eclipse进行交叉编译,同时编译Java和c++代码。并且把硬件操作函数生成.so文件直接打包APK中。
下面我们利用ANDROID NDK来开发一个简单实例: "光电开关控制UI上的灯泡亮灭"
第一步:开发环境的搭建
1、安装Eclipse
2、安装ADT-v20插件(该版本已经直接支持Native编程)
3、安装CDT(编译c++代码)
3、安装android-ndk-r8e(该版本支持Windows,不用在Cygwin下编译了)
按照这种模式搭建的开发环境用起来非常上手,java和c++程序直接交叉编译,然后打包生成APK.
第二步:实例演练
1、新建Android 工程HelloJni,编写Java代码如下(定义本地函数)
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTitle(getHelloJniData());
}
//c++中要实现的函数接口
public native String getHelloJniData(); //从本地函数获得字符串
public native void OpenLed(); //打开LED灯,本例子对应GPIO3
public native void CloseLed(); //关闭LED灯
public native int ReadGpioState(int i); //读取某个GPIO的状态,然后返回给Java层
//库载入代码
static
{
System.loadLibrary("Hellojni"); //Hellojni本地SO库
}
}
2、实现本地c++代码
(此处注意可以利用 javah 生成头文件,也可以自己按照Jni规则写)
#define GPIO_MODE_DIR "/sys/devices/virtual/misc/gpio/mode/"
#define GPIO_PIN_DIR "/sys/devices/virtual/misc/gpio/pin/"
#define GPIO_IF_PREFIX "gpio"
JNIEXPORT jstring JNICALL Java_com_hellojni_MainActivity_getHelloJniData (JNIEnv * env, jobject obj )
{
return (*env)->NewStringUTF(env, "hello jni");
}
JNIEXPORT void JNICALL Java_com_hellojni_MainActivity_OpenLed (JNIEnv * env, jobject obj) //打开LED
{
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,"OPEN- LED");
memset(path, 0, sizeof(path));
sprintf(path, "%s%s%d", GPIO_MODE_DIR, GPIO_IF_PREFIX, 3); //此处对应地址/sys/devices/virtual/misc/gpio/mode/gpio3 设置为输出
fd = open(path, O_RDWR);
write(fd,"1",1);
close(fd);
memset(path, 0, sizeof(path));
sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, 3); //此处对应地址/sys/devices/virtual/misc/gpio/pin/gpio3 设置为高定平
fd = open(path, O_RDWR);
write(fd,"1",1);
close(fd);
}
JNIEXPORT void JNICALL Java_com_hellojni_MainActivity_CloseLed(JNIEnv * env, jobject obj) //关闭LED
{
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,"CLOSE LED");
memset(path, 0, sizeof(path));
sprintf(path, "%s%s%d", GPIO_MODE_DIR, GPIO_IF_PREFIX, 3);
fd = open(path, O_RDWR);
write(fd,"1",1);
close(fd);
memset(path, 0, sizeof(path));
sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, 3);
fd = open(path, O_RDWR);
write(fd,"0",1);
close(fd);
}
JNIEXPORT jint JNICALL Java_com_hellojni_MainActivity_ReadGpioState (JNIEnv *env, jobject obj,jint i) //读取某个IO口的状态
{
char buf[4];
int ret = -1;
int fd = -1;
int state;
memset((void *)buf, 0, sizeof(buf));
memset(path, 0, sizeof(path));
sprintf(path, "%s%s%d", GPIO_PIN_DIR, GPIO_IF_PREFIX, i);
fd = open(path, O_RDWR);
ret = read(fd, buf, sizeof(buf));
ret = buf[0] - '0';
switch( ret )
{
case 0:
state=0;
// __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"LOW"); 返回LOG调试信息
break;
case 1:
state=1;
// __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"HIGHT");
break;
default:
state=-1;
ret = -1;
break;
}
close(fd);
// __android_log_print(ANDROID_LOG_INFO,LOG_TAG,"READ GPIO STATE");
return state;
}
3、到这里关键代码就都准备好了,可以直接在Java层调用这些接口函数操作IO了。下面最后再配置一下Eclipse交叉编译环境。
右击HelloJni的工程属性,弹出 窗口,选Builders --->New---NDK_Builder。
到此开发环境搭建完毕!具体的细节哪里有问题,可以问度娘哦!!!
工程文件见附件!!!
感谢Lucifer㊣(1094294)大神的指导!!!
hellojni.rar (985.58 KB, 下载次数: 22)