如何请求C 代码的Android NDK摄像机许可

How to Request Android NDK Camera Permission from C++ code?

本文关键字:Android NDK 摄像机 许可 代码 何请求 请求      更新时间:2023-10-16

我正在用纯C 编写该应用,并且我有打开相机的代码。并设置AndroidManifest.xml为:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera2" android:required="true" />

第一次运行应用程序时,它没有提供提示以打开许可的提示。安装后,我必须手动进行操作,设置 ->应用 ->" myApp" ->权限。

如何在不引入Java代码的情况下在C 中提供提示?非常感谢所有帮助。

这可以使用JNI调用来完成。请参阅下面的示例,以获取read_external_storage和write_external_storage(可以轻松适应相机perms)。

调用函数:

check_android_permissions(struct android_app* app)
(下面的源)应用程序启动时。

几个陷阱:

  • android.manifest.permission是嵌套在android.manifest中的类因此,其JNI名称为" Android/Sustest $许可"。
  • 我没有设法访问contextCompat(android.support.v4.content.contextcompat)和jni的ActivityCompat(android.support.v4.app.activitycompat)我使用了上下文(android.content.context)和活动(android.app.Activity)直接。结果,需要Android API 23级(2015年5月棉花糖)。
  • 常数需要在类中检索,尤其是read_external_storage和write_external_storage是android.manifest.permission中的静态字符串,并且ofermission_grant_grant android.content.content.content.packagemanager。
  • 当用户单击"不再次问我"按钮时,我没有实现如何处理,这将需要实现onrequestpermissionsresult()回调。
 
/**
 * 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, e.g.,
 *   "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, e.g.,
 *   "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);
    }
}

,所以我也看过。

  1. 手动执行您也可以通过命令行使用adb shell pm grant com.package.name android.permission.CAMERA

  2. 进行操作。
  3. 检查权限是否存在adb shell dumpsys package com.package.name

  4. 这是要求使用Java的权限的一系列步骤

  5. 要弄清楚没有Java的情况,您将需要深入研究AOSP才能找到它在引擎盖下的工作方式……这不是微不足道的,找不到示例。p>