@@ -40,6 +40,14 @@ static jclass jni_GetObjectClass(JNIEnv *env, jobject obj) {
4040 return (*env)->GetObjectClass(env, obj);
4141}
4242
43+ static jclass jni_FindClass(JNIEnv *env, const char *name) {
44+ return (*env)->FindClass(env, name);
45+ }
46+
47+ static jobject jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID) {
48+ return (*env)->NewObject(env, clazz, methodID);
49+ }
50+
4351static jmethodID jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
4452 return (*env)->GetMethodID(env, clazz, name, sig);
4553}
@@ -774,6 +782,59 @@ func getObjectClass(env *C.JNIEnv, obj C.jobject) C.jclass {
774782 return cls
775783}
776784
785+ // getIntent loads class and returns an android.content.Intent or error
786+ func getIntent (env * C.JNIEnv , obj C.jobject , class string ) (C.jobject , error ) {
787+ cls := getObjectClass (env , obj ) // android.app.Application
788+ getClassLoader := getMethodID (env , cls , "getClassLoader" , "()Ljava/lang/ClassLoader;" )
789+ ldr , err := callObjectMethod (env , obj , getClassLoader )
790+ if err != nil {
791+ return 0 , err
792+ }
793+ loadClassMethod := getMethodID (env , getObjectClass (env , ldr ), "loadClass" , "(Ljava/lang/String;)Ljava/lang/Class;" )
794+ loaded , err := callObjectMethod (env , ldr , loadClassMethod , jvalue (javaString (env , class )))
795+ if err != nil {
796+ return 0 , err
797+ }
798+ c := C .CString ("android/content/Intent" )
799+ defer C .free (unsafe .Pointer (c ))
800+ intentClass := C .jni_FindClass (env , c )
801+ if err := exception (env ); err != nil {
802+ return 0 , err
803+ }
804+ intentInit := getMethodID (env , intentClass , "<init>" , "()V" )
805+ intent := C .jni_NewObject (env , intentClass , intentInit )
806+ setClassMethod := getMethodID (env , intentClass , "setClass" , "(Landroid/content/Context;Ljava/lang/Class;)Landroid/content/Intent;" )
807+ _ , err = callObjectMethod (env , intent , setClassMethod , jvalue (obj ), jvalue (C .jclass (loaded )))
808+ if err != nil {
809+ return 0 , err
810+ }
811+
812+ return intent , nil
813+ }
814+
815+ // setforegroundIntentExtras adds the notification text to the intent.
816+ func setforegroundIntentExtras (env * C.JNIEnv , intent C.jobject , id int , name , desc string ) {
817+ cls := getObjectClass (env , intent )
818+ putExtraStringMethod := getMethodID (env , cls , "putExtra" , "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;" )
819+ putExtraIntMethod := getMethodID (env , cls , "putExtra" , "(Ljava/lang/String;I)Landroid/content/Intent;" )
820+ _ , err := callObjectMethod (env , intent , putExtraStringMethod , jvalue (javaString (env , "channelID" )), jvalue (javaString (env , name )))
821+ if err != nil {
822+ panic (err )
823+ }
824+ _ , err = callObjectMethod (env , intent , putExtraStringMethod , jvalue (javaString (env , "channelName" )), jvalue (javaString (env , name )))
825+ if err != nil {
826+ panic (err )
827+ }
828+ _ , err = callObjectMethod (env , intent , putExtraStringMethod , jvalue (javaString (env , "channelDesc" )), jvalue (javaString (env , desc )))
829+ if err != nil {
830+ panic (err )
831+ }
832+ _ , err = callObjectMethod (env , intent , putExtraIntMethod , jvalue (javaString (env , "notificationID" )), jvalue (id ))
833+ if err != nil {
834+ panic (err )
835+ }
836+ }
837+
777838// goString converts the JVM jstring to a Go string.
778839func goString (env * C.JNIEnv , str C.jstring ) string {
779840 if str == 0 {
@@ -951,3 +1012,38 @@ func Java_org_gioui_Gio_scheduleMainFuncs(env *C.JNIEnv, cls C.jclass) {
9511012}
9521013
9531014func (_ ViewEvent ) ImplementsEvent () {}
1015+
1016+ // StartForeground starts a foreground service and returns a channel that stops the service when closed or error.
1017+ func StartForeground (title , text string ) (chan struct {}, error ) {
1018+ var closeChan chan struct {}
1019+ errChan := make (chan error )
1020+
1021+ // get a handle on the startService, stopService methods of GioForegroundService
1022+ // run everything in a goroutine so that start/stop calls are from the same thread
1023+ go func () {
1024+ runInJVM (javaVM (), func (env * C.JNIEnv ) {
1025+ startForegroundService := getStaticMethodID (env , android .gioCls ,
1026+ "startForegroundService" , "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V" )
1027+
1028+ err := callStaticVoidMethod (env , android .gioCls ,
1029+ startForegroundService ,
1030+ jvalue (android .appCtx ),
1031+ jvalue (javaString (env , "org/gioui/GioForegroundService" )),
1032+ jvalue (javaString (env , title )),
1033+ jvalue (javaString (env , text )),
1034+ )
1035+ if err != nil {
1036+ errChan <- err
1037+ return
1038+ }
1039+
1040+ // wait for the channel to close, and then halt the foreground service
1041+ // create an intent and set it to the foregroundService
1042+ errChan <- nil
1043+ <- closeChan
1044+ callVoidMethod (env , android .appCtx , stopServiceMethod , jvalue (intent ))
1045+ })
1046+ }()
1047+
1048+ return closeChan , <- errChan
1049+ }
0 commit comments