@@ -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,40 @@ 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;)Landroid/content/Intent;" )
1027+ 
1028+ 			intent , err  :=  callStaticObjectMethod (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+ 			cls  :=  getObjectClass (env , android .appCtx )
1045+ 			stopServiceMethod  :=  getMethodID (env , cls , "stopService" , "(Landroid/content/Intent;)Z" )
1046+ 			callVoidMethod (env , android .appCtx , stopServiceMethod , jvalue (intent ))
1047+ 		})
1048+ 	}()
1049+ 
1050+ 	return  closeChan , <- errChan 
1051+ }
0 commit comments