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; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题