libusb icon indicating copy to clipboard operation
libusb copied to clipboard

JNI Android Support on Unrooted devices

Open CraigHutchinson opened this issue 3 years ago • 23 comments

Rebase of work on #874:

This code implements connection and device listing on unrooted android devices, without requiring any user-provided java. This PR is usable now 🎉

The java native interface library is used, which is always available when building on android, to do the sdk calls within libusb itself. The approach is modularised to aid expanding if new features are needed.

  • Device enumeration by generating usb descriptors from the android sdk, which requires no user permission for this information.
  • Detect if permission is needed when an unpermissioned device is opened, and perform the requestPermission call if necessary. This pops up a dialogue to the user asking if they will allow the connection. 📓 Dispatching this request involves setting an action string on the intent for permission that the application can optionally subscribe to. The permission intent I dispatch has action string libusb.android.USB_PERMISSION.

The code only takes effect if the user provides their JNIEnv* or JavaVM* pointer via a new libusb option.

CraigHutchinson avatar Jul 11 '22 13:07 CraigHutchinson

Integrated Android support for device relisting https://github.com/xloem/libusb/pull/3

CraigHutchinson avatar Jul 11 '22 13:07 CraigHutchinson

I'm happy to have this replace #874 or merge and rebase it too, whatever works better for maintainers and contributors.

xloem avatar Jul 12 '22 14:07 xloem

@xloem I'm not sure but one option could be to force push this onto #874 then the conversation history is maintained while adding a cleaner set of commits? I would be happy to have this replace that pull also. Primarily its amazing work you have made and it needs to get merged as has significant value.

Also, I would very much be in a position to aid/maintain for testing purposes.

Current identified issues(s):

  1. [Minor] When device is being polled the USB Permissions prompt can occur multiple-times i.e. First prompt gives permission but a second prompt still is also pending and must therefore click 'ok' twice. EDIT: This may be due to before permission being granted a "libusb generates fake descriptors for it from Android's API" and this may be using to generate the second request due to application level logic TBC

CraigHutchinson avatar Jul 15 '22 09:07 CraigHutchinson

For people who are interested in better Android support, please come here and post your review or success/fail testing results. Thanks.

mcuee avatar Nov 15 '22 00:11 mcuee

NOTE: libusb now requires Signed-Commits on PR so has been rebased onto latest libusb/master. The code has not yet been retested after this update but no merge issues moving from master@2022-07 to master@2022-11

CraigHutchinson avatar Nov 17 '22 14:11 CraigHutchinson

Thanks for the rebasing work!

For information, the maintainers typically rebase any PR locally when merging, regardless of Signed-Commits or not, so just ignore the GitHub warning about this (dunno how to turn it off). However, before this PR can be merged it should ideally be worked down to the smallest number of commits that makes sense, so e.g. without fixups commits. If there are multiple authors it can be correct to have their commits separated for credit attribution, but minor fixups of other people's commit can be amended in-place and commented in the commit message.

tormodvolden avatar Nov 17 '22 16:11 tormodvolden

Now that we have libusb_init_context() in git master, it would be a good time to rebase this. The NO_DEVICE_DISCOVERY option should be set in the libusb_init_context() call.

tormodvolden avatar Jan 22 '23 21:01 tormodvolden

Its unclear to me whats preventing this from merging. Can someone summarize the action items needed ?

ankurvdev avatar Aug 11 '23 16:08 ankurvdev

Its unclear to me whats preventing this from merging. Can someone summarize the action items needed ?

Need more reviews and tests.

Another thing, as of now this PR has conflicts with the git repo which needs to be fixed.

mcuee avatar Aug 12 '23 10:08 mcuee

hello,I'm new here. Is there any Android demo using this branch? @CraigHutchinson @xloem

ben1681 avatar Sep 11 '23 09:09 ben1681

Not entirely sure what sort of demo you mean. But the Libusb should work as per any other example as long as you provide the JNI for the context configurable iirc. Edit: actually, it may be the lack of a SIMPLE android demonstration app for test etc that prevents this getting merged as AFAIK as in use I didn't find any major bugs apart from hot plug issues earlier on.

CraigHutchinson avatar Sep 11 '23 10:09 CraigHutchinson

@CraigHutchinson Thank you for your answer. I'm new to jni and I think need a sample program like this, where the author gets the file descriptor through usbmanager and passes it to jni, which works. Then I found your branch, and I was very interested in what you said about "to do the sdk calls within libusb itself." Next I'll replace all the libusb code in this example with yours and try to modify the jni code. As I understand it, if I provide JNIEnv*, the code automatically runs the code that gets the permissions and file descriptors, calling the jni function directly. For a quick test, I simply changed the connect_device function in the example to look like this. std::string connect_device(int fileDescriptor) { libusb_device **devs; int r; ssize_t cnt;

r = libusb_init(NULL); if (r < 0) return "r<0";

cnt = libusb_get_device_list(NULL, &devs); if (cnt < 0){ libusb_exit(NULL); return "fail"; } if (cnt == 0){ libusb_exit(NULL); return "cnt=0"; }

print_devs(devs); libusb_free_device_list(devs, 1);

libusb_exit(NULL); return "success"; } When I connect my ipad to my Android phone using the Apple to type-c cable, and then run the program, no permission request window appears, I just get a "cnt=0". So I think an example like the one I provided, showing how to call your code to get device information, would be very helpful for beginners like me.

Rebase of work on #874:

This code implements connection and device listing on unrooted android devices, without requiring any user-provided java. This PR is usable now 🎉

The java native interface library is used, which is always available when building on android, to do the sdk calls within libusb itself. The approach is modularised to aid expanding if new features are needed.

  • Device enumeration by generating usb descriptors from the android sdk, which requires no user permission for this information.
  • Detect if permission is needed when an unpermissioned device is opened, and perform the requestPermission call if necessary. This pops up a dialogue to the user asking if they will allow the connection. 📓 Dispatching this request involves setting an action string on the intent for permission that the application can optionally subscribe to. The permission intent I dispatch has action string libusb.android.USB_PERMISSION.

The code only takes effect if the user provides their JNIEnv* or JavaVM* pointer via a new libusb option.

ben1681 avatar Sep 11 '23 14:09 ben1681

I only rebased @xloem work but yes that is looking nearly there. Check the original PR for details which is linked on this rebase key bit is this (which I hope you gathered)

The code only takes effect if the user provides their JNIEnv* or JavaVM* pointer via a new libusb option.

I'm not at a PC nor working in this area for last year. As far as I recall the PR adds context options for setting these. It's upto your android code to choose where/how you get them but pass them in.

CraigHutchinson avatar Sep 11 '23 21:09 CraigHutchinson

@CraigHutchinson Thank you so much for your answer, I have read this today#874, hard for me to fully understand by now. But finally I found out that @xloem has added an example to his libusb-android codehere, the guy I mentioned last time also wrote ademo program for this example, just I didn't find and understand it yesterday.

ben1681 avatar Sep 12 '23 04:09 ben1681