Dlaczego Twoja aplikacja na Androida nie może dodać systemowego profilu VPN
VpnService buduje tunel, który należy do Twojej aplikacji; nie może dodawać ani edytować wpisów PPTP, L2TP czy IPsec telefonu. Prześledź granicę i wybierz właściwą drogę.
Dotykasz wiersza VPN w Ustawieniach, widzisz profil zainstalowany przez kogoś innego i zaczynasz szukać wywołania, które go dodaje. Takiego wywołania nie ma. Aplikacja może otworzyć własny tunel przez VpnService, ale wpisy na tej liście należą do platformy i do klienta, który je utworzył. Dokładna wiedza o tym, gdzie leży granica, oszczędza tydzień ścigania ukrytych klas.
Zacznij od tego, co pokazuje ekran Ustawień
Lista VPN to rejestr profili zainstalowanych przez system lub klienta producenta: PPTP, L2TP/IPsec, IKEv2 oraz wiersze wepchnięte przez aplikację OEM lub MDM. Każdy wiersz niesie adres serwera, dane logowania i implementację protokołu, która żyje poza Twoim procesem. Gdy użytkownik dotknie tam Połącz, tunel podnosi klient platformy, a nie Twój kod. Dlatego wiersz przetrwa restart i dlatego odinstalowanie Twojej aplikacji nigdy go nie usuwa.
Z perspektywy użytkownika lista wygląda jak powierzchnia API, miejsce, w którym dodanie VPN powinno być o jedno wywołanie intencji. Nie jest. Jedyne publiczne punkty wejścia, które jej dotykają, to intencje nawigacyjne, a wszystko, co do niej pisze, należy do platformy lub uprzywilejowanego komponentu.
Praktyczna konsekwencja: jeśli tekst pomocy każe użytkownikom dodać profil w Ustawieniach, Twoja aplikacja w ogóle nie jest częścią tego przepływu.
Co VpnService naprawdę Ci daje
VpnService i VpnService.Builder opisują jeden tunel, który należy do Twojej aplikacji. Dodajesz adresy, trasy, serwery DNS i MTU, ograniczasz ruch za pomocą addAllowedApplication() lub addDisallowedApplication(), a potem establish() zwraca ParcelFileDescriptor dla interfejsu TUN. Od tego momentu aplikacja czyta pakiety IP i pisze odpowiedzi, czyli protokół jest Twoją sprawą do zaimplementowania lub wbudowania: OpenVPN, WireGuard, własny transport.
Nic w tej sekwencji nie mówi PPTP, L2TP/IPsec ani IKEv2. Builder nie ma przełącznika, który by mówił użyj systemowego klienta L2TP, i nie ma wywołania zwrotnego, które pozwoliłoby sterować profilem, którego platforma już jest właścicielem. To jest prawdziwa granica i jest to granica projektu, a nie luka w uprawnieniach.
Aplikacja może więc jak najbardziej być klientem VPN na Androidzie. Po prostu nie może być menedżerem klientów dostarczanych z telefonem.
Okno zgody nie jest ozdobnikiem
Ponieważ Twój tunel może przechwycić ruch innych aplikacji, system wymaga, aby użytkownik wyraźnie go zatwierdził. prepare() zwraca Intent, który musisz uruchomić, zgoda jest powiązana z Twoim pakietem, a gdy tunel działa, pasek stanu pokazuje stały wskaźnik. Drugi VPN, który się podnosi, dezaktywuje pierwszy, bo Android prowadzi jednocześnie jeden aktywny VPN.
Ta zasada jednego aktywnego wywraca ludzi w testach. Podnosisz swój tunel, gdy podłączony jest klient firmowy, i dochodzisz do wniosku, że kod jest zepsuty, a platforma po prostu przełączyła się z innego klienta. Zgody można później wycofać, a prepare() może zwrócić null na urządzeniach, gdzie brakuje aktywności zgody, więc establish() nadal musi obsługiwać błąd.
Ukryte API i intencje ustawień
Starsze odpowiedzi wskazują klasy com.android.internal i interfejsy AIDL używane przez wbudowanego klienta. Nie ma ich w SDK, zmieniają się między wydaniami bez zapowiedzi, a sklepy traktują ten dostęp jako ryzyko. Rootowanie urządzenia też ich nie stabilizuje, bo root i dostęp do ukrytych API to niepowiązane problemy.
Wspieraną pomocą nawigacyjną jest Settings.ACTION_VPN_SETTINGS, którego wartością jest android.net.vpn.SETTINGS. Rozwiąż go przed uruchomieniem, bo niektóre kompilacje OEM nie dostarczają tej aktywności; gdy rozwiązanie zawiedzie, przejdź do opisanych kroków. Prowadzi użytkownika do ekranu i niczego nie konfiguruje.
Ścieżki właściciela urządzenia i MDM to wyjątek, który ludzie zwykle mają na myśli. DevicePolicyManager może wyznaczyć pakiet zawsze włączonego VPN, a konfiguracje zarządzane mogą wstępnie wczytywać ustawienia dla klienta, który je obsługuje, ale to nadal nie jest publiczne SDK piszące profil PPTP.
Prześledź decyzję z punktu widzenia użytkownika
Jeśli Twój produkt ma przenosić ruch, zaplanuj VpnService plus prawdziwy stos protokołów i zarezerwuj czas na przepływ zgody oraz zasadę jednego VPN. Jeśli celem jest połączenie z istniejącym profilem firmowym, Twoja praca to prowadzenie: głęboki link do ekranu ustawień, udokumentowanie pól i pozwolenie klientowi platformy na tunelowanie. Jeśli aplikacja ma tylko dotrzeć do prywatnego punktu końcowego, w ogóle nie potrzebuje własnego tunelu.
Zapisz tę decyzję, zanim napiszesz kod, bo trzy ścieżki po pierwszym sprincie nie mają prawie nic wspólnego.
Ostatnia kontrola przed startem: czy wymaganie mówi, że łączy się nasza aplikacja, czy że łączy się urządzenie? Pierwsze to VpnService, drugie to profil, którego nie możesz utworzyć. Poprawne sformułowanie tego zdania jest tańsze niż jakikolwiek refaktoring.