mirror of
https://github.com/yggdrasil-network/yggdrasil-android.git
synced 2025-04-28 14:15:08 +03:00
Merge 70dfab37e7
into 9df80c0612
This commit is contained in:
commit
a97823b440
11 changed files with 204 additions and 12 deletions
|
@ -4,13 +4,13 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 31
|
||||||
buildToolsVersion "30.0.3"
|
buildToolsVersion "30.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "eu.neilalexander.yggdrasil"
|
applicationId "eu.neilalexander.yggdrasil"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 31
|
||||||
versionCode 13
|
versionCode 13
|
||||||
versionName "0.1-013"
|
versionName "0.1-013"
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ android {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
signingConfig = signingConfigs.getByName("yggdrasil")
|
signingConfig = signingConfigs.getByName("yggdrasil")
|
||||||
|
matchingFallbacks = ['release']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -51,12 +52,19 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.aar'], dir: 'libs')
|
implementation fileTree(include: ['*.aar'], dir: 'libs')
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
|
||||||
implementation 'androidx.core:core-ktx:1.5.0'
|
implementation 'androidx.core:core-ktx:1.5.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||||
implementation 'com.google.android.material:material:1.3.0'
|
implementation 'com.google.android.material:material:1.3.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.0'
|
implementation 'androidx.preference:preference-ktx:1.1.0'
|
||||||
|
implementation 'com.guolindev.permissionx:permissionx:1.6.4'
|
||||||
testImplementation 'junit:junit:4.+'
|
testImplementation 'junit:junit:4.+'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
implementation('org.akselrod.blemesh:lib:0.0.1') {
|
||||||
|
version {
|
||||||
|
branch = 'main'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".GlobalApplication"
|
android:name=".GlobalApplication"
|
||||||
|
@ -41,6 +45,7 @@
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".PacketTunnelProvider"
|
android:name=".PacketTunnelProvider"
|
||||||
|
android:foregroundServiceType="location"
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -55,6 +55,7 @@ object ConfigurationProxy {
|
||||||
json.put("AdminListen", "none")
|
json.put("AdminListen", "none")
|
||||||
json.put("IfName", "none")
|
json.put("IfName", "none")
|
||||||
json.put("IfMTU", 65535)
|
json.put("IfMTU", 65535)
|
||||||
|
json.put("Listen", JSONArray(arrayOf("tcp://127.0.0.1:9004")))
|
||||||
|
|
||||||
if (json.getJSONArray("MulticastInterfaces").get(0) is String) {
|
if (json.getJSONArray("MulticastInterfaces").get(0) is String) {
|
||||||
var ar = JSONArray()
|
var ar = JSONArray()
|
||||||
|
|
|
@ -10,6 +10,8 @@ import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
|
||||||
const val PREF_KEY_ENABLED = "enabled"
|
const val PREF_KEY_ENABLED = "enabled"
|
||||||
|
const val BLE_ENABLED = "ble"
|
||||||
|
const val CODED_PHY_ENABLED = "codedPhy"
|
||||||
const val MAIN_CHANNEL_ID = "Yggdrasil Service"
|
const val MAIN_CHANNEL_ID = "Yggdrasil Service"
|
||||||
|
|
||||||
class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
|
class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
|
||||||
|
@ -68,7 +70,7 @@ fun createServiceNotification(context: Context, state: State): Notification {
|
||||||
val intent = Intent(context, MainActivity::class.java).apply {
|
val intent = Intent(context, MainActivity::class.java).apply {
|
||||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
}
|
}
|
||||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
val text = when (state) {
|
val text = when (state) {
|
||||||
State.Disabled -> context.getText(R.string.tile_disabled)
|
State.Disabled -> context.getText(R.string.tile_disabled)
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package eu.neilalexander.yggdrasil
|
package eu.neilalexander.yggdrasil
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.net.VpnService
|
import android.net.VpnService
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Switch
|
import android.widget.Switch
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -14,6 +16,7 @@ import androidx.appcompat.widget.LinearLayoutCompat
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.permissionx.guolindev.PermissionX
|
||||||
import eu.neilalexander.yggdrasil.PacketTunnelProvider.Companion.STATE_INTENT
|
import eu.neilalexander.yggdrasil.PacketTunnelProvider.Companion.STATE_INTENT
|
||||||
import mobile.Mobile
|
import mobile.Mobile
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
@ -43,6 +46,46 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkBLEPermissions() {
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this.baseContext)
|
||||||
|
val bleEnabled = preferences.getBoolean(BLE_ENABLED, (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S))
|
||||||
|
if (!bleEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
PermissionX.init(this)
|
||||||
|
.permissions(
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
Manifest.permission.BLUETOOTH_ADVERTISE,
|
||||||
|
Manifest.permission.BLUETOOTH_CONNECT,
|
||||||
|
Manifest.permission.BLUETOOTH_SCAN,
|
||||||
|
)
|
||||||
|
.onExplainRequestReason { scope, deniedList ->
|
||||||
|
scope.showRequestReasonDialog(
|
||||||
|
deniedList,
|
||||||
|
getString(R.string.explain_perms),
|
||||||
|
getString(R.string.ok),
|
||||||
|
getString(R.string.cancel),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.onForwardToSettings { scope, deniedList ->
|
||||||
|
scope.showForwardToSettingsDialog(
|
||||||
|
deniedList,
|
||||||
|
getString(R.string.manual_perms),
|
||||||
|
getString(R.string.ok),
|
||||||
|
getString(R.string.cancel),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.request { allGranted, _, _ ->
|
||||||
|
if(!allGranted) {
|
||||||
|
preferences.edit().apply {
|
||||||
|
putBoolean(BLE_ENABLED, false)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
@ -65,6 +108,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
enabledSwitch.setOnCheckedChangeListener { _, isChecked ->
|
enabledSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||||
when (isChecked) {
|
when (isChecked) {
|
||||||
true -> {
|
true -> {
|
||||||
|
checkBLEPermissions()
|
||||||
val vpnIntent = VpnService.prepare(this)
|
val vpnIntent = VpnService.prepare(this)
|
||||||
if (vpnIntent != null) {
|
if (vpnIntent != null) {
|
||||||
startVpnActivity.launch(vpnIntent)
|
startVpnActivity.launch(vpnIntent)
|
||||||
|
|
|
@ -9,11 +9,16 @@ import android.util.Log
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import eu.neilalexander.yggdrasil.YggStateReceiver.Companion.YGG_STATE_INTENT
|
import eu.neilalexander.yggdrasil.YggStateReceiver.Companion.YGG_STATE_INTENT
|
||||||
|
import org.akselrod.blemesh.BLEService
|
||||||
import mobile.Yggdrasil
|
import mobile.Yggdrasil
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.net.Socket
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.UUID
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +48,8 @@ open class PacketTunnelProvider: VpnService() {
|
||||||
private var readerStream: FileInputStream? = null
|
private var readerStream: FileInputStream? = null
|
||||||
private var writerStream: FileOutputStream? = null
|
private var writerStream: FileOutputStream? = null
|
||||||
|
|
||||||
|
private var bleService: BLEService? = null
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
config = ConfigurationProxy(applicationContext)
|
config = ConfigurationProxy(applicationContext)
|
||||||
|
@ -175,6 +182,20 @@ open class PacketTunnelProvider: VpnService() {
|
||||||
intent = Intent(YGG_STATE_INTENT)
|
intent = Intent(YGG_STATE_INTENT)
|
||||||
intent.putExtra("state", STATE_ENABLED)
|
intent.putExtra("state", STATE_ENABLED)
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||||
|
|
||||||
|
if (preferences.getBoolean(BLE_ENABLED, (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S))) {
|
||||||
|
val publicKey = config.getJSON().getString("PublicKey")
|
||||||
|
val codedPhy = preferences.getBoolean(CODED_PHY_ENABLED, false)
|
||||||
|
bleService = BLEService(
|
||||||
|
this.baseContext,
|
||||||
|
UUID.fromString("4ec394b1-44c7-5f5b-9172-530cbf056f8e"),
|
||||||
|
UUID.fromString("9ed2717f-4dad-53fb-b682-52b2a4b077f8"),
|
||||||
|
publicKey,
|
||||||
|
codedPhy,
|
||||||
|
::peerConnect,
|
||||||
|
)
|
||||||
|
bleService?.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stop() {
|
private fun stop() {
|
||||||
|
@ -182,6 +203,9 @@ open class PacketTunnelProvider: VpnService() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bleService?.stop()
|
||||||
|
bleService = null
|
||||||
|
|
||||||
yggdrasil.stop()
|
yggdrasil.stop()
|
||||||
|
|
||||||
readerStream?.let {
|
readerStream?.let {
|
||||||
|
@ -336,4 +360,17 @@ open class PacketTunnelProvider: VpnService() {
|
||||||
readerStream = null
|
readerStream = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun peerConnect(): Pair<InputStream, OutputStream>? {
|
||||||
|
var socket: Socket?
|
||||||
|
try {
|
||||||
|
socket = Socket("127.0.0.1", 9004)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Couldn't open peer socket: $e")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return Pair(socket.inputStream, socket.outputStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,13 @@ import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Build
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
@ -27,6 +29,8 @@ class PeersActivity : AppCompatActivity() {
|
||||||
private lateinit var configuredTableLabel: TextView
|
private lateinit var configuredTableLabel: TextView
|
||||||
private lateinit var multicastListenSwitch: Switch
|
private lateinit var multicastListenSwitch: Switch
|
||||||
private lateinit var multicastBeaconSwitch: Switch
|
private lateinit var multicastBeaconSwitch: Switch
|
||||||
|
private lateinit var enableBLESwitch: Switch
|
||||||
|
private lateinit var enableCodedPHYSwitch: Switch
|
||||||
private lateinit var addPeerButton: ImageButton
|
private lateinit var addPeerButton: ImageButton
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -51,8 +55,28 @@ class PeersActivity : AppCompatActivity() {
|
||||||
multicastBeaconSwitch.setOnCheckedChangeListener { button, _ ->
|
multicastBeaconSwitch.setOnCheckedChangeListener { button, _ ->
|
||||||
config.multicastBeacon = button.isChecked
|
config.multicastBeacon = button.isChecked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this.baseContext)
|
||||||
|
|
||||||
|
enableBLESwitch = findViewById(R.id.enableBLE)
|
||||||
|
enableBLESwitch.setOnCheckedChangeListener { button, _ ->
|
||||||
|
preferences.edit().apply {
|
||||||
|
putBoolean(BLE_ENABLED, button.isChecked)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enableCodedPHYSwitch = findViewById(R.id.enableCodedPHY)
|
||||||
|
enableCodedPHYSwitch.setOnCheckedChangeListener { button, _ ->
|
||||||
|
preferences.edit().apply {
|
||||||
|
putBoolean(CODED_PHY_ENABLED, button.isChecked)
|
||||||
|
commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
multicastListenSwitch.isChecked = config.multicastListen
|
multicastListenSwitch.isChecked = config.multicastListen
|
||||||
multicastBeaconSwitch.isChecked = config.multicastBeacon
|
multicastBeaconSwitch.isChecked = config.multicastBeacon
|
||||||
|
enableBLESwitch.isChecked = preferences.getBoolean(BLE_ENABLED, (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S))
|
||||||
|
enableCodedPHYSwitch.isChecked = preferences.getBoolean(CODED_PHY_ENABLED, false)
|
||||||
|
|
||||||
val multicastBeaconPanel = findViewById<TableRow>(R.id.enableMulticastBeaconPanel)
|
val multicastBeaconPanel = findViewById<TableRow>(R.id.enableMulticastBeaconPanel)
|
||||||
multicastBeaconPanel.setOnClickListener {
|
multicastBeaconPanel.setOnClickListener {
|
||||||
|
@ -63,6 +87,19 @@ class PeersActivity : AppCompatActivity() {
|
||||||
multicastListenSwitch.toggle()
|
multicastListenSwitch.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val enableBLEPanel = findViewById<TableRow>(R.id.enableBLEPanel)
|
||||||
|
val enableCodedPHYPanel = findViewById<TableRow>(R.id.enableCodedPHYPanel)
|
||||||
|
|
||||||
|
enableBLEPanel.isEnabled = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||||
|
enableCodedPHYPanel.isEnabled = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||||
|
|
||||||
|
enableBLEPanel.setOnClickListener {
|
||||||
|
enableBLESwitch.toggle()
|
||||||
|
}
|
||||||
|
enableCodedPHYPanel.setOnClickListener {
|
||||||
|
enableCodedPHYSwitch.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
addPeerButton = findViewById(R.id.addPeerButton)
|
addPeerButton = findViewById(R.id.addPeerButton)
|
||||||
addPeerButton.setOnClickListener {
|
addPeerButton.setOnClickListener {
|
||||||
val view = inflater.inflate(R.layout.dialog_addpeer, null)
|
val view = inflater.inflate(R.layout.dialog_addpeer, null)
|
||||||
|
|
|
@ -217,6 +217,50 @@
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:id="@+id/enableBLEPanel"
|
||||||
|
style="@style/SelectableSwitchItemStyle">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/enable_ble"
|
||||||
|
android:textColor="?attr/textDefault" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2" />
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/enableBLE"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:id="@+id/enableCodedPHYPanel"
|
||||||
|
style="@style/SelectableSwitchItemStyle">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/enable_coded_phy"
|
||||||
|
android:textColor="?attr/textDefault" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2" />
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/enableCodedPHY"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -57,8 +57,12 @@
|
||||||
<string name="peer_connectivity_title">Подключения пиров</string>
|
<string name="peer_connectivity_title">Подключения пиров</string>
|
||||||
<string name="discoverable_over_multicast">Находимый через multicast</string>
|
<string name="discoverable_over_multicast">Находимый через multicast</string>
|
||||||
<string name="search_for_multicast_peers">Искать пиров через multicast</string>
|
<string name="search_for_multicast_peers">Искать пиров через multicast</string>
|
||||||
|
<string name="enable_ble">Искать пиров через Bluetooth LE</string>
|
||||||
|
<string name="enable_coded_phy">Использовать BLE Coded PHY</string>
|
||||||
|
<string name="explain_perms">Для поиска Bluetooth пиров, разрешите Nearby Devices и Location</string>
|
||||||
|
<string name="manual_perms">Для поиска Bluetooth пиров, разрешите Nearby Devices и Location в настройках</string>
|
||||||
<string name="configured_peers_hint">Yggdrasil будет пытаться подключаться к этим пирам автоматически. Если вы добавите несколько пиров, ваше устройство может быть использовано для переноса данных между другими узлами сети. Чтобы этого избежать настройте только один пир.</string>
|
<string name="configured_peers_hint">Yggdrasil будет пытаться подключаться к этим пирам автоматически. Если вы добавите несколько пиров, ваше устройство может быть использовано для переноса данных между другими узлами сети. Чтобы этого избежать настройте только один пир.</string>
|
||||||
<string name="peer_connectivity_hint">Пиры могут быть найдены с помощью Multicast если они находятся в той же Wi-Fi сети, либо через USB. Трафик в мобильной сети может быть платным. Вы можете отключить мобильные данные в настройках устройства.</string>
|
<string name="peer_connectivity_hint">Пиры могут быть найдены с помощью Multicast если они находятся в той же Wi-Fi сети, либо через USB или BLE (Android 12+). Трафик в мобильной сети может быть платным. Вы можете отключить мобильные данные в настройках устройства.</string>
|
||||||
<string name="node_info">Об узле</string>
|
<string name="node_info">Об узле</string>
|
||||||
<string name="device_name">Название устройства</string>
|
<string name="device_name">Название устройства</string>
|
||||||
<string name="tap_to_edit">Нажмите для изменения</string>
|
<string name="tap_to_edit">Нажмите для изменения</string>
|
||||||
|
|
|
@ -57,8 +57,12 @@
|
||||||
<string name="peer_connectivity_title">Peer Connectivity</string>
|
<string name="peer_connectivity_title">Peer Connectivity</string>
|
||||||
<string name="discoverable_over_multicast">Discoverable over multicast</string>
|
<string name="discoverable_over_multicast">Discoverable over multicast</string>
|
||||||
<string name="search_for_multicast_peers">Search for multicast peers</string>
|
<string name="search_for_multicast_peers">Search for multicast peers</string>
|
||||||
|
<string name="enable_ble">Search for peers over Bluetooth LE</string>
|
||||||
|
<string name="enable_coded_phy">Use BLE Coded PHY</string>
|
||||||
|
<string name="explain_perms">Bluetooth peering requires Nearby Devices and Location permissions</string>
|
||||||
|
<string name="manual_perms">To use Bluetooth peering, enable Nearby Devices and Location permissions manually</string>
|
||||||
<string name="configured_peers_hint">Yggdrasil will automatically attempt to connect to configured peers when started. If you configure more than one peer, your device may carry traffic on behalf of other network nodes. Avoid this by configuring only a single peer.</string>
|
<string name="configured_peers_hint">Yggdrasil will automatically attempt to connect to configured peers when started. If you configure more than one peer, your device may carry traffic on behalf of other network nodes. Avoid this by configuring only a single peer.</string>
|
||||||
<string name="peer_connectivity_hint">Multicast peers will be discovered on the same Wi-Fi network or via USB. Data charges may apply when using mobile data. You can prevent data usage in the device settings.</string>
|
<string name="peer_connectivity_hint">Multicast peers will be discovered on the same Wi-Fi network or via USB or BLE (Android 12+). Data charges may apply when using mobile data. You can prevent data usage in the device settings.</string>
|
||||||
<string name="node_info">Node Info</string>
|
<string name="node_info">Node Info</string>
|
||||||
<string name="device_name">Device Name</string>
|
<string name="device_name">Device Name</string>
|
||||||
<string name="tap_to_edit">Tap to edit</string>
|
<string name="tap_to_edit">Tap to edit</string>
|
||||||
|
|
|
@ -1,2 +1,8 @@
|
||||||
rootProject.name = "Yggdrasil"
|
rootProject.name = "Yggdrasil"
|
||||||
include ':app'
|
include ':app'
|
||||||
|
|
||||||
|
sourceControl {
|
||||||
|
gitRepository("https://codeberg.org/aakselrod/blemesh-android.git") {
|
||||||
|
producesModule("org.akselrod.blemesh:lib")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue