-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
android intent call and read response #2790
Comments
Currently the only way to do this is to call out using CGo and use the Android NDK. |
at this point I have question: the function "RunOnJVM" is interna,l I understand why, but since move imports from go/src to readonly go/pkg is dificult add to program own ndk code run on your jvm..., will you plan how to solve it? |
That is a good point @MatejMagat305 - this used to be possible but since we "inlined" the go-mobile code it isn't any more. |
This is too much work to do fast, and not really a blocker. So de-prioritising so we can get 2.2 out then move on with things like this. |
hi, I do not want to be rude or annoying (with silly pull request), and I understand why you de-prioritising this, but I have 2 solutions with relativly small modifications:
the main deference is location of new code, but it is irelevant where it will be, I want pay attantion that the first one return not implemented error the second solution run function on other platform than android ...... (if my changes will be relevant I will create pull request) |
Thank you for trying to help with this. Unfortunately this new API is not easy to understand - the parameters required cannot be discovered from the API usage. We have avoided using |
As with so many things this is not technically very difficult, but designing the correct API to work for all platforms is very difficult - the semantics very for Android/iOS and others. |
I have some work on a proposal that could help here fyne-io/proposals#7 |
Any further update on this? It doesn't seem like iOS has any such equivalent, so this may just need to be a new method on |
The Android "RunNative" from the proposal was released in 2.3. There is no particular API added for activity interaction but if you can use just NDK or the JNI it is now technically possible. |
Can you clarify. Because as I mentioned, |
I was not explaining how to do any specific thing. I was providing an update on the ticket as you requested - as I noticed the progress had not been reported here. No, the API we have does not allow you to intercept or override how the bootstrapping application works. |
Sorry for the misunderstanding. When you said "if you can use just NDK or the JNI it is now technically possible." I interpreted that as saying the requested functionality this issue is for was technically possible. It sounded like the issue was considered resolved and that there was no further work to be done. I'm aware RunNative is implemented, and though the info is appreciated, I was more curious about the planned remaining work. Thanks |
I don't know what we would have to do to make this possible, but I do know that it has not been scheduled and I don't know of anyone working on it at this time. |
I came across this issue while looking for a way to call ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, since my use case involves needing to maintain long running sockets in the background (I'll also probably want to find a way to call this function). It's a little unclear to me what the state of this is. Is it correct to say that I can use #3385 to, in theory, interact with android to directly start an activity or call a function, but that there are no abstractions in Fyne yet to represent an android activity / intent? |
Yes. You can see it in action at https://fynelabs.com/2024/03/01/running-native-android-code-in-a-fyne-app/ |
I've been playing around with this (big thanks for the example up here: https://github.com/fynelabs/devicename). I'm not too familiar with the android subsystems tbh but I've come across an issue where I appear to be using the wrong context for a call (based on The context I'm using comes from using the JNI to call Anyway, posting this here just in case anyone else has run into a similar thing. A bit difficult to describe without sharing a lot of code context, I'm working out of a fork of that example though so perhaps I can push that up if there's interest. |
The error says that you are calling an Activity method on an Application instance - so check that you are passing the right object to the method execution. |
Yes, I should be passing my activity context but I don't know how to get my activity context from the JNI yet. This isn't really a fyne problem (though I was curious if this is something Fyne provides on the Progress at least: |
Alright, sorry to continue to be a bit off topic here, but I did figure this out and it might be helpful to others who get stuck and stumble onto this issue. I learned from looking at the internal android driver code in Fyne that I was right that the So with that, here's some quick and dirty code that should allow you to interact with the power manager using the Fyne run native example :) const char *batteryOptimizationsIgnored(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) {
JNIEnv *env = (JNIEnv*)jni_env;
jclass classNativeActivity = (*env)->FindClass(env, "android/app/NativeActivity");
jclass classPowerManager = (*env)->FindClass(env, "android/os/PowerManager");
jmethodID idNativeActivity_getAppContext = (*env)->GetMethodID(env, classNativeActivity, "getApplicationContext", "()Landroid/content/Context;");
jmethodID idNativeActivity_getSystemService = (*env)->GetMethodID(env, classNativeActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
jstring POWER_SERVICE = (*env)->NewStringUTF(env, "power");
jobject PowerManager = (*env)->CallObjectMethod(env, (jobject)ctx, idNativeActivity_getSystemService, POWER_SERVICE);
jmethodID idPowerManager_isIgnoringBatteryOptimizations = (*env)->GetMethodID(env, classPowerManager, "isIgnoringBatteryOptimizations", "(Ljava/lang/String;)Z");
jstring jPackageName = (*env)->NewStringUTF(env, "fynelabs.devicename");
jboolean isIgnoredBool = (*env)->CallBooleanMethod(env, PowerManager, idPowerManager_isIgnoringBatteryOptimizations, jPackageName);
(*env)->DeleteLocalRef(env, jPackageName);
(*env)->DeleteLocalRef(env, POWER_SERVICE);
if (isIgnoredBool == JNI_TRUE) {
return "ignored";
}
return "not ignored";
} |
Sweet, thanks for sharing. I guess that doesn't quite resolve the headline issue title though right? I think calling and listening to intent calls will be more complex? |
Not yet. I'm currently working on calling an intent (the ignore_battery_optimization action I mentioned earlier) and think I'll have something to share soon there, using the JNI like I did for the power manager stuff. I'm not sure how listening would work, and I don't think I'll need to figure that out for my purposes, but hopefully I can share a working example of calling an intent at least, and that can be a starting point for building something more generalized. |
Alright, here's some code successfully starting an intent via the JNI in Fyne: const char *requestIgnoreBatteryOptimizations(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) {
JNIEnv *env = (JNIEnv*)jni_env;
jclass intentClass = (*env)->FindClass(env, "android/content/Intent");
jmethodID newIntent = (*env)->GetMethodID(env, intentClass, "<init>", "()V");
jobject intent = (*env)->NewObject(env, intentClass, newIntent);
jmethodID methodSetAction = (*env)->GetMethodID(env, intentClass, "setAction", "(Ljava/lang/String;)Landroid/content/Intent;");
jstring actionString = (*env)->NewStringUTF(env, "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS");
jobject intentActivity = (*env)->CallObjectMethod(env, intent, methodSetAction, actionString);
jclass uriClass = (*env)->FindClass(env, "android/net/Uri");
jmethodID uriParse = (*env)->GetStaticMethodID(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
jstring packageName = (*env)->NewStringUTF(env, "package:devicename.fynelabs");
jobject uri = (*env)->CallStaticObjectMethod(env, uriClass, uriParse, packageName);
jmethodID methodSetData = (*env)->GetMethodID(env, intentClass, "setData", "(Landroid/net/Uri;)Landroid/content/Intent;");
(*env)->CallObjectMethod(env, intent, methodSetData, uri);
jclass contextClass = (*env)->GetObjectClass(env, (jobject)ctx);
jmethodID startActivityMethodId = (*env)->GetMethodID(env, contextClass, "startActivity", "(Landroid/content/Intent;)V");
(*env)->CallVoidMethod(env, (jobject)ctx, startActivityMethodId, intentActivity);
return "";
} pretty rough example as before, since I haven't done any error checking or made sure the naming scheme was consistent yet. But it works! As far as getting the result of an activity, I'm not sure, that looks a bit more complicated. But hopefully this serves as a little proof of concept for how intents can be fired off in Fyne. |
Reading an intent response might require modifying Something like myApp.HandleIntentResponse(requestCode, resultCode int, func(Intent data) {
// Fyne got an intent response that matched my request and result codes, now I can act on the data...
}) |
Is your feature request related to a problem? Please describe:
on android side require some operations that provide os or other apps like barcode scan, capture video from camera
Is it possible to construct a solution with the existing API?
no as know
Describe the solution you'd like to see:
I want to call android intent and read response
The text was updated successfully, but these errors were encountered: