Skip to content
This repository has been archived by the owner on Jul 11, 2024. It is now read-only.

Commit

Permalink
feat: improve logging and refactor (#56)
Browse files Browse the repository at this point in the history
Added improved logging with both file logging and live flow for ui to display.

Refactored file utilities.

Added coroutine injection and application scope injection.

Cleaned up redundant coroutine declarations.

Improve quick tile state management and efficiency.

Refactored vpn lib and vpn service stop.
  • Loading branch information
zaneschepke authored May 27, 2024
1 parent 00b5d24 commit bc0e7ac
Show file tree
Hide file tree
Showing 52 changed files with 1,164 additions and 564 deletions.
194 changes: 104 additions & 90 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<!--start vpn on boot permission-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".NymVpn"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppSplashScreen"
tools:node="merge"
tools:targetApi="33">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<!--start vpn on boot permission-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".NymVpn"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppSplashScreen"
tools:node="merge"
tools:targetApi="33">
<activity
android:name=".ui.SplashActivity"
android:exported="true"
Expand All @@ -38,83 +38,97 @@
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
tools:replace="screenOrientation" />
<activity
android:name=".ui.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="true"
<activity
android:name=".ui.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:exported="true"
android:theme="@style/Theme.NymVPN"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
</intent-filter>
</activity>
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data
android:host="10.0.1.91"
android:port="5500" />
<data android:mimeType="text/plain" />
<data android:path="/index.html" />
</intent-filter>
</activity>
<activity
android:name=".ui.ShortcutActivity"
android:enabled="true"
android:exported="true"
android:finishOnTaskLaunch="true"
android:theme="@android:style/Theme.NoDisplay" />
<service
android:name=".service.tile.VpnQuickTile"
android:exported="true"
android:icon="@drawable/ic_stat_name"
android:label="@string/app_name"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<meta-data
android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
<meta-data
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />

<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<receiver
android:name=".receiver.BootReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<service
android:name=".service.tile.VpnQuickTile"
android:exported="true"
android:icon="@drawable/ic_stat_name"
android:label="@string/app_name"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<meta-data
android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
<meta-data
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />

<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<receiver
android:name=".receiver.BootReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />

<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name=".service.AlwaysOnVpnService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="systemExempted"
android:permission="android.permission.BIND_VPN_SERVICE"
android:persistent="true"
tools:node="merge">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
<meta-data
android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
android:value="true" />
</service>
<!-- Sentry -->
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />
<!-- enable screenshot for crashes -->
<meta-data
android:name="io.sentry.attach-screenshot"
android:value="true" />
<!-- enable view hierarchy for crashes -->
<meta-data
android:name="io.sentry.attach-view-hierarchy"
android:value="true" />
<meta-data
android:name="io.sentry.release"
android:value="@string/fullVersionName" />
</application>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name=".service.AlwaysOnVpnService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="systemExempted"
android:permission="android.permission.BIND_VPN_SERVICE"
android:persistent="true"
tools:node="merge">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
<meta-data
android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
android:value="true" />
</service>
<!-- Sentry -->
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />
<!-- enable screenshot for crashes -->
<meta-data
android:name="io.sentry.attach-screenshot"
android:value="true" />
<!-- enable view hierarchy for crashes -->
<meta-data
android:name="io.sentry.attach-view-hierarchy"
android:value="true" />
<meta-data
android:name="io.sentry.release"
android:value="@string/fullVersionName" />
</application>

</manifest>
39 changes: 39 additions & 0 deletions app/src/main/java/net/nymtech/nymvpn/NymVpn.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,39 @@ import android.service.quicksettings.TileService
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import dagger.hilt.android.HiltAndroidApp
import io.sentry.Sentry
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.nymtech.logcathelper.LogCollect
import net.nymtech.logcathelper.model.LogLevel
import net.nymtech.logcathelper.model.LogMessage
import net.nymtech.nymvpn.module.ApplicationScope
import net.nymtech.nymvpn.module.IoDispatcher
import net.nymtech.nymvpn.service.tile.VpnQuickTile
import net.nymtech.nymvpn.util.Constants
import net.nymtech.nymvpn.util.actionBarSize
import net.nymtech.nymvpn.util.log.DebugTree
import net.nymtech.nymvpn.util.log.NymLibException
import net.nymtech.nymvpn.util.log.ReleaseTree
import net.nymtech.vpn.model.Environment
import timber.log.Timber
import javax.inject.Inject

@HiltAndroidApp
class NymVpn : Application() {

@Inject
@ApplicationScope
lateinit var applicationScope: CoroutineScope

@Inject
@IoDispatcher
lateinit var ioDispatcher: CoroutineDispatcher

@Inject
lateinit var logCollect: LogCollect

override fun onCreate() {
super.onCreate()
instance = this
Expand All @@ -34,6 +57,22 @@ class NymVpn : Application() {
} else {
Timber.plant(ReleaseTree())
}
applicationScope.launch(ioDispatcher) {
logCollect.start(onLogMessage = { reportLibExceptions(it) })
}
}

private fun reportLibExceptions(message: LogMessage) {
when (message.level) {
LogLevel.ERROR -> {
if (message.tag.contains(Constants.NYM_VPN_LIB_TAG)) {
Sentry.captureException(
NymLibException("${message.time} - ${message.tag} ${message.message}"),
)
}
}
else -> Unit
}
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException

class DataStoreManager(private val context: Context) {
class DataStoreManager(
private val context: Context,
private val ioDispatcher: CoroutineDispatcher,
) {

// preferences
private val preferencesKey = "preferences"
Expand All @@ -21,29 +26,35 @@ class DataStoreManager(private val context: Context) {
)

suspend fun <T> saveToDataStore(key: Preferences.Key<T>, value: T) {
try {
context.dataStore.edit { it[key] = value }
} catch (e: IOException) {
Timber.e(e)
withContext(ioDispatcher) {
try {
context.dataStore.edit { it[key] = value }
} catch (e: IOException) {
Timber.e(e)
}
}
}

suspend fun <T> clear(key: Preferences.Key<T>) {
try {
context.dataStore.edit { it.remove(key) }
} catch (e: IOException) {
Timber.e(e)
withContext(ioDispatcher) {
try {
context.dataStore.edit { it.remove(key) }
} catch (e: IOException) {
Timber.e(e)
}
}
}

fun <T> getFromStoreFlow(key: Preferences.Key<T>) = context.dataStore.data.map { it[key] }

suspend fun <T> getFromStore(key: Preferences.Key<T>): T? {
return try {
context.dataStore.data.map { it[key] }.first()
} catch (e: IOException) {
Timber.e(e)
null
return withContext(ioDispatcher) {
try {
context.dataStore.data.map { it[key] }.first()
} catch (e: IOException) {
Timber.e(e)
null
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class DataStoreSettingsRepository(private val dataStoreManager: DataStoreManager
}

override suspend fun setTheme(theme: Theme) {
dataStoreManager.saveToDataStore(this.theme, theme.name)
dataStoreManager.saveToDataStore(this@DataStoreSettingsRepository.theme, theme.name)
}

override suspend fun getVpnMode(): VpnMode {
Expand Down Expand Up @@ -77,7 +77,7 @@ class DataStoreSettingsRepository(private val dataStoreManager: DataStoreManager
}

override suspend fun setLastHopCountry(country: Country) {
dataStoreManager.saveToDataStore(lastHopCountry, country.toString())
return dataStoreManager.saveToDataStore(lastHopCountry, country.toString())
}

override suspend fun isAutoStartEnabled(): Boolean {
Expand Down
Loading

0 comments on commit bc0e7ac

Please sign in to comment.