開發工具: Eclipse
開發語言: Java和c++
Pcduino跑Android系統讓我興奮了很長時間,也由此幻想了不少有趣的應用。例如 結合Yeelink作遠程加電控制;結合微信開放接口與傳感器向好友推送信息等等。 固然這些有趣的應用都離不開PCDUINO硬件的操做。那麼在Android系統下怎麼來操做硬件呢?我想大概有如下幾種方式:
一、利用Arduino 庫本身寫c++程序而後編譯成可執行文件,而後把可執行文件拷到PCDUINO中,添加權限,在模擬中端裏運行可執行文件。
優勢:Arduino庫函數完善,很是容易操做。
缺點:貌似和Android開發的應用不能完美的結合。
二、利用Android 的Jni編程,直接驅動GPIO。
優勢:開發工具簡單,利用Eclipse進行交叉編譯,同時編譯Java和c++代碼。而且把硬件操做函數生成.so文件直接打包APK中。
下面咱們利用ANDROID NDK來開發一個簡單實例: "光電開關控制UI上的燈泡亮滅"
第一步:開發環境的搭建
一、安裝Eclipse
二、安裝ADT-v20插件(該版本已經直接支持Native編程)
三、安裝CDT(編譯c++代碼)
三、安裝android-ndk-r8e(該版本支持Windows,不用在Cygwin下編譯了)
按照這種模式搭建的開發環境用起來很是上手,java和c++程序直接交叉編譯,而後打包生成APK.
第二步:實例演練
一、新建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庫
}
}
二、實現本地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;
}
三、到這裏關鍵代碼就都準備好了,能夠直接在Java層調用這些接口函數操做IO了。下面最後再配置一下Eclipse交叉編譯環境。
右擊HelloJni的工程屬性,彈出 窗口,選Builders --->New---NDK_Builder。
php
到此開發環境搭建完畢!具體的細節哪裏有問題,能夠問度娘哦!!!java
工程文件見附件!!!android
感謝Lucifer㊣(1094294)大神的指導!!!c++
hellojni.rar (985.58 KB, 下載次數: 22)
web