首页 > 代码库 > android4.2串口jni收发数据(基于自定义协议)

android4.2串口jni收发数据(基于自定义协议)

代码已经验证过,没问题 !

代码层次结构:

|-----serial_communication_class---

|                     |-------src---------

|                                  |------com------

|                                             |----object-----

|                                                      |------nvs------

|                                                                     |-----client------

|                                                                                   |---MainActivity.java

|                                                                                   |----SerialJNI.java

|                     |--------jni-----------------------------------------------------

|                                    |------- Android.mk

|                                    |--------object_nvs_client_SerialJNI.c

|                     |--------Android.mk

|                     |---------AndroidManifest.xml

现在贴代码:

-------------------------------------------SerialJNI.java---------------------------------------------------

package object.nvs.client;


public class SerialJNI{

     

    public native int OpenDev(String Dev);

    public native void set_speed(int fd, int speed);

    public native int set_Parity(int fd, int databits, int stopbits, int parity);

    public native int send_command(int fd, char[] sb, int len);

    public native void receive_data(int fd, int len);

    public native int close_dev(int fd);

         

    static{

        System.loadLibrary("serialjni");//与jni中的Android.mk中的jni模块名LOCAL_MODULE:= libserialjni相比少了lib

    }

  private byte[] bytes = new byte[12]; //Accessing Fields,用于装载JNI中的返回数据


private void callback() {//方法回调,JNI中一有数据此方法就被回调一次,所以对数据的所有操作建议都放于此

int i;

for(i=0;i<12;i++){

System.out.println(bytes[i]&0xff);

}

}

    private int fd;

     

    public SerialJNI(String Dev, int speed, int databits, int stopbits, int parity)

    {   

        fd = OpenDev(Dev);

        set_speed(fd, speed);

        if(set_Parity(fd, 8, 1, ‘N‘) == -1)

        {

            System.out.println("Set Parity Error");

            return;

        }

    }

     

    public int getSerialPort()

    {

        return fd;

    }

}

---------------------------------------------------end--------------------------------------------------

应用层调用:

---------------------------------------------MainActivity.java-------------------------------------------

package object.nvs.client;


import java.io.BufferedWriter;

import java.io.File;


import android.os.Bundle;

import android.app.Activity;


public class MainActivity extends Activity {

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

char stop[]={0xFF,0x0B,0x01,0x40,0x25,0x07,0x00,0x01,0x0b,0x00,0x84};

SerialJNI serialPort = new SerialJNI("/dev/ttyS7", 9600, 8, 1, ‘N‘);

int fd = serialPort.getSerialPort();

for(int i=0; i<10; i++){

int ret = serialPort.send_command(fd, stop, 11);//只做演示,并未实际意义

if(ret < 0)

    System.out.println("send command error!\n");

try {

        Thread.sleep(1000);

} catch (InterruptedException e) {

       e.printStackTrace();

}

}

// serialPort.callback();

// serialPort.receive_data(fd, 11);

    serialPort.close_dev(fd);

}

}

--------------------------------------------end--------------------------------------------------------

jni部分:

----------------------------------object_nvs_client_SerialJNI.c------------------------------

/*

 * Copyright (C) 2009 The Android Open Source Project

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

//wangjian1937@live.cn

//#include "object_nvs_client_SerialJNI.h"


#include   <stdarg.h>

#include   <stdio.h>     

#include   <stdlib.h>   

#include   <unistd.h>    

#include   <sys/types.h>

#include   <sys/stat.h>  

#include   <fcntl.h>    

#include   <termios.h>  

#include   <errno.h>    

#include   <string.h>

#include <jni.h>

#include <android/log.h>

#include <sys/file.h>


#define LOG    "serial-jni"

#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)  

#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__) 

#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__)  

#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__)  

#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__)

#define TRUE 1

#define FALSE -1

#define BUFSIZE 11

static int speed_arr[] = {B115200,B38400,B19200,B9600,B4800,B2400,B1200,B300,

    B38400,B19200,B9600,B4800,B2400,B1200,B300};

static int name_arr[] = {115200,38400,19200,9600,4800,2400,1200,300,

    38400,19200,9600,4800,2400,1200,300};

char resend[]={0xFF,0x0B,0x02,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0E}; 

char stop[]={0xFF,0x0B,0x02,0x02,0x0,0x0,0x0,0x0,0x0,0x0,0x0F};


/*

 * Class:     com_test_serial_MainActivity

 * Method:    open_dev

 * Signature: (Ljava/lang/String;)I

 */

 

JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_OpenDev

  (JNIEnv *env, jobject obj, jstring dev){

 const char *Dev_utf = (*env)->GetStringUTFChars(env, dev, JNI_FALSE);

    int fd = open(Dev_utf, O_RDWR|O_NOCTTY);

    (*env)->ReleaseStringUTFChars(env, dev, Dev_utf);

if (-1 == fd)

{ /*设置数据位数*/

LOGE("Can‘t Open Serial Port\n");

return -1;

}

LOGD("Open Serial Port:%s\n",(char *)Dev_utf);

return fd;

  }

 

/*

 * Class:     com_test_serial_MainActivity

 * Method:    close_dev

 * Signature: (I)I

 */


JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_close_1dev

  (JNIEnv *env, jobject obj, jint fd){

if(close(fd))

   {

       LOGE("close failed!\n");

       return (FALSE);

   }

   else

   {

       LOGD("close success!\n");

       return TRUE;

   }

}

 

/*

 * Class:     com_test_serial_SerialJNI

 * Method:    set_speed

 * Signature: (II)V

 */

JNIEXPORT void JNICALL Java_object_nvs_client_SerialJNI_set_1speed

  (JNIEnv *env, jobject obj, jint fd, jint speed)

 {

    int i;

    int status;

    struct termios Opt;

    for(i=0; i<sizeof(speed_arr)/sizeof(int); i++)

    {

        if(speed == name_arr[i])

        {

            tcflush(fd, TCIOFLUSH);

            cfsetispeed(&Opt, speed_arr[i]);

            cfsetospeed(&Opt, speed_arr[i]);

            status = tcsetattr(fd, TCSANOW, &Opt);

            if(status != 0)

                perror("tcsetattr fd1\n");

            return ;

        }

        tcflush(fd, TCIOFLUSH);

    }

}

/*

 * Class:     com_test_serial_MainActivity

 * Method:    set_Parity

 * Signature: (IIIC)I

 */

JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_set_1Parity

  (JNIEnv *env, jobject obj, jint fd, jint databits, jint stopbits, jint parity)

{

    struct termios opt;

    if(tcgetattr(fd, &opt) != 0)

    {

        LOGE("SetupSerial 1\n");

        return -1;

    }

    opt.c_cflag &= ~CSIZE;

    opt.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG);

    opt.c_oflag &= ~OPOST;


    switch(databits)

    {

        case 7: opt.c_cflag |= CS7; break;

        case 8: opt.c_cflag |= CS8; break;

        default: LOGE("Unsupported data size\n");

             return -1;

    }

    switch(parity)

    {

        case ‘n‘:

        case ‘N‘: opt.c_cflag &= ~PARENB;

              //opt.c_iflag &= ~INPCK;

              break;

        case ‘o‘:

        case ‘O‘: opt.c_cflag |= (PARODD|PARENB);

              opt.c_iflag |= INPCK;

              break;

        case ‘e‘:

        case ‘E‘: opt.c_cflag |= PARENB;

              opt.c_cflag &= ~PARODD;

              opt.c_iflag |= INPCK;

              break;

        case ‘s‘:

        case ‘S‘: opt.c_cflag &= ~PARENB;

              opt.c_cflag &= ~CSTOPB;

              break;

        default: LOGE("Unsupported parity\n");

             return -1;


    }

    switch(stopbits)

    {

        case 1: opt.c_cflag &= ~CSTOPB;

                           break;

        case 2: opt.c_cflag |= CSTOPB;

            break;

        default: LOGE("Unsupported stop bits\n");

             return -1;

    }


 //   if (parity != ‘n‘)  opt.c_iflag |= INPCK;

    tcflush(fd,TCIFLUSH);

    opt.c_cc[VTIME] = 150; /* 设置超时 15 seconds*/

    opt.c_cc[VMIN] = 0;

    tcflush(fd, TCIFLUSH);

    if (tcsetattr(fd,TCSANOW,&opt) != 0)

    {

        LOGE("SetupSerial 3\n");

        return -1;

    }

     return 0;

}

 

/*

 * Class:     com_test_serial_MainActivity

 * Method:    send_command

 * Signature: (ILjava/lang/String;)Ljava/lang/String;

 */


