您的位置:首页 > 移动开发 > Android开发

Android NDK——监听USB的连接与断开

2015-09-02 17:57 731 查看
Mainctivity:主界面,功能是把监听到的USB事件用Toast显示出来


package com.wind.usb;

import com.wind.usb.UsbManager.OnUsbListener;
import com.wind.usb.UsbManager.UsbEvent;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
private UsbManager usbManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
usbManager = new UsbManager(usbListener);
usbManager.startService();
}

private OnUsbListener usbListener = new OnUsbListener() {

@Override
public void onMessage(final String msg) {
runOnUiThread(new Runnable() {

@Override
public void run() {
showToast(msg);
}
});
}

@Override
public void onEven(UsbEvent even) {

}
};

private void showToast(String msg) {
Toast.makeText(this, msg, Toast
4000
.LENGTH_LONG).show();
}

@Override
protected void onDestroy() {
usbManager.stopService();
super.onDestroy();
}
}


UsbManager:监听USB事件的Java类,通过native方法与C层交互,实现监听功能


package com.wind.usb;

public class UsbManager {
private boolean isEventThreadStart = false;
private OnUsbListener usbListener; //usb事件通知接口
private EventThread eventThread; //usb事件监听线程

public UsbManager(OnUsbListener listener) {
usbListener = listener;
}

/**
* 开始监听服务
*/
public synchronized void  startService() {
if(!isEventThreadStart) {
eventThread = new EventThread();
eventThread.start();
isEventThreadStart = true;
}
}

/**
* 结束监听服务
*/
public synchronized void stopService() {
eventThread.finish();
isEventThreadStart = false;
}

/**
* 本地方法,初始化监听
*/
private static native void nativeSetup();

/**
* 本地方法,监听下一个usb事件
* @param buffer
* @return
*/
private static native int nativeNext(byte[] buffer);

static {
System.loadLibrary("usb");
}

/**
* usb状态
*
* @author Administrator
*
*/
public enum UsbEvent {
CONNECT, DISCONNECT;
}

/**
* usb状态通知接口
*
* @author Administrator
*
*/
public interface OnUsbListener {
public void onEven(UsbEvent even);
public void onMessage(String msg);
}

/**
* usb监听线程
*
* @author Administrator
*
*/
private class EventThread extends Thread {
private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0";

private boolean runFlag = true;

@Override
public void run() {
int len;
byte[] buffer = new byte[1024];

nativeSetup();
while(runFlag) {
len = nativeNext(buffer);
if(len > 0) {
String msg = new String(buffer, 0, len);
if(msg.contains(USB_STATE_MATCH)) {
usbListener.onMessage(msg);
}
}
}
}

public void finish() {
runFlag = false;
}
}
}


usb.cpp:USB事件监听的核心逻辑所在,通过socket获取usb事件,返回给Java层


#include <jni.h>

#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <pthread.h>

#include <sys/socket.h>
#include <sys/un.h>
#include <sys/queue.h>
#include <linux/netlink.h>

LIST_HEAD(uevent_handler_head, uevent_handler) uevent_handler_list;
pthread_mutex_t uevent_handler_list_lock = PTHREAD_MUTEX_INITIALIZER;

struct uevent_handler {
void (*handler)(void *data, const char *msg, int msg_len);
void *handler_data;
LIST_ENTRY(uevent_handler) list;
};

static int fd = -1;

//uevent初始化
int uevent_init()
{
struct sockaddr_nl addr;
int sz = 64*1024;
int s;

memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 0xffffffff;

s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return 0;

setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));

if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return 0;
}

fd = s;
return (fd > 0);
}

//初始化
void setup(JNIEnv* evn, jclass cls)
{
if (!uevent_init()) {
jclass c = evn->FindClass("java/lang/RuntimeException");
evn->ThrowNew(c, "Unable to open socket for UEventObserver");
}
}

//获取下一次事件
int uevent_next_event(char* buffer, int buffer_length)
{
while (1) {
struct pollfd fds;
int nr;

fds.fd = fd;
fds.events = POLLIN;
fds.revents = 0;
nr = poll(&fds, 1, -1);

if(nr > 0 && fds.revents == POLLIN) {
int count = recv(fd, buffer, buffer_length, 0);
if (count > 0) {
struct uevent_handler *h;
pthread_mutex_lock(&uevent_handler_list_lock);
LIST_FOREACH(h, &uevent_handler_list, list)
h->handler(h->handler_data, buffer, buffer_length);
pthread_mutex_unlock(&uevent_handler_list_lock);

return count;
}
}
}

// won't get here
return 0;
}

//获取下一次事件并返回给java环境
jint next(JNIEnv* evn, jclass cls, jbyteArray jbuffer)
{
int buf_sz = evn->GetArrayLength(jbuffer);
char *buffer = (char*)evn->GetByteArrayElements(jbuffer, NULL);

int length = uevent_next_event(buffer, buf_sz - 1);

evn->ReleaseByteArrayElements(jbuffer, (jbyte*)buffer, 0);

return length;
}

static JNINativeMethod methods[] = {
{"nativeSetup", "()V", (void*)setup},
{"nativeNext", "([B)I", (void*)next},
};

static bool registerNativeMethods(JNIEnv* evn)
{
jclass cls = evn->FindClass("com/wind/usb/UsbManager");
if(cls == NULL) {
return false;
}

int number = sizeof(methods) / sizeof(methods[0]);
if(evn->RegisterNatives(cls, methods, number) < 0 ) {
return false;
}
return true;
}

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* evn = NULL;
if(vm->GetEnv((void**)&evn, JNI_VERSION_1_6)) {
return -1;
}

if(!registerNativeMethods(evn)) {
return -1;
}

return JNI_VERSION_1_6;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jni android