Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android-application/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ if (useGoogleServices) {
}

android {
compileSdk = 34
compileSdk = 35
namespace = "com.inkapplications.ack.android"
defaultConfig {
minSdk = 21
targetSdk = 34
targetSdk = 35
multiDexEnabled = true
buildConfigField("boolean", "USE_GOOGLE_SERVICES", useGoogleServices.toString())
buildConfigField("String", "COMMIT", optionalStringProperty("commit").buildQuote())
Expand Down
6 changes: 5 additions & 1 deletion android-application/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
Expand Down Expand Up @@ -33,7 +36,8 @@
<activity android:name="com.inkapplications.ack.android.tnc.ConnectTncActivity" />
<activity android:name="com.inkapplications.ack.android.onboard.OnboardActivity" android:windowSoftInputMode="adjustResize" />
<activity android:name="com.inkapplications.ack.android.settings.license.LicenseEditActivity" android:windowSoftInputMode="adjustResize" />
<service android:name=".capture.service.BackgroundCaptureService" android:foregroundServiceType="microphone|location" />
<service android:name=".capture.service.BackgroundCaptureServiceAudio" android:foregroundServiceType="microphone|location" />
<service android:name=".capture.service.BackgroundCaptureService" android:foregroundServiceType="location" />
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="@style/AckActionBarTheme.Compat.DayNight"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ package com.inkapplications.ack.android.capture

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.activity.compose.setContent
import androidx.appcompat.app.AlertDialog
import androidx.compose.runtime.collectAsState
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand All @@ -12,6 +18,7 @@ import com.inkapplications.ack.android.capture.messages.conversation.startConver
import com.inkapplications.ack.android.capture.messages.create.CreateConversationActivity
import com.inkapplications.ack.android.capture.messages.index.MessagesScreenController
import com.inkapplications.ack.android.capture.service.BackgroundCaptureService
import com.inkapplications.ack.android.capture.service.BackgroundCaptureServiceAudio
import com.inkapplications.ack.android.connection.DriverSelection
import com.inkapplications.ack.android.log.LogItemViewState
import com.inkapplications.ack.android.log.details.startLogInspectActivity
Expand Down Expand Up @@ -52,6 +59,7 @@ class CaptureActivity: ExtendedActivity(), CaptureNavController, LogIndexControl

private val permissionGate = PermissionGate(this)
private val backgroundCaptureServiceIntent by lazy { Intent(this, BackgroundCaptureService::class.java) }
private val backgroundCaptureAudioServiceIntent by lazy { Intent(this, BackgroundCaptureServiceAudio::class.java) }

override fun onCreate() {
super.onCreate()
Expand Down Expand Up @@ -123,14 +131,40 @@ class CaptureActivity: ExtendedActivity(), CaptureNavController, LogIndexControl

override fun onConnectClick() {
Kimchi.trackEvent("capture_connect")

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val hasBackgroundLocation = checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED

if (!hasBackgroundLocation) {
AlertDialog.Builder(this)
.setTitle("Background Location Permission Required")
.setMessage("To capture data in the background, this app needs access to your location even when the app is closed.\n\nPlease grant \"Allow all the time\" location permission in the application settings.")
.setPositiveButton("Open Settings") { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}
startActivity(intent)
}
.setNegativeButton("Cancel", null)
.show()
return
}
}

lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
permissionGate.withPermissions(*captureEvents.getDriverConnectPermissions().toTypedArray()) {
lifecycleScope.launch {
if (captureEvents.driverSelection.first() == DriverSelection.Tnc) {
startConnectTncActivity(backgroundCaptureServiceIntent)
} else {
startService(backgroundCaptureServiceIntent)
when (captureEvents.driverSelection.first()) {
DriverSelection.Tnc -> {
startConnectTncActivity(backgroundCaptureServiceIntent)
}
DriverSelection.Audio -> {
startForegroundService(backgroundCaptureAudioServiceIntent)
}
else -> {
startForegroundService(backgroundCaptureServiceIntent)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ fun CaptureScreen(
) {
Column {
Scaffold(
modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars),
bottomBar = { CaptureBottomBar(navController) },
floatingActionButton = { CaptureSettingsFab(settingsSheetState) },
isFloatingActionButtonDocked = true,
Expand Down Expand Up @@ -197,7 +198,10 @@ private fun CaptureSettingsSheet(
controlPanelState: ControlPanelState,
captureController: CaptureNavController,
settingsSheetState: BottomSheetScaffoldState,
) = Column(horizontalAlignment = Alignment.CenterHorizontally) {
) = Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars),
) {
val scope = rememberCoroutineScope()
BackHandler(enabled = settingsSheetState.bottomSheetState.isExpanded) {
scope.launch { settingsSheetState.bottomSheetState.collapse() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import javax.inject.Inject
* Service that runs in the background to collect and transmit packets.
*/
@AndroidEntryPoint
class BackgroundCaptureService: Service() {
open class BackgroundCaptureService: Service() {
private lateinit var runScope: CoroutineScope

@Inject
Expand Down Expand Up @@ -51,3 +51,5 @@ class BackgroundCaptureService: Service() {
super.onDestroy()
}
}

class BackgroundCaptureServiceAudio: BackgroundCaptureService()
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,21 @@ private fun Details(
interactive = false,
modifier = Modifier.aspectRatio(16f / 9f),
)
IconButton(
onClick = controller::onBackPressed
Box(
modifier = Modifier
.padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding())
) {
Icon(Icons.Default.ArrowBack, stringResource(R.string.navigate_up))
IconButton(
onClick = controller::onBackPressed
) {
Icon(Icons.Default.ArrowBack, stringResource(R.string.navigate_up))
}
}
}
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = AckTheme.spacing.gutter)) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(top = AckTheme.spacing.gutter)
) {
Text(
viewState.name,
style = AckTheme.typography.h1,
Expand All @@ -78,11 +86,15 @@ private fun Details(
}
} else {
Box(
Modifier.padding(
start = AckTheme.spacing.gutter,
top = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
)
Modifier
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
)
.padding(
start = AckTheme.spacing.gutter,
top = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
)
) {
NavigationRow(
title = {
Expand All @@ -104,12 +116,16 @@ private fun Details(
}
}
Column(
modifier = Modifier.padding(
top = AckTheme.spacing.content,
start = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
bottom = AckTheme.spacing.gutter,
),
modifier = Modifier
.padding(
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
.padding(
top = AckTheme.spacing.content,
start = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
bottom = AckTheme.spacing.gutter,
),
) {
IconRow(
icon = viewState.receiveIcon,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.inkapplications.ack.android.map

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.contentColorFor
Expand Down Expand Up @@ -40,7 +37,11 @@ fun MapScreen(
)
val logState = state.selectedItem
if (state.selectedItemVisible && logState != null) {
Row (modifier = Modifier.padding(top = AckTheme.spacing.gutter)) {
Row (
modifier = Modifier
.padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding())
.padding(top = AckTheme.spacing.gutter)
) {
AprsLogItem(
log = logState,
onClick = onLogItemClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ fun UsageAgreementPrompt(
controller: UserAgreementController,
) {
Column(
modifier = Modifier.padding(AckTheme.spacing.gutter)
modifier = Modifier
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
.padding(AckTheme.spacing.gutter)
.fillMaxHeight()
.verticalScroll(rememberScrollState()),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ fun SettingsScreen(
controller: SettingsController,
) = AckScreen {
Column(
modifier = Modifier.verticalScroll(rememberScrollState()),
modifier = Modifier
.fillMaxSize()
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
.verticalScroll(rememberScrollState()),
) {
NavigationRow(
title = stringResource(R.string.settings_title),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ fun LicensePromptScreen(
onContinue: (LicensePromptFieldValues) -> Unit,
) = AckScreen {
Column (
modifier = Modifier.padding(AckTheme.spacing.gutter),
modifier = Modifier
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
.padding(AckTheme.spacing.gutter),
) {
Text(
"License Info",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,21 @@ private fun StationDetails(
interactive = false,
modifier = Modifier.aspectRatio(16f / 9f),
)
IconButton(
onClick = controller::onBackPressed
Box(
modifier = Modifier
.padding(top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding())
) {
Icon(Icons.Default.ArrowBack, stringResource(R.string.navigate_up))
IconButton(
onClick = controller::onBackPressed
) {
Icon(Icons.Default.ArrowBack, stringResource(R.string.navigate_up))
}
}
}
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = AckTheme.spacing.gutter)) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(top = AckTheme.spacing.gutter)
) {
Text(
viewState.insight.name,
style = AckTheme.typography.h1,
Expand All @@ -69,11 +77,15 @@ private fun StationDetails(
}
} else {
Box(
Modifier.padding(
start = AckTheme.spacing.gutter,
top = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
)
Modifier
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
)
.padding(
start = AckTheme.spacing.gutter,
top = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
)
) {
NavigationRow(
title = {
Expand All @@ -91,12 +103,16 @@ private fun StationDetails(
}
}
Column(
modifier = Modifier.padding(
top = AckTheme.spacing.content,
start = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
bottom = AckTheme.spacing.gutter,
),
modifier = Modifier
.padding(
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
.padding(
top = AckTheme.spacing.content,
start = AckTheme.spacing.gutter,
end = AckTheme.spacing.gutter,
bottom = AckTheme.spacing.gutter,
),
) {
if (viewState.insight.temperature != null) {
IconRow(Icons.Default.WbSunny, viewState.insight.temperature)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AndroidSymbolFactory @Inject constructor(
}

private fun Bitmap.withOverlay(other: Bitmap): Bitmap {
val bmOverlay = Bitmap.createBitmap(width, height, config)
val bmOverlay = Bitmap.createBitmap(width, height, config ?: Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmOverlay)
canvas.drawBitmap(this, Matrix(), null)
canvas.drawBitmap(other, 0f, 0f, null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ fun DeviceList(
is ConnectTncState.Discovering.Empty -> {
Box(
modifier = Modifier.fillMaxSize()
.padding(
top = WindowInsets.statusBars.asPaddingValues().calculateTopPadding(),
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
),
) {
DeviceHeader(controller::onCloseClick)
Column(
Expand Down
2 changes: 1 addition & 1 deletion aprs-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ sqldelight {

android {
namespace = "com.inkapplications.ack.data"
compileSdk = 33
compileSdk = 34
ndkVersion = "21.3.6528147"

defaultConfig {
Expand Down
Loading