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
8 changes: 6 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
tools:targetApi="34" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- TODO(auto-connect): enable when an explicit auto-connect-on-boot setting exists. -->
<!-- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<queries>
Expand Down Expand Up @@ -76,12 +77,15 @@
</intent-filter>
</service>

<!--
TODO(auto-connect): enable only after adding explicit Settings UI and permission-safe startup flow.
<receiver
android:name=".service.BootReceiver"
android:exported="true">
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
-->
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ interface ProfileDao {
@Query("SELECT * FROM profiles WHERE isSelected = 1 LIMIT 1")
fun getSelectedProfileFlow(): Flow<ProfileEntity?>

@Query("SELECT * FROM profiles ORDER BY createdAt DESC LIMIT 1")
suspend fun getNewestProfile(): ProfileEntity?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertProfile(profile: ProfileEntity): Long

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@ class ProfileRepository @Inject constructor(

suspend fun updateProfile(profile: ProfileEntity) = profileDao.updateProfile(profile)

suspend fun deleteProfile(profile: ProfileEntity) = profileDao.deleteProfile(profile)
suspend fun deleteProfile(profile: ProfileEntity) {
val wasSelected = profile.isSelected
profileDao.deleteProfile(profile)
if (wasSelected) {
profileDao.getNewestProfile()?.let { remaining ->
profileDao.setSelectedProfile(remaining.id)
}
}
}

suspend fun setSelectedProfile(id: Long) = profileDao.setSelectedProfile(id)
}
28 changes: 14 additions & 14 deletions android/app/src/main/java/com/masterdns/vpn/service/BootReceiver.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.masterdns.vpn.service

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log

class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
Log.i("MasterDnsVPN", "Boot completed, auto-connect can be triggered here")
// TODO: Check settings if auto-connect on boot is enabled
// If so, load selected profile and start VPN service
}
}
}
/*
* TODO(auto-connect): keep this receiver dormant until the app has an explicit
* auto-connect-on-boot setting and a permission-safe startup flow.
*
* Intended shape:
*
* class BootReceiver : BroadcastReceiver() {
* override fun onReceive(context: Context, intent: Intent) {
* if (intent.action != Intent.ACTION_BOOT_COMPLETED) return
* // Check user setting, VPN permission, and selected profile.
* // Start MasterDnsVpnService only when all prerequisites are satisfied.
* }
* }
*/
Loading