Add methods for requesting and querying permissions ()

* add methods for requesting and querying permissions

* change requestPermission to void and handle jni errors

* move permissions to utils

* how could i forget the mac operating system

* genuinely blind

* make a permission enum

* call permission callbacks on unimpl platforms
This commit is contained in:
dankmeme01 2024-01-27 20:02:34 +01:00 committed by GitHub
parent 7d8bb9b8af
commit 9ff919118e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 116 additions and 7 deletions
loader
include/Geode
src/platform

View file

@ -8,6 +8,7 @@
#include "utils/map.hpp"
#include "utils/string.hpp"
#include "utils/file.hpp"
#include "utils/permission.hpp"
#include "utils/general.hpp"
#include "utils/timer.hpp"
#include "utils/MiniFunction.hpp"

View file

@ -115,7 +115,7 @@ namespace geode {
/**
* @brief Take the next mod to load
*
*
* @return Mod* The next mod to load
*/
inline GEODE_HIDDEN Mod* takeNextLoaderMod() {

View file

@ -0,0 +1,27 @@
#pragma once
#include <Geode/DefaultInclude.hpp>
#include "MiniFunction.hpp"
#include <string_view>
namespace geode::utils::permission {
enum class Permission {
ReadAudio,
ReadImages,
ReadVideo,
RecordAudio,
};
/**
* Request whether the given permission is granted to Geode by the operating system.
* @param permission The permission
*/
bool getPermissionStatus(Permission permission);
/**
* Request a permission to be granted by the operating system.
* @param permission The permission
* @param callback The callback, passed value is 'true' if permission was granted and 'false' otherwise.
*/
void requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback);
}

View file

@ -10,6 +10,8 @@ using namespace geode::prelude;
#include <jni.h>
#include <Geode/cocos/platform/android/jni/JniHelper.h>
using geode::utils::permission::Permission;
bool utils::clipboard::write(std::string const& data) {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "writeClipboard", "(Ljava/lang/String;)V")) {
@ -306,3 +308,58 @@ void geode::utils::game::restart() {
nullptr
), CCDirector::get()->getRunningScene(), false);
}
static const char* permissionToName(Permission permission) {
#define PERM(x) "android.permission." x
switch (permission) {
case Permission::ReadAudio: return PERM("READ_MEDIA_AUDIO");
case Permission::ReadImages: return PERM("READ_MEDIA_IMAGES");
case Permission::ReadVideo: return PERM("READ_MEDIA_VIDEO");
case Permission::RecordAudio: return PERM("RECORD_AUDIO");
}
#undef PERM
}
bool geode::utils::permission::getPermissionStatus(Permission permission) {
JniMethodInfo info;
if (JniHelper::getStaticMethodInfo(info, "com/geode/launcher/utils/GeodeUtils", "getPermissionStatus", "(Ljava/lang/String;)Z")) {
jstring permString = info.env->NewStringUTF(permissionToName(permission));
jboolean result = info.env->CallStaticBooleanMethod(info.classID, info.methodID, permString);
info.env->DeleteLocalRef(info.classID);
info.env->DeleteLocalRef(permString);
return result == JNI_TRUE;
} else {
clearJNIException();
}
return false;
}
static MiniFunction<void(bool)> s_permissionCallback;
extern "C"
JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_permissionCallback(
JNIEnv* env,
jobject,
jboolean granted
) {
if (s_permissionCallback) {
Loader::get()->queueInMainThread([granted] {
s_permissionCallback(granted == JNI_TRUE);
});
}
}
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
s_permissionCallback = callback;
JniMethodInfo info;
if (JniHelper::getStaticMethodInfo(info, "com/geode/launcher/utils/GeodeUtils", "requestPermission", "(Ljava/lang/String;)V")) {
jstring permString = info.env->NewStringUTF(permissionToName(permission));
info.env->CallStaticVoidMethod(info.classID, info.methodID, permString);
info.env->DeleteLocalRef(info.classID);
info.env->DeleteLocalRef(permString);
} else {
clearJNIException();
}
}

View file

@ -46,4 +46,4 @@ bool Loader::Impl::supportsLaunchArguments() const {
std::string Loader::Impl::getLaunchCommand() const {
return std::string(); // Empty
}
}

View file

@ -34,3 +34,11 @@ ghc::filesystem::path dirs::getGameDir() {
ghc::filesystem::path dirs::getSaveDir() {
return weaklyCanonical(CCFileUtils::sharedFileUtils()->getWritablePath().c_str());
}
bool geode::utils::permission::getPermissionStatus(Permission permission) {
return true; // unimplemented
}
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
callback(true); // unimplemented
}

View file

@ -281,9 +281,9 @@ Result<> geode::hook::addObjcMethod(std::string const& className, std::string co
auto cls = objc_getClass(className.c_str());
if (!cls)
return Err("Class not found");
auto sel = sel_registerName(selectorName.c_str());
class_addMethod(cls, sel, (IMP)imp, "v@:");
return Ok();
@ -292,12 +292,20 @@ Result<void*> geode::hook::getObjcMethodImp(std::string const& className, std::s
auto cls = objc_getClass(className.c_str());
if (!cls)
return Err("Class not found");
auto sel = sel_registerName(selectorName.c_str());
auto method = class_getInstanceMethod(cls, sel);
if (!method)
return Err("Method not found");
return Ok((void*)method_getImplementation(method));
}
bool geode::utils::permission::getPermissionStatus(Permission permission) {
return true; // unimplemented
}
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
callback(true); // unimplemented
}

View file

@ -192,7 +192,7 @@ ghc::filesystem::path dirs::getSaveDir() {
return std::filesystem::weakly_canonical(savePath.wstring()).wstring();
}
}
return std::filesystem::weakly_canonical(executablePath.parent_path().wstring()).wstring();
}();
@ -269,3 +269,11 @@ Result<> geode::hook::addObjcMethod(std::string const& className, std::string co
Result<void*> geode::hook::getObjcMethodImp(std::string const& className, std::string const& selectorName) {
return Err("Wrong platform");
}
bool geode::utils::permission::getPermissionStatus(Permission permission) {
return true; // unimplemented
}
void geode::utils::permission::requestPermission(Permission permission, utils::MiniFunction<void(bool)> callback) {
callback(true); // unimplemented
}