Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: x/mobile: add permission request on android #50104

Open
MatejMagat305 opened this issue Dec 11, 2021 · 10 comments
Open

proposal: x/mobile: add permission request on android #50104

MatejMagat305 opened this issue Dec 11, 2021 · 10 comments
Labels
FeatureRequest mobile Android, iOS, and x/mobile NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Proposal
Milestone

Comments

@MatejMagat305
Copy link

MatejMagat305 commented Dec 11, 2021

What version of Go are you using (go version)?

go version go1.17.3 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/matejmag305/.cache/go-build"
GOENV="/home/matejmag305/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/matejmag305/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/matejmag305/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/matejmag305/go_sdk/go1.17.3"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/matejmag305/go_sdk/go1.17.3/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.3"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build16419202=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I was found problem: is no easy way how request permission by runtime..........

More story

I m interesting in programing android apps with go, I have created small library for my (experimental) project, the library is trying implement bluetooth socket ....., but I have problem with manifest (androids ignore Bluetooth permission........), I was trying to fix(by runtime), then I realize that there is not easy way how request permission by runtime.........., I was writing this problem to fyne-io/fyne, which forms the graphics library of my experimental project, but now I think it is issue to gomobile.

Solution Proposal

The Solution would be use existing way how from ndk request permission. It would add two functions to programmer (user) interface. It is support with ndk solution:

More story

Add to code to mobile/app/android.c or somewhere where it pass best a few functions(or one, it depends on ordering of code) to background (in the fact I suggest the implementation solution, but it will be on implementation team how it will works) and two functions to user interface (the reason of this topic), pattern of these functions is the first answer in ndk request camera

Exported GO side (main Proposal)

func RequestPermision(permission string) Next code would use RunOnJVM from "mobileinit" package, it would have argument like "permission string" but in final version it could be "permission int", the code call `C.android_permissions(env, n)`, which could be void or return something, in further code is void ...
func RequestPermision(permission string){
	n := C.CString(permission)
	mobileinit.RunOnJVM(func(vm, jniEnv, ctx uintptr) error {
		env := (*C.JNIEnv)(unsafe.Pointer(jniEnv))
		C.android_permissions(env, n)// or result := ...
		return nil // or return result
	})
	C.free(unsafe.Pointer(n))
}

Other OS (IOS) should have: func RequestPermision(permission string){} // dummy function.
Of course probably IOS has similar system of permission, but I haven't experience for suggest any example...........

func IsPermision(permission string) bool

The next exported function would have similar situation with argument like previous one - I do not know whether solution of type functions is the best..... and in the fact it: it would unnecessary function, could be skipped because it could be execute at the beginning android_permissions, but sometime you want only find out whether permission is given and nothing more, therefore I mention this option .....

func IsPermision(permission string) bool{
	n := C.CString(permission)
        var result bool
	mobileinit.RunOnJVM(func(vm, jniEnv, ctx uintptr) error {
		env := (*C.JNIEnv)(unsafe.Pointer(jniEnv))
		result = bool(android_has_permission( env, perm_name))
		return nil // or return result
	})
	C.free(unsafe.Pointer(n))
        return result
}

Unexported - Background C side (of course only example how it could be done)

void android_permissions(JNIEnv* env, char* perm_name) In this example it is void, but it could be string (char*) or bool and of course argument could be int, at the beginning function control whether permission would be granted and after that if it was not granted it would be call function to "real" request.:
void android_permissions(JNIEnv* env,  char* perm_name) {// or bool or string to indentify error
    bool OK = android_has_permission(
       env, perm_name
    ) ;
    if(!OK) {
       android_request_permission(env,perm_name ); // or return  android_request_file_permissions(env,perm_name ); due to error
    }
}
void android_request_permission(JNIEnv* env, char* permissions) It would be call ndk java api to granted permission.
void android_request_permission(JNIEnv* env, char* permissions) { // or bool or string to reference error
    jobjectArray perm_array = (*env)->NewObjectArray(env,
      2,
      find_class(env, "java/lang/String"),
      (*env)->NewStringUTF(env, "")
    );
    (*env)->SetObjectArrayElement(env,
          perm_array, 1,
          android_permission_name(env, permissions)
        );
    (*env)->CallVoidMethod(
       current_class, request_permissions, perm_array, 0
    );
}
bool android_has_permission(JNIEnv* env, const char* perm_name) The function to check whether permission is granted:
bool android_has_permission(JNIEnv* env, const char* perm_name) {  
    bool result = false;
    jstring ls_PERM = android_permission_name(env, perm_name);
    int PERMISSION_GRANTED = -1;
    {
       jclass ClassPackageManager = find_class(env, "android/content/pm/PackageManager" );
       jfieldID lid_PERMISSION_GRANTED = (*env)->GetStaticFieldID(env,
          ClassPackageManager, "PERMISSION_GRANTED", "I"
       );
       PERMISSION_GRANTED = (*env)->GetStaticIntField(env,
          ClassPackageManager, lid_PERMISSION_GRANTED
       );
    }
    {
       jclass ClassContext = find_class(env,  "android/content/Context"   );
       jmethodID MethodcheckSelfPermission = find_method(env, ClassContext,
       "checkSelfPermission", "(Ljava/lang/String;)I" );
       int int_result =(int) (*env)->CallIntMethod(env,
           current_class, MethodcheckSelfPermission, ls_PERM
       );
       result = (int_result == PERMISSION_GRANTED);
    }
    return result;
}
jclass android_permission_name(JNIEnv* env, const char* perm_name) The function to get permission class from (char*) string:
jclass android_permission_name(JNIEnv* env, const char* perm_name) {
    // nested class permission in class android.Manifest,
    // hence android 'slash' Manifest 'dollar' permission
    jclass ClassManifestpermission = find_class(env, "android/Manifest$permission");
    jfieldID lid_PERM = (*env)->GetStaticFieldID(env,
       ClassManifestpermission, perm_name, "Ljava/lang/String;"
    );
    jclass ls_PERM = (jclass)((*env)->GetStaticObjectField(env,
        ClassManifestpermission, lid_PERM
    ));
    return ls_PERM;
}
static jmethodID request_permissions And of course some functions could be "extracted" at init:
static jmethodID request_permissions;  
//which init in function ANativeActivity_onCreate

Like show: https://github.com/golang/mobile/blob/4e6c2922fdeed32d3596616518aaee7b0d79ce55/app/android.c#L71
and https://github.com/golang/mobile/blob/4e6c2922fdeed32d3596616518aaee7b0d79ce55/app/android.c#L78


I m sorry for my English, which is not best.......

EDITED:

Of course there is further reason, why implement this request: dangerous permission: https://developer.android.com/training. Yes I know that golang isn't primary for android and majority of request will never need (because missing API), but there are some permissions, which gomobile could use ..............., for example above mentioned Bluetooth.

ADDED LATER:

I have made some prototype of this (it is working on my android simulator): https://github.com/MatejMagat305/golang-prototype-permision (without adding to current code, only use function RunOnJVM) - it is only prototype which probably contains memory leak and maybe it should be good added or change functions to request multiple strings ............... And yes, something similar is on IOS, but I haven't suitable device, experience and internet claim that work a little bit diferent

@gopherbot gopherbot added the mobile Android, iOS, and x/mobile label Dec 11, 2021
@gopherbot gopherbot added this to the Unreleased milestone Dec 11, 2021
@cherrymui
Copy link
Member

How will the Go requestPermision function be called? Is it to be called from x/mobile itself, or user code? If this needs adding a public API, you may want to start a proposal (see https://golang.org/s/proposal ). Thanks.

cc @hyangah @eliasnaur @changkun

@cherrymui cherrymui changed the title x/mobile add permision request on android x/mobile: add permission request on android Dec 13, 2021
@cherrymui cherrymui added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Dec 13, 2021
@MatejMagat305
Copy link
Author

MatejMagat305 commented Dec 13, 2021

So my english is not the best, therefore I´m sorry if I missanderstood........., so in my opinion it is (relative) small piece of code, which will need add to x/mobile and it do´nt need add extra files or infrastrukture, because all things are in current code......... ( now I was edited original for some mistake), yes I sugest only one function for users and that is requestPermision (I m really sorry on final version it should be exported), which will request for permision at runtime(if user wants)..........., other functions shows how could be done ........

@cherrymui
Copy link
Member

Thanks. So requestPermision will be an exported function?

As this adds a new API, following the proposal process ( https://golang.org/s/proposal ) may still be a good idea. I'll let x/mobile maintainers decide. Thanks.

@MatejMagat305
Copy link
Author

yes function will be exported........., so now should I close this and open proposal isues without "Author background"?

@cherrymui
Copy link
Member

You don't have to open a new one. You can edit this issue to become a proposal. Thanks.

@MatejMagat305
Copy link
Author

I hope that it is finally in proposal form

@cherrymui cherrymui changed the title x/mobile: add permission request on android proposal: x/mobile: add permission request on android Dec 15, 2021
@cherrymui cherrymui modified the milestones: Unreleased, Proposal Dec 15, 2021
@ianlancetaylor ianlancetaylor added this to Incoming in Proposals (old) Dec 15, 2021
@MatejMagat305 MatejMagat305 reopened this Dec 26, 2021
@MatejMagat305
Copy link
Author

above I mention jni option, but maybe it is not nessesery: https://developer.android.com/ndk/reference/group/permission

@bon-ami
Copy link

bon-ami commented Oct 10, 2022

To check a runtime permission, it seems NDK can be used, but with pid & uid?
To request one, according to [question] NDK request permissions, JNI is needed. So I think fyne needs to adopt this.

@ohuolo
Copy link

ohuolo commented May 25, 2023

how can i import Java/java/nio/ByteBuffer with gobind?
when i use gomobile.exe bind -target=android
it reponse cannot find package "Java/java/nio/ByteBuffer" in any of xxx

what class or function in android api can be import to go?

@MatejMagat305
Copy link
Author

MatejMagat305 commented May 25, 2023

how can i import Java/java/nio/ByteBuffer with gobind? when i use gomobile.exe bind -target=android it reponse cannot find package "Java/java/nio/ByteBuffer" in any of xxx

what class or function in android api can be import to go?

you can not direcly do this, you must do this

// #include <jni>
// jobject some_function(...){ ... use jni ...}
// int value(...){ ... use jni ...>
import "C"

func main(){
    o := C.some_function(...) // call C jni
    v := int(C.value(o, ...)) 
}

for example I try bring to go (fyne) android bluetooth: https://github.com/MatejMagat305/fyne-x/blob/master/driver/bluetooth/bluetooth_and.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FeatureRequest mobile Android, iOS, and x/mobile NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Proposal
Projects
Status: Incoming
Development

No branches or pull requests

5 participants