Skip to content

Commit 2eb9fc7

Browse files
committed
[ui] add IPs and credentials to the Home screen
1 parent 73c0f05 commit 2eb9fc7

File tree

14 files changed

+394
-5
lines changed

14 files changed

+394
-5
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
android:name="android.hardware.telephony"
77
android:required="true" />
88

9+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
910
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
1011
<uses-permission android:name="android.permission.CALL_PHONE" />
1112
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

app/src/main/java/app/callgate/android/App.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package app.callgate.android
22

33
import android.app.Application
44
import app.callgate.android.modules.calls.callsModule
5+
import app.callgate.android.modules.connection.connectionModule
56
import app.callgate.android.modules.db.dbModule
67
import app.callgate.android.modules.notifications.notificationsModule
78
import app.callgate.android.modules.orchestrator.OrchestratorService
@@ -28,6 +29,7 @@ class App : Application() {
2829
serverService,
2930
callsModule,
3031
webhooksModule,
32+
connectionModule,
3133
orchestratorModule,
3234
)
3335
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package app.callgate.android.modules.connection
2+
3+
import android.content.Context
4+
import app.callgate.android.modules.connection.ip.LocalIPProvider
5+
import app.callgate.android.modules.connection.ip.PublicIPProvider
6+
7+
class ConnectionService(
8+
context: Context
9+
) {
10+
private val localIPProvider = LocalIPProvider(context)
11+
private val publicIPProvider = PublicIPProvider()
12+
13+
suspend fun getLocalIP(): String? = localIPProvider.getIP()
14+
suspend fun getPublicIP(): String? = publicIPProvider.getIP()
15+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package app.callgate.android.modules.connection
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
5+
import androidx.lifecycle.ViewModel
6+
import androidx.lifecycle.viewModelScope
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.launch
9+
10+
class ConnectionViewModel(
11+
private val connectionSvc: ConnectionService
12+
) : ViewModel() {
13+
private val _localIP = MutableLiveData<String>()
14+
val localIP: LiveData<String> = _localIP
15+
16+
private val _publicIP = MutableLiveData<String>()
17+
val publicIP: LiveData<String> = _publicIP
18+
19+
fun getLocalIP() {
20+
viewModelScope.launch(Dispatchers.IO) {
21+
_localIP.postValue(connectionSvc.getLocalIP())
22+
}
23+
}
24+
25+
fun getPublicIP() {
26+
viewModelScope.launch(Dispatchers.IO) {
27+
_publicIP.postValue(connectionSvc.getPublicIP())
28+
}
29+
}
30+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package app.callgate.android.modules.connection
2+
3+
import org.koin.core.module.dsl.singleOf
4+
import org.koin.core.module.dsl.viewModelOf
5+
import org.koin.dsl.module
6+
7+
val connectionModule = module {
8+
singleOf(::ConnectionService)
9+
viewModelOf(::ConnectionViewModel)
10+
}
11+
12+
val MODULE_NAME = "connection"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package app.callgate.android.modules.connection.ip
2+
3+
interface IPProvider {
4+
suspend fun getIP(): String?
5+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package app.callgate.android.modules.connection.ip
2+
3+
import android.content.Context
4+
import android.net.wifi.WifiManager
5+
import java.net.Inet4Address
6+
import java.net.NetworkInterface
7+
8+
9+
class LocalIPProvider(private val context: Context) : IPProvider {
10+
override suspend fun getIP(): String? {
11+
try {
12+
val wifiManager =
13+
context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
14+
15+
// If the device is in tethering mode, the following method may return null or a default IP
16+
wifiManager.connectionInfo?.let { connectionInfo ->
17+
val ipInt = connectionInfo.ipAddress
18+
if (ipInt != 0) {
19+
return java.net.InetAddress.getByAddress(
20+
byteArrayOf(
21+
(ipInt and 0xFF).toByte(),
22+
((ipInt shr 8) and 0xFF).toByte(),
23+
((ipInt shr 16) and 0xFF).toByte(),
24+
((ipInt shr 24) and 0xFF).toByte()
25+
)
26+
).hostAddress
27+
}
28+
}
29+
30+
// If the above doesn't work, try to find the WiFi network interface directly
31+
val wifiInterface = NetworkInterface.getNetworkInterfaces().asSequence()
32+
.find { it.name.contains("wlan", ignoreCase = true) }
33+
34+
wifiInterface?.inetAddresses?.asSequence()
35+
?.find { !it.isLoopbackAddress && it is Inet4Address }
36+
?.let { inetAddress ->
37+
return inetAddress.hostAddress
38+
}
39+
40+
// Check any other network interface
41+
NetworkInterface.getNetworkInterfaces().asSequence()
42+
.flatMap { intf -> intf.inetAddresses.asSequence() }
43+
.find { !it.isLoopbackAddress && it is Inet4Address }
44+
?.let { return it.hostAddress }
45+
} catch (e: Exception) {
46+
e.printStackTrace()
47+
}
48+
49+
return null
50+
}
51+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package app.callgate.android.modules.connection.ip
2+
3+
import io.ktor.client.HttpClient
4+
import io.ktor.client.call.body
5+
import io.ktor.client.engine.okhttp.OkHttp
6+
import io.ktor.client.plugins.HttpTimeout
7+
import io.ktor.client.request.get
8+
9+
class PublicIPProvider : IPProvider {
10+
override suspend fun getIP(): String? {
11+
val client = HttpClient(OkHttp) {
12+
install(HttpTimeout) {
13+
requestTimeoutMillis = REQUEST_TIMEOUT_MS
14+
}
15+
}
16+
17+
return try {
18+
client.get(PUBLIC_IP_URL).body<String>()
19+
} catch (e: Exception) {
20+
e.printStackTrace()
21+
null
22+
} finally {
23+
client.close()
24+
}
25+
}
26+
27+
companion object {
28+
private const val PUBLIC_IP_URL = "https://api.ipify.org"
29+
private const val REQUEST_TIMEOUT_MS = 5000L
30+
}
31+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package app.callgate.android.modules.server
22

33
import org.koin.core.module.dsl.singleOf
4+
import org.koin.core.module.dsl.viewModelOf
45
import org.koin.dsl.module
56

67
val serverService = module {
78
singleOf(::ServerService)
9+
viewModelOf(::ServerViewModel)
810
}

app/src/main/java/app/callgate/android/modules/server/ServerService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import android.content.Context
44
import android.os.Build
55

66
class ServerService(
7-
private val settings: ServerSettings,
7+
val settings: ServerSettings,
88
) {
99
fun start(context: Context) {
1010
settings.deviceId = settings.deviceId ?: getDeviceId(context)

0 commit comments

Comments
 (0)