JNIEXPORT jint JNICALL Java_object_nvs_client_SerialJNI_send_1command

  (JNIEnv *env, jobject obj, jint fd, jcharArray buff, jint len){

  int i;

  char command[BUFSIZE+1] = {0}; 

  jchar *jc = (*env)->GetCharArrayElements(env, buff, NULL);

  for(i=0;i<BUFSIZE;i++){

  command[i] = (char)jc[i]&0xff;//java中char[]数组元素是char类型占2个字节和jni中的jchar相同,要转换成一个字节的char类型所以要去掉一个字节,方法就是将每个元素&oxff

  }

  if(flock(fd,LOCK_EX)==0){//读写文件锁保护,后面还有很多地方用到

  LOGD(" write lock!");

  }else LOGD(" write lock fail!");

  if(write(fd, command, len)>0)

    {

        LOGD("write success!\n");

    }

    else

    {

        LOGE("write failed!\n");

    }

  if(flock(fd,LOCK_UN)==0){//读写文件解锁

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

  (*env)->ReleaseCharArrayElements(env, buff, jc, 0);

  return 0;  

  }

 

/*

 * Class:     com_test_serial_MainActivity

 * Method:    receive_data

 * Signature: (II)Ljava/lang/String;

 */

JNIEXPORT void JNICALL Java_object_nvs_client_SerialJNI_receive_1data

  (JNIEnv *env, jobject obj, jint fd, jint len){

  jstring jstr;

  jfieldID fid;

  jbyteArray bytearray;

  const char *str;

int i,sum=0;

    int nread,nwrite;

    fd_set rfds;

    struct timeval tv;

    char buff[BUFSIZE+1];

    char buff1[BUFSIZE+1];

    char buff2[BUFSIZE+1];

    bzero(buff, BUFSIZE+1);

bzero(buff1, BUFSIZE+1);

bzero(buff2, BUFSIZE+1);


/*    

    struct termios oldtio, newtio;

tcgetattr(fd, &oldtio);

setTermios(&newtio, B38400);

    tcsetattr(fd, TCSANOW, &newtio);

    if (serial_set_parity(fd,8,1,‘N‘) == FALSE)

 {

   LOGE("Set Parity Error\n");

   serial_close(fd);

   return;

 }

*/  

    tcflush(fd, TCIFLUSH);

    tv.tv_sec=30;

    tv.tv_usec=0;

  

    bytearray = (*env)->NewByteArray(env,BUFSIZE+1);

    jclass cls1 = (*env)->GetObjectClass(env, obj);

    jclass cls2 = (*env)->GetObjectClass(env, obj);

    fid = (*env)->GetFieldID(env, cls1, "bytes", "[B");

    if (fid == NULL) 

    {

    LOGE("failed to find the field!");

    close(fd);

return; /* failed to find the field */

}

jmethodID mid = (*env)->GetMethodID(env, cls2, "callback", "()V");

if (mid == NULL) 

{

LOGE("method not found!");

close(fd);

return; /* method not found */

}

    while(TRUE)

    {

    sum = 0;

    usleep(1000);

   LOGD("wait wait...");

   FD_ZERO(&rfds);

   FD_SET(fd, &rfds);

   if(select(1+fd, &rfds, &rfds, NULL, &tv)>0)

   {

      if(FD_ISSET(fd, &rfds))

        {

        if(flock(fd,LOCK_EX)==0){

  LOGD("read lock!");

  }else LOGD("read lock fail!");

        nread=read(fd, buff, BUFSIZE);

        if(flock(fd,LOCK_UN)==0){

  LOGD(" read unlock!");

  }else LOGD("read unlock fail!");

           if(nread == BUFSIZE)

  {

  //LOGD("BUFSIZE:%d", BUFSIZE);      

             //printf("readlength=%d\n", nread);

             buff[nread]=‘\0‘;

             //printf("buff[1]=%c\n", buff[0]);


           if((buff[0] == 0xff) && (buff[1] == 0x0b))

           {

            for(i=1;i<=nread-2;i++)

           {

            sum += buff[i];

            //LOGD("buff[%d]=%0x, sum =%0x", i, buff[i], (char)sum);

           }

            //printf("(buff[0] == 0xff) && (buff[1] == 0x0b)\n");           

             if(buff[nread-1] == (char)sum)

           

            LOGD("Accept frame correct!");

            switch(buff[2])

            {

            case 0X01:

            if(memcpy(buff1, buff, nread) != NULL)

            {

            //LOGD("memcpy success!");

            buff[2]=0x03;

            buff[nread-1] = buff[nread-1]+0x02;

            if(flock(fd,LOCK_EX)==0){

  LOGD(" write lock!");

  }else LOGD(" write lock fail!");

            nwrite=write(fd, buff, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

LOGD("write_response_length=%d", nwrite);

if(memcpy(buff2, buff, nread) != NULL)

//LOGD("response buff memcpy to buff2 success!");

(*env)->SetByteArrayRegion(env, bytearray, 0, BUFSIZE+1, buff1);

(*env)->SetObjectField(env, obj, fid, bytearray);

(*env)->CallVoidMethod(env, obj, mid);

}

            }else

            {

            LOGE("memcpy fail!");

            if(flock(fd,LOCK_EX)==0){

  LOGD(" write lock!");

  }else LOGD(" write lock fail!"); 

            nwrite=write(fd, resend, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

if(memcpy(buff2, resend, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!");

//LOGD("write_resend_length=%d", nwrite);

}

            }            

            continue;

            case 0X02:

            switch(buff[3])

            {

            case 0x01:

            if(flock(fd,LOCK_EX)==0){

  LOGD(" write lock!");

  }else LOGD(" write lock fail!"); 

            nwrite=write(fd, buff2, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_buff2_length=%d", nwrite);

}            

            continue;

            case 0x02:

            continue;

            case 0x03:

            continue;

            case 0x04:

            continue;

            case 0x05:

            continue;

            case 0x06:

            continue;

            case 0x07:

            continue;

            default :

            continue;            

            }

            case 0X03:

            switch(buff[4])

            {

            case 0X01:

            continue;

            case 0X02:

            LOGE("receive fail!");

            if(flock(fd,LOCK_EX)==0){

  LOGD(" write lock!");

  }else LOGD(" write lock fail!");

            nwrite=write(fd, buff2, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_buff2_length=%d\n", nwrite);

}

            continue;

            case 0X03:

            continue;

            case 0X04:

            LOGE("receive fail!");

            if(flock(fd,LOCK_EX)==0){

  LOGD("write lock!");

  }else LOGD("write lock fail!");

            nwrite=write(fd, buff2, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

if(memmove(buff2, buff2, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!");

//LOGE("write_buff2_length=%d", nwrite);

}

            continue;

            default:

            continue;

            }

            default :            

            continue;

            }            

            }else

            {

            LOGE("buff[nread-1] != (char)sum,Accept frame wrong!");

            if(flock(fd,LOCK_EX)==0){

  LOGD(" write lock!");

  }else LOGD(" write lock fail!");

            nwrite=write(fd, resend, BUFSIZE);

            if(flock(fd,LOCK_UN)==0){

  LOGD(" write unlock!");

  }else LOGD("write unlock fail!");

            if(nwrite == BUFSIZE)

{

if(memcpy(buff2, resend, nread) == NULL)

LOGE("resend buff memcpy to buff2 failed!\n");

//LOGD("write_resend_length=%d", nwrite);

}

            }

            }else

            {

            //LOGD("buff[0] != 0xff || buff[1] != 0x0b");

            }

          }             

        }

    }

   tcflush(fd, TCIOFLUSH);

    }

//    tcsetattr(fd, TCSANOW, &oldtio);

    close(fd);

return;

  }

  ----------------------------------------------end----------------------------------------------------------

  顶层makefile:

---------------------------------------Android.mk---------------------------------------------

#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


# This makefile shows how to build a shared library and an activity that

# bundles the shared library and calls it using JNI.


TOP_LOCAL_PATH:= $(call my-dir)


# Build activity



LOCAL_PATH:= $(TOP_LOCAL_PATH)

include $(CLEAR_VARS)


LOCAL_MODULE_TAGS := optional


LOCAL_SRC_FILES := $(call all-subdir-java-files)


LOCAL_PACKAGE_NAME := Serial


LOCAL_JNI_SHARED_LIBRARIES := libSerialjni


LOCAL_PROGUARD_ENABLED := disabled


LOCAL_SDK_VERSION := current


include $(BUILD_PACKAGE)


# ============================================================


# Also build all of the sub-targets under this one: the shared library.

include $(call all-makefiles-under,$(LOCAL_PATH))

-------------------------------------------end--------------------------------------------------------------

jni下的MAKEFILE

-----------------------------------------Android.mk--------------------------------------------------------

#

# Copyright (C) 2008 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#      http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#


# This makefile supplies the rules for building a library of JNI code for

# use by our example of how to bundle a shared library with an APK.


LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)


LOCAL_MODULE_TAGS := optional


# This is the target being built.

LOCAL_MODULE:= libserialjni


LOCAL_LDLIBS :=-llog


# All of the source files that we will compile.

LOCAL_SRC_FILES:= \

    object_nvs_client_SerialJNI.c


# All of the shared libraries we link against.

LOCAL_SHARED_LIBRARIES := \

libutils\


# No static libraries.

LOCAL_STATIC_LIBRARIES := 


# Also need the JNI headers.

LOCAL_C_INCLUDES += \

$(JNI_H_INCLUDE)\


# No special compiler flags.

LOCAL_CFLAGS +=


include $(BUILD_SHARED_LIBRARY)

--------------------------------------------------------end-----------------------------------------------

AndroidManifest.xml

--------------------------------------------AndroidManifest.xml--------------------------------------

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="com.test.serial">

    <application android:label="serial">

        <activity android:name="object.nvs.client.MainActivity">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

</manifest> 

-------------------------------------------------------end-------------------------------------------