Android'де VPN туташкан-туташпаганын код аркылуу текшерүү жолу
Android'де VPN туташуу абалын кайтаруучу getter жок. Тармак мүмкүнчүлүктөрүн сураңыз, транспорт өзгөрүүлөрүн көзөмөлдөңүз жана колдонмо макулдугун, түзмөк абалын жана сервер далилин өз-өзүнчө кармаңыз.
Android'ден VPN туташканбы деп сурай албайсыз. VpnService туташуу абалын кайтаруучу getter сунуштабайт, ал эми статус тилкесиндеги ачкыч белгисин система тартат, колдонмоңуз окуй алган нерсе эмес. Кыла алатканыңыз байланыш стегине тар маанидеги суроо берүү: бул колдонмонун трафиги кайсы тармакты колдонуп жатат жана ошол тармак VPN транспортун алып жүрөбү. Бул колдонмо жалган оң жыйынтыктардан оолак болгон тартипте текшерүүлөрдү жүргүзөт: түзмөктөгү shell буйругунан колдонмодо калтырган callback'ке чейин.
Колдонмо кодун кыймылдатпай туруп, түзмөктү shell'ден текшериңиз
Алгач баштапкы абалды алыңыз. adb shell dumpsys connectivity система билген бардык тармактарды чыгарат, ар бир блок өз транспортторун тизмелейт, ошондуктан VPN тармагы ошол тизмеде VPN менен көрүнөт. Баарынан мурун демейки тармак блогун окуңуз, анан ошол эле транспортту алып жүргөн башка тармактарды издеңиз.
Эки чыгарылыш ар башка суроолорго жооп берет. VPN тармагынын бар экени колдонмоңуз аны колдонуп жатканы менен бирдей эмес, ал эми жумуш профили же экинчи колдонуучу бар түзмөктө процесс интернет менен түз сүйлөшүп жатканда экөө тең бир убакта чын болушу мүмкүн. Сокеттериңиз эмне кыларын активдүү тармак сабы чечет.
Колдонмо колдонуп жаткан тармакты сураңыз
Коддо мүмкүнчүлүк тести төрт сап. Манифестте ACCESS_NETWORK_STATE сураңыз, анан активдүү тармактын мүмкүнчүлүктөрүн VPN транспорту менен салыштырыңыз:
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network active = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
boolean vpnInUse = caps != null
&& caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
Жооп атайын тар: колдонмонун демейки тармагы азыр VPNбы. Кайсы VPN, ал сиздикиби, тоннель алыскы учка жеттиби дегенди айтпайт. true маанисин «трафик кандайдыр бир тоннель аркылуу чыгат» деп кабыл алыңыз жана өз эсебиңизди өзүнчө кармаңыз. Үч маанини унчукпай эле бирге билдирген boolean — жөндөөлөр экраны колдонуучу VPN аркылуу серептеп жатканда VPN өчүк деп көрсөтүшүнүн себеби.
Тескерисинче, кандайдыр бир VPN тармагы барбы-жокпу билүү керек болсо, cm.getAllNetworks() боюнча кайталап, ар бир мүмкүнчүлүк топтомун текшериңиз. Эки жооп башка колдонмолорду камтыган, бирок сиздикини камтыбаган колдонмого тиешелүү VPN иштеп жаткан түзмөктө ажырайт, жана ошол ажырау «ачык күйүп турган VPNди колдонмо көрбөйт» деген ката билдирүүлөрдүн көбүнүн булагы.
Polling ордуна өзгөрүүлөрдү көзөмөлдөңүз
Таймер боюнча polling бул суроого туура келген форма эмес, анткени абал өзгөрүүлөрү окуя катары келет. VPN транспортуна дал келген сурамды каттап, дал келген тармак пайда болгондо, жоголгондо же өзгөргөндө фреймворк өзү кабарласын:
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();
cm.registerNetworkCallback(request, callback);
VPN тармагы эч качан NET_CAPABILITY_NOT_VPN алып жүрбөйт, ошондуктан аны ачык алып салуу ниетти документтештирет. Ансыз да сурам дал келет, бирок кийинки окуучу муну өзү аныктоого туура келет.
Каттоо көзөмөл керек болгон чөйрөгө таандык, адатта экран же алдыңкы пландагы кызмат. onStop же onDestroy ичинде каттоодон чыгарыңыз жана жоголуп кеткен activity'ге callback калтырбаңыз. Көрүнүүчү компоненти жок колдонмо туруктуу көзөмөлчү үчүн начар кожоюн, ал эми унутулган callback'тер конфигурация өзгөргөндөн кийин кулагандар.
Үч суроону өз-өзүнчө кармаңыз
Бул тармактагы баш аламандыктын көбү үч башка текшерүүнү бир деп кароодон келип чыгат. Алар ар башка API колдонушат жана бири чын болгондо калгандары жалган болушу мүмкүн.
| Question | How you answer it | What a yes means |
|---|---|---|
| Did the user grant VPN consent to my app? | VpnService.prepare() returns null | Consent exists; the tunnel may still be down |
| Is the device sending default traffic through a VPN? | TRANSPORT_VPN on the active network | Something is tunneling, not necessarily your app |
| Did this request arrive through the VPN? | Source address seen by the server | Proof for that connection, nothing wider |
Үчүнчү сап — адамдар клиентте жооп берүүгө аракет кылган, бирок ал жерде жооп берилбей турган сап. VPN клиенттерине өзүнүн дарек пулун бериңиз жана серверде баштапкы даректи окуңуз; бул колдонуучу сессия ортосунда тоннелди алмаштырса да сакталган жалгыз далил.
Жалган оң жыйынтыктарды жокко чыгарган текшерүү тартиби
Азыр да айланууда жүргөн эски үлгү код getNetworkInfo(ConnectivityManager.TYPE_VPN) чакырат. Ал чакыруу эскирген жана бир нече чыгарылышта VPN туташып турса да null кайтарган, ошондуктан көчүрүлгөн үзүндүлөр иштеп турган түзмөктө бузук көрүнөт. Мүмкүнчүлүк текшерүүлөрү бул тузактан качат жана Android 5.0'дон баштап бирдей иштейт. Эгер дагы эле аны чакырган код базасын кармасаңыз, чакырууну fallback'ке ороп койбой, анын өзүн алмаштырыңыз, анткени туура эмес жоопту так ошол fallback жараткан.
Бир кыска жол эскертүүгө татыктуу. Сырткы кызмат билдирген коомдук даректи VPN чыгуу дареги менен салыштыруу жол тууралуу бир нерсени далилдейт, бирок ар бир текшерүүгө үчүнчү тараптын сурамын кошот, ошол кызматтын иштеп турушуна көз каранды жана кэштелиши же бөгөттөлүшү мүмкүн. Аны кол менен жасалган диагностика катары кармаңыз, эч качан колдонмо ичиндеги абал текшерүүсү катары эмес.
Текшерүүлөрдү ушул тартипте аткарыңыз жана колдонуучунун билдирүүсүнө каршы келген биринчисинде токтоңуз: shell'деги транспорт тизмеси, активдүү тармактын мүмкүнчүлүктөрү, тоннелди күйгүзүп-өчүргөндөгү callback окуялары, анан сервер тараптагы баштапкы дарек. Төртөө тең дал келип, колдонмо дагы эле туура эмес иштесе, ката Android'дин тармакты көрүүсүндө эмес, өзүңүздүн абал машинаңызда.