GnunetCoreService.kt (4183B)
1 package org.gnu.gnunet.core 2 3 import android.app.Notification 4 import android.app.NotificationChannel 5 import android.app.NotificationManager 6 import android.app.PendingIntent 7 import android.app.Service 8 import android.content.Context 9 import android.content.Intent 10 import android.content.res.AssetManager 11 import android.os.Build 12 import android.os.Handler 13 import android.os.HandlerThread 14 import android.os.IBinder 15 import android.util.Log 16 import androidx.core.app.NotificationCompat 17 import org.gnu.gnunet.R 18 import org.gnu.gnunet.MainActivity 19 import org.gnunet.gnunetmessenger.ipc.IAccountCallback 20 import org.gnunet.gnunetmessenger.ipc.IChatCallback 21 22 23 object NativeBridge { 24 init { 25 System.loadLibrary("gnunet") 26 } 27 external fun stringFromJNI(assets: AssetManager, path: String): String 28 @JvmStatic external fun initCfgFromAsset(assetManager: AssetManager, assetName: String): Long 29 @JvmStatic external fun destroyCfg(cfgPtr: Long) 30 @JvmStatic external fun nativeStartChatUsingCfg(cfgPtr: Long, appName: String, cb: IChatCallback): Long 31 @JvmStatic external fun nativeDisconnect(sessionHandle: Long) 32 @JvmStatic external fun nativeGetProfileName(sessionHandle: Long): String 33 @JvmStatic external fun nativeSetProfileName(sessionHandle: Long, name: String) 34 @JvmStatic external fun nativeCreateAccount(sessionHandle: Long, name: String): Int 35 @JvmStatic external fun nativeConnect(sessionHandle: Long, accountKey: String, accountName: String) 36 @JvmStatic external fun nativeIterateAccounts(sessionHandle: Long, cb: IAccountCallback) 37 } 38 39 class GnunetCoreService : Service() { 40 41 companion object { 42 private const val TAG = "GnunetCoreService" 43 private const val CHANNEL_ID = "gnunet_core_channel" 44 private const val NOTIF_ID = 1001 45 } 46 47 private lateinit var thread: HandlerThread 48 private lateinit var handler: Handler 49 50 override fun onCreate() { 51 super.onCreate() 52 createNotificationChannel() 53 54 // Vordergrunddienst starten (ab Android 8 Pflicht, wenn dauerhaft läuft) 55 startForeground(NOTIF_ID, buildOngoingNotification()) 56 57 // Eigener Looper-Thread für GNUnet 58 thread = HandlerThread("gnunet-core") 59 thread.start() 60 handler = Handler(thread.looper) 61 62 // GNUnet-Start in den Worker-Thread verschieben (niemals im UI-Thread!) 63 handler.post { 64 try { 65 val res = NativeBridge.stringFromJNI(assets, filesDir.absolutePath) 66 Log.d(TAG, "GNUnet started: $res") 67 } catch (t: Throwable) { 68 Log.e(TAG, "GNUnet start failed", t) 69 stopSelf() 70 } 71 } 72 } 73 74 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 75 // dauerhaft laufen lassen 76 return START_STICKY 77 } 78 79 override fun onDestroy() { 80 super.onDestroy() 81 if (this::thread.isInitialized) { 82 thread.quitSafely() 83 } 84 } 85 86 override fun onBind(intent: Intent?): IBinder? = null 87 88 // ---- Notification Helfer ---- 89 90 private fun buildOngoingNotification(): Notification { 91 // Optional: Tap öffnet deine App 92 val contentIntent = PendingIntent.getActivity( 93 this, 94 0, 95 Intent(this, MainActivity::class.java), 96 PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT 97 ) 98 99 return NotificationCompat.Builder(this, CHANNEL_ID) 100 .setSmallIcon(R.mipmap.ic_launcher) // eigenes Icon verwenden 101 .setContentTitle("GNUnet läuft") 102 .setContentText("Der GNUnet-Dienst ist aktiv.") 103 .setOngoing(true) 104 .setContentIntent(contentIntent) 105 .build() 106 } 107 108 private fun createNotificationChannel() { 109 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 110 val mgr = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 111 val ch = NotificationChannel( 112 CHANNEL_ID, 113 "GNUnet Core", 114 NotificationManager.IMPORTANCE_LOW 115 ) 116 mgr.createNotificationChannel(ch) 117 } 118 } 119 }