简体   繁体   English

如何从C ++代码请求Android NDK摄像机许可?

[英]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. 所以我也看到了这一点。

  1. 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

  2. To check if permissions are there adb shell dumpsys package com.package.name 要检查权限是否存在adb shell dumpsys package com.package.name

  3. This is the series of steps to ask for permissions with Java 这是请求Java权限的一系列步骤

  4. 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: 几个陷阱:

  • android.Manifest.permission is a class nested in android.Manifest, hence its JNI name is "android/Manifest$permission". android.Manifest.permission是嵌套在android.Manifest中的类,因此其JNI名称为“ android / Manifest $ permission”。
  • I did not manage to access ContextCompat (android.support.v4.content.ContextCompat) and ActivityCompat (android.support.v4.app.ActivityCompat ) from JNI, so I used Context (android.content.Context) and Activity (android.app.Activity) directly. 我没有从JNI访问ContextCompat(android.support.v4.content.ContextCompat)和ActivityCompat(android.support.v4.app.ActivityCompat),所以我使用了Context(android.content.Context)和Activity(android。 app.Activity)。 As a consequence, Android API Level 23 (Marshmallow, May 2015) is needed. 因此,需要使用Android API级别23(棉花糖,2015年5月)。
  • The constants need to be retrieved in the classes, in particular READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE are static strings in android.Manifest.permission, and PERMISSION_GRANTED a static integer in android.content.pm.PackageManager. 需要在类中检索常量,尤其是READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE是android.Manifest.permission中的静态字符串,而PERMISSION_GRANTED是android.content.pm.PackageManager中的静态整数。
  • I did not implement how to handle when the user clicks the 'do not ask me again' button, this would require to implement the onRequestPermissionsResult() callback. 当用户单击“不再询问我”按钮时,我没有实现如何处理,这将需要实现onRequestPermissionsResult()回调。
\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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM