owenclave / app/src/main/java/io/nekohasekai/sagernet/ui/VpnRequestActivity.kt

github - dev - back to tree - upstream
/****************************************************************************** * * * Copyright (C) 2021 by nekohasekai * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************/ package io.nekohasekai.sagernet.ui import android.app.Activity import android.app.KeyguardManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.VpnService import android.os.Build import android.os.Bundle import android.widget.Toast import androidx.activity.result.contract.ActivityResultContract import androidx.appcompat.app.AppCompatActivity import androidx.core.content.getSystemService import io.nekohasekai.sagernet.Key import io.nekohasekai.sagernet.R import io.nekohasekai.sagernet.SagerNet import io.nekohasekai.sagernet.database.DataStore import io.nekohasekai.sagernet.ktx.Logs import io.nekohasekai.sagernet.ktx.broadcastReceiver import io.nekohasekai.sagernet.ktx.readableMessage class VpnRequestActivity : AppCompatActivity() { private var receiver: BroadcastReceiver? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (getSystemService()!!.isKeyguardLocked) { receiver = broadcastReceiver { _, _ -> connect.launch(null) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT), Context.RECEIVER_EXPORTED) } else { registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT)) } } else connect.launch(null) } private val connect = registerForActivityResult(StartService()) { if (it) Toast.makeText(this, R.string.vpn_permission_denied, Toast.LENGTH_LONG).show() finish() } override fun onDestroy() { super.onDestroy() if (receiver != null) unregisterReceiver(receiver) } class StartService : ActivityResultContract() { private var cachedIntent: Intent? = null override fun getSynchronousResult( context: Context, input: Void?, ): SynchronousResult? { if (DataStore.serviceMode == Key.MODE_VPN) { try { VpnService.prepare(context) } catch (e: Exception) { Logs.w(e) Toast.makeText(context, e.readableMessage, Toast.LENGTH_LONG).show() null }?.let { intent -> cachedIntent = intent return null } } SagerNet.startService() return SynchronousResult(false) } override fun createIntent(context: Context, input: Void?) = cachedIntent!!.also { cachedIntent = null } override fun parseResult(resultCode: Int, intent: Intent?) = if (resultCode == Activity.RESULT_OK) { SagerNet.startService() false } else { Logs.e("Failed to start VpnService: $intent") true } } }