安卓应用白名单,调整请求展示列表

This commit is contained in:
wanghongenpin
2023-08-16 17:54:34 +08:00
parent 9fff736536
commit 237cca3cf3
18 changed files with 358 additions and 44 deletions

View File

@@ -3,6 +3,8 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:label="ProxyPin"

View File

@@ -1,22 +1,38 @@
package com.network.proxy
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.net.ProxyInfo
import android.net.VpnService
import android.os.Build
import android.os.ParcelFileDescriptor
import androidx.core.app.NotificationCompat
class ProxyVpnService : VpnService() {
/**
* VPN服务
* @author wanghongen
*/
class ProxyVpnService : VpnService(), IProtectSocket {
private var vpnInterface: ParcelFileDescriptor? = null
companion object {
const val ProxyHost = "ProxyHost"
const val ProxyPort = "ProxyPort"
const val AllowApps = "AllowApps" //允许的名单
/**
* 动作:断开连接
*/
const val ACTION_DISCONNECT = "DISCONNECT"
/**
* 通知配置
*/
private const val NOTIFICATION_ID = 9527
const val VPN_NOTIFICATION_CHANNEL_ID = "vpn-notifications"
}
override fun onDestroy() {
@@ -29,36 +45,84 @@ class ProxyVpnService : VpnService() {
disconnect()
START_NOT_STICKY
} else {
connect(intent?.getStringExtra(ProxyHost)!!, intent.getIntExtra(ProxyPort, 0))
connect(
intent?.getStringExtra(ProxyHost)!!, intent.getIntExtra(ProxyPort, 0),
intent.getStringArrayListExtra(AllowApps)
)
START_STICKY
}
}
private fun disconnect() {
vpnInterface?.close()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE)
}
vpnInterface = null
}
private fun connect(proxyHost: String, proxyPort: Int) {
vpnInterface = createVpnInterface(proxyHost, proxyPort)
private fun connect(proxyHost: String, proxyPort: Int, allowPackages: List<String>?) {
vpnInterface = createVpnInterface(proxyHost, proxyPort, allowPackages)
if (vpnInterface == null) {
val alertDialog = Intent(applicationContext, VpnAlertDialog::class.java)
.setAction("com.network.proxy.ProxyVpnService")
alertDialog.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(alertDialog)
return
}
showServiceNotification()
}
private fun createVpnInterface(proxyHost: String, proxyPort: Int): ParcelFileDescriptor? {
return Builder()
.addAddress("10.0.0.2", 32)
.addRoute("0.0.0.0", 0)
.setSession(baseContext.applicationInfo.name)
.also {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
it.addDisallowedApplication(baseContext.packageName)
.setHttpProxy(ProxyInfo.buildDirectProxy(proxyHost, proxyPort))
private fun showServiceNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val notificationChannel = NotificationChannel(
VPN_NOTIFICATION_CHANNEL_ID,
"VPN Status",
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(notificationChannel)
}
val pendingActivityIntent: PendingIntent =
Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
}
val notification: Notification =
NotificationCompat.Builder(this, VPN_NOTIFICATION_CHANNEL_ID)
.setContentIntent(pendingActivityIntent)
.setContentTitle(getString(R.string.vpn_active_notification_title))
.setContentText(getString(R.string.vpn_active_notification_content))
.setOngoing(true)
.build()
startForeground(NOTIFICATION_ID, notification)
}
private fun createVpnInterface(proxyHost: String, proxyPort: Int, allowPackages: List<String>?):
ParcelFileDescriptor? {
val build = Builder()
.setMtu(MAX_PACKET_LEN)
.addAddress("10.0.0.2", 32)
.addRoute("0.0.0.0", 0)
.setSession(baseContext.applicationInfo.name)
if (allowPackages?.isNotEmpty() == true) {
allowPackages.forEach {
if (it != baseContext.packageName)
build.addAllowedApplication(it)
}
.establish()
} else {
build.addDisallowedApplication(baseContext.packageName)
}
return build.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setHttpProxy(ProxyInfo.buildDirectProxy(proxyHost, proxyPort))
}
}.establish()
}

View File

@@ -20,13 +20,22 @@ class VpnServicePlugin : AndroidFlutterPlugin() {
"startVpn" -> {
val host = call.argument<String>("proxyHost")
val port = call.argument<Int>("proxyPort")
startVpn(host!!, port!!)
val allowApps = call.argument<ArrayList<String>>("allowApps")
startVpn(host!!, port!!, allowApps)
}
"stopVpn" -> {
stopVpn()
}
"restartVpn" -> {
val host = call.argument<String>("proxyHost")
val port = call.argument<Int>("proxyPort")
val allowApps = call.argument<ArrayList<String>>("allowApps")
stopVpn()
startVpn(host!!, port!!, allowApps)
}
else -> {
result.notImplemented()
}
@@ -37,11 +46,12 @@ class VpnServicePlugin : AndroidFlutterPlugin() {
/**
* 启动vpn服务
*/
private fun startVpn(host: String, port: Int) {
Log.i("com.network.proxy", "startVpn")
private fun startVpn(host: String, port: Int, allowApps: ArrayList<String>?) {
Log.i("com.network.proxy", "startVpn $allowApps")
val intent = Intent(activity, ProxyVpnService::class.java)
intent.putExtra(ProxyVpnService.ProxyHost, host)
intent.putExtra(ProxyVpnService.ProxyPort, port)
intent.putStringArrayListExtra(ProxyVpnService.AllowApps, allowApps)
activity.startService(intent)
}

View File

@@ -15,4 +15,8 @@
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
<string name="vpn_active_notification_title">ProxyPin Active</string>
<string name="vpn_active_notification_content">抓包正在运行</string>
</resources>