Reputation: 114
in android programming you need to get usb permission before working with connected device to client device.
i am trying to connect a hack-rf
to android device and use it... but first of all i need to get usb permission and detect that hackrf
.
setup:
1- qt6.3.0
2- ndk 21.3.6528147
3- ui with QML
this is my c++ code to get permission of storage:
bool checkAppPermissions(QString permission)
{
auto result = QtAndroidPrivate::checkPermission(permission).result();
if (result == QtAndroidPrivate::Denied) {
auto result2 = QtAndroidPrivate::requestPermission(permission).result();
qDebug() << permission << result2;
if (result2 == QtAndroidPrivate::Denied)
return false;
else {
return true;
}
}
else {
return true;
}
}
and it's usage:
checkAppPermissions("android.permission.WRITE_EXTERNAL_STORAGE")
but i cannot get usb permisson this way.. its not working.
in AndroidManifest.xml
i put these:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.usb.host"/>
also i think the permission that i had to get is "com.android.example.USB_PERMISSION"
but i dont know how should i Grant or request for that.
this kotlin code works fine... it detects device and gets the permission but i don't know how it is working! or how can i implement it in Qt with cpp.
i also see this answer but i dont know how he uses C++ native side code
or MyActivity.java
could you help me to detect device and grant it's permission at run time.
Upvotes: 0
Views: 773
Reputation: 26
To ask for USB permission you need to use the Java class called UsbManager
.
In Qt6, they changed how QJniObject works, so it is kinda hard to find how to use it but here is what you need to do :
Get the context and usb manager object :
QJniObject context = QtAndroidPrivate::context();
if (context.isValid()) {
QJniObject usbManager = context.callObjectMethod(
"getSystemService",
"(Ljava/lang/String;)Ljava/lang/Object;",
QJniObject::getStaticObjectField(
"android/content/Context",
"USB_SERVICE",
"Ljava/lang/String;"
).object<jstring>()
);
Iterate on the deviceList
obtained from usbManager
:
QJniObject deviceList = usbManager.callObjectMethod(
"getDeviceList",
"()Ljava/util/HashMap;"
);
//Retrieve Java objects to be able to iterate deviceList
QJniEnvironment env;
jobject jMap = deviceList.object();
jclass mapClass = env->GetObjectClass(jMap);
jmethodID entrySet = env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
jobject jEntrySet = env->CallObjectMethod(jMap, entrySet);
jclass setClass = env->FindClass("java/util/Set");
jmethodID iterator = env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
jobject jIterator = env->CallObjectMethod(jEntrySet, iterator);
jclass iteratorClass = env->FindClass("java/util/Iterator");
jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
jmethodID next = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
jclass entryClass = env->FindClass("java/util/Map$Entry");
jmethodID getKey = env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
jmethodID getValue = env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
Get your device object and obtain all information needed (if you want to print for debug or something else)
while (env->CallBooleanMethod(jIterator, hasNext)) {
jobject jEntry = env->CallObjectMethod(jIterator, next);
jstring jDeviceName = static_cast<jstring>(env->CallObjectMethod(jEntry, getKey));
jobject jDevice = env->CallObjectMethod(jEntry, getValue);
QJniObject device(jDevice);
jint vendorId = device.callMethod<jint>("getVendorId", "()I");
jint productId = device.callMethod<jint>("getProductId", "()I");
QString manufacturer = (device.callMethod<jstring>("getManufacturerName", "()Ljava/lang/String;")).toString();
QString productname = (device.callMethod<jstring>("getProductName", "()Ljava/lang/String;")).toString();
And this is how you request permission to a specific device
jstring permissionString = env->NewStringUTF("org.qtproject.example.USB_PERMISSION");
QJniObject intent("android/content/Intent");
jclass stringClass = env->FindClass("java/lang/String");
jmethodID constructor = env->GetMethodID(stringClass, "<init>", "(Ljava/lang/String;)V");
jobject stringObject = env->NewObject(stringClass, constructor, permissionString);
intent.callMethod<void>("<init>", "(Ljava/lang/String;)V", stringObject);
QJniObject permissionIntent("android/app/PendingIntent");
jclass pendingIntentClass = env->FindClass("android/app/PendingIntent");
jmethodID getBroadcastMethod = env->GetStaticMethodID(pendingIntentClass, "getBroadcast", "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;");
permissionIntent = permissionIntent.callStaticObjectMethod(pendingIntentClass, getBroadcastMethod, context.object(), 0, intent.object(), 0);
usbManager.callMethod<void>(
"requestPermission",
"(Landroid/hardware/usb/UsbDevice;Landroid/app/PendingIntent;)V",
device.object(),
permissionIntent.object()
);
Upvotes: 1