mirror of
				https://github.com/yggdrasil-network/yggdrasil-android.git
				synced 2025-11-01 01:35:06 +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
	
	 Revertron
						Revertron