66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

最近项目中对usb进行使用的场景比较多,了解到libusb是比较出名的usb跨平台方案,学习libusb可以对android/linux底层的外设usb直接进行操作,理论上可以绕开android的弹窗授权限制.另外如果以后进行业务的移植会比较迅速.网上看了一些例子,有说修改源码的,增加方法然后android列出usb节点之后进行操作的.其实demo不需要那么复杂,这个库本来就能列出节点,也不需要usb授权之类的操作.另外使用android自带的可能还会导致没法搜索到usb节点,需要在/system/etc/permissions下添加android.hardware.usb.host.xml文件之后重启设备.

下载源码编译,方法一–ndk-build先编译libusb,然后导入so库和头文件使用

首先我们去官网的Downloads下载Latest Sources.解压之后进去android-jni目录.这个时候我们可以看到README文件,已经有编译方案了.1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31Building:

---------

To build libusb for Android do the following:

1. Download the latest NDK from:

http://developer.android.com/tools/sdk/ndk/index.html

2. Extract the NDK.

3. Open a shell and make sure there exist an NDK global variable

set to the directory where you extracted the NDK.

4. Change directory to libusb's "android/jni"

5. Run "$NDK/ndk-build".

The libusb library, examples and tests can then be found in:

"android/libs/$ARCH"

Where $ARCH is one of:

armeabi

armeabi-v7a

mips

mips64

x86

x86_64

Installing

-----------

.......

..........

因为我要直接在app里面使用,所以我只是进行编译,Installing部分我直接忽略.编译我们可以参考这篇文章android开发ndk调用第三方so库,下面我会把我的android.mk文件释放出来.

几个坑找不到”libusb.h”`

我由于没这样使用过,头文件一直提示找不到,如:fatal error: 'libusb.h' file not found #include "libusb.h" ,这个我们时候的时候需要在添加头文件的路径LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../libusb/libusb.这样就能搜索到头文件,不然没法使用.

libusb.so: incompatible target error: undefined reference to ‘libusb_init’

这个bug浪费了我很多时间,是由于我一开始拷贝的so文件仅仅是arm64-v8a类型的LOCAL_SRC_FILES := libusb.so,但是我编译的时候没留意到,所以一直报错,一直找不到libusb_init,我都怀疑是头文件导入不合理,google了很久,有一次突然发现arm64-v8a目录下的so文件生成了(也可能编译不出来,arm64-v8a是碰巧第一执行,如果armeabi-v7a先编译那么直接就中断编译了),在后来在stackoverflow上居然也找到了这个bug的解释.后来我把所有的lib包都添加到lib目录下,修改LOCAL_SRC_FILES := libs/arm64-v8a/libusb.so,Application.mk也修改APP_ABI := armeabi-v7a成对应的cup类型那个.每修改一次cpu类型就编译一次,应该也可以直接添加多个cpu类型的so,然后一次编译,不过我试过不行,后面可以继续尝试.

testlibusb的jni的目录结构1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38jni

├── Android.mk

├── Application.mk

├── libusb

│   ├── aclocal.m4

│   ├── android

│   ├── AUTHORS

│   ├── ChangeLog

│   ├── compile

│   ├── config.guess

│   ├── config.h.in

│   ├── config.sub

│   ├── configure

│   ├── configure.ac

│   ├── COPYING

│   ├── depcomp

│   ├── doc

│   ├── examples

│   ├── INSTALL

│   ├── install-sh

│   ├── libusb

│   ├── libusb-1.0.pc.in

│   ├── ltmain.sh

│   ├── m4

│   ├── Makefile.am

│   ├── Makefile.in

│   ├── missing

│   ├── msvc

│   ├── NEWS

│   ├── PORTING

│   ├── README

│   ├── tests

│   ├── TODO

│   └── Xcode

└── testlibusb

├── Android.mk

├── libs

└── testlibusb.cpp

/TestLibusb/app/src/main/jni/Application.mk文件内容1

2

3

4

5

6# APP_ABI := all

APP_ABI := armeabi-v7a

# Workaround for MIPS toolchain linker being unable to find liblog dependency

# of shared object in NDK versions at least up to r9.

#

APP_LDFLAGS := -llog

TestLibusb/app/src/main/jni/Android.mk 文件内容1

2

3

4LOCAL_PATH2:= $(call my-dir)

include $(CLEAR_VARS)

# include $(LOCAL_PATH2)/libusb/android/jni/Android.mk

include $(LOCAL_PATH2)/testlibusb/Android.mk

/TestLibusb/app/src/main/jni/testlibusb/Android.mk 文件内容1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

######################################################################

# Make shared library libUVCCamera.so

######################################################################

CFLAGS := -Werror

LOCAL_LDLIBS := -llog

##LOCAL_SHARED_LIBRARIES += libusb

#------test-------------

include $(CLEAR_VARS)

LOCAL_MODULE := myusb

#LOCAL_SRC_FILES := libs/arm64-v8a/libusb.so

LOCAL_SRC_FILES := libs/armeabi-v7a/libusb.so

#LOCAL_SRC_FILES := libs/x86/libusb.so

# LOCAL_SRC_FILES := libs/x86_64/libusb.so

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../libusb/libusb

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

#-------end----------------

LOCAL_SHARED_LIBRARIES += myusb

LOCAL_SRC_FILES :=

./testlibusb.cpp

LOCAL_MODULE := testlibusb

include $(BUILD_SHARED_LIBRARY)

编译过程1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19➜ jni ndk-build

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.

Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in /home/steve/work/android/AndroidStudioProjects/TestLibusb/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.

[armeabi-v7a] Compile++ thumb: testlibusb <= testlibusb.cpp

[armeabi-v7a] Compile thumb : usb <= core.c

[armeabi-v7a] Compile thumb : usb <= descriptor.c

[armeabi-v7a] Compile thumb : usb <= hotplug.c

[armeabi-v7a] Compile thumb : usb <= io.c

[armeabi-v7a] Compile thumb : usb <= sync.c

[armeabi-v7a] Compile thumb : usb <= strerror.c

[armeabi-v7a] Compile thumb : usb <= linux_usbfs.c

[armeabi-v7a] Compile thumb : usb <= poll_posix.c

[armeabi-v7a] Compile thumb : usb <= threads_posix.c

[armeabi-v7a] Compile thumb : usb <= linux_netlink.c

[armeabi-v7a] SharedLibrary : libusb.so

[armeabi-v7a] StaticLibrary : libstdc++.a

[armeabi-v7a] SharedLibrary : libtestlibusb.so

[armeabi-v7a] Install : libtestlibusb.so => libs/armeabi-v7a/libtestlibusb.so

[armeabi-v7a] Install : libusb.so => libs/armeabi-v7a/libusb.so

下载源码编译,方法二–ndk-build编译adnrod.mk文件直接使用

其实我一开始不是按照方法一使用的,是先参考的UVCCamera的使用方式,也是爬了一些坑,把mk文件贴出来先.

/TestLibusb/app/src/main/jni/Application.mk文件内容1

2

3

4

5APP_ABI := all

# Workaround for MIPS toolchain linker being unable to find liblog dependency

# of shared object in NDK versions at least up to r9.

#

APP_LDFLAGS := -llog

TestLibusb/app/src/main/jni/Android.mk 文件内容1

2

3

4LOCAL_PATH2:= $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH2)/libusb/android/jni/Android.mk

include $(LOCAL_PATH2)/testlibusb/Android.mk

/TestLibusb/app/src/main/jni/testlibusb/Android.mk 文件内容1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

######################################################################

# Make shared library libUVCCamera.so

######################################################################

CFLAGS := -Werror

LOCAL_LDLIBS := -llog

LOCAL_SHARED_LIBRARIES += libusb

LOCAL_SRC_FILES :=

./testlibusb.cpp

LOCAL_MODULE := testlibusb

include $(BUILD_SHARED_LIBRARY)

编译过程

这个方案不需要进行so的导入,很方便,各个cpu也直接能编译出来了.这也是我方案一在多个so同时导入编译不成功之后不继续的原因,因为有更好的方案了1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67➜ jni ndk-build

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.

Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in /home/steve/work/android/AndroidStudioProjects/TestLibusb/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.

[arm64-v8a] Compile++ : testlibusb <= testlibusb.cpp

[arm64-v8a] Compile : usb <= core.c

[arm64-v8a] Compile : usb <= descriptor.c

[arm64-v8a] Compile : usb <= hotplug.c

[arm64-v8a] Compile : usb <= io.c

[arm64-v8a] Compile : usb <= sync.c

[arm64-v8a] Compile : usb <= strerror.c

[arm64-v8a] Compile : usb <= linux_usbfs.c

[arm64-v8a] Compile : usb <= poll_posix.c

[arm64-v8a] Compile : usb <= threads_posix.c

[arm64-v8a] Compile : usb <= linux_netlink.c

[arm64-v8a] SharedLibrary : libusb.so

[arm64-v8a] StaticLibrary : libstdc++.a

[arm64-v8a] SharedLibrary : libtestlibusb.so

[arm64-v8a] Install : libtestlibusb.so => libs/arm64-v8a/libtestlibusb.so

[arm64-v8a] Install : libusb.so => libs/arm64-v8a/libusb.so

[x86_64] Compile++ : testlibusb <= testlibusb.cpp

[x86_64] Compile : usb <= core.c

[x86_64] Compile : usb <= descriptor.c

[x86_64] Compile : usb <= hotplug.c

[x86_64] Compile : usb <= io.c

[x86_64] Compile : usb <= sync.c

[x86_64] Compile : usb <= strerror.c

[x86_64] Compile : usb <= linux_usbfs.c

[x86_64] Compile : usb <= poll_posix.c

[x86_64] Compile : usb <= threads_posix.c

[x86_64] Compile : usb <= linux_netlink.c

[x86_64] SharedLibrary : libusb.so

[x86_64] StaticLibrary : libstdc++.a

[x86_64] SharedLibrary : libtestlibusb.so

[x86_64] Install : libtestlibusb.so => libs/x86_64/libtestlibusb.so

[x86_64] Install : libusb.so => libs/x86_64/libusb.so

[armeabi-v7a] Compile++ thumb: testlibusb <= testlibusb.cpp

[armeabi-v7a] Compile thumb : usb <= core.c

[armeabi-v7a] Compile thumb : usb <= descriptor.c

[armeabi-v7a] Compile thumb : usb <= hotplug.c

[armeabi-v7a] Compile thumb : usb <= io.c

[armeabi-v7a] Compile thumb : usb <= sync.c

[armeabi-v7a] Compile thumb : usb <= strerror.c

[armeabi-v7a] Compile thumb : usb <= linux_usbfs.c

[armeabi-v7a] Compile thumb : usb <= poll_posix.c

[armeabi-v7a] Compile thumb : usb <= threads_posix.c

[armeabi-v7a] Compile thumb : usb <= linux_netlink.c

[armeabi-v7a] SharedLibrary : libusb.so

[armeabi-v7a] StaticLibrary : libstdc++.a

[armeabi-v7a] SharedLibrary : libtestlibusb.so

[armeabi-v7a] Install : libtestlibusb.so => libs/armeabi-v7a/libtestlibusb.so

[armeabi-v7a] Install : libusb.so => libs/armeabi-v7a/libusb.so

[x86] Compile++ : testlibusb <= testlibusb.cpp

[x86] Compile : usb <= core.c

[x86] Compile : usb <= descriptor.c

[x86] Compile : usb <= hotplug.c

[x86] Compile : usb <= io.c

[x86] Compile : usb <= sync.c

[x86] Compile : usb <= strerror.c

[x86] Compile : usb <= linux_usbfs.c

[x86] Compile : usb <= poll_posix.c

[x86] Compile : usb <= threads_posix.c

[x86] Compile : usb <= linux_netlink.c

[x86] SharedLibrary : libusb.so

[x86] StaticLibrary : libstdc++.a

[x86] SharedLibrary : libtestlibusb.so

[x86] Install : libtestlibusb.so => libs/x86/libtestlibusb.so

[x86] Install : libusb.so => libs/x86/libusb.so

总结

方案二很适合我们有源码的情况,这样能快速的编译使用,配置也更加简单.由于现在android studio都使用cmake编译,所以接下来就是用尝试直接配置CMakeLists.txt文件进行编译.这部分实现了再更新.

使用libusb的例子打印usb设备

我看了下app/src/main/jni/libusb/examples下的例子,listdevs.c比较简单,那么我们就进行藏这个demo的尝试.

MainActivity文件

这个文件很简单,导入** System.loadLibrary(“testlibusb”);,定义jni方法public native String getubs();**.1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.

static {

// System.loadLibrary("usb");

System.loadLibrary("testlibusb");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

findViewById(R.id.buttonPlay).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Log.e("device","call getubs ");

getubs();

}

});

}

/**

* A native method that is implemented by the 'native-lib' native library,

* which is packaged with this application.

*/

public native String getubs();

}

app/src/main/jni/testlibusb/testlibusb.cpp文件

print_devs内容从listdevs.c中拷贝修改过来1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65//

// Created by steve on 19-7-23.

//

#include

#include

#include "libusb.h"

#include

#include "libusb.h"

#include

#define TAG "libusb" // 这个是自定义的LOG的标识

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) // 定义LOGD类型

static void print_devs()

{

libusb_device **devs;

int r;

ssize_t cnt;

LOGD("print_devs");

r = libusb_init(NULL);

LOGD("libusb_init");

cnt = libusb_get_device_list(NULL, &devs);

LOGD("libusb_get_device_list");

libusb_device *dev;

int i = 0, j = 0;

uint8_t path[8];

while ((dev = devs[i++]) != NULL) {

struct libusb_device_descriptor desc;

int r = libusb_get_device_descriptor(dev, &desc);

if (r < 0) {

LOGD("failed to get device descriptor");

}

LOGD("%04x:%04x (bus %d, device %d)",

desc.idVendor, desc.idProduct,

libusb_get_bus_number(dev), libusb_get_device_address(dev));

r = libusb_get_port_numbers(dev, path, sizeof(path));

if (r > 0) {

LOGD(" path: %d", path[0]);

for (j = 1; j < r; j++)

printf(".%d", path[j]);

}

printf("n");

}

libusb_free_device_list(devs, 1);

libusb_exit(NULL);

}

extern "C"

JNIEXPORT jstring JNICALL

Java_com_example_testlibusb_MainActivity_getubs

(JNIEnv *env, jobject obj){

print_devs();

//test();

return env->NewStringUTF("111");

}

执行

点击button,执行getubs方法就可以打印出系统的usb设备,日志如下:1

2

3

4

5

607-25 00:00:54.963 23280-23280/com.example.testlibusb D/libusb: print_devs

07-25 00:00:54.965 23280-23280/com.example.testlibusb D/libusb: libusb_init

07-25 00:00:54.965 23280-23280/com.example.testlibusb D/libusb: libusb_get_device_list

07-25 00:00:54.966 23280-23280/com.example.testlibusb D/libusb: 1c4f:0065 (bus 1, device 18)

07-25 00:00:54.966 23280-23280/com.example.testlibusb D/libusb: path: 1

07-25 00:00:54.966 23280-23280/com.example.testlibusb D/libusb: 1d6b:0002 (bus 1, device 1)

1c4f就是VendorId,0065就是ProductId,有了这2个就可以过滤出你想要的设备,之后就能进行数据的读取和发送了,这块后面有时间再研究.

总结

这个使用需要先ndk编译后使用,整个编译和使用已经可以完整走通,之后还需要研究使用cmake编译,和设备信息的读取.

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