[英]How to Request Android NDK Camera Permission from C++ code?
I'm Writing the app in pure c++ and i have the code to open the camera. 我正在用纯C ++编写应用程序,并且我有打开相机的代码。 and set-up the AndroidManifest.xml as:
并将AndroidManifest.xml设置为:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera2" android:required="true" />
when running the app for the first time it does not provide the prompt to turn permission on. 首次运行该应用程序时,它不会提示您打开权限。 after the installation i have to do it manually by, Settings->Apps->"MyApp"->Permissions.
安装后,我必须通过“设置”->“应用程序”->“ MyApp”->“权限”手动进行操作。
How do I provide the prompt in c++, without introducing java code? 如何在c ++中提供提示而不引入Java代码? All help is greatly Appreciated.
非常感谢所有帮助。
So I have seen this as well. 所以我也看到了这一点。
To do it manually you can also do it via command line with adb shell pm grant com.package.name android.permission.CAMERA
要手动执行此操作,您也可以通过命令行使用
adb shell pm grant com.package.name android.permission.CAMERA
To check if permissions are there adb shell dumpsys package com.package.name
要检查权限是否存在
adb shell dumpsys package com.package.name
This is the series of steps to ask for permissions with Java 这是请求Java权限的一系列步骤
To figure out how to do it without Java, you will need to dig into the AOSP to find how it is working under the hood ... which isn't trivial and no examples to be found. 为了弄清楚如何在不使用Java的情况下进行操作,您将需要深入研究AOSP,以了解其在幕后的运作方式 ……这并非易事,也找不到示例。
This can be done using JNI calls. 可以使用JNI调用来完成。 See example below for READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE (can be easily adapted to camera perms).
有关READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE的信息,请参见下面的示例(可以很容易地适应相机的烫发)。
Call the function: 调用函数:
check_android_permissions(struct android_app* app)(source below) when the application starts.
Several gotchas: 几个陷阱:
\n/** * \\brief Gets the internal name for an android permission. * \\param[in] lJNIEnv a pointer to the JNI environment * \\param[in] perm_name the name of the permission, eg, * "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE". * \\return a jstring with the internal name of the permission, * to be used with android Java functions * Context.checkSelfPermission() or Activity.requestPermissions() */ jstring android_permission_name(JNIEnv* lJNIEnv, const char* perm_name) { // nested class permission in class android.Manifest, // hence android 'slash' Manifest 'dollar' permission jclass ClassManifestpermission = lJNIEnv->FindClass( "android/Manifest$permission" ); jfieldID lid_PERM = lJNIEnv->GetStaticFieldID( ClassManifestpermission, perm_name, "Ljava/lang/String;" ); jstring ls_PERM = (jstring)(lJNIEnv->GetStaticObjectField( ClassManifestpermission, lid_PERM )); return ls_PERM; } /** * \\brief Tests whether a permission is granted. * \\param[in] app a pointer to the android app. * \\param[in] perm_name the name of the permission, eg, * "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE". * \\retval true if the permission is granted. * \\retval false otherwise. * \\note Requires Android API level 23 (Marshmallow, May 2015) */ bool android_has_permission(struct android_app* app, const char* perm_name) { JavaVM* lJavaVM = app->activity->vm; JNIEnv* lJNIEnv = nullptr; bool lThreadAttached = false; // Get JNIEnv from lJavaVM using GetEnv to test whether // thread is attached or not to the VM. If not, attach it // (and note that it will need to be detached at the end // of the function). switch (lJavaVM->GetEnv((void**)&lJNIEnv, JNI_VERSION_1_6)) { case JNI_OK: break; case JNI_EDETACHED: { jint lResult = lJavaVM->AttachCurrentThread(&lJNIEnv, nullptr); if(lResult == JNI_ERR) { throw std::runtime_error("Could not attach current thread"); } lThreadAttached = true; } break; case JNI_EVERSION: throw std::runtime_error("Invalid java version"); } bool result = false; jstring ls_PERM = android_permission_name(lJNIEnv, perm_name); jint PERMISSION_GRANTED = jint(-1); { jclass ClassPackageManager = lJNIEnv->FindClass( "android/content/pm/PackageManager" ); jfieldID lid_PERMISSION_GRANTED = lJNIEnv->GetStaticFieldID( ClassPackageManager, "PERMISSION_GRANTED", "I" ); PERMISSION_GRANTED = lJNIEnv->GetStaticIntField( ClassPackageManager, lid_PERMISSION_GRANTED ); } { jobject activity = app->activity->clazz; jclass ClassContext = lJNIEnv->FindClass( "android/content/Context" ); jmethodID MethodcheckSelfPermission = lJNIEnv->GetMethodID( ClassContext, "checkSelfPermission", "(Ljava/lang/String;)I" ); jint int_result = lJNIEnv->CallIntMethod( activity, MethodcheckSelfPermission, ls_PERM ); result = (int_result == PERMISSION_GRANTED); } if(lThreadAttached) { lJavaVM->DetachCurrentThread(); } return result; } /** * \\brief Query file permissions. * \\details This opens the system dialog that lets the user * grant (or deny) the permission. * \\param[in] app a pointer to the android app. * \\note Requires Android API level 23 (Marshmallow, May 2015) */ void android_request_file_permissions(struct android_app* app) { JavaVM* lJavaVM = app->activity->vm; JNIEnv* lJNIEnv = nullptr; bool lThreadAttached = false; // Get JNIEnv from lJavaVM using GetEnv to test whether // thread is attached or not to the VM. If not, attach it // (and note that it will need to be detached at the end // of the function). switch (lJavaVM->GetEnv((void**)&lJNIEnv, JNI_VERSION_1_6)) { case JNI_OK: break; case JNI_EDETACHED: { jint lResult = lJavaVM->AttachCurrentThread(&lJNIEnv, nullptr); if(lResult == JNI_ERR) { throw std::runtime_error("Could not attach current thread"); } lThreadAttached = true; } break; case JNI_EVERSION: throw std::runtime_error("Invalid java version"); } jobjectArray perm_array = lJNIEnv->NewObjectArray( 2, lJNIEnv->FindClass("java/lang/String"), lJNIEnv->NewStringUTF("") ); lJNIEnv->SetObjectArrayElement( perm_array, 0, android_permission_name(lJNIEnv, "READ_EXTERNAL_STORAGE") ); lJNIEnv->SetObjectArrayElement( perm_array, 1, android_permission_name(lJNIEnv, "WRITE_EXTERNAL_STORAGE") ); jobject activity = app->activity->clazz; jclass ClassActivity = lJNIEnv->FindClass( "android/app/Activity" ); jmethodID MethodrequestPermissions = lJNIEnv->GetMethodID( ClassActivity, "requestPermissions", "([Ljava/lang/String;I)V" ); // Last arg (0) is just for the callback (that I do not use) lJNIEnv->CallVoidMethod( activity, MethodrequestPermissions, perm_array, 0 ); if(lThreadAttached) { lJavaVM->DetachCurrentThread(); } } void check_android_permissions(struct android_app* app) { bool OK = android_has_permission( app, "READ_EXTERNAL_STORAGE" ) && android_has_permission( app, "WRITE_EXTERNAL_STORAGE" ); if(!OK) { android_request_file_permissions(app); } }
\n/** * \\brief Gets the internal name for an android permission. * \\param[in] lJNIEnv a pointer to the JNI environment * \\param[in] perm_name the name of the permission, eg, * "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE". * \\return a jstring with the internal name of the permission, * to be used with android Java functions * Context.checkSelfPermission() or Activity.requestPermissions() */ jstring android_permission_name(JNIEnv* lJNIEnv, const char* perm_name) { // nested class permission in class android.Manifest, // hence android 'slash' Manifest 'dollar' permission jclass ClassManifestpermission = lJNIEnv->FindClass( "android/Manifest$permission" ); jfieldID lid_PERM = lJNIEnv->GetStaticFieldID( ClassManifestpermission, perm_name, "Ljava/lang/String;" ); jstring ls_PERM = (jstring)(lJNIEnv->GetStaticObjectField( ClassManifestpermission, lid_PERM )); return ls_PERM; } /** * \\brief Tests whether a permission is granted. * \\param[in] app a pointer to the android app. * \\param[in] perm_name the name of the permission, eg, * "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE". * \\retval true if the permission is granted. * \\retval false otherwise. * \\note Requires Android API level 23 (Marshmallow, May 2015) */ bool android_has_permission(struct android_app* app, const char* perm_name) { JavaVM* lJavaVM = app->activity->vm; JNIEnv* lJNIEnv = nullptr; bool lThreadAttached = false; // Get JNIEnv from lJavaVM using GetEnv to test whether // thread is attached or not to the VM. If not, attach it // (and note that it will need to be detached at the end // of the function). switch (lJavaVM->GetEnv((void**)&lJNIEnv, JNI_VERSION_1_6)) { case JNI_OK: break; case JNI_EDETACHED: { jint lResult = lJavaVM->AttachCurrentThread(&lJNIEnv, nullptr); if(lResult == JNI_ERR) { throw std::runtime_error("Could not attach current thread"); } lThreadAttached = true; } break; case JNI_EVERSION: throw std::runtime_error("Invalid java version"); } bool result = false; jstring ls_PERM = android_permission_name(lJNIEnv, perm_name); jint PERMISSION_GRANTED = jint(-1); { jclass ClassPackageManager = lJNIEnv->FindClass( "android/content/pm/PackageManager" ); jfieldID lid_PERMISSION_GRANTED = lJNIEnv->GetStaticFieldID( ClassPackageManager, "PERMISSION_GRANTED", "I" ); PERMISSION_GRANTED = lJNIEnv->GetStaticIntField( ClassPackageManager, lid_PERMISSION_GRANTED ); } { jobject activity = app->activity->clazz; jclass ClassContext = lJNIEnv->FindClass( "android/content/Context" ); jmethodID MethodcheckSelfPermission = lJNIEnv->GetMethodID( ClassContext, "checkSelfPermission", "(Ljava/lang/String;)I" ); jint int_result = lJNIEnv->CallIntMethod( activity, MethodcheckSelfPermission, ls_PERM ); result = (int_result == PERMISSION_GRANTED); } if(lThreadAttached) { lJavaVM->DetachCurrentThread(); } return result; } /** * \\brief Query file permissions. * \\details This opens the system dialog that lets the user * grant (or deny) the permission. * \\param[in] app a pointer to the android app. * \\note Requires Android API level 23 (Marshmallow, May 2015) */ void android_request_file_permissions(struct android_app* app) { JavaVM* lJavaVM = app->activity->vm; JNIEnv* lJNIEnv = nullptr; bool lThreadAttached = false; // Get JNIEnv from lJavaVM using GetEnv to test whether // thread is attached or not to the VM. If not, attach it // (and note that it will need to be detached at the end // of the function). switch (lJavaVM->GetEnv((void**)&lJNIEnv, JNI_VERSION_1_6)) { case JNI_OK: break; case JNI_EDETACHED: { jint lResult = lJavaVM->AttachCurrentThread(&lJNIEnv, nullptr); if(lResult == JNI_ERR) { throw std::runtime_error("Could not attach current thread"); } lThreadAttached = true; } break; case JNI_EVERSION: throw std::runtime_error("Invalid java version"); } jobjectArray perm_array = lJNIEnv->NewObjectArray( 2, lJNIEnv->FindClass("java/lang/String"), lJNIEnv->NewStringUTF("") ); lJNIEnv->SetObjectArrayElement( perm_array, 0, android_permission_name(lJNIEnv, "READ_EXTERNAL_STORAGE") ); lJNIEnv->SetObjectArrayElement( perm_array, 1, android_permission_name(lJNIEnv, "WRITE_EXTERNAL_STORAGE") ); jobject activity = app->activity->clazz; jclass ClassActivity = lJNIEnv->FindClass( "android/app/Activity" ); jmethodID MethodrequestPermissions = lJNIEnv->GetMethodID( ClassActivity, "requestPermissions", "([Ljava/lang/String;I)V" ); // Last arg (0) is just for the callback (that I do not use) lJNIEnv->CallVoidMethod( activity, MethodrequestPermissions, perm_array, 0 ); if(lThreadAttached) { lJavaVM->DetachCurrentThread(); } } void check_android_permissions(struct android_app* app) { bool OK = android_has_permission( app, "READ_EXTERNAL_STORAGE" ) && android_has_permission( app, "WRITE_EXTERNAL_STORAGE" ); if(!OK) { android_request_file_permissions(app); } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.