Advertisement
Guest User

Vpn Service Impl

a guest
Jun 16th, 2025
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 7.27 KB | None | 0 0
  1. class SecureDataModeVpnService :
  2.         VpnService(),
  3.         Handler.Callback {
  4.         private var vpnThread: SecureThread = SecureThread(this)
  5.         private val connectivityChangedReceiver: BroadcastReceiver =
  6.             object : BroadcastReceiver() {
  7.                 override fun onReceive(
  8.                     context: Context,
  9.                     intent: Intent,
  10.                 ) {
  11.                     onConnectivityChanged(intent)
  12.                 }
  13.             }
  14.    
  15.         private val stopSignalBroadcastReceiver: BroadcastReceiver =
  16.             object : BroadcastReceiver() {
  17.                 override fun onReceive(
  18.                     context: Context?,
  19.                     intent: Intent,
  20.                 ) {
  21.                     if (STOP_MESSAGE == intent.action) {
  22.                         debugLog("Received stop signal via stopSignalBroadcastReceiver")
  23.                         onRevoke()
  24.                     }
  25.                 }
  26.             }
  27.    
  28.         override fun onStartCommand(
  29.             intent: Intent?,
  30.             flags: Int,
  31.             startId: Int,
  32.         ): Int {
  33.             debugLog("Received start command")
  34.    
  35.             if (intent?.action == STOP_MESSAGE) {
  36.                 debugLog("Received STOP_MESSAGE via intent action")
  37.                 onRevoke()
  38.                 return START_NOT_STICKY
  39.             }
  40.    
  41.             val notif = buildVpnNotification()
  42.             // Must call startForeground within ~5s or system kills the app
  43.             startForeground(NOTIF_ID, notif)
  44.             debugLog("Started foreground service")
  45.             startVpn()
  46.             return Service.START_STICKY
  47.         }
  48.    
  49.         private fun buildVpnNotification(): Notification {
  50.             debugLog("Building notification channel for foreground service")
  51.             val disconnectIntent =
  52.                 Intent(this, SecureDataModeVpnService::class.java).apply {
  53.                     action = STOP_MESSAGE
  54.                 }
  55.             val pending =
  56.                 PendingIntent.getBroadcast(
  57.                     this,
  58.                     0,
  59.                     disconnectIntent,
  60.                     PendingIntent.FLAG_IMMUTABLE,
  61.                 )
  62.    
  63.             return NotificationCompat
  64.                 .Builder(this, CHANNEL_ID)
  65.                 .setContentTitle("Secure Data Mode")
  66.                 .setContentText("VPN is active")
  67.                 .setSmallIcon(android.R.drawable.ic_secure)
  68.                 .addAction(
  69.                     android.R.drawable.ic_delete,
  70.                     "Disconnect",
  71.                     pending,
  72.                 ).setOngoing(true)
  73.                 .setOnlyAlertOnce(true)
  74.                 .build()
  75.         }
  76.    
  77.         override fun handleMessage(message: Message): Boolean {
  78.     //        when (message.what) {
  79.     //            SecureMessage -> updateVpnStatus(message.arg1)
  80.     //            VPN_MSG_NETWORK_CHANGED -> connectivityChanged(message.obj as Intent)
  81.     //            else -> throw java.lang.IllegalArgumentException("Invalid message with what = " + message.what)
  82.     //        }
  83.             return true
  84.         }
  85.    
  86.         override fun onCreate() {
  87.             super.onCreate()
  88.    
  89.             buildNotificationChannel()
  90.    
  91.             LocalBroadcastManager.getInstance(this).registerReceiver(
  92.                 stopSignalBroadcastReceiver,
  93.                 IntentFilter(STOP_MESSAGE),
  94.             )
  95.             registerReceiver(
  96.                 connectivityChangedReceiver,
  97.                 IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION),
  98.             )
  99.         }
  100.    
  101.         private fun buildNotificationChannel() {
  102.             // start foreground notification, mandatory on newer
  103.             // android versions
  104.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  105.                 NotificationChannel(
  106.                     CHANNEL_ID,
  107.                     "Secure VPN",
  108.                     NotificationManager.IMPORTANCE_LOW,
  109.                 ).apply {
  110.                     description = "Running Secure Data VPN"
  111.                     lockscreenVisibility = Notification.VISIBILITY_PRIVATE
  112.                 }.also { channel ->
  113.                     getSystemService(NotificationManager::class.java)
  114.                         .createNotificationChannel(channel)
  115.                 }
  116.             }
  117.         }
  118.    
  119.         override fun onRevoke() {
  120.             debugLog("Executing onRevoke()...")
  121.             stopVpn()
  122.             super.onRevoke()
  123.         }
  124.    
  125.         override fun onDestroy() {
  126.             stopVpn()
  127.             super.onDestroy()
  128.         }
  129.    
  130.         private fun startVpn() {
  131.             debugLog("Starting VPN Service..")
  132.             status = Status.STARTING
  133.             vpnThread.startThread()
  134.         }
  135.    
  136.         private fun restartVpn() {
  137.             debugLog("Restarting VPN service")
  138.             vpnThread.stopThread()
  139.             vpnThread.startThread()
  140.         }
  141.    
  142.         private fun stopVpn() {
  143.             debugLog("Stopping VPN service")
  144.             vpnThread.stopThread()
  145.             try {
  146.                 LocalBroadcastManager.getInstance(this).unregisterReceiver(stopSignalBroadcastReceiver)
  147.                 debugLog("Unregistered stopSignalBroadcastReceiver")
  148.             } catch (_: IllegalArgumentException) {
  149.                 debugLog("stopSignalBroadcastReceiver already unregistered.")
  150.             }
  151.    
  152.             try {
  153.                 unregisterReceiver(connectivityChangedReceiver)
  154.                 debugLog("Unregistered connectivityChangedReceiver")
  155.             } catch (_: IllegalArgumentException) {
  156.                 debugLog("connectivityChangedReceiver already unregistered.")
  157.             }
  158.             status = Status.STOPPED
  159.             stopSelf()
  160.             debugLog("Stopped VPN service")
  161.         }
  162.    
  163.         private fun waitForNetwork() {
  164.             status = Status.WAITING_FOR_NETWORK
  165.             debugLog("Waiting for network...")
  166.             vpnThread.stopThread()
  167.         }
  168.    
  169.         private fun onConnectivityChanged(intent: Intent) {
  170.             // todo:sp use network capabilities, tranasport_vpn instead
  171.             if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 0) == ConnectivityManager.TYPE_VPN) {
  172.                 return
  173.             }
  174.    
  175.             if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
  176.                 debugLog("No internet connection")
  177.                 waitForNetwork()
  178.             } else {
  179.                 status = Status.RECONNECTING
  180.                 debugLog("Reconnecting to network...")
  181.                 restartVpn()
  182.             }
  183.         }
  184.    
  185.         private fun debugLog(msg: String) {
  186.             Timber.d("$TAG-${SecureDataModeVpnService::class.simpleName}:: $msg")
  187.         }
  188.    
  189.         companion object {
  190.             const val TAG = "SecureDataMode"
  191.             const val VPN_PERMISSION_REQUEST_CODE = 666
  192.             const val STOP_MESSAGE = "STOP"
  193.             var status = Status.STOPPED
  194.             const val CHANNEL_ID = "secure_vpn_channel"
  195.             const val NOTIF_ID = 79467
  196.         }
  197.    
  198.         enum class Status {
  199.             STARTING,
  200.             RUNNING,
  201.             STOPPING,
  202.             STOPPED,
  203.             RECONNECTING,
  204.             WAITING_FOR_NETWORK,
  205.         }
  206.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement