diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 7643783a82f60b3b876fe58a9314fb50520df486..f6631329795d70f75db972aac4a1f206dfdaf754 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,6 +1,11 @@ <component name="ProjectCodeStyleConfiguration"> <code_scheme name="Project" version="173"> <JetCodeStyleSettings> + <option name="PACKAGES_TO_USE_STAR_IMPORTS"> + <value /> + </option> + <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" /> + <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> </JetCodeStyleSettings> <codeStyleSettings language="XML"> diff --git a/mailbox/build.gradle b/mailbox/build.gradle index f6fe2964fe6b7a4ec8d82c172f1348161bf1dd29..1e313bb4db1b61bc056b0d14b851689cfa8dcc5d 100644 --- a/mailbox/build.gradle +++ b/mailbox/build.gradle @@ -16,6 +16,7 @@ android { targetSdkVersion 30 versionCode 1 versionName "1.0" + multiDexEnabled true // only needed when minSdkVersion < 21 testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } @@ -29,16 +30,23 @@ android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 + coreLibraryDesugaringEnabled true } kotlinOptions { jvmTarget = '1.8' } + packagingOptions { + exclude 'META-INF/*' + // Due to https://github.com/Kotlin/kotlinx.coroutines/issues/2023 + exclude 'META-INF/licenses/*' + exclude '**/attach_hotspot_windows.dll' + } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.3.1' - implementation "androidx.activity:activity-ktx:1.2.4" + implementation "androidx.activity:activity-ktx:1.3.0" implementation "androidx.fragment:fragment-ktx:1.3.6" def lifecycle_version = "2.3.1" @@ -47,10 +55,21 @@ dependencies { implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version" - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.constraintlayout:constraintlayout:2.1.0' implementation "com.google.dagger:hilt-android:$hilt_version" kapt "com.google.dagger:hilt-compiler:$hilt_version" + // Java 8 + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + // Multidex needed if we target API < 21 + def multidex_version = "2.0.1" + implementation "androidx.multidex:multidex:$multidex_version" + + def ktorVersion = '1.6.2' + implementation "io.ktor:ktor-server-core:$ktorVersion" + implementation "io.ktor:ktor-server-netty:$ktorVersion" + implementation "ch.qos.logback:logback-classic:1.2.5" + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/mailbox/src/main/AndroidManifest.xml b/mailbox/src/main/AndroidManifest.xml index 9342203e8b08b5809989fe1c470b1e9adf76e6e1..0e535a95782692fe221e63d110bd0f2681c52fde 100644 --- a/mailbox/src/main/AndroidManifest.xml +++ b/mailbox/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.briarproject.mailbox"> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt index cc46087350518193bc455a354cc73ba0ae9a5e4a..72f53354ea774fdd788292aa6d9ed7ac7632e282 100644 --- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt +++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxApplication.kt @@ -1,10 +1,10 @@ package org.briarproject.mailbox -import android.app.Application +import androidx.multidex.MultiDexApplication import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class MailboxApplication : Application() { +class MailboxApplication : MultiDexApplication() { override fun onCreate() { super.onCreate() diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt index 96869014364a7fd79fc275da4628493a66906ef0..476aaaa040e4063c423d7f474704e382bd245359 100644 --- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt +++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxNotificationManager.kt @@ -14,7 +14,9 @@ import androidx.core.app.NotificationCompat.PRIORITY_MIN import androidx.core.content.ContextCompat.getSystemService import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject +import javax.inject.Singleton +@Singleton class MailboxNotificationManager @Inject constructor( @ApplicationContext private val ctx: Context, ) { diff --git a/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt b/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt index 71e14e59152d4a6fc9d2485013c6ffc49439db3b..be22c09ac7b0bd3c973b98601fcdc7c59e14edf7 100644 --- a/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt +++ b/mailbox/src/main/java/org/briarproject/mailbox/MailboxService.kt @@ -7,6 +7,7 @@ import android.os.IBinder import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint import org.briarproject.mailbox.MailboxNotificationManager.Companion.NOTIFICATION_MAIN_ID +import org.briarproject.mailbox.server.WebServerManager import javax.inject.Inject @AndroidEntryPoint @@ -25,10 +26,14 @@ class MailboxService : Service() { } @Inject - lateinit var notificationManager: MailboxNotificationManager + internal lateinit var notificationManager: MailboxNotificationManager + @Inject + internal lateinit var webServerManager: WebServerManager override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { startForeground(NOTIFICATION_MAIN_ID, notificationManager.serviceNotification) + // TODO handle inside LifecycleManager + webServerManager.start() return START_NOT_STICKY } @@ -36,4 +41,9 @@ class MailboxService : Service() { return null } + override fun onDestroy() { + // TODO handle inside LifecycleManager + webServerManager.stop() + super.onDestroy() + } } diff --git a/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt b/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt new file mode 100644 index 0000000000000000000000000000000000000000..0225cdc73862036e637aa15493651f301c3e814a --- /dev/null +++ b/mailbox/src/main/java/org/briarproject/mailbox/server/Routing.kt @@ -0,0 +1,15 @@ +package org.briarproject.mailbox.server + +import android.os.Build +import io.ktor.application.Application +import io.ktor.application.call +import io.ktor.http.ContentType +import io.ktor.response.respondText +import io.ktor.routing.get +import io.ktor.routing.routing + +internal fun Application.configureRouting() = routing { + get("/") { + call.respondText("All good here in ${Build.MODEL}", ContentType.Text.Plain) + } +} diff --git a/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt b/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..13c5afc2c3c96cf1e8b8c5eb11986a944e78407b --- /dev/null +++ b/mailbox/src/main/java/org/briarproject/mailbox/server/WebServerManager.kt @@ -0,0 +1,46 @@ +package org.briarproject.mailbox.server + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import io.ktor.application.install +import io.ktor.features.CallLogging +import io.ktor.server.engine.embeddedServer +import io.ktor.server.netty.Netty +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import java.util.logging.Logger.getLogger +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +internal class WebServerManager @Inject constructor( + @ApplicationContext private val ctx: Context, +) { + + internal companion object { + private const val PORT = 8888 + private val LOG = getLogger(WebServerManager::class.java.name) + } + + private val server by lazy { + embeddedServer(Netty, PORT, watchPaths = emptyList()) { + install(CallLogging) + configureRouting() + } + } + + fun start() { + // hangs if not starting inside a coroutine + GlobalScope.launch(Dispatchers.IO) { + LOG.info("starting") + server.start(wait = true) + LOG.info("started") + } + } + + fun stop() { + server.stop(1_000, 2_000) + } + +}