mirror of
https://github.com/yggdrasil-network/yggdrasil-android.git
synced 2025-04-27 21:55:08 +03:00
Implemented Yggdrasil start after device boot (#39)
Implemented Yggdrasil start after device boot (even if Always-On VPN disabled).
This commit is contained in:
parent
055aab328d
commit
a07412d02d
7 changed files with 93 additions and 21 deletions
|
@ -5,6 +5,7 @@
|
|||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
android:name=".GlobalApplication"
|
||||
|
@ -13,7 +14,8 @@
|
|||
android:label="@string/app_name"
|
||||
android:roundIcon="@drawable/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Yggdrasil">
|
||||
android:theme="@style/Theme.Yggdrasil"
|
||||
android:largeHeap="true">
|
||||
<activity android:name=".MainActivity" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -57,6 +59,12 @@
|
|||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:name=".BootUpReceiver" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,40 @@
|
|||
package eu.neilalexander.yggdrasil
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.util.Log
|
||||
import androidx.preference.PreferenceManager
|
||||
|
||||
class BootUpReceiver : BroadcastReceiver() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "BootUpReceiver"
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action != Intent.ACTION_BOOT_COMPLETED) {
|
||||
Log.w(TAG, "Wrong action: ${intent.action}")
|
||||
}
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
if (!preferences.getBoolean(PREF_KEY_ENABLED, false)) {
|
||||
Log.i(TAG, "Yggdrasil disabled, not starting service")
|
||||
return
|
||||
}
|
||||
Log.i(TAG, "Yggdrasil enabled, starting service")
|
||||
val serviceIntent = Intent(context, PacketTunnelProvider::class.java)
|
||||
serviceIntent.action = PacketTunnelProvider.ACTION_START
|
||||
|
||||
val vpnIntent = VpnService.prepare(context)
|
||||
if (vpnIntent != null) {
|
||||
Log.i(TAG, "Need to ask for VPN permission")
|
||||
val notification = createPermissionMissingNotification(context)
|
||||
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
manager.notify(444, notification)
|
||||
} else {
|
||||
context.startService(serviceIntent)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ class DnsActivity : AppCompatActivity() {
|
|||
val builder: AlertDialog.Builder = AlertDialog.Builder(ContextThemeWrapper(this, R.style.Theme_MaterialComponents_DayNight_Dialog))
|
||||
builder.setTitle(getString(R.string.dns_add_server_dialog_title))
|
||||
builder.setView(view)
|
||||
builder.setPositiveButton(getString(R.string.add)) { dialog, _ ->
|
||||
builder.setPositiveButton(getString(R.string.add)) { _, _ ->
|
||||
val server = input.text.toString()
|
||||
if (!servers.contains(server)) {
|
||||
servers.add(server)
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.annotation.RequiresApi
|
|||
import androidx.core.app.NotificationCompat
|
||||
|
||||
const val PREF_KEY_ENABLED = "enabled"
|
||||
const val MAIN_CHANNEL_ID = "Yggdrasil Service"
|
||||
|
||||
class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
|
||||
private lateinit var config: ConfigurationProxy
|
||||
|
@ -62,21 +63,7 @@ class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
|
|||
}
|
||||
|
||||
fun createServiceNotification(context: Context, state: State): Notification {
|
||||
// Create the NotificationChannel, but only on API 26+ because
|
||||
// the NotificationChannel class is new and not in the support library
|
||||
val channelId = "Foreground Service"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val name = context.getString(R.string.channel_name)
|
||||
val descriptionText = context.getString(R.string.channel_description)
|
||||
val importance = NotificationManager.IMPORTANCE_MIN
|
||||
val channel = NotificationChannel(channelId, name, importance).apply {
|
||||
description = descriptionText
|
||||
}
|
||||
// Register the channel with the system
|
||||
val notificationManager: NotificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
createNotificationChannels(context)
|
||||
|
||||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
|
@ -90,7 +77,7 @@ fun createServiceNotification(context: Context, state: State): Notification {
|
|||
else -> context.getText(R.string.tile_disabled)
|
||||
}
|
||||
|
||||
return NotificationCompat.Builder(context, channelId)
|
||||
return NotificationCompat.Builder(context, MAIN_CHANNEL_ID)
|
||||
.setShowWhen(false)
|
||||
.setContentTitle(text)
|
||||
.setSmallIcon(R.drawable.ic_tile_icon)
|
||||
|
@ -98,3 +85,38 @@ fun createServiceNotification(context: Context, state: State): Notification {
|
|||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun createPermissionMissingNotification(context: Context): Notification {
|
||||
createNotificationChannels(context)
|
||||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
return NotificationCompat.Builder(context, MAIN_CHANNEL_ID)
|
||||
.setShowWhen(false)
|
||||
.setContentTitle(context.getText(R.string.app_name))
|
||||
.setContentText(context.getText(R.string.permission_notification_text))
|
||||
.setSmallIcon(R.drawable.ic_tile_icon)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun createNotificationChannels(context: Context) {
|
||||
// Create the NotificationChannel, but only on API 26+ because
|
||||
// the NotificationChannel class is new and not in the support library
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val name = context.getString(R.string.channel_name)
|
||||
val descriptionText = context.getString(R.string.channel_description)
|
||||
val importance = NotificationManager.IMPORTANCE_MIN
|
||||
val channel = NotificationChannel(MAIN_CHANNEL_ID, name, importance).apply {
|
||||
description = descriptionText
|
||||
}
|
||||
// Register the channel with the system
|
||||
val notificationManager: NotificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ import kotlin.concurrent.thread
|
|||
private const val TAG = "PacketTunnelProvider"
|
||||
const val SERVICE_NOTIFICATION_ID = 1000
|
||||
|
||||
class PacketTunnelProvider: VpnService() {
|
||||
open class PacketTunnelProvider: VpnService() {
|
||||
companion object {
|
||||
const val STATE_INTENT = "eu.neilalexander.yggdrasil.PacketTunnelProvider.STATE_MESSAGE"
|
||||
|
||||
|
@ -68,9 +68,9 @@ class PacketTunnelProvider: VpnService() {
|
|||
ACTION_CONNECT -> {
|
||||
Log.d(TAG, "Connecting...")
|
||||
if (started.get()) {
|
||||
connect();
|
||||
connect()
|
||||
} else {
|
||||
start();
|
||||
start()
|
||||
}
|
||||
START_STICKY
|
||||
}
|
||||
|
|
|
@ -75,4 +75,5 @@
|
|||
<string name="location_buffalo">Баффало, США</string>
|
||||
<string name="channel_name">Сервис VPN</string>
|
||||
<string name="channel_description">Главный канал нотификаций сервиса</string>
|
||||
<string name="permission_notification_text">Нажмите здесь чтобы включить Yggdrasil.</string>
|
||||
</resources>
|
|
@ -75,4 +75,5 @@
|
|||
<string name="location_buffalo">Buffalo, US</string>
|
||||
<string name="channel_name">VPN Service</string>
|
||||
<string name="channel_description">Main channel for foreground notification</string>
|
||||
<string name="permission_notification_text">Tap here to enable Yggdrasil.</string>
|
||||
</resources>
|
Loading…
Add table
Add a link
Reference in a new issue