kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
refactor permissions
rodzic
40313ddca6
commit
4f4750c339
|
@ -1,7 +1,6 @@
|
|||
package com.geeksville.mesh
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.content.*
|
||||
|
@ -34,7 +33,7 @@ import com.geeksville.android.GeeksvilleApplication
|
|||
import com.geeksville.android.Logging
|
||||
import com.geeksville.android.ServiceClient
|
||||
import com.geeksville.concurrent.handledLaunch
|
||||
import com.geeksville.mesh.android.*
|
||||
import com.geeksville.mesh.android.getMissingPermissions
|
||||
import com.geeksville.mesh.databinding.ActivityMainBinding
|
||||
import com.geeksville.mesh.model.BTScanModel
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
|
@ -116,16 +115,7 @@ eventually:
|
|||
val utf8: Charset = Charset.forName("UTF-8")
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : BaseActivity(), Logging,
|
||||
ActivityCompat.OnRequestPermissionsResultCallback {
|
||||
|
||||
companion object {
|
||||
// const val REQUEST_ENABLE_BT = 10
|
||||
const val DID_REQUEST_PERM = 11
|
||||
// const val RC_SIGN_IN = 12 // google signin completed
|
||||
// const val SELECT_DEVICE_REQUEST_CODE = 13
|
||||
// const val CREATE_CSV_FILE = 14
|
||||
}
|
||||
class MainActivity : BaseActivity(), Logging {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
|
@ -139,6 +129,15 @@ class MainActivity : BaseActivity(), Logging,
|
|||
@Inject
|
||||
internal lateinit var radioInterfaceService: RadioInterfaceService
|
||||
|
||||
private val requestPermissionsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||
if (!permissions.entries.all { it.value }) {
|
||||
errormsg("User denied permissions")
|
||||
showSnackbar(getString(R.string.permission_missing_31))
|
||||
}
|
||||
bluetoothViewModel.permissionsUpdated()
|
||||
}
|
||||
|
||||
data class TabInfo(val text: String, val icon: Int, val content: Fragment)
|
||||
|
||||
// private val tabIndexes = generateSequence(0) { it + 1 } FIXME, instead do withIndex or zip? to get the ids below, also stop duplicating strings
|
||||
|
@ -188,74 +187,28 @@ class MainActivity : BaseActivity(), Logging,
|
|||
/** Get the minimum permissions our app needs to run correctly
|
||||
*/
|
||||
private fun getMinimumPermissions(): Array<String> {
|
||||
val perms = mutableListOf(
|
||||
Manifest.permission.WAKE_LOCK
|
||||
val perms = mutableListOf<String>()
|
||||
|
||||
// We only need this for logging to capture files for the simulator - turn off for most users
|
||||
// Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
)
|
||||
// We only need this for logging to capture files for the simulator - turn off for production
|
||||
// perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
|
||||
/* TODO - wait for targetSdkVersion 31
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
perms.add(Manifest.permission.BLUETOOTH_SCAN)
|
||||
perms.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
} else {
|
||||
perms.add(Manifest.permission.BLUETOOTH)
|
||||
}
|
||||
*/
|
||||
perms.add(Manifest.permission.BLUETOOTH)
|
||||
|
||||
// Some old phones complain about requesting perms they don't understand
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
perms.add(Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND)
|
||||
perms.add(Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)
|
||||
}
|
||||
|
||||
return getMissingPermissions(perms)
|
||||
}
|
||||
|
||||
/** Ask the user to grant Bluetooth scan/discovery permission */
|
||||
fun requestScanPermission() = requestPermission(getScanPermissions(), true)
|
||||
|
||||
/**
|
||||
* @return a localized string warning user about missing permissions. Or null if everything is find
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
fun getMissingMessage(
|
||||
missingPerms: Array<String> = getMinimumPermissions()
|
||||
): String? {
|
||||
val renamedPermissions = mapOf(
|
||||
// Older versions of android don't know about these permissions - ignore failure to grant
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION to null,
|
||||
Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND to null,
|
||||
Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND to null,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION to getString(R.string.location),
|
||||
Manifest.permission.BLUETOOTH_CONNECT to "Bluetooth"
|
||||
)
|
||||
|
||||
val deniedPermissions = missingPerms.mapNotNull {
|
||||
if (renamedPermissions.containsKey(it))
|
||||
renamedPermissions[it]
|
||||
else // No localization found - just show the nasty android string
|
||||
it
|
||||
}
|
||||
|
||||
return if (deniedPermissions.isEmpty())
|
||||
null
|
||||
else {
|
||||
val asEnglish = deniedPermissions.joinToString(" & ")
|
||||
|
||||
getString(R.string.permission_missing).format(asEnglish)
|
||||
}
|
||||
}
|
||||
|
||||
/** Possibly prompt user to grant permissions
|
||||
* @param shouldShowDialog usually false in cases where we've already shown a dialog elsewhere we skip it.
|
||||
* @param shouldShowDialog usually true, but in cases where we've already shown a dialog elsewhere we skip it.
|
||||
*
|
||||
* @return true if we already have the needed permissions
|
||||
*/
|
||||
private fun requestPermission(
|
||||
missingPerms: Array<String> = getMinimumPermissions(),
|
||||
shouldShowDialog: Boolean = false
|
||||
shouldShowDialog: Boolean = true
|
||||
): Boolean =
|
||||
if (missingPerms.isNotEmpty()) {
|
||||
val shouldShow = missingPerms.filter {
|
||||
|
@ -265,11 +218,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
fun doRequest() {
|
||||
info("requesting permissions")
|
||||
// Ask for all the missing perms
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
missingPerms,
|
||||
DID_REQUEST_PERM
|
||||
)
|
||||
requestPermissionsLauncher.launch(missingPerms)
|
||||
}
|
||||
|
||||
if (shouldShow.isNotEmpty() && shouldShowDialog) {
|
||||
|
@ -280,7 +229,7 @@ class MainActivity : BaseActivity(), Logging,
|
|||
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.required_permissions))
|
||||
.setMessage(getMissingMessage(missingPerms))
|
||||
.setMessage(getString(R.string.permission_missing_31))
|
||||
.setNeutralButton(R.string.cancel) { _, _ ->
|
||||
warn("User bailed due to permissions")
|
||||
}
|
||||
|
@ -300,81 +249,6 @@ class MainActivity : BaseActivity(), Logging,
|
|||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* Remind user he's disabled permissions we need
|
||||
*
|
||||
* @return true if we did warn
|
||||
*/
|
||||
@SuppressLint("InlinedApi") // This function is careful to work with old APIs correctly
|
||||
fun warnMissingPermissions(): Boolean {
|
||||
val message = getMissingMessage()
|
||||
|
||||
return if (message != null) {
|
||||
errormsg("Denied permissions: $message")
|
||||
showSnackbar(message)
|
||||
true
|
||||
} else
|
||||
false
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
when (requestCode) {
|
||||
DID_REQUEST_PERM -> {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
if ((grantResults.isNotEmpty() &&
|
||||
grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
||||
) {
|
||||
// Permission is granted. Continue the action or workflow
|
||||
// in your app.
|
||||
|
||||
// yay!
|
||||
} else {
|
||||
// Explain to the user that the feature is unavailable because
|
||||
// the features requires a permission that the user has denied.
|
||||
// At the same time, respect the user's decision. Don't link to
|
||||
// system settings in an effort to convince the user to change
|
||||
// their decision.
|
||||
warnMissingPermissions()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// ignore other requests
|
||||
}
|
||||
}
|
||||
|
||||
bluetoothViewModel.permissionsUpdated()
|
||||
}
|
||||
|
||||
|
||||
private fun sendTestPackets() {
|
||||
exceptionReporter {
|
||||
val m = model.meshService!!
|
||||
|
||||
// Do some test operations
|
||||
val testPayload = "hello world".toByteArray()
|
||||
m.send(
|
||||
DataPacket(
|
||||
"+16508675310",
|
||||
testPayload,
|
||||
Portnums.PortNum.PRIVATE_APP_VALUE
|
||||
)
|
||||
)
|
||||
m.send(
|
||||
DataPacket(
|
||||
"+16508675310",
|
||||
testPayload,
|
||||
Portnums.PortNum.TEXT_MESSAGE_APP_VALUE
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Ask user to rate in play store
|
||||
private fun askToRate() {
|
||||
exceptionReporter { // Got one IllegalArgumentException from inside this lib, but we don't want to crash our app because of bugs in this optional feature
|
||||
|
@ -417,23 +291,6 @@ class MainActivity : BaseActivity(), Logging,
|
|||
|
||||
/// Set theme
|
||||
setUITheme(prefs)
|
||||
|
||||
/* not yet working
|
||||
// Configure sign-in to request the user's ID, email address, and basic
|
||||
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
|
||||
val gso =
|
||||
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
||||
.requestEmail()
|
||||
.build()
|
||||
|
||||
// Build a GoogleSignInClient with the options specified by gso.
|
||||
UIState.googleSignInClient = GoogleSignIn.getClient(this, gso);
|
||||
|
||||
*/
|
||||
|
||||
/* setContent {
|
||||
MeshApp()
|
||||
} */
|
||||
setContentView(binding.root)
|
||||
|
||||
initToolbar()
|
||||
|
|
|
@ -55,48 +55,22 @@ fun Context.getMissingPermissions(perms: List<String>): Array<String> = perms.fi
|
|||
}.toTypedArray()
|
||||
|
||||
/**
|
||||
* Bluetooth connect permissions (or empty if we already have what we need)
|
||||
* Bluetooth permissions (or empty if we already have what we need)
|
||||
*/
|
||||
fun Context.getConnectPermissions(): Array<String> {
|
||||
fun Context.getBluetoothPermissions(): Array<String> {
|
||||
val perms = mutableListOf<String>()
|
||||
|
||||
/* TODO - wait for targetSdkVersion 31
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
perms.add(Manifest.permission.BLUETOOTH_SCAN)
|
||||
perms.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
} else {
|
||||
perms.add(Manifest.permission.BLUETOOTH)
|
||||
}
|
||||
*/
|
||||
return getMissingPermissions(perms)
|
||||
}
|
||||
|
||||
/** @return true if the user already has Bluetooth connect permission */
|
||||
fun Context.hasConnectPermission() = getConnectPermissions().isEmpty()
|
||||
|
||||
/**
|
||||
* Bluetooth scan/discovery permissions (or empty if we already have what we need)
|
||||
*/
|
||||
fun Context.getScanPermissions(): Array<String> {
|
||||
val perms = mutableListOf<String>()
|
||||
|
||||
/* TODO - wait for targetSdkVersion 31
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
perms.add(Manifest.permission.BLUETOOTH_SCAN)
|
||||
} else if (!BluetoothInterface.hasCompanionDeviceApi(this)) {
|
||||
perms.add(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
perms.add(Manifest.permission.BLUETOOTH_ADMIN)
|
||||
}
|
||||
*/
|
||||
if (!hasCompanionDeviceApi()) {
|
||||
perms.add(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
perms.add(Manifest.permission.BLUETOOTH_ADMIN)
|
||||
}
|
||||
|
||||
return getMissingPermissions(perms)
|
||||
}
|
||||
|
||||
/** @return true if the user already has Bluetooth scan/discovery permission */
|
||||
fun Context.hasScanPermission() = getScanPermissions().isEmpty()
|
||||
fun Context.hasBluetoothPermission() = getBluetoothPermissions().isEmpty()
|
||||
|
||||
/**
|
||||
* Camera permission (or empty if we already have what we need)
|
||||
|
|
|
@ -131,7 +131,7 @@ class BTScanModel @Inject constructor(
|
|||
private val bluetoothAdapter = context.bluetoothManager?.adapter
|
||||
private val deviceManager get() = context.deviceManager
|
||||
val hasCompanionDeviceApi get() = context.hasCompanionDeviceApi()
|
||||
private val hasConnectPermission get() = application.hasConnectPermission()
|
||||
private val hasBluetoothPermission get() = application.hasBluetoothPermission()
|
||||
private val usbManager get() = context.usbManager
|
||||
|
||||
var selectedAddress: String? = null
|
||||
|
|
|
@ -9,7 +9,7 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.coroutineScope
|
||||
import com.geeksville.android.Logging
|
||||
import com.geeksville.mesh.CoroutineDispatchers
|
||||
import com.geeksville.mesh.android.hasConnectPermission
|
||||
import com.geeksville.mesh.android.hasBluetoothPermission
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -66,7 +66,7 @@ class BluetoothRepository @Inject constructor(
|
|||
@SuppressLint("MissingPermission")
|
||||
internal suspend fun updateBluetoothState() {
|
||||
val newState: BluetoothState = bluetoothAdapterLazy.get()?.takeIf {
|
||||
application.hasConnectPermission().also { hasPerms ->
|
||||
application.hasBluetoothPermission().also { hasPerms ->
|
||||
if (!hasPerms) errormsg("Still missing needed bluetooth permissions")
|
||||
}
|
||||
}?.let { adapter ->
|
||||
|
|
|
@ -179,19 +179,16 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
// Update the status string (highest priority messages first)
|
||||
val info = model.myNodeInfo.value
|
||||
val statusText = binding.scanStatusText
|
||||
val permissionsWarning = myActivity.getMissingMessage()
|
||||
when {
|
||||
(permissionsWarning != null) ->
|
||||
statusText.text = permissionsWarning
|
||||
|
||||
connected == MeshService.ConnectionState.CONNECTED -> {
|
||||
when (connected) {
|
||||
MeshService.ConnectionState.CONNECTED -> {
|
||||
statusText.text = if (region.number == 0) getString(R.string.must_set_region)
|
||||
else getString(R.string.connected_to).format(info?.firmwareString ?: "unknown")
|
||||
}
|
||||
connected == MeshService.ConnectionState.DISCONNECTED ->
|
||||
MeshService.ConnectionState.DISCONNECTED ->
|
||||
statusText.text = getString(R.string.not_connected)
|
||||
connected == MeshService.ConnectionState.DEVICE_SLEEP ->
|
||||
MeshService.ConnectionState.DEVICE_SLEEP ->
|
||||
statusText.text = getString(R.string.connected_sleeping)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,14 +477,40 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
|
||||
initCommonUI()
|
||||
|
||||
val requestPermissionAndScanLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||
if (permissions.entries.all { it.value }) {
|
||||
checkLocationEnabled()
|
||||
scanLeDevice()
|
||||
} else {
|
||||
errormsg("User denied scan permissions")
|
||||
showSnackbar(getString(R.string.permission_missing))
|
||||
}
|
||||
}
|
||||
|
||||
binding.changeRadioButton.setOnClickListener {
|
||||
debug("User clicked changeRadioButton")
|
||||
if (!myActivity.hasScanPermission()) {
|
||||
myActivity.requestScanPermission()
|
||||
} else {
|
||||
checkBTEnabled()
|
||||
if (!scanModel.hasCompanionDeviceApi) checkLocationEnabled()
|
||||
checkBTEnabled()
|
||||
if ((scanModel.hasCompanionDeviceApi)) {
|
||||
scanLeDevice()
|
||||
} else {
|
||||
// Location is the only runtime permission for classic bluetooth scan
|
||||
if (myActivity.hasLocationPermission()) {
|
||||
checkLocationEnabled()
|
||||
scanLeDevice()
|
||||
} else {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(getString(R.string.required_permissions))
|
||||
.setMessage(getString(R.string.permission_missing))
|
||||
.setNeutralButton(R.string.cancel) { _, _ ->
|
||||
warn("User bailed due to permissions")
|
||||
}
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
info("requesting scan permissions")
|
||||
requestPermissionAndScanLauncher.launch(myActivity.getLocationPermissions())
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,6 @@
|
|||
<string name="show_system_settings">시스템 설정 보기</string>
|
||||
<string name="why_background_required">기능을위해서, 옵션에서 위치권한을 \"항상 허용\" 으로 설정해야합니다.앱이 닫혀있거나 사용중이지 않을때에도 메쉬태스틱이 당신의 스마트폰의 위치를 읽어 당신의 메쉬의 다른 사용자에게 위치를 전송할수있게합니다.</string>
|
||||
<string name="required_permissions">권한부여 필요</string>
|
||||
<string name="location">장소</string>
|
||||
<string name="cancel_no_radio">취소 (no radio access)</string>
|
||||
<string name="allow_will_show">허용 (대화에 보일것입니다)</string>
|
||||
<string name="provide_location_to_mesh">메쉬에 현재 위치 공유</string>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="are_you_sure_channel">Are you sure you want to change the channel? All communication with other nodes will stop until you share the new channel settings.</string>
|
||||
<string name="new_channel_rcvd">Odebrano nowy URL kanału</string>
|
||||
<string name="do_you_want_switch">Chcesz przełączyć na \'%s\' kanał?</string>
|
||||
<string name="permission_missing">Meshtastic potrzebuje %s zezwolenie i lokalizacja muszą być włączone, aby można było znaleźć nowe urządzenia przez Bluetooth. Możesz go później wyłączyć.</string>
|
||||
<string name="permission_missing">Meshtastic potrzebuje lokalizacja zezwolenie i lokalizacja muszą być włączone, aby można było znaleźć nowe urządzenia przez Bluetooth. Możesz go później wyłączyć.</string>
|
||||
<string name="radio_sleeping">Radio było w trybie uśpienia, nie mogło zmienić kanału</string>
|
||||
<string name="report_bug">Zgłoś bug</string>
|
||||
<string name="report_a_bug">Zgłoś bug</string>
|
||||
|
@ -105,7 +105,6 @@
|
|||
<string name="background_required">Lokalizacja w tle</string>
|
||||
<string name="show_system_settings">Pokaż ustawienia systemowe</string>
|
||||
<string name="required_permissions">Wymagane uprawnienia</string>
|
||||
<string name="location">Lokalizacja</string>
|
||||
<string name="provide_location_to_mesh">Podaj lokalizację do sieci</string>
|
||||
<plurals name="delete_messages">
|
||||
<item quantity="one">Usunąć wiadomość?</item>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<string name="are_you_sure_channel">Tem certeza que deseja mudar de canal? Toda comunicação com os outros dispositivos será interrompida até serem compartilhadas as novas configurações do canal.</string>
|
||||
<string name="new_channel_rcvd">Novo link de canal recebido</string>
|
||||
<string name="do_you_want_switch">Deseja mudar para o canal \'%s\'?</string>
|
||||
<string name="permission_missing">Meshtastic precisa da permissão de %s e da localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois.</string>
|
||||
<string name="permission_missing">Meshtastic precisa da permissão de localização e localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois.</string>
|
||||
<string name="radio_sleeping">Rádio estava em suspensão (sleep), não foi possível mudar de canal</string>
|
||||
<string name="report_bug">Informar Bug</string>
|
||||
<string name="report_a_bug">Informar um bug</string>
|
||||
|
@ -102,7 +102,6 @@
|
|||
<string name="show_system_settings">Exibir configurações do sistema</string>
|
||||
<string name="why_background_required">Para este recurso, você deve conceder permissão para acessar Local com a opção \"Permitir o tempo todo\".\nIsto permite ao Meshtastic ler a localização do seu smartphone e enviar aos membros da sua mesh, mesmo quando o aplicativo está fechado ou não em uso.</string>
|
||||
<string name="required_permissions">Permissões necessárias</string>
|
||||
<string name="location">localização</string>
|
||||
<string name="cancel_no_radio">Cancelar (sem acesso ao rádio)</string>
|
||||
<string name="allow_will_show">Permitir (exibe diálogo)</string>
|
||||
<string name="provide_location_to_mesh">Fornecer localização para mesh</string>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<string name="are_you_sure_channel">Tem certeza que deseja mudar de canal? Todas as comunicações com outros nós serão interrompidas até que partilhe as novas configurações do canal.</string>
|
||||
<string name="new_channel_rcvd">Novo Link Recebido do Canal</string>
|
||||
<string name="do_you_want_switch">Pretende mudar para o canal \'%s\' ?</string>
|
||||
<string name="permission_missing">Meshtastic precisa da permissão de %s e da localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois.</string>
|
||||
<string name="permission_missing">Meshtastic precisa da permissão de localização e localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois.</string>
|
||||
<string name="radio_sleeping">O rádio estava a dormir, não conseguia mudar de canal</string>
|
||||
<string name="report_bug">Reportar Bug</string>
|
||||
<string name="report_a_bug">Reportar a bug</string>
|
||||
|
@ -102,7 +102,6 @@
|
|||
<string name="show_system_settings">Exibir configurações do sistema</string>
|
||||
<string name="why_background_required">Para este recurso, você deve conceder permissão para acessar Local com a opção \"Permitir o tempo todo\".\nIsto permite ao Meshtastic ler a localização do seu smartphone e enviar aos membros da sua mesh, mesmo quando o aplicativo está fechado ou não em uso.</string>
|
||||
<string name="required_permissions">Permissões necessárias</string>
|
||||
<string name="location">localização</string>
|
||||
<string name="cancel_no_radio">Cancelar (sem acesso ao rádio)</string>
|
||||
<string name="allow_will_show">Permitir (exibe diálogo)</string>
|
||||
<string name="provide_location_to_mesh">Fornecer localização para mesh</string>
|
||||
|
|
|
@ -107,7 +107,6 @@
|
|||
<string name="show_system_settings">Zobraziť nastavenia systému</string>
|
||||
<string name="why_background_required">Pre túto možnosť musíte povoliť prístup ku polohe zariadenia v režime \"Vždy povolené\".\nTáto možnosť povolí aplikácii Meshtastic zistiť polohu Vášho zariadenia a odoslať ju členom Vašej siete aj keď je aplikácia Meshtastic vypnutá alebo sa nepoužíva.</string>
|
||||
<string name="required_permissions">Požadované oprávnenia</string>
|
||||
<string name="location">poloha</string>
|
||||
<string name="cancel_no_radio">Zrušiť (žiaden dosah na vysielač)</string>
|
||||
<string name="allow_will_show">Povoliť (zobrazí potvrdzovací dialóg)</string>
|
||||
<string name="provide_location_to_mesh">Odoslať polohu do siete</string>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<string name="are_you_sure_channel">Are you sure you want to change the channel? All communication with other nodes will stop until you share the new channel settings.</string>
|
||||
<string name="new_channel_rcvd">New Channel URL received</string>
|
||||
<string name="do_you_want_switch">Do you want to switch to the \'%s\' channel?</string>
|
||||
<string name="permission_missing">Meshtastic needs %s permission and location must be turned on to find new devices via bluetooth. You can turn it off again afterwards.</string>
|
||||
<string name="permission_missing">Meshtastic needs location permission and location must be turned on to find new devices via Bluetooth. You can turn it off again afterwards.</string>
|
||||
<string name="radio_sleeping">Radio was sleeping, could not change channel</string>
|
||||
<string name="report_bug">Report Bug</string>
|
||||
<string name="report_a_bug">Report a bug</string>
|
||||
|
@ -108,7 +108,6 @@
|
|||
<string name="show_system_settings">Show system settings</string>
|
||||
<string name="why_background_required">For this feature, you must grant Location permission option \"Allow all the time\".\nThis allows Meshtastic to read your smartphone location and send it to other members of your mesh, even when the app is closed or not in use.</string>
|
||||
<string name="required_permissions">Required permissions</string>
|
||||
<string name="location">location</string>
|
||||
<string name="cancel_no_radio">Cancel (no radio access)</string>
|
||||
<string name="allow_will_show">Allow (will show dialog)</string>
|
||||
<string name="provide_location_to_mesh">Provide location to mesh</string>
|
||||
|
@ -155,4 +154,5 @@
|
|||
<string name="are_you_sure_factory_reset">Are you sure you want to factory reset?</string>
|
||||
<string name="factory_reset_description">This will clear all device configuration you have done.</string>
|
||||
<string name="bluetooth_disabled">Bluetooth disabled.</string>
|
||||
<string name="permission_missing_31">Meshtastic needs Nearby devices permission to find and connect to devices via Bluetooth. You can turn it off when not in use.</string>
|
||||
</resources>
|
||||
|
|
Ładowanie…
Reference in New Issue