diff --git a/controller/app/src/main/AndroidManifest.xml b/controller/app/src/main/AndroidManifest.xml index cba273c96..f6a2e562a 100644 --- a/controller/app/src/main/AndroidManifest.xml +++ b/controller/app/src/main/AndroidManifest.xml @@ -6,10 +6,15 @@ - - - - + + + + + + diff --git a/controller/app/src/main/java/org/appdevforall/k2go/hotspot/HotspotPermissions.java b/controller/app/src/main/java/org/appdevforall/k2go/hotspot/HotspotPermissions.java new file mode 100644 index 000000000..98e1aed1b --- /dev/null +++ b/controller/app/src/main/java/org/appdevforall/k2go/hotspot/HotspotPermissions.java @@ -0,0 +1,54 @@ +/* + * ============================================================================ + * Name : HotspotPermissions.java + * Author : AppDevForAll + * Copyright : Copyright (c) 2026 AppDevForAll + * Description : Single source for the runtime permission a LocalOnlyHotspot needs + * on this OS (K2GO-439). From API 33 (TIRAMISU) + * WifiManager.startLocalOnlyHotspot requires NEARBY_WIFI_DEVICES; + * API 32 and below need ACCESS_FINE_LOCATION. The Connect and Clone + * screens read this instead of each hardcoding the location gate. + * See the startLocalOnlyHotspot javadoc. + * ============================================================================ + */ +package org.appdevforall.k2go.hotspot; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; + +import androidx.core.content.ContextCompat; + +/** Stateless permission rule for the LocalOnlyHotspot, shared by the Connect and Clone screens. */ +public final class HotspotPermissions { + + private HotspotPermissions() {} + + /** The permission(s) startLocalOnlyHotspot requires on this device's API level. */ + public static String[] required() { + return requiredFor(Build.VERSION.SDK_INT); + } + + /** + * The rule as a pure function of the API level. Package-private for unit testing. + * Keyed off the device API: startLocalOnlyHotspot bases its requirement on the app + * targetSdk, and keying off the device API matches only because the app targets >= 33. + */ + static String[] requiredFor(int sdkInt) { + if (sdkInt >= Build.VERSION_CODES.TIRAMISU) { + return new String[]{ Manifest.permission.NEARBY_WIFI_DEVICES }; + } + return new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }; + } + + /** True when every required permission is granted. */ + public static boolean granted(Context ctx) { + for (String p : required()) { + if (ContextCompat.checkSelfPermission(ctx, p) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } +} diff --git a/controller/app/src/main/java/org/appdevforall/k2go/hotspot/LocalHotspotManager.java b/controller/app/src/main/java/org/appdevforall/k2go/hotspot/LocalHotspotManager.java index 5ab4b394c..d4f34a8e6 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/hotspot/LocalHotspotManager.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/hotspot/LocalHotspotManager.java @@ -8,8 +8,9 @@ * the carrier tethering-entitlement check, so it works with no SIM and * no data plan. The reservation is process-bound: it stays up while this * app process is alive and is torn down on close() or process death. - * API 26+ only; callers must gate on Build.VERSION and hold - * CHANGE_WIFI_STATE + ACCESS_FINE_LOCATION (with Location services on). + * API 26+ only; callers must gate on Build.VERSION and hold CHANGE_WIFI_STATE + * plus the hotspot permission from HotspotPermissions (NEARBY_WIFI_DEVICES on + * API 33+, or ACCESS_FINE_LOCATION with Location services on 32 and below). * * V1 scope (ADFA-4520): manual opt-in from Advanced settings, plus a * contextual recommendation surfaced only when BOTH conditions hold @@ -110,13 +111,15 @@ public boolean isOn() { } /** - * Starts a LocalOnlyHotspot. Caller must have already granted CHANGE_WIFI_STATE + - * ACCESS_FINE_LOCATION and enabled Location services; otherwise onFailed fires. + * Starts a LocalOnlyHotspot. Caller must have already granted CHANGE_WIFI_STATE and the + * hotspot permission (see HotspotPermissions); on API 32 and below that also needs Location + * services on. Otherwise onFailed fires. */ // NewApi is suppressed because every API-26 reference below is protected by the // explicit Build.VERSION.SDK_INT guard (lint cannot see through isSupported(), and // @RequiresApi does not cover the anonymous callback class). MissingPermission is - // suppressed because CHANGE_WIFI_STATE + ACCESS_FINE_LOCATION are requested at runtime. + // suppressed because CHANGE_WIFI_STATE and the hotspot permission (HotspotPermissions) are + // requested at runtime. @SuppressLint({"MissingPermission", "NewApi"}) public void start(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/CloneFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/CloneFragment.java index dbdc14ae6..fe8a2f6ce 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/CloneFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/CloneFragment.java @@ -1,11 +1,9 @@ package org.appdevforall.k2go.redesign; -import android.Manifest; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.net.Uri; @@ -42,6 +40,7 @@ import org.appdevforall.k2go.SyncHandshakeHelper; import org.appdevforall.k2go.env.EnvironmentLock; import org.appdevforall.k2go.sync.domain.ApkShareName; +import org.appdevforall.k2go.hotspot.HotspotPermissions; import org.appdevforall.k2go.hotspot.LocalHotspotManager; import org.appdevforall.k2go.sync.domain.ShareConfig; import org.appdevforall.k2go.sync.presentation.SyncProgressRepository; @@ -109,7 +108,7 @@ private enum Page { PREPARE, COPY } private ApkServer apkServer; private String apkFileName; - private ActivityResultLauncher locationPerm; + private ActivityResultLauncher hotspotPerm; // ADFA-5146: request the location permission at most once per attempt. ensureHotspot() runs on every // render, and the permission callback re-renders; on OEMs that return a denied permission result // synchronously that becomes unbounded recursion (render -> ensureHotspot -> launch -> sync-deny -> @@ -170,9 +169,14 @@ private enum RStage { JOIN, START } @Override public void onCreate(@Nullable Bundle s) { super.onCreate(s); - locationPerm = registerForActivityResult( - new ActivityResultContracts.RequestPermission(), - granted -> { if (granted) hs.start(requireContext().getApplicationContext()); render(); }); + hotspotPerm = registerForActivityResult( + new ActivityResultContracts.RequestMultiplePermissions(), + result -> { + if (HotspotPermissions.granted(requireContext())) { + hs.start(requireContext().getApplicationContext()); + } + render(); + }); barcodeLauncher = registerForActivityResult(new ScanContract(), r -> onScan(r.getContents())); } @@ -445,14 +449,13 @@ private void ensureHotspot() { // (the "Caller already has an active LocalOnlyHotspot request" log spam). LocalHotspotManager.State st = hs.state().getValue(); if (st != null && st.phase == LocalHotspotManager.Phase.STARTING) return; - if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED) { + if (HotspotPermissions.granted(requireContext())) { hs.start(requireContext().getApplicationContext()); } else if (!locationAsked) { // ADFA-5146: launch the request exactly once. Do NOT re-launch on later renders (incl. the one - // the permission callback triggers) — a synchronous deny would otherwise recurse into overflow. + // the permission callback triggers): a synchronous deny would otherwise recurse into overflow. locationAsked = true; - locationPerm.launch(Manifest.permission.ACCESS_FINE_LOCATION); + hotspotPerm.launch(HotspotPermissions.required()); } } @@ -727,7 +730,10 @@ private void renderPrepare() { secJoin.setFallback(requireContext(), null); secJoin.caption.setText(getString(R.string.k2go_connect_hotspot_unsupported)); secJoin.subCaption.setText(getString(R.string.k2go_connect_try_wifi)); - } else if (phase == LocalHotspotManager.Phase.FAILED) { + } else if (phase == LocalHotspotManager.Phase.FAILED + || (phase != LocalHotspotManager.Phase.ON && !HotspotPermissions.granted(requireContext()))) { + // FAILED, or the hotspot permission is not granted (denied): show the hint instead of a + // perpetual "starting" placeholder (K2GO-439). secJoin.frame.setVisibility(View.GONE); secJoin.setFallback(requireContext(), null); secJoin.caption.setText(getString(R.string.k2go_connect_hotspot_failed)); diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/ConnectFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/ConnectFragment.java index 9d1a17865..ef1a77db3 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/ConnectFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/ConnectFragment.java @@ -1,8 +1,6 @@ package org.appdevforall.k2go.redesign; -import android.Manifest; import android.content.Context; -import android.content.pm.PackageManager; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.view.Gravity; @@ -19,6 +17,7 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import org.appdevforall.k2go.R; +import org.appdevforall.k2go.hotspot.HotspotPermissions; import org.appdevforall.k2go.hotspot.LocalHotspotManager; import org.appdevforall.k2go.sync.transport.NetworkInterfaces; import org.appdevforall.k2go.sync.transport.NetworkStateLiveData; @@ -51,7 +50,7 @@ private enum Mode { HOTSPOT, WIFI } // the QR would point at a dead port. Read on onResume (a system is not gained while this is open). private final LocalHotspotManager hs = LocalHotspotManager.get(); - private ActivityResultLauncher locationPerm; + private ActivityResultLauncher hotspotPerm; private TextView tabHotspot, tabWifi, finish, connFooter; // ADFA-5346: advance CTA is a MaterialButton (shape/size from the shared style); styleAdvance only @@ -63,10 +62,12 @@ private enum Mode { HOTSPOT, WIFI } @Override public void onCreate(@Nullable Bundle s) { super.onCreate(s); - locationPerm = registerForActivityResult( - new ActivityResultContracts.RequestPermission(), - granted -> { - if (granted) hs.start(requireContext().getApplicationContext()); + hotspotPerm = registerForActivityResult( + new ActivityResultContracts.RequestMultiplePermissions(), + result -> { + if (HotspotPermissions.granted(requireContext())) { + hs.start(requireContext().getApplicationContext()); + } render(); }); } @@ -126,11 +127,10 @@ private void setMode(Mode m) { private void ensureHotspot() { if (!LocalHotspotManager.isSupported() || hs.isOn()) return; - if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED) { + if (HotspotPermissions.granted(requireContext())) { hs.start(requireContext().getApplicationContext()); } else { - locationPerm.launch(Manifest.permission.ACCESS_FINE_LOCATION); + hotspotPerm.launch(HotspotPermissions.required()); } } @@ -141,6 +141,12 @@ public void onResume() { super.onResume(); // ADFA-5150/5312: redraw on the way to the front — a system may have been recovered, or an // install may have finished, while the user was away. render() re-reads the shared verdict. + // K2GO-439: if the hotspot permission was granted while away (e.g. in Settings), start it now so + // the user is not stuck on "Starting...". Only when already granted: do NOT re-launch the request + // here, which would re-prompt on every resume (ensureHotspot has no one-shot guard in Connect). + if (mode == Mode.HOTSPOT && HotspotPermissions.granted(requireContext())) { + ensureHotspot(); + } render(); } @@ -216,7 +222,10 @@ private void renderHotspot() { singleStatus(getString(R.string.k2go_connect_hotspot_unsupported), getString(R.string.k2go_connect_try_wifi)); return; } - if (phase == LocalHotspotManager.Phase.FAILED) { + // FAILED, or the hotspot permission is not granted (denied): show the hint instead of a + // perpetual "starting" placeholder (K2GO-439). + if (phase == LocalHotspotManager.Phase.FAILED + || (phase != LocalHotspotManager.Phase.ON && !HotspotPermissions.granted(requireContext()))) { singleStatus(getString(R.string.k2go_connect_hotspot_failed), getString(R.string.k2go_connect_enable_location)); return; } diff --git a/controller/app/src/main/res/values-ar/strings.xml b/controller/app/src/main/res/values-ar/strings.xml index 7cfcc7aa4..193327e8f 100644 --- a/controller/app/src/main/res/values-ar/strings.xml +++ b/controller/app/src/main/res/values-ar/strings.xml @@ -799,7 +799,7 @@ جارٍ بدء نقطة الاتصال… جارٍ العثور على عنوان نقطة الاتصال… تعذّر بدء نقطة الاتصال - فعّل إذن الموقع، ثم أعد المحاولة. + فعّل Wi-Fi وامنح الإذن، ثم حاول مرة أخرى. لست على شبكة Wi-Fi انضم إلى نفس شبكة Wi-Fi أو اتصل بنقطة اتصال المكتبة. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-az/strings.xml b/controller/app/src/main/res/values-az/strings.xml index 576078e8c..7dc1959de 100644 --- a/controller/app/src/main/res/values-az/strings.xml +++ b/controller/app/src/main/res/values-az/strings.xml @@ -819,7 +819,7 @@ Hotspot başladılır… Hotspot ünvanı tapılır… Hotspot başladıla bilmədi - Məkan icazəsini aktiv edin və yenidən cəhd edin. + Wi-Fi-ni yandırın və icazəni verin, sonra yenidən cəhd edin. Wi-Fi şəbəkəsində deyil Eyni Wi-Fi-yə və ya kitabxananın hotspotuna qoşulun. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-bg/strings.xml b/controller/app/src/main/res/values-bg/strings.xml index a220548a9..e48d0fd70 100644 --- a/controller/app/src/main/res/values-bg/strings.xml +++ b/controller/app/src/main/res/values-bg/strings.xml @@ -806,7 +806,7 @@ Стартиране на точката за достъп… Търсене на адрес на точката за достъп… Неуспешно стартиране на точката за достъп - Включете разрешението за местоположение и опитайте отново. + Включете Wi-Fi и дайте разрешението, след което опитайте отново. Не сте в Wi-Fi мрежа Свържете се със същата Wi-Fi или с точката за достъп на библиотеката. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-bn/strings.xml b/controller/app/src/main/res/values-bn/strings.xml index 3cce6b295..27c08d0ef 100644 --- a/controller/app/src/main/res/values-bn/strings.xml +++ b/controller/app/src/main/res/values-bn/strings.xml @@ -812,7 +812,7 @@ হটস্পট শুরু হচ্ছে… হটস্পট ঠিকানা খোঁজা হচ্ছে… হটস্পট শুরু করা যায়নি - অবস্থান অনুমতি চালু করুন, তারপর আবার চেষ্টা করুন। + Wi-Fi চালু করুন এবং অনুমতি দিন, তারপর আবার চেষ্টা করুন। কোনো Wi-Fi নেটওয়ার্কে নেই একই Wi-Fi-তে বা লাইব্রেরির হটস্পটে যুক্ত হন। Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-cs/strings.xml b/controller/app/src/main/res/values-cs/strings.xml index 33bd23551..728822b25 100644 --- a/controller/app/src/main/res/values-cs/strings.xml +++ b/controller/app/src/main/res/values-cs/strings.xml @@ -806,7 +806,7 @@ Spouštění hotspotu… Hledání adresy hotspotu… Nepodařilo se spustit hotspot - Povol oprávnění k poloze a zkus to znovu. + Zapněte Wi-Fi a udělte oprávnění, poté to zkuste znovu. Nepřipojeno k síti Wi-Fi Připoj se ke stejné Wi-Fi nebo k hotspotu knihovny. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-de/strings.xml b/controller/app/src/main/res/values-de/strings.xml index 1cd62eba9..b6e1c2fb7 100644 --- a/controller/app/src/main/res/values-de/strings.xml +++ b/controller/app/src/main/res/values-de/strings.xml @@ -799,7 +799,7 @@ Hotspot wird gestartet… Hotspot-Adresse wird gesucht… Hotspot konnte nicht gestartet werden - Aktiviere die Standortberechtigung und versuche es erneut. + Schalten Sie WLAN ein und erteilen Sie die Berechtigung, und versuchen Sie es erneut. Nicht in einem Wi-Fi-Netzwerk Tritt demselben WLAN bei oder verbinde dich mit dem Hotspot der Bibliothek. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-el/strings.xml b/controller/app/src/main/res/values-el/strings.xml index 2945b31c9..819ca28e7 100644 --- a/controller/app/src/main/res/values-el/strings.xml +++ b/controller/app/src/main/res/values-el/strings.xml @@ -806,7 +806,7 @@ Έναρξη σημείου πρόσβασης… Εύρεση διεύθυνσης hotspot… Δεν ήταν δυνατή η έναρξη του σημείου πρόσβασης - Ενεργοποιήστε την άδεια Τοποθεσίας και δοκιμάστε ξανά. + Ενεργοποιήστε το Wi-Fi και δώστε την άδεια, και δοκιμάστε ξανά. Δεν υπάρχει σύνδεση σε δίκτυο Wi-Fi Συνδεθείτε στο ίδιο Wi-Fi ή στο hotspot της βιβλιοθήκης. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-es/strings.xml b/controller/app/src/main/res/values-es/strings.xml index 1f80d2f18..c28e321a5 100644 --- a/controller/app/src/main/res/values-es/strings.xml +++ b/controller/app/src/main/res/values-es/strings.xml @@ -875,7 +875,7 @@ Iniciando punto de acceso… Buscando la dirección del hotspot… No se pudo iniciar el punto de acceso - Activa el permiso de Ubicación y vuelve a intentarlo. + Activa el Wi-Fi y concede el permiso, luego inténtalo de nuevo. No estás en una red Wi-Fi Únete a la misma Wi-Fi o conéctate al hotspot de la biblioteca. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-fa/strings.xml b/controller/app/src/main/res/values-fa/strings.xml index 4cdb967c2..8a052b644 100644 --- a/controller/app/src/main/res/values-fa/strings.xml +++ b/controller/app/src/main/res/values-fa/strings.xml @@ -799,7 +799,7 @@ در حال شروع هات‌اسپات… در حال یافتن آدرس هات‌اسپات… هات‌اسپات شروع نشد - اجازهٔ موقعیت مکانی را روشن کنید، سپس دوباره تلاش کنید. + Wi-Fi را روشن کنید و مجوز را بدهید، سپس دوباره امتحان کنید. به شبکه Wi-Fi متصل نیستید به همان Wi-Fi یا به نقطهٔ اتصال کتابخانه وصل شوید. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-fr/strings.xml b/controller/app/src/main/res/values-fr/strings.xml index 184129e57..11759edc6 100644 --- a/controller/app/src/main/res/values-fr/strings.xml +++ b/controller/app/src/main/res/values-fr/strings.xml @@ -878,7 +878,7 @@ Démarrage du point d\'accès… Recherche de l’adresse du point d’accès… Impossible de démarrer le point d\'accès - Activez l\'autorisation de localisation, puis réessayez. + Activez le Wi-Fi et accordez l\'autorisation, puis réessayez. Pas connecté à un réseau Wi-Fi Rejoignez le même Wi-Fi ou connectez-vous au hotspot de la bibliothèque. Wi-Fi : %1$s diff --git a/controller/app/src/main/res/values-gu/strings.xml b/controller/app/src/main/res/values-gu/strings.xml index c2bba2bec..2d26d597c 100644 --- a/controller/app/src/main/res/values-gu/strings.xml +++ b/controller/app/src/main/res/values-gu/strings.xml @@ -812,7 +812,7 @@ હૉટસ્પૉટ શરૂ થઈ રહ્યું છે… હોટસ્પોટ સરનામું શોધી રહ્યું છે… હૉટસ્પૉટ શરૂ ન થઈ શક્યું - સ્થાન પરવાનગી ચાલુ કરો, પછી ફરી પ્રયાસ કરો. + Wi-Fi ચાલુ કરો અને પરવાનગી આપો, પછી ફરી પ્રયાસ કરો. Wi-Fi નેટવર્ક પર નથી સમાન Wi-Fi સાથે અથવા લાઇબ્રેરીના હૉટસ્પૉટ સાથે જોડાઓ. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-hi/strings.xml b/controller/app/src/main/res/values-hi/strings.xml index 3d2dde69f..7c0b212aa 100644 --- a/controller/app/src/main/res/values-hi/strings.xml +++ b/controller/app/src/main/res/values-hi/strings.xml @@ -876,7 +876,7 @@ हॉटस्पॉट शुरू हो रहा है… हॉटस्पॉट पता ढूँढ रहे हैं… हॉटस्पॉट शुरू नहीं हो सका - स्थान अनुमति चालू करें, फिर पुनः प्रयास करें। + Wi-Fi चालू करें और अनुमति दें, फिर पुनः प्रयास करें। किसी Wi-Fi नेटवर्क पर नहीं उसी Wi-Fi से या लाइब्रेरी के हॉटस्पॉट से जुड़ें। Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-hu/strings.xml b/controller/app/src/main/res/values-hu/strings.xml index 88dd37368..0553a3941 100644 --- a/controller/app/src/main/res/values-hu/strings.xml +++ b/controller/app/src/main/res/values-hu/strings.xml @@ -799,7 +799,7 @@ Hotspot indítása… Hotspotcím keresése… Nem sikerült elindítani a hotspotot - Engedélyezd a Helyhozzáférést, majd próbáld újra. + Kapcsolja be a Wi-Fit és adja meg az engedélyt, majd próbálja újra. Nincs Wi-Fi hálózaton Csatlakozz ugyanahhoz a Wi-Fi-hez, vagy a könyvtár hotspotjához. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-in/strings.xml b/controller/app/src/main/res/values-in/strings.xml index 77116249e..1b5522787 100644 --- a/controller/app/src/main/res/values-in/strings.xml +++ b/controller/app/src/main/res/values-in/strings.xml @@ -806,7 +806,7 @@ Memulai hotspot… Menemukan alamat hotspot… Tidak bisa memulai hotspot - Aktifkan izin Lokasi, lalu coba lagi. + Aktifkan Wi-Fi dan berikan izinnya, lalu coba lagi. Tidak terhubung ke jaringan Wi-Fi Sambungkan ke Wi-Fi yang sama atau ke hotspot pustaka. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-it/strings.xml b/controller/app/src/main/res/values-it/strings.xml index 80236612c..85d909298 100644 --- a/controller/app/src/main/res/values-it/strings.xml +++ b/controller/app/src/main/res/values-it/strings.xml @@ -799,7 +799,7 @@ Avvio dell\'hotspot… Ricerca dell’indirizzo dell’hotspot… Impossibile avviare l\'hotspot - Attiva l\'autorizzazione alla posizione, poi riprova. + Attiva il Wi-Fi e concedi l\'autorizzazione, quindi riprova. Non connesso a una rete Wi-Fi Connettiti alla stessa Wi-Fi o all\'hotspot della libreria. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-ja/strings.xml b/controller/app/src/main/res/values-ja/strings.xml index faaa547f3..c9f89256e 100644 --- a/controller/app/src/main/res/values-ja/strings.xml +++ b/controller/app/src/main/res/values-ja/strings.xml @@ -800,7 +800,7 @@ ホットスポットを開始中… ホットスポットのアドレスを検索中… ホットスポットを開始できませんでした - 位置情報の権限をオンにして、もう一度お試しください。 + Wi-Fi をオンにして権限を許可し、もう一度お試しください。 Wi-Fi ネットワークに接続していません 同じ Wi-Fi、またはライブラリのホットスポットに接続してください。 Wi-Fi:%1$s diff --git a/controller/app/src/main/res/values-ko/strings.xml b/controller/app/src/main/res/values-ko/strings.xml index 1412bfbfd..990235cdd 100644 --- a/controller/app/src/main/res/values-ko/strings.xml +++ b/controller/app/src/main/res/values-ko/strings.xml @@ -800,7 +800,7 @@ 핫스팟을 시작하는 중… 핫스팟 주소 찾는 중… 핫스팟을 시작할 수 없습니다 - 위치 권한을 켠 다음 다시 시도하세요. + Wi-Fi를 켜고 권한을 허용한 후 다시 시도하세요. Wi-Fi 네트워크에 연결되어 있지 않음 같은 Wi-Fi 또는 라이브러리의 핫스팟에 연결하세요. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-lt/strings.xml b/controller/app/src/main/res/values-lt/strings.xml index 77b834241..8816b2756 100644 --- a/controller/app/src/main/res/values-lt/strings.xml +++ b/controller/app/src/main/res/values-lt/strings.xml @@ -808,7 +808,7 @@ Paleidžiamas prieigos taškas… Ieškoma prieigos taško adreso… Nepavyko paleisti prieigos taško - Įjunkite vietovės leidimą ir bandykite dar kartą. + Įjunkite „Wi-Fi“ ir suteikite leidimą, tada bandykite dar kartą. Neprisijungta prie Wi-Fi tinklo Prisijunkite prie to paties „Wi-Fi“ arba prie bibliotekos viešosios prieigos taško. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-nl/strings.xml b/controller/app/src/main/res/values-nl/strings.xml index 397b1e8e7..54e6e61bb 100644 --- a/controller/app/src/main/res/values-nl/strings.xml +++ b/controller/app/src/main/res/values-nl/strings.xml @@ -799,7 +799,7 @@ Hotspot starten… Hotspotadres zoeken… Hotspot starten mislukt - Schakel de locatietoestemming in en probeer het opnieuw. + Schakel wifi in en verleen de toestemming, en probeer het opnieuw. Niet op een Wi-Fi-netwerk Maak verbinding met dezelfde wifi of met de hotspot van de bibliotheek. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-no/strings.xml b/controller/app/src/main/res/values-no/strings.xml index 058d0c763..b3663bb58 100644 --- a/controller/app/src/main/res/values-no/strings.xml +++ b/controller/app/src/main/res/values-no/strings.xml @@ -801,7 +801,7 @@ Starter Wi-Fi-sone… Finner hotspot-adresse… Kunne ikke starte Wi-Fi-sonen - Slå på stedstillatelsen, og prøv igjen. + Slå på Wi-Fi og gi tillatelsen, og prøv igjen. Ikke på et Wi-Fi-nettverk Koble til samme Wi-Fi eller til bibliotekets hotspot. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-pl/strings.xml b/controller/app/src/main/res/values-pl/strings.xml index 3a544ad62..a6329be33 100644 --- a/controller/app/src/main/res/values-pl/strings.xml +++ b/controller/app/src/main/res/values-pl/strings.xml @@ -801,7 +801,7 @@ Uruchamianie hotspotu… Wyszukiwanie adresu hotspotu… Nie udało się uruchomić hotspotu - Włącz uprawnienie lokalizacji i spróbuj ponownie. + Włącz Wi-Fi i przyznaj uprawnienie, a następnie spróbuj ponownie. Brak połączenia z siecią Wi-Fi Połącz się z tą samą siecią Wi-Fi lub z hotspotem biblioteki. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-pt/strings.xml b/controller/app/src/main/res/values-pt/strings.xml index b6d847c78..c16be2147 100644 --- a/controller/app/src/main/res/values-pt/strings.xml +++ b/controller/app/src/main/res/values-pt/strings.xml @@ -878,7 +878,7 @@ A iniciar o hotspot… Procurando o endereço do hotspot… Não foi possível iniciar o hotspot - Ativa a permissão de Localização e tenta novamente. + Ative o Wi-Fi e conceda a permissão, depois tente novamente. Sem ligação a uma rede Wi-Fi Liga-te à mesma Wi-Fi ou ao hotspot da biblioteca. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-ro/strings.xml b/controller/app/src/main/res/values-ro/strings.xml index b2e6959db..819d7e48f 100644 --- a/controller/app/src/main/res/values-ro/strings.xml +++ b/controller/app/src/main/res/values-ro/strings.xml @@ -799,7 +799,7 @@ Se pornește hotspotul… Se caută adresa hotspotului… Nu s-a putut porni hotspotul - Activează permisiunea de Locație, apoi încearcă din nou. + Activați Wi-Fi și acordați permisiunea, apoi încercați din nou. Nu ești pe o rețea Wi-Fi Conectează-te la aceeași rețea Wi-Fi sau la hotspotul bibliotecii. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-ru-rRU/strings.xml b/controller/app/src/main/res/values-ru-rRU/strings.xml index 1c1a2b828..ecc5c8ddb 100644 --- a/controller/app/src/main/res/values-ru-rRU/strings.xml +++ b/controller/app/src/main/res/values-ru-rRU/strings.xml @@ -875,7 +875,7 @@ Запуск точки доступа… Поиск адреса точки доступа… Не удалось запустить точку доступа - Включите разрешение на геолокацию и повторите попытку. + Включите Wi-Fi и предоставьте разрешение, затем повторите попытку. Нет подключения к сети Wi-Fi Подключитесь к той же сети Wi-Fi или к точке доступа библиотеки. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-sk/strings.xml b/controller/app/src/main/res/values-sk/strings.xml index 0c7108fcc..8c8ca0b7e 100644 --- a/controller/app/src/main/res/values-sk/strings.xml +++ b/controller/app/src/main/res/values-sk/strings.xml @@ -806,7 +806,7 @@ Spúšťa sa hotspot… Hľadá sa adresa hotspotu… Nepodarilo sa spustiť hotspot - Povol povolenie polohy a skús to znova. + Zapnite Wi-Fi a udeľte povolenie, potom to skúste znova. Nie ste v sieti Wi-Fi Pripoj sa k rovnakej Wi-Fi alebo k hotspotu knižnice. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-sr/strings.xml b/controller/app/src/main/res/values-sr/strings.xml index 7cd9bf113..8dcbfb0f8 100644 --- a/controller/app/src/main/res/values-sr/strings.xml +++ b/controller/app/src/main/res/values-sr/strings.xml @@ -812,7 +812,7 @@ Покретање хотспота… Тражење адресе хотспота… Покретање хотспота није успело - Укључите дозволу за локацију, па покушајте поново. + Укључите Wi-Fi и дајте дозволу, па покушајте поново. Нисте на Wi-Fi мрежи Повежите се на исти Wi-Fi или на хотспот библиотеке. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-sw/strings.xml b/controller/app/src/main/res/values-sw/strings.xml index fa01f31c0..685400f32 100644 --- a/controller/app/src/main/res/values-sw/strings.xml +++ b/controller/app/src/main/res/values-sw/strings.xml @@ -819,7 +819,7 @@ Inaanzisha hotspot… Inatafuta anwani ya hotspot… Haikuweza kuanzisha hotspot - Washa ruhusa ya Mahali, kisha ujaribu tena. + Washa Wi-Fi na uruhusu kibali, kisha ujaribu tena. Hujaunganishwa kwenye mtandao wa Wi-Fi Unganisha kwenye Wi-Fi ile ile au kwenye mtandao-hewa wa maktaba. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-ta/strings.xml b/controller/app/src/main/res/values-ta/strings.xml index 91c8f08c8..5cb9a48a9 100644 --- a/controller/app/src/main/res/values-ta/strings.xml +++ b/controller/app/src/main/res/values-ta/strings.xml @@ -819,7 +819,7 @@ ஹாட்ஸ்பாட் தொடங்கப்படுகிறது… ஹாட்ஸ்பாட் முகவரியைத் தேடுகிறது… ஹாட்ஸ்பாட்டைத் தொடங்க முடியவில்லை - இட அனுமதியை இயக்கி, மீண்டும் முயற்சிக்கவும். + Wi-Fi ஐ இயக்கி அனுமதியை வழங்கவும், பிறகு மீண்டும் முயற்சிக்கவும். Wi-Fi நெட்வொர்க்கில் இல்லை அதே Wi-Fi உடன் அல்லது நூலகத்தின் ஹாட்ஸ்பாட்டுடன் இணையவும். Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-tr/strings.xml b/controller/app/src/main/res/values-tr/strings.xml index 4a027207b..24ec8a9c1 100644 --- a/controller/app/src/main/res/values-tr/strings.xml +++ b/controller/app/src/main/res/values-tr/strings.xml @@ -799,7 +799,7 @@ Etkin nokta başlatılıyor… Erişim noktası adresi bulunuyor… Etkin nokta başlatılamadı - Konum iznini açın, sonra tekrar deneyin. + Wi-Fi\'yi açın ve izni verin, ardından tekrar deneyin. Bir Wi-Fi ağında değilsiniz Aynı Wi-Fi\'ye ya da kitaplığın hotspot\'una bağlanın. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-uk/strings.xml b/controller/app/src/main/res/values-uk/strings.xml index 885bede97..75cfbd189 100644 --- a/controller/app/src/main/res/values-uk/strings.xml +++ b/controller/app/src/main/res/values-uk/strings.xml @@ -799,7 +799,7 @@ Запуск точки доступу… Пошук адреси точки доступу… Не вдалося запустити точку доступу - Увімкніть дозвіл на геолокацію та повторіть спробу. + Увімкніть Wi-Fi і надайте дозвіл, потім повторіть спробу. Немає підключення до Wi-Fi Підключіться до тієї ж Wi-Fi або до точки доступу бібліотеки. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-vi/strings.xml b/controller/app/src/main/res/values-vi/strings.xml index 77bf474b0..332a5ef37 100644 --- a/controller/app/src/main/res/values-vi/strings.xml +++ b/controller/app/src/main/res/values-vi/strings.xml @@ -799,7 +799,7 @@ Đang khởi động điểm phát sóng… Đang tìm địa chỉ điểm phát sóng… Không thể khởi động điểm phát sóng - Bật quyền Vị trí, rồi thử lại. + Bật Wi-Fi và cấp quyền, sau đó thử lại. Không có trên mạng Wi-Fi Kết nối cùng Wi-Fi hoặc với điểm phát sóng của thư viện. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-yo/strings.xml b/controller/app/src/main/res/values-yo/strings.xml index 06b0148cd..f91eb4230 100644 --- a/controller/app/src/main/res/values-yo/strings.xml +++ b/controller/app/src/main/res/values-yo/strings.xml @@ -819,7 +819,7 @@ Ń bẹ̀rẹ̀ hotspot… Ń wá àdírẹ́sì hotspot… Kò lè bẹ̀rẹ̀ hotspot - Tan àṣẹ Ìpò-ilẹ̀, lẹ́yìn náà gbìyànjú lẹ́ẹ̀kansi. + Tan Wi-Fi ki o si funni ni igbanilaaye, lehinna gbiyanju lekansi. Kò sí lórí nẹ́tíwọ́ọ̀kì Wi-Fi Dara pọ̀ mọ́ Wi-Fi kan náà tàbí mọ́ hotspot ilé-ìkàwé. Wi-Fi: %1$s diff --git a/controller/app/src/main/res/values-zh-rCN/strings.xml b/controller/app/src/main/res/values-zh-rCN/strings.xml index 64c3c914c..91b1150f7 100644 --- a/controller/app/src/main/res/values-zh-rCN/strings.xml +++ b/controller/app/src/main/res/values-zh-rCN/strings.xml @@ -800,7 +800,7 @@ 正在启动热点… 正在查找热点地址… 无法启动热点 - 开启位置权限,然后重试。 + 请开启 Wi-Fi 并授予权限,然后重试。 未连接到 Wi-Fi 网络 连接到同一 Wi-Fi 或图书馆的热点。 Wi-Fi:%1$s diff --git a/controller/app/src/main/res/values/strings.xml b/controller/app/src/main/res/values/strings.xml index ad972cc9c..cac315907 100644 --- a/controller/app/src/main/res/values/strings.xml +++ b/controller/app/src/main/res/values/strings.xml @@ -966,7 +966,7 @@ Finding hotspot address… Couldn\'t start the hotspot - Enable the Location permission, then try again. + Turn on Wi-Fi and grant the permission, then try again. Not on a Wi-Fi network Join the same Wi-Fi or connect to the library\'s hotspot. Wi-Fi: %1$s diff --git a/controller/app/src/test/java/org/appdevforall/k2go/hotspot/HotspotPermissionsTest.java b/controller/app/src/test/java/org/appdevforall/k2go/hotspot/HotspotPermissionsTest.java new file mode 100644 index 000000000..fcfb2097d --- /dev/null +++ b/controller/app/src/test/java/org/appdevforall/k2go/hotspot/HotspotPermissionsTest.java @@ -0,0 +1,31 @@ +package org.appdevforall.k2go.hotspot; + +import static org.junit.Assert.assertArrayEquals; + +import android.Manifest; +import android.os.Build; + +import org.junit.Test; + +/** + * Unit tests for {@link HotspotPermissions} (K2GO-439): the rule that picks the + * runtime permission startLocalOnlyHotspot needs per API level. + */ +public class HotspotPermissionsTest { + + @Test + public void api33AndAboveRequiresNearbyWifiDevices() { + assertArrayEquals(new String[]{ Manifest.permission.NEARBY_WIFI_DEVICES }, + HotspotPermissions.requiredFor(Build.VERSION_CODES.TIRAMISU)); + assertArrayEquals(new String[]{ Manifest.permission.NEARBY_WIFI_DEVICES }, + HotspotPermissions.requiredFor(35)); + } + + @Test + public void api32AndBelowRequiresFineLocation() { + assertArrayEquals(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }, + HotspotPermissions.requiredFor(Build.VERSION_CODES.S_V2)); + assertArrayEquals(new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }, + HotspotPermissions.requiredFor(24)); + } +}