Khubaib преди 1 година
родител
ревизия
e6b0374487

+ 19 - 0
app/src/main/AndroidManifest.xml

@@ -133,6 +133,25 @@
             </intent-filter>
         </service>
 
+        <receiver
+            android:name=".widgets.SimpleAppWidget"
+            android:permission="android.permission.BIND_VPN_SERVICE"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/simple_app_widget_info" />
+        </receiver>
+
+        <service android:name=".utils.WireGuardService"
+            android:exported="true"
+            android:enabled="true"
+            android:foregroundServiceType="specialUse"
+            />
+
     </application>
 
 </manifest>

+ 2 - 0
app/src/main/java/com/vpn/fastestvpnservice/MainActivity.kt

@@ -35,6 +35,7 @@ import com.vpn.fastestvpnservice.beans.isDarkTheme
 import com.vpn.fastestvpnservice.beans.selectedtheme
 import com.vpn.fastestvpnservice.beans.themesList
 import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.interfaces.VPNConnectionCallBacks
 import com.vpn.fastestvpnservice.navigation.SetUpNavGraph
 import com.vpn.fastestvpnservice.ui.theme.FastestVPNTheme
 import com.vpn.fastestvpnservice.viewmodels.BillingViewModel
@@ -108,6 +109,7 @@ class MainActivity : ComponentActivity() {
         var isAutoEnabled: Boolean = false
         var isSnrNotify: Boolean = false
         var isSelectedServersShown: Boolean = false
+        var vpnConnectionCallBacks: VPNConnectionCallBacks? = null
     }
 }
 

+ 11 - 0
app/src/main/java/com/vpn/fastestvpnservice/interfaces/VPNConnectionCallBacks.kt

@@ -0,0 +1,11 @@
+package com.vpn.fastestvpnservice.interfaces
+
+interface VPNConnectionCallBacks {
+
+    fun onVpnConnecting()
+    fun onVpnConnected()
+    fun onVpnDisconnected()
+    fun onGetIp()
+    fun onServerNotResponding()
+
+}

+ 2 - 1
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/HomeScreen.kt

@@ -1,5 +1,6 @@
 package com.vpn.fastestvpnservice.screens.bottomNavBarScreens
 
+import android.appwidget.AppWidgetProvider
 import android.content.Context
 import android.content.res.Configuration
 import android.location.Location
@@ -1327,4 +1328,4 @@ fun HomePreview() {
 @Composable
 fun HomePreviewDark() {
 //    Home(rememberNavController())
-}
+}

+ 9 - 0
app/src/main/java/com/vpn/fastestvpnservice/utils/VPNConnectionsUtil.kt

@@ -34,6 +34,7 @@ import com.vpn.fastestvpnservice.helpers.UIHelper
 import com.vpn.fastestvpnservice.openVpnUtils.EncryptData
 import com.vpn.fastestvpnservice.screens.bottomNavBarScreens.ikev2Callback
 import com.vpn.fastestvpnservice.viewmodels.HomeViewModel
+import com.vpn.fastestvpnservice.widgets.SimpleAppWidget
 import com.wireguard.android.backend.Backend
 import com.wireguard.android.backend.GoBackend
 import com.wireguard.android.backend.Tunnel
@@ -358,10 +359,18 @@ class VPNConnectionsUtil: VpnStatus.StateListener {
                     homeViewModel.setConnectState(App.CONNECTED)
                     Log.d("test_wg", "tunnelStatus if = ${App.tunnelStatus}")
 
+                    val widgetIntent = Intent(context, SimpleAppWidget::class.java)
+                    widgetIntent.action = SimpleAppWidget.ACTION_CONNECT_VPN
+                    context.sendBroadcast(widgetIntent)
+
                 } else {
                     App.tunnelStatus = Tunnel.State.DOWN
                     homeViewModel.setConnectState(App.DISCONNECTED)
                     Log.d("test_wg", "tunnelStatus else = ${App.tunnelStatus}")
+
+                    val widgetIntent = Intent(context, SimpleAppWidget::class.java)
+                    widgetIntent.action = SimpleAppWidget.ACTION_DISCONNECT_VPN
+                    context.sendBroadcast(widgetIntent)
                 }
 
                 val server = basePreferenceHelper.getConnectedServer()

+ 740 - 0
app/src/main/java/com/vpn/fastestvpnservice/utils/WireGuardService.kt

@@ -0,0 +1,740 @@
+package com.vpn.fastestvpnservice.utils
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.ServiceConnection
+import android.content.pm.PackageManager
+import android.os.AsyncTask
+import android.os.Build
+import android.os.CountDownTimer
+import android.os.Handler
+import android.os.IBinder
+import android.os.RemoteException
+import android.util.Log
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.vpn.fastestvpnservice.MainActivity
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.constants.AppConstant
+import com.vpn.fastestvpnservice.constants.AppEnum
+import com.vpn.fastestvpnservice.constants.splitList
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.openVpnUtils.EncryptData
+import com.vpn.fastestvpnservice.widgets.SimpleAppWidget
+import com.wireguard.android.backend.GoBackend
+import com.wireguard.android.backend.Tunnel
+import com.wireguard.config.Config
+import com.wireguard.config.InetEndpoint
+import com.wireguard.config.InetNetwork
+import com.wireguard.config.Interface
+import de.blinkt.openvpn.LaunchVPN
+import de.blinkt.openvpn.VpnProfile
+import de.blinkt.openvpn.core.App
+import de.blinkt.openvpn.core.ConfigParser
+import de.blinkt.openvpn.core.ConnectionStatus
+import de.blinkt.openvpn.core.IOpenVPNServiceInternal
+import de.blinkt.openvpn.core.OpenVPNService
+import de.blinkt.openvpn.core.ProfileManager
+import de.blinkt.openvpn.core.VpnStatus
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import org.json.JSONObject
+import org.strongswan.android.logic.CharonVpnService
+import org.strongswan.android.ui.VpnProfileControlActivity
+import java.io.BufferedReader
+import java.io.InputStream
+import java.io.InputStreamReader
+import java.util.SortedSet
+
+class WireGuardService : Service(), VpnStatus.StateListener {
+    lateinit var basePreferenceHelper: BasePreferenceHelper
+    var countDownTimer: CountDownTimer? = null
+
+//    /*IKEV2*/
+//    private lateinit var ikevConnectionStatesReceiver: IkevConnectionStatesReceiverWidget
+
+    /*TCP, UDP*/
+    var mService: IOpenVPNServiceInternal? = null
+    var inputStream: InputStream? = null
+    var bufferedReader: BufferedReader? = null
+    var cp: ConfigParser? = null
+    var vp: VpnProfile? = null
+    var pm: ProfileManager? = null
+
+    private val mConnection: ServiceConnection = object : ServiceConnection {
+
+        override fun onServiceConnected(className: ComponentName, service: IBinder) {
+
+            App.mService = IOpenVPNServiceInternal.Stub.asInterface(service)
+            Log.d("wg test s tcp wid", "onServiceConnected widget ${App.mService}")
+
+        }
+
+        override fun onServiceDisconnected(arg0: ComponentName) {
+            Log.d("wg test s tcp", "onServiceDisconnected")
+
+            App.mService = null
+        }
+    }
+    private val job = Job()
+    private val coroutineScope = CoroutineScope(Dispatchers.IO + job)
+
+    companion object {
+        /*IKEV2*/
+        lateinit var ikevConnectionStatesReceiver: IkevConnectionStatesReceiverWidget
+    }
+
+    override fun onCreate() {
+        super.onCreate()
+
+
+    }
+    fun connectVpn() {
+
+        basePreferenceHelper = BasePreferenceHelper(applicationContext)
+        val connectState = basePreferenceHelper.getConnectState()
+        Log.d("wg test s connectVpn", "connectState = $connectState")
+        if (connectState == App.DISCONNECTED) {
+            startVpn()
+        }
+        else if (connectState == App.CONNECTED ||
+            connectState == App.CONNECTING) {
+
+            Log.d("testing func", "1")
+            stopVpn()
+            Log.d("testing func", "3")
+
+        }
+        else if (connectState == App.CONNECTION_STATE_SERVER_NOT_RESPONDING) {
+         startTcpUDP()
+        }
+    }
+
+    fun startVpn() {
+        countDownTimer()
+        try {
+            basePreferenceHelper = BasePreferenceHelper(applicationContext)
+            Log.d("wg test s startVpn", App.connection_status.toString())
+            if (CheckInternetConnection.getInternetConnection(applicationContext).isConnectedToInternet) {
+                if (basePreferenceHelper.getProtocol().title.toLowerCase()
+                        .contentEquals(AppEnum.WG_PROTOCOL.key.toLowerCase())
+                ) {
+                    /*Connect Wire-Guard*/
+                    MainActivity.isWGDown = true
+                    vpnWireGuardPermission(true)
+                }
+                else if (basePreferenceHelper.getProtocol().title.contentEquals(AppEnum.IKEV2_PROTOCOL.key))
+                {
+
+                    basePreferenceHelper.getServerObject().let { server ->
+
+                            /*Connect IKEV2*/
+                            Log.d("test wid onstart", "IKEv2 Connection")
+
+//                            startListenerIKEV2()
+//                        App.createIKEV2Listener()
+
+                            val intent = Intent(applicationContext, VpnProfileControlActivity::class.java)
+                            App.connection_status = App.CONNECTION_STATE_CONNECTING
+                            MainActivity.vpnConnectionCallBacks?.onVpnConnecting()
+                            val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                            widgetIntent.action = SimpleAppWidget.ACTION_CONNECTING_VPN
+                            applicationContext?.sendBroadcast(widgetIntent)
+
+                            intent.action = VpnProfileControlActivity.START_PROFILE
+                            intent.putExtra(VpnProfileControlActivity.EXTRA_VPN_PROFILE_ID, server?.id)
+                            intent.putExtra(AppConstant.SERVER, Gson().toJson(server))
+                            intent.putExtra("username", basePreferenceHelper.getUser()?.userinfo?.email)
+                            intent.putExtra(
+                                "password", basePreferenceHelper.getPassword()
+                            )
+                            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+                            applicationContext.startActivity(intent)
+
+                        }
+
+                    /* setting receiver to listen ikev2 protocol connection states */
+                }
+                else {
+
+                    startTcpUDP()
+                }
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun startTcpUDP() {
+        countDownTimer?.start()
+
+        /*Connect UDP,TCP*/
+        App.connection_status = App.CONNECTION_STATE_CONNECTING
+        MainActivity.vpnConnectionCallBacks?.onVpnConnecting()
+
+        val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+        widgetIntent.action = SimpleAppWidget.ACTION_CONNECTING_VPN
+        applicationContext?.sendBroadcast(widgetIntent)
+
+        try {
+            VpnStatus.addStateListener(this)
+            val intent = Intent(applicationContext, OpenVPNService::class.java)
+            intent.action = OpenVPNService.START_SERVICE
+            applicationContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+        try {
+            inputStream = null
+            bufferedReader = null
+            inputStream = getJsonFileDetails()
+            assert(inputStream != null)
+            bufferedReader =
+                BufferedReader(InputStreamReader(inputStream /*, Charset.forName("UTF-8")*/))
+            cp = ConfigParser(applicationContext)
+            cp!!.parseConfig(bufferedReader)
+            vp = cp!!.convertProfile()
+
+            ///////////////// openvpn split tunneling start /////////////////
+            val type = object : TypeToken<SortedSet<String?>?>() {}.type
+
+            val selectedApps = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledApps(), type
+            )
+            val selectedAppsNoVpn = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledAppsNotAllow(), type
+            )
+
+            basePreferenceHelper.getSplitPosition().let {
+                    when (it) {
+                        splitList[0] -> {
+                        }
+                        splitList[1] -> {
+                            if (selectedApps != null && selectedApps.size > 0) {
+                                for (app in selectedApps) {
+                                    try {
+                                        vp?.mAllowedAppsVpn?.add(app)
+                                        Log.d("packages Vpn", app)
+                                    } catch (e: PackageManager.NameNotFoundException) {
+                                        e.printStackTrace()
+                                    }
+                                }
+                            }
+                        }
+                        splitList[2] -> {
+                            if (selectedAppsNoVpn != null && selectedAppsNoVpn.size > 0) {
+                                for (app in selectedAppsNoVpn) {
+                                    try {
+                                        vp?.mAllowedAppsVpn?.add(app)
+                                        Log.d("packages NoVpn", app)
+                                    } catch (e: PackageManager.NameNotFoundException) {
+                                        e.printStackTrace()
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }   // Android
+
+            ///////////////// openvpn split tunneling end /////////////////
+            vp?.mAllowedAppsVpnAreDisallowed = false
+            val En = EncryptData()
+            val AppDetailsValues = En.decrypt(basePreferenceHelper.getAppDetails())
+
+            val json_response = JSONObject(AppDetailsValues)
+            val jsonArray = json_response.getJSONArray("blocked")
+            for (i in 0 until jsonArray.length()) {
+                val json_object = jsonArray.getJSONObject(i)
+                vp?.mAllowedAppsVpn?.add(json_object.getString("app"))
+                Log.e("packages end", json_object.getString("app"))
+            }
+
+            vp?.mName = Build.MODEL
+            vp?.mUsername = basePreferenceHelper.getUser()?.userinfo?.email
+            vp?.mPassword = basePreferenceHelper.getPassword()
+            pm = ProfileManager.getInstance(applicationContext)
+            pm?.addProfile(vp)
+            pm?.saveProfileList(applicationContext)
+            pm?.saveProfile(applicationContext, vp)
+            vp = pm?.getProfileByName(Build.MODEL)
+            val intent = Intent(applicationContext, LaunchVPN::class.java)
+            intent.putExtra(LaunchVPN.EXTRA_KEY, vp?.uuid.toString())
+            intent.action = Intent.ACTION_MAIN
+            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+            applicationContext.startActivity(intent)
+        }
+        catch (e: Exception) {
+            e.printStackTrace()
+
+        }
+    }
+
+    fun startListenerIKEV2() {
+        try {
+            ikevConnectionStatesReceiver = IkevConnectionStatesReceiverWidget()
+            val filter = IntentFilter()
+            filter.addAction(CharonVpnService.ACTION_VPN_CONNECTED)
+            filter.addAction(CharonVpnService.ACTION_VPN_NOT_CONNECTED)
+            filter.addAction(CharonVpnService.ACTION_VPN_CONNECTING)
+            filter.addAction(CharonVpnService.ACTION_VPN_SERVER_NOT_RESPONDING)
+            filter.addAction(CharonVpnService.ACTION_VPN_DISABLED)
+            LocalBroadcastManager.getInstance(applicationContext)
+                .registerReceiver(ikevConnectionStatesReceiver, filter)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun stopVpn() {
+        Log.d("testing func", "2")
+
+        try {
+            basePreferenceHelper = BasePreferenceHelper(applicationContext)
+
+            Log.d("wg test s stopVpn", App.connection_status.toString())
+
+            /*Disconnect Wireguard*/
+            if (basePreferenceHelper.getProtocol().title.toLowerCase()
+                    .contentEquals(AppEnum.WG_PROTOCOL.key.toLowerCase())
+            )
+            {
+                vpnWireGuardPermission(false)
+            }
+            else if (basePreferenceHelper.getProtocol().title.contentEquals(AppEnum.IKEV2_PROTOCOL.key))
+            {
+                /*Disconnect IKEV2*/
+                val intent = Intent(applicationContext, VpnProfileControlActivity::class.java)
+                intent.action = VpnProfileControlActivity.DISCONNECT
+                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+                applicationContext.startActivity(intent)
+
+//                App.connection_status = App.CONNECTION_STATE_DISCONNECTED
+//                MainActivity.vpnConnectionCallBacks?.onVpnDisconnected()
+            }
+            else {
+
+//                applicationContext.unbindService(mConnection)
+
+                Log.d("wg test s msr mcon", App.mService.toString() + " " + mConnection.toString())
+
+                /*Disconnect TCP,UDP*/
+                App.connection_status = App.CONNECTION_STATE_DISCONNECTED
+                MainActivity.vpnConnectionCallBacks?.onVpnDisconnected()
+                val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                widgetIntent.action = SimpleAppWidget.ACTION_DISCONNECT_VPN
+                applicationContext?.sendBroadcast(widgetIntent)
+                OpenVPNService.abortConnectionVPN = true
+                ProfileManager.setConntectedVpnProfileDisconnected(applicationContext)
+
+                if (App.mService != null) {
+                    try {
+                        Log.d("wg test s msr1 try", App.mService.toString())
+
+                        App.mService!!.stopVPN(false)
+                    } catch (e: RemoteException) {
+                        e.printStackTrace()
+                    }
+                    try {
+                        Log.d("wg test s msr2 try", App.mService.toString())
+
+                        pm = ProfileManager.getInstance(applicationContext)
+                        vp = pm?.getProfileByName(Build.MODEL)
+                        pm?.removeProfile(applicationContext, vp)
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                }
+            }
+
+            val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+            widgetIntent.action = SimpleAppWidget.ACTION_STOP_SERVICE
+            applicationContext.sendBroadcast(widgetIntent)
+
+            Handler().postDelayed({
+                try {
+                    LocalBroadcastManager.getInstance(applicationContext)
+                            .unregisterReceiver(ikevConnectionStatesReceiver)
+
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                }
+            }, 500)
+
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    fun vpnWireGuardPermission(isUp: Boolean) {
+
+        try{
+            vpnWireGuard(isUp)
+//            val intentPrepare: Intent = GoBackend.VpnService.prepare(context)
+//            if (intentPrepare != null) {
+//                context.startActivity(intentPrepare)
+//            }
+        }catch (e :Exception){
+        }
+    }
+
+    fun vpnWireGuard(isUp: Boolean) {
+        AsyncTask.execute {
+            try {
+                basePreferenceHelper = BasePreferenceHelper(applicationContext)
+
+                Log.d("wg app widget", "${App.tunnelStatus}, ${App.getTunnel()}, ${App.backend}, ${App.peerBuilder}")
+
+
+                if (isUp) {
+                    App.connection_status = App.CONNECTION_STATE_UP_WG
+                    App.tunnelStatus = Tunnel.State.UP
+                    App.backend = GoBackend(App.getContext())
+                    MainActivity.vpnConnectionCallBacks?.onVpnConnected()
+
+                    basePreferenceHelper.setConnectState(App.CONNECTED)
+
+                    val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                    widgetIntent.action = SimpleAppWidget.ACTION_CONNECT_VPN
+                    applicationContext?.sendBroadcast(widgetIntent)
+
+                } else {
+                    App.connection_status = App.CONNECTION_STATE_DOWN_WG
+                    App.tunnelStatus = Tunnel.State.DOWN
+                    MainActivity.vpnConnectionCallBacks?.onVpnDisconnected()
+
+                    basePreferenceHelper.setConnectState(App.DISCONNECTED)
+
+                    val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                    widgetIntent.action = SimpleAppWidget.ACTION_DISCONNECT_VPN
+                    applicationContext?.sendBroadcast(widgetIntent)
+                }
+
+                basePreferenceHelper.getSplitPosition().let {
+                    when(it){
+                        splitList[0] -> {
+                            App.backend.setState(App.getTunnel(), App.tunnelStatus, createWireGuardConfiguration()?.build())
+                        }
+                        splitList[1] -> {
+                            App.backend.setState(App.getTunnel(), App.tunnelStatus, createWireGuardConfigurationInclude()?.build())
+                        }
+                        splitList[2] -> {
+                            App.backend.setState(App.getTunnel(), App.tunnelStatus, createWireGuardConfigurationExclude()?.build())
+                        }
+                        else -> {}
+                    }
+                }
+
+//                App.backend.setState(App.getTunnel(), App.tunnelStatus, createWireGuardConfiguration()?.build())
+
+            } catch (e: java.lang.Exception) {
+                e.printStackTrace()
+            }
+        }
+
+    }
+
+    fun createWireGuardConfiguration(): Config.Builder? {
+        return try {
+            basePreferenceHelper = BasePreferenceHelper(applicationContext)
+            var dnswg = if (basePreferenceHelper.getAdBlockState()) {
+                "10.8.8.8"
+            } else {
+                "10.9.9.9"
+            }
+            val prefHelper = BasePreferenceHelper(App.getContext().applicationContext)
+            val interfaceBuilder = Interface.Builder()
+            val builder = Config.Builder()
+            builder.setInterface(
+                interfaceBuilder.addAddress(InetNetwork.parse(prefHelper.getWireGuard()!!.ip + "/32"))
+                    .parsePrivateKey(prefHelper.getWireGuard()!!.key)
+                    .parseDnsServers(dnswg)
+                    .build()
+            ).addPeer(
+                App.peerBuilder.addAllowedIp(InetNetwork.parse("0.0.0.0/0"))
+                    .setEndpoint(InetEndpoint.parse(prefHelper.getServerObject()!!.dns + ":51820"))
+                    .parsePublicKey(prefHelper.getServerObject()!!.wg_key)
+                    .build()
+            )
+            builder
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+            null
+        }
+    }
+
+    fun createWireGuardConfigurationInclude(): Config.Builder? {
+        return try {
+            basePreferenceHelper = BasePreferenceHelper(applicationContext)
+            val type = object : TypeToken<SortedSet<String?>?>() {}.type
+            val selectedApps = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledApps(), type
+            )
+            val selectedAppsNoVpn = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledAppsNotAllow(), type
+            )
+
+            val dnswg = if (basePreferenceHelper.getAdBlockState()) {
+                "10.8.8.8"
+            } else {
+                "10.9.9.9"
+            }
+            val prefHelper = BasePreferenceHelper(App.getContext().applicationContext)
+            val interfaceBuilder = Interface.Builder()
+            val builder = Config.Builder()
+            builder.setInterface(
+                interfaceBuilder.addAddress(InetNetwork.parse(prefHelper.getWireGuard()!!.ip + "/32"))
+                    .parsePrivateKey(prefHelper.getWireGuard()!!.key)
+                    .parseDnsServers(dnswg)
+                    .includeApplications(selectedApps)
+                    .build()
+            ).addPeer(
+                App.peerBuilder.addAllowedIp(InetNetwork.parse("0.0.0.0/0"))
+                    .setEndpoint(InetEndpoint.parse(prefHelper.getServerObject()!!.dns + ":51820"))
+                    .parsePublicKey(prefHelper.getServerObject()!!.wg_key)
+                    .build()
+            )
+            builder
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+            null
+        }
+    }
+
+    fun createWireGuardConfigurationExclude(): Config.Builder? {
+        return try {
+            basePreferenceHelper = BasePreferenceHelper(applicationContext)
+            val type = object : TypeToken<SortedSet<String?>?>() {}.type
+            val selectedApps = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledApps(), type
+            )
+            val selectedAppsNoVpn = Gson().fromJson<SortedSet<String>>(
+                basePreferenceHelper.getSplitTunneledAppsNotAllow(), type
+            )
+
+            val dnswg = if (basePreferenceHelper.getAdBlockState()) {
+                "10.8.8.8"
+            } else {
+                "10.9.9.9"
+            }
+            val prefHelper = BasePreferenceHelper(App.getContext().applicationContext)
+            val interfaceBuilder = Interface.Builder()
+            val builder = Config.Builder()
+            builder.setInterface(
+                interfaceBuilder.addAddress(InetNetwork.parse(prefHelper.getWireGuard()!!.ip + "/32"))
+                    .parsePrivateKey(prefHelper.getWireGuard()!!.key)
+                    .parseDnsServers(dnswg)
+                    .includeApplications(selectedAppsNoVpn)
+                    .build()
+            ).addPeer(
+                App.peerBuilder.addAllowedIp(InetNetwork.parse("0.0.0.0/0"))
+                    .setEndpoint(InetEndpoint.parse(prefHelper.getServerObject()!!.dns + ":51820"))
+                    .parsePublicKey(prefHelper.getServerObject()!!.wg_key)
+                    .build()
+            )
+            builder
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+            null
+        }
+    }
+
+    fun countDownTimer() {
+
+        countDownTimer = object : CountDownTimer(32000, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                if (App.connection_status == App.CONNECTION_STATE_CONNECTED
+                    || App.connection_status == App.CONNECTION_STATE_CONNECTED_2) {
+                    MainActivity.vpnConnectionCallBacks?.onVpnConnected()
+                    val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                    widgetIntent.action = SimpleAppWidget.ACTION_CONNECT_VPN
+                    applicationContext?.sendBroadcast(widgetIntent)
+                    countDownTimer!!.cancel()
+                }
+            }
+
+            override fun onFinish() {
+                if (App.connection_status == App.CONNECTION_STATE_CONNECTING) {
+                    stopVpn()
+                }
+            }
+        }
+
+    }
+
+    override fun onBind(intent: Intent?): IBinder? {
+        return null
+    }
+
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+
+        Log.d("test wid onstart", "onStartCommand")
+
+        startNotification()
+        startListenerIKEV2()
+
+        connectVpn()
+
+//        if (intent?.action.equals(SimpleAppWidget.ACTION_START_TCP_UDP)){
+//            Log.d("test wid onstart", "ACTION_START_TCP_UDP")
+//
+//            startTcpUDP()
+//        }
+//        else {
+//            Log.d("test wid onstart", "connectVpn")
+//
+//        }
+
+        return START_STICKY
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        Log.d("test_widget_service", "onDestroy called WireGuardService")
+        stopVpn()
+    }
+    override fun stopService(name: Intent?): Boolean {
+        Log.d("test stop serv wid", "stopService")
+        return true
+    }
+
+    private fun startNotification() {
+        Log.d("wg test s notify", "startNotification")
+
+        basePreferenceHelper = BasePreferenceHelper(applicationContext)
+        val server = basePreferenceHelper.getServerObject()
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            val channelId = "FastestVPN_Foreground"
+            val channel = NotificationChannel(channelId, "FastestVPN", NotificationManager.IMPORTANCE_LOW)
+            val notificationManager = getSystemService(NotificationManager::class.java
+            )
+            notificationManager.createNotificationChannel(channel)
+            val notification: Notification.Builder = Notification.Builder(applicationContext, channelId)
+                .setContentTitle("FastestVPN")
+                .setContentText("${server?.server_name ?: server?.name}")
+                .setColor(applicationContext.resources.getColor(R.color.app_yellow_color))
+                .setSmallIcon(R.drawable.ic_logo_notify)
+            startForeground(1, notification.build())
+        }
+    }
+
+    inner class IkevConnectionStatesReceiverWidget : BroadcastReceiver() {
+        override fun onReceive(context: Context?, intent: Intent?) {
+            if (intent != null && intent.action != null) {
+                basePreferenceHelper = BasePreferenceHelper(applicationContext)
+                val action = intent.action
+                when (action) {
+                    CharonVpnService.ACTION_VPN_CONNECTED -> {
+                        Log.d("vpnConnectionCall ip w", "ACTION_VPN_CONNECTED widget " + App.connection_status)
+                        App.connection_status = App.CONNECTION_STATE_CONNECTED
+                        MainActivity.vpnConnectionCallBacks?.onVpnConnected()
+                        val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                        widgetIntent.action = SimpleAppWidget.ACTION_CONNECT_VPN
+                        applicationContext?.sendBroadcast(widgetIntent)
+                    }
+                    CharonVpnService.ACTION_VPN_DISABLED -> {
+                        Log.d("vpnConnectionCall ip w", "ACTION_VPN_DISABLED widget " + App.connection_status)
+
+                        if (App.connection_status == App.CONNECTION_STATE_CONNECTING)
+                        {
+                            App.connection_status = App.CONNECTION_STATE_CONNECTING
+                            MainActivity.vpnConnectionCallBacks?.onVpnConnecting()
+
+                            val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                            widgetIntent.action = SimpleAppWidget.ACTION_CONNECTING_VPN
+                            applicationContext?.sendBroadcast(widgetIntent)
+                        }
+                        else {
+                            App.connection_status = App.CONNECTION_STATE_DISCONNECTED
+                            MainActivity.vpnConnectionCallBacks?.onVpnDisconnected()
+
+                            val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                            widgetIntent.action = SimpleAppWidget.ACTION_DISCONNECT_VPN
+                            applicationContext?.sendBroadcast(widgetIntent)
+//                          MainActivity.vpnConnectionCallBacks?.onGetIp()
+                        }
+                    }
+                    CharonVpnService.ACTION_VPN_NOT_CONNECTED -> {
+                        Log.d("vpnConnectionCall ip w", "ACTION_VPN_NOT_CONNECTED widget " + App.connection_status)
+//                        App.connection_status = App.CONNECTION_STATE_DISCONNECTED
+//                        MainActivity.vpnConnectionCallBacks?.onVpnDisconnected()
+                    }
+                    CharonVpnService.ACTION_VPN_CONNECTING -> {
+                        Log.d("vpnConnectionCall ip w", "ACTION_VPN_CONNECTING widget")
+                        App.connection_status = App.CONNECTION_STATE_CONNECTING
+                        MainActivity.vpnConnectionCallBacks?.onVpnConnecting()
+
+                        val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                        widgetIntent.action = SimpleAppWidget.ACTION_CONNECTING_VPN
+                        applicationContext?.sendBroadcast(widgetIntent)
+                    }
+                    CharonVpnService.ACTION_VPN_SERVER_NOT_RESPONDING -> {
+                        Log.d("vpnConnectionCall ip w", "ACTION_VPN_SERVER_NOT_RESPONDING widget")
+                        App.connection_status = App.CONNECTION_STATE_SERVER_NOT_RESPONDING
+                        if (basePreferenceHelper.getProtocol().index == 0)
+                        {
+                            Log.d("vpnConnectionCall ip w", "ACTION_VPN_SERVER_NOT_RESPONDING tcp/udp")
+                            startTcpUDP()
+                        }
+                        MainActivity.vpnConnectionCallBacks?.onServerNotResponding()
+                        val widgetIntent = Intent(applicationContext, SimpleAppWidget::class.java)
+                        widgetIntent.action = SimpleAppWidget.ACTION_SERVER_NOT_RESPONDING
+                        applicationContext?.sendBroadcast(widgetIntent)
+                    }
+                }
+            }
+        }
+    }
+
+    private fun getJsonFileDetails(): InputStream? {
+        var conf: InputStream? = null
+        try {
+            conf = if (basePreferenceHelper.getProtocol().title.equals(AppEnum.TCP_PROTOCOL.key)) {
+                applicationContext.assets.open("fileDetails/tcp.ovpn")
+            } else {
+                applicationContext.assets.open("fileDetails/udp.ovpn")
+            }
+
+            return conf
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+        }
+        return null
+    }
+
+    override fun updateState(
+        state: String?,
+        logmessage: String?,
+        localizedResId: Int,
+        level: ConnectionStatus?
+    ) {
+        Log.d("vpnConnectionCall ip w", "LEVEL_NOTCONNECTED widget")
+
+    }
+
+    override fun setConnectedVPN(uuid: String?) {
+    }
+
+}
+
+//new Config.Builder().setInterface(
+//interfaceBuilder.addAddress(InetNetwork.parse(basePreferenceHelper.getWireGuard().getIp() + "/32"))
+//.parsePrivateKey(basePreferenceHelper.getWireGuard().getKey())
+//.parseDnsServers("10.8.8.8")
+//.build()
+//)
+//.addPeer(
+//App.peerBuilder.addAllowedIp(InetNetwork.parse("0.0.0.0/0"))
+//.setEndpoint(InetEndpoint.parse(basePreferenceHelper.getServerObject().getDns() + ":51820"))
+//.parsePublicKey(basePreferenceHelper.getServerObject().getWg_key()).build()
+//)

+ 594 - 0
app/src/main/java/com/vpn/fastestvpnservice/widgets/SimpleAppWidget.kt

@@ -0,0 +1,594 @@
+package com.vpn.fastestvpnservice.widgets
+
+import android.app.ActivityManager
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetProvider
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.icu.text.ListFormatter.Width
+import android.os.Build
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.RemoteViews
+import android.widget.Toast
+import com.vpn.fastestvpnservice.MainActivity
+import com.vpn.fastestvpnservice.R
+import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
+import com.vpn.fastestvpnservice.interfaces.VPNConnectionCallBacks
+import com.vpn.fastestvpnservice.utils.WireGuardService
+import de.blinkt.openvpn.core.App
+import java.util.Random
+
+class SimpleAppWidget() : AppWidgetProvider(), VPNConnectionCallBacks {
+
+    lateinit var context: Context
+
+    companion object {
+        const val ACTION_BROADCAST_RECEIVER = "ACTION_BROADCAST_RECEIVER"
+        const val ACTION_BROADCAST_ACTIVITY = "ACTION_BROADCAST_ACTIVITY"
+        const val ACTION_CHANGE_SERVER = "ACTION_CHANGE_SERVER"
+        const val ACTION_STOP_SERVICE = "ACTION_STOP_SERVICE"
+        const val ACTION_START_TCP_UDP = "ACTION_START_TCP_UDP"
+        const val ACTION_LOGIN = "ACTION_LOGIN"
+        const val ACTION_LOGOUT = "ACTION_LOGOUT"
+        const val ACTION_CONNECT_VPN = "ACTION_CONNECT_VPN"
+        const val ACTION_CONNECTING_VPN = "ACTION_CONNECTING_VPN"
+        const val ACTION_DISCONNECT_VPN = "ACTION_DISCONNECT_VPN"
+        const val ACTION_SERVER_NOT_RESPONDING = "ACTION_SERVER_NOT_RESPONDING"
+
+
+        var mCounter: Int = 0
+    }
+
+    init {
+//        vpnConnectionCallBacks = this
+    }
+    override fun onUpdate(
+        context: Context,
+        appWidgetManager: AppWidgetManager,
+        appWidgetIds: IntArray
+    ) {
+
+        Log.d("test_called_func_widget", "onUpdate")
+        this.context = context
+        for (appWidgetId in appWidgetIds) {
+            updateAppWidget(context, appWidgetManager, appWidgetId)
+        }
+
+    }
+
+    fun updateAppWidget(
+        context: Context,
+        appWidgetManager: AppWidgetManager,
+        appWidgetId: Int
+    ) {
+        Log.d("widget func calls", "updateAppWidget")
+//        Toast.makeText(context, "onUpdate Called!", Toast.LENGTH_SHORT).show()
+
+//        vpnConnectionCallBacks = this
+
+        val basePreferenceHelper = BasePreferenceHelper(context)
+        val connectState = basePreferenceHelper.getConnectState()
+        val views = RemoteViews(context.packageName, R.layout.simple_app_widget)
+
+        if (basePreferenceHelper.getUser() != null)         // HomeFragment
+        {
+//            val random = Random().nextInt(601) + 200
+            views.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+            val serverObj = basePreferenceHelper.getServerObject()
+            val serverName = serverObj?.server_name ?: serverObj?.name
+
+            views.setViewVisibility(R.id.fl_ivLogo, View.VISIBLE)
+            views.setViewVisibility(R.id.fl_ivCountry, View.VISIBLE)
+
+            var image: Int = 0
+            if (connectState == App.CONNECTED)
+            {
+                views.setTextViewText(R.id.tvWidget, "Connected")
+                views.setTextViewText(R.id.tvServerIP, serverObj?.ip.toString())
+                image = getDrawable(context, serverObj?.iso)
+                views.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_connected)
+                views.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_widget_y)
+                views.setTextColor(R.id.tvWidget, Color.parseColor("#fdb900"))
+            }
+            else if (connectState == App.DISCONNECTED)
+            {
+                views.setTextViewText(R.id.tvWidget, "Disconnected")
+                views.setTextViewText(R.id.tvServerIP, "-")
+                image = getDrawableGray(context, serverObj?.iso)
+                views.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+                views.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+                views.setTextColor(R.id.tvWidget, Color.parseColor("#81FFFFFF"))
+            }
+            else if (connectState == App.CONNECTING) {
+                views.setTextViewText(R.id.tvWidget, "Connecting...")
+                views.setTextViewText(R.id.tvServerIP, "-")
+                image = getDrawableGray(context, serverObj?.iso)
+                views.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+                views.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+                views.setTextColor(R.id.tvWidget, Color.parseColor("#81FFFFFF"))
+            }
+
+            if (image != 0)
+            {
+                views.setImageViewResource(R.id.ivCountryImage, image)
+            }
+            serverName?.let {
+                views.setTextViewText(R.id.tvServerName, it)
+            }
+
+            val intent1 = Intent(context, MainActivity::class.java)
+            intent1.action = ACTION_BROADCAST_ACTIVITY
+            intent1.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
+            val pendingIntent = PendingIntent.getActivity(context, 0, intent1, PendingIntent.FLAG_IMMUTABLE)
+
+            views.setOnClickPendingIntent(R.id.main_app, pendingIntent)
+        }
+        else {                                                          // LoginFragment
+            views.setTextViewText(R.id.tvWidget, "App is not active")
+            views.setTextViewText(R.id.tvServerName, "")
+            views.setTextViewText(R.id.tvServerIP, "Sign in to continue")
+            views.setViewVisibility(R.id.fl_ivLogo, View.GONE)
+            views.setViewVisibility(R.id.fl_ivCountry, View.GONE)
+            val intent3 = Intent(context, MainActivity::class.java)
+            intent3.action = ACTION_BROADCAST_ACTIVITY
+            val pendingIntent = PendingIntent.getActivity(context, 0, intent3, PendingIntent.FLAG_IMMUTABLE)
+            views.setOnClickPendingIntent(R.id.main_app, pendingIntent)
+        }
+
+        val intent2 = Intent(context, SimpleAppWidget::class.java)
+        intent2.action = ACTION_BROADCAST_RECEIVER
+        val pendingIntent2 = PendingIntent.getBroadcast(context, 0, intent2, PendingIntent.FLAG_IMMUTABLE)
+        views.setOnClickPendingIntent(R.id.ivConnect, pendingIntent2)
+
+        appWidgetManager.updateAppWidget(appWidgetId, views)
+    }
+
+    override fun onEnabled(context: Context) {
+        Log.d("widget func calls", "onEnabled")
+
+        // Enter relevant functionality for when the first widget is created
+    }
+
+    override fun onDisabled(context: Context) {
+        Log.d("widget func calls", "onDisabled")
+
+        // Enter relevant functionality for when the last widget is disabled
+    }
+
+    override fun onRestored(context: Context?, oldWidgetIds: IntArray?, newWidgetIds: IntArray?) {
+        super.onRestored(context, oldWidgetIds, newWidgetIds)
+//        Toast.makeText(context, "onRestored Called!", Toast.LENGTH_SHORT).show()
+
+    }
+
+    override fun onAppWidgetOptionsChanged(
+        context: Context?,
+        appWidgetManager: AppWidgetManager?,
+        appWidgetId: Int,
+        newOptions: Bundle?
+    ) {
+        Log.d("widget func calls", "onAppWidgetOptionsChanged")
+
+    }
+
+    override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
+        Log.d("widget func calls", "onDeleted")
+
+    }
+
+    override fun onReceive(context: Context?, intent: Intent?) {
+        super.onReceive(context, intent)
+
+        Log.d("widget func calls", "onReceive ${intent?.action.toString()}")
+        val basePreferenceHelper = context?.let { BasePreferenceHelper(it) }
+
+        context?.let {
+            this.context = it
+        }
+        val connectState = basePreferenceHelper?.getConnectState()
+
+//        vpnConnectionCallBacks = this
+
+        if (intent?.action.equals(ACTION_BROADCAST_RECEIVER))   // Widget Connect Button
+        {
+//            Toast.makeText(context, "Button Clicked!", Toast.LENGTH_SHORT).show()
+            Log.d("widget func calls", "ACTION_BROADCAST_RECEIVER")
+
+            context?.let {
+
+            val serverObj = basePreferenceHelper?.getServerObject()
+
+            val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(it)
+            val remoteViews = RemoteViews(context.packageName, R.layout.simple_app_widget)
+            val appWidget = ComponentName(context, SimpleAppWidget::class.java)
+
+//            remoteViews.setTextViewText(R.id.tvServerName, serverObj?.server_name)
+
+            basePreferenceHelper?.setServerObject(serverObj)
+
+            val status = isForegroundServiceRunning(context, WireGuardService::class.java)
+
+            if (basePreferenceHelper?.getUser() != null)
+            {
+                Log.d("wg test s user", "getUser In")
+
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                        Log.d("wg test s fore", "startForegroundService")
+
+                        context.startForegroundService(Intent(context, WireGuardService::class.java))
+
+//                    Handler(Looper.getMainLooper()).post {
+//                    }
+                    }
+                    else{
+                        Log.d("wg test s serv", "startService")
+
+                        context.startService(Intent(context, WireGuardService::class.java))
+                    }
+            }
+
+            appWidgetManager.updateAppWidget(appWidget, remoteViews)
+
+        }
+    }
+
+        if (intent?.action.equals(ACTION_BROADCAST_ACTIVITY)){  // Initialize callbacks ...
+//            Toast.makeText(context, "Activity Opened!", Toast.LENGTH_SHORT).show()
+
+//            vpnConnectionCallBacks = this
+        }
+        if (intent?.action.equals(ACTION_STOP_SERVICE)){
+            context?.stopService(Intent(context, WireGuardService::class.java))
+        }   // Stop Service
+
+        if (intent?.action.equals(ACTION_CHANGE_SERVER)){
+
+            if (connectState == App.CONNECTED)
+            {
+                onVpnConnected()
+            }
+            else if (connectState == App.DISCONNECTED)
+            {
+                onVpnDisconnected()
+            }
+            else {
+                onVpnConnecting()
+            }
+
+        }   // Change Server
+
+        if (intent?.action.equals(ACTION_LOGIN)) {      // Login UI Widget
+
+            if (connectState == App.CONNECTED)
+            {
+                onVpnConnected()
+            }
+            else if (connectState == App.DISCONNECTED)
+            {
+                onVpnDisconnected()
+            }
+            else {
+                onVpnConnecting()
+            }
+
+//            context?.let {
+//                val basePreferenceHelper = BasePreferenceHelper(context)
+//                val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(it)
+//                val views = RemoteViews(context.packageName, R.layout.simple_app_widget)
+//                val appWidget = ComponentName(context, SimpleAppWidget::class.java)
+//
+//                if (basePreferenceHelper.getUser() != null)         // HomeFragment
+//                {
+//                    Toast.makeText(context, "Home Screen", Toast.LENGTH_SHORT).show()
+//
+//                    views.setViewVisibility(R.id.fl_ivLogo, View.VISIBLE)
+//                    views.setViewVisibility(R.id.fl_ivCountry, View.VISIBLE)
+//
+//                    val random = Random().nextInt(601) + 200
+//                    views.setTextViewText(R.id.tvWidget, "Disconnected -- $random")
+//                    views.setTextViewText(R.id.tvServerIP, "-")
+//
+//                    views.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+//                    val serverObj = basePreferenceHelper.getServerObject()
+//                    val serverName = serverObj?.server_name ?: serverObj?.name
+//
+//                    val image: Int = if (App.connection_status == App.CONNECTION_STATE_CONNECTED
+//                        || App.connection_status == App.CONNECTION_STATE_UP_WG)
+//                    {
+//                        getDrawable(context, serverObj?.iso)
+//                    }
+//                    else
+//                    {
+//                        getDrawableGray(context, serverObj?.iso)
+//                    }
+//
+//                    if (image != 0)
+//                    {
+//                        views.setImageViewResource(R.id.ivCountryImage, image)
+//                    }
+//                    serverName?.let {
+//                        views.setTextViewText(R.id.tvServerName, it)
+//                    }
+//
+//                }
+//                else {                                                          // LoginFragment
+//                }
+//
+//                appWidgetManager.updateAppWidget(appWidget, views)
+//
+//            }
+        }
+
+        if (intent?.action.equals(ACTION_LOGOUT)) {      // Logout UI Widget
+
+            if (connectState == App.CONNECTED)
+            {
+                onVpnConnected()
+            }
+            else if (connectState == App.DISCONNECTED)
+            {
+                onVpnDisconnected()
+            }
+            else {
+                onVpnConnecting()
+            }
+
+//            context?.let {
+//                val basePreferenceHelper = BasePreferenceHelper(context)
+//                val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(it)
+//                val views = RemoteViews(context.packageName, R.layout.simple_app_widget)
+//                val appWidget = ComponentName(context, SimpleAppWidget::class.java)
+//
+//                if (basePreferenceHelper.getUser() != null)         // HomeFragment
+//                {
+//                }
+//                else {                                                          // LoginFragment
+//                    Log.d("widget func calls", "onReceive ${intent?.action.toString()} Inside...")
+//
+//
+//                    views.setTextViewText(R.id.tvWidget, "App is not active")
+//                    views.setTextViewText(R.id.tvServerName, "")
+//                    views.setTextViewText(R.id.tvServerIP, "Sign in to continue")
+//                    views.setViewVisibility(R.id.fl_ivLogo, View.GONE)
+//                    views.setViewVisibility(R.id.fl_ivCountry, View.GONE)
+//                }
+//
+//                appWidgetManager.updateAppWidget(appWidget, views)
+//            }
+        }
+
+        if (intent?.action.equals(ACTION_CONNECT_VPN)) {
+            onVpnConnected()
+        }
+        if (intent?.action.equals(ACTION_DISCONNECT_VPN)) {
+            onVpnDisconnected()
+        }
+        if (intent?.action.equals(ACTION_CONNECTING_VPN)) {
+            onVpnConnecting()
+        }
+        if (intent?.action.equals(ACTION_SERVER_NOT_RESPONDING)) {
+            onServerNotResponding()
+        }
+    }
+
+    fun stopService(context: Context) {
+        val serviceIntent = Intent(context, WireGuardService::class.java)
+        context.stopService(serviceIntent)
+    }
+
+    fun isForegroundServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
+        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+        for (service in activityManager.getRunningServices(Int.MAX_VALUE)) {
+            if (serviceClass.name == service.service.className && service.foreground) {
+                return true
+            }
+        }
+        return false
+    }
+    fun getDrawable(context: Context, name: String?): Int {
+        val iso = name?.toLowerCase().toString()
+        return context.resources.getIdentifier(iso, "drawable", context.packageName)
+    }
+
+    fun getDrawableGray(context: Context, name: String?): Int {
+        val iso = name?.toLowerCase().toString()
+        val iso_gray = "gray_$iso"
+        return context.resources.getIdentifier(iso_gray, "drawable", context.packageName)
+    }
+    override fun onVpnConnecting() {
+//        Toast.makeText(context, "onVpnConnecting", Toast.LENGTH_SHORT).show()
+        val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(context)
+        val remoteViews = RemoteViews(context.packageName, R.layout.simple_app_widget)
+        val appWidget: ComponentName = ComponentName(context, SimpleAppWidget::class.java)
+        val basePreferenceHelper = BasePreferenceHelper(context)
+
+        if (basePreferenceHelper.getUser() != null)         // HomeFragment
+        {
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.VISIBLE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.VISIBLE)
+
+            remoteViews.setTextViewText(R.id.tvWidget, "Connecting...")
+            remoteViews.setTextColor(R.id.tvWidget, context.resources.getColor(R.color.white_half))
+
+            val serverObj = basePreferenceHelper.getServerObject()
+            val serverName = serverObj?.server_name ?: serverObj?.name
+            serverName?.let {
+                remoteViews.setTextViewText(R.id.tvServerName, it)
+            }
+
+            val serverIP = serverObj?.ip.toString()
+            remoteViews.setTextViewText(R.id.tvServerIP, "-")
+
+            remoteViews.setTextColor(R.id.tvServerName, Color.parseColor("#81FFFFFF"))
+            remoteViews.setTextColor(R.id.tvServerIP, Color.parseColor("#81FFFFFF"))
+
+            remoteViews.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+            remoteViews.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+
+            val image = getDrawableGray(context, serverObj?.iso)
+            if (image != 0) {
+                remoteViews.setImageViewResource(R.id.ivCountryImage, image)
+            }
+        }
+        else {                                                          // LoginFragment
+            remoteViews.setTextViewText(R.id.tvWidget, "App is not active")
+            remoteViews.setTextViewText(R.id.tvServerName, "")
+            remoteViews.setTextViewText(R.id.tvServerIP, "Sign in to continue")
+            remoteViews.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.GONE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.GONE)
+        }
+
+
+        appWidgetManager.updateAppWidget(appWidget, remoteViews)
+    }
+
+    override fun onVpnConnected() {
+//        Toast.makeText(context, "onVpnConnected", Toast.LENGTH_SHORT).show()
+
+        val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(context)
+        val remoteViews = RemoteViews(context.packageName, R.layout.simple_app_widget)
+        val appWidget: ComponentName = ComponentName(context, SimpleAppWidget::class.java)
+        val basePreferenceHelper = BasePreferenceHelper(context)
+
+        if (basePreferenceHelper.getUser() != null)         // HomeFragment
+        {
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.VISIBLE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.VISIBLE)
+
+//            val random = Random().nextInt(601) + 200
+
+            remoteViews.setTextViewText(R.id.tvWidget, "Connected")
+            remoteViews.setTextColor(R.id.tvWidget, Color.parseColor("#fdb900"))
+
+            val serverObj = basePreferenceHelper.getServerObject()
+            val serverName = serverObj?.server_name ?: serverObj?.name
+            serverName?.let {
+                remoteViews.setTextViewText(R.id.tvServerName, it)
+            }
+
+            val serverIP = serverObj?.ip.toString()
+            serverIP.let {
+                remoteViews.setTextViewText(R.id.tvServerIP, it)
+            }
+
+            remoteViews.setTextColor(R.id.tvServerName, Color.parseColor("#81FFFFFF"))
+            remoteViews.setTextColor(R.id.tvServerIP, Color.parseColor("#81FFFFFF"))
+
+            remoteViews.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_widget_y)
+            remoteViews.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_connected)
+
+            val image = getDrawable(context, serverObj?.iso)
+            if (image != 0) {
+                remoteViews.setImageViewResource(R.id.ivCountryImage, image)
+            }
+        }
+        else {                                                          // LoginFragment
+            remoteViews.setTextViewText(R.id.tvWidget, "App is not active")
+            remoteViews.setTextViewText(R.id.tvServerName, "")
+            remoteViews.setTextViewText(R.id.tvServerIP, "Sign in to continue")
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.GONE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.GONE)
+        }
+
+        appWidgetManager.updateAppWidget(appWidget, remoteViews)
+    }
+
+    override fun onVpnDisconnected() {
+//        Toast.makeText(context, "onVpnDisconnected", Toast.LENGTH_SHORT).show()
+
+        Log.d("widget func calls", "onVpnDisconnected")
+
+        val appWidgetManager: AppWidgetManager = AppWidgetManager.getInstance(context)
+        val remoteViews = RemoteViews(context.packageName, R.layout.simple_app_widget)
+        val appWidget: ComponentName = ComponentName(context, SimpleAppWidget::class.java)
+        val basePreferenceHelper = BasePreferenceHelper(context)
+
+        if (basePreferenceHelper.getUser() != null)         // HomeFragment
+        {
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.VISIBLE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.VISIBLE)
+
+//            val random = Random().nextInt(601) + 200
+            remoteViews.setTextViewText(R.id.tvWidget, "Disconnected")
+            remoteViews.setTextColor(R.id.tvWidget, context.resources.getColor(R.color.white_half))
+
+            val serverObj = basePreferenceHelper.getServerObject()
+
+            val serverName = serverObj?.server_name ?: serverObj?.name
+
+            val serverIP = serverObj?.ip.toString()
+            remoteViews.setTextViewText(R.id.tvServerIP, "-")
+
+            remoteViews.setTextColor(R.id.tvServerName, Color.parseColor("#81FFFFFF"))
+            remoteViews.setTextColor(R.id.tvServerIP, Color.parseColor("#81FFFFFF"))
+
+            remoteViews.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+            remoteViews.setImageViewResource(R.id.ivLogo, R.drawable.logo_spark_disconnected)
+
+            val image = getDrawableGray(context, serverObj?.iso)
+            if (image != 0)
+            {
+                remoteViews.setImageViewResource(R.id.ivCountryImage, image)
+            }
+            serverName?.let {
+                remoteViews.setTextViewText(R.id.tvServerName, it)
+            }
+
+        }
+        else {                                                          // LoginFragment
+            remoteViews.setTextViewText(R.id.tvWidget, "App is not active")
+            remoteViews.setTextViewText(R.id.tvServerName, "")
+            remoteViews.setTextViewText(R.id.tvServerIP, "Sign in to continue")
+            remoteViews.setTextColor(R.id.tvWidget, Color.parseColor("#81FFFFFF"))
+            remoteViews.setImageViewResource(R.id.ivConnect, R.drawable.ic_connect_n_new)
+            remoteViews.setViewVisibility(R.id.fl_ivLogo, View.GONE)
+            remoteViews.setViewVisibility(R.id.fl_ivCountry, View.GONE)
+        }
+
+        appWidgetManager.updateAppWidget(appWidget, remoteViews)
+    }
+
+    override fun onGetIp() {
+    }
+
+    override fun onServerNotResponding() {
+
+//        Log.d("onVpn test not respond", "onServerNotResponding... Widget")
+        val basePreferenceHelper = BasePreferenceHelper(context)
+
+        if (basePreferenceHelper.getProtocol().index == 0) {
+
+//            val serviceIntent = Intent(context, WireGuardService::class.java)
+//            serviceIntent.action = ACTION_START_TCP_UDP
+//
+//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+//                Log.d("wg test s fore", "startForegroundService again")
+//
+//                context.startForegroundService(serviceIntent)
+//
+//            }
+//            else{
+//                Log.d("wg test s serv", "startService again")
+//
+//                context.startService(serviceIntent)
+//            }
+
+        }
+        else {
+            onVpnDisconnected()
+            context.stopService(Intent(context, WireGuardService::class.java))
+        }
+
+    }
+
+}
+
+//                val image = Utils.getCountryFlag(context, serverISO!!)
+//                val bitmap = BitmapFactory.decodeResource(context.getResources(), image as Int);
+//                remoteViews.setImageViewBitmap(R.id.ivCountryImage, bitmap)

+ 147 - 0
app/src/main/res/layout/simple_app_widget.xml

@@ -0,0 +1,147 @@
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:id="@+id/main_app"
+    android:clickable="true"
+    android:focusable="true"
+    android:background="@color/app_blue_color"
+    android:paddingBottom="5dp"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <FrameLayout
+        android:id="@+id/fl_ivLogo"
+        android:layout_width="20dp"
+        android:layout_height="20dp"
+        android:clickable="false"
+        android:focusable="false"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="5dp"
+        android:layout_below="@id/tvWidget"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentStart="true"
+        android:visibility="visible"
+        >
+        <ImageView
+            android:id="@+id/ivLogo"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:src="@drawable/logo_spark_disconnected"
+            android:scaleType="fitXY"
+            />
+
+    </FrameLayout>
+
+    <TextView
+        android:id="@+id/tvWidget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="5dp"
+        android:background="@color/app_blue_color"
+        android:clickable="false"
+        android:contentDescription="@string/disconnected"
+        android:focusable="false"
+        android:gravity="start"
+        android:padding="0dp"
+        android:visibility="visible"
+        android:text="@string/disconnected"
+        android:textColor="@color/white_half"
+        android:textSize="16sp"
+        android:textStyle="bold|italic"
+        android:layout_alignParentTop="true"
+        android:layout_toEndOf="@id/fl_ivLogo"
+        />
+
+    <FrameLayout
+        android:id="@+id/fl_ivConnect"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
+        android:background="@drawable/round_button_connect"
+        android:clickable="true"
+        android:focusable="true"
+        android:layout_alignParentEnd="true"
+        android:layout_centerInParent="true"
+        android:layout_marginEnd="5dp"
+        android:layout_marginBottom="5dp"
+        >
+
+        <ImageView
+            android:id="@+id/ivConnect"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_connect_n_new"
+            android:clickable="true"
+            android:focusable="true"
+            />
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/fl_ivCountry"
+        android:layout_width="45dp"
+        android:layout_height="35dp"
+        android:clickable="false"
+        android:focusable="false"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="5dp"
+        android:layout_marginBottom="5dp"
+        android:layout_below="@id/fl_ivLogo"
+        android:layout_alignParentStart="true"
+        android:visibility="visible"
+        >
+        <ImageView
+            android:id="@+id/ivCountryImage"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:src="@drawable/gray_us"
+            android:scaleType="fitXY"
+            />
+
+    </FrameLayout>
+
+    <TextView
+        android:id="@+id/tvServerName"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/tvWidget"
+        android:layout_centerInParent="false"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="0dp"
+        android:layout_marginEnd="25dp"
+        android:layout_marginBottom="0dp"
+        android:layout_toEndOf="@id/fl_ivCountry"
+        android:clickable="false"
+        android:contentDescription="USA"
+        android:focusable="false"
+        android:text="USA"
+        android:textColor="@color/white_half"
+        android:textSize="15sp"
+        android:textStyle="bold|italic"
+        android:visibility="visible"
+        />
+
+    <TextView
+        android:id="@+id/tvServerIP"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/tvServerName"
+        android:layout_centerInParent="false"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="2dp"
+        android:layout_marginEnd="25dp"
+        android:layout_marginBottom="0dp"
+        android:layout_toEndOf="@id/fl_ivCountry"
+        android:clickable="false"
+        android:contentDescription="173.208.96.144"
+        android:focusable="false"
+        android:text="173.208.96.144"
+        android:textColor="@color/white_half"
+        android:textSize="12sp"
+        android:textStyle="bold|italic"
+        android:visibility="visible"
+        />
+
+</RelativeLayout>

+ 19 - 0
app/src/main/res/xml/simple_app_widget_info.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<appwidget-provider
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:initialKeyguardLayout="@layout/simple_app_widget"
+    android:initialLayout="@layout/simple_app_widget"
+    android:minWidth="250dp"
+    android:minHeight="40dp"
+    android:targetCellHeight="1"
+    android:targetCellWidth="3"
+    android:maxResizeWidth="250dp"
+    android:maxResizeHeight="40dp"
+    android:previewLayout="@layout/simple_app_widget"
+    android:previewImage="@drawable/widgetappprev"
+    android:resizeMode="horizontal|vertical"
+    android:updatePeriodMillis="1800000"
+    android:widgetCategory="home_screen"
+    >
+</appwidget-provider>