మీ యాప్ VpnService.prepare ను పిలుస్తుంది, null పొందుతుంది, ఒక సొరంగాన్ని నిర్మిస్తుంది, డిస్క్రిప్టర్ చెల్లుబాటు అయినట్లు కనిపిస్తుంది, కానీ సర్వర్కు ఏదీ చేరుకోదు. లేదా prepare ఒక Intent ను తిరిగి ఇస్తుంది, వినియోగదారు దాన్ని ఆమోదిస్తారు, establish ఇప్పటికీ విఫలమవుతుంది. రెండు ఫలితాలు సాధారణంగా ఒకే విషయాన్ని సూచిస్తాయి: మరో యాప్ ఇప్పటికే ఈ వినియోగదారు యొక్క VPN ఇంటర్ఫేస్ను కలిగి ఉంది, మీ protect పిలుపులు మీ సొరంగం ఉపయోగించలేని సాకెట్లను గుర్తిస్తున్నాయి. క్రింది తనిఖీలను వరుసగా పూర్తి చేసి విఫలమయ్యే మొదటి తనిఖీ వద్ద ఆగండి, ఎందుకంటే తర్వాతి దశ మునుపటి దశను సరిచేయలేదు.

protect ను తాకే ముందు VPN స్లాట్ను తనిఖీ చేయండి

Android ప్రతి వినియోగదారునికి సరిగ్గా ఒక సక్రియ VPN ఇంటర్ఫేస్ను ఇస్తుంది. ఇది ప్లాట్ఫారమ్ నియమం, మీ యాప్ అడగగల అనుమతి కాదు, కాబట్టి ఇద్దరూ సొరంగం కావాలనుకునే రెండు క్లయింట్లు కలిసి ఉండలేవు.

మరో యాప్ కోసం సెట్ చేసిన ఎల్లప్పుడూ ఆన్లో ఉండే VPN అత్యంత కఠినమైన సందర్భం, ఎందుకంటే సిస్టమ్ ఆ యాప్ను కనెక్ట్ చేసి ఉంచి స్వాధీనాన్ని తిరస్కరిస్తుంది. AdGuard వంటి ట్రాఫిక్ ఫిల్టర్, కార్పొరేట్ క్లయింట్ లేదా వినియోగదారు VPN వినియోగదారు అది ఇన్స్టాల్ అయినట్లు మరచిపోయినప్పుడు స్లాట్ను పట్టుకోవచ్చు. వినియోగదారుని సెట్టింగ్లను తెరిచి VPN క్రింద జాబితా చేయబడిన ఎంట్రీని చదవమని అడగండి; అక్కడి పేరే మీరు పోటీ పడుతున్న యజమాని. ఆ ఎంట్రీ డిస్కనెక్ట్ అయ్యే వరకు లేదా ఎల్లప్పుడూ ఆన్ సెట్టింగ్ తొలగించబడే వరకు మీ VpnService ఇంటర్ఫేస్ కాలేదు.

దశ 1: prepare ఏమి తిరిగి ఇస్తుందో చదవండి

VpnService.prepare ఒకే ప్రశ్నకు సమాధానమిస్తుంది: ఈ యాప్ VPN కాగలదా? అనుమతి ఇప్పటికే ఉంటే అది null తిరిగి ఇస్తుంది, వినియోగదారు ఇంకా ఆమోదించాల్సి ఉంటే Intent ఇస్తుంది, దాన్ని మీరు startActivityForResult తో ప్రారంభించాలి. null తిరిగి రావడాన్ని కొనసాగడానికి అనుమతిగా భావించండి, establish విజయవంతమవుతుందని రుజువుగా కాదు.

Intent intent = VpnService.prepare(context);
if (intent != null) {
    startActivityForResult(intent, REQUEST_VPN);
}

Intent మార్గం తిరిగి వచ్చి వినియోగదారు నిరాకరిస్తే, తదుపరి ప్రయత్నంలో prepare మళ్లీ Intent తిరిగి ఇస్తూనే ఉంటుంది. లూప్లో మళ్లీ ప్రయత్నించడం బదులు ఫలిత కోడ్ను లాగ్ చేయండి, ఎందుకంటే నిరాకరించిన అనుమతి వినియోగదారు నిర్ణయం, తాత్కాలిక లోపం కాదు.

దశ 2: ఇంటర్ఫేస్ మీ యాప్దే అని నిర్ధారించుకోండి

establish తర్వాత పొందే ParcelFileDescriptor మీ యాజమాన్యానికి రుజువు, ఏదైనా సాకెట్ పని ముందు దాన్ని తనిఖీ చేయడం విలువైనది. null లేదా ఇప్పటికే మూసివేసిన డిస్క్రిప్టర్ అంటే ఇంటర్ఫేస్ ఎప్పుడూ సృష్టించబడలేదు, ఏ మినహాయింపూ కనిపించకపోయినా. builder ఇంటర్ఫేస్ పేరును సిస్టమ్ సక్రియ VPN కోసం నివేదించే పేరుతో పోల్చండి, పరీక్ష పరికరంలో dumpsys ఉపయోగించి. అవి భిన్నంగా ఉంటే, మీరు నిర్మించిన సొరంగం ట్రాఫిక్ మోసుకెళ్లే సొరంగం కాదు.

adb shell dumpsys connectivity

అదే అసమానత కనెక్ట్ అయిన ఐకాన్తో చనిపోయిన ట్రాఫిక్ను వివరిస్తుంది. సిస్టమ్ మరో యాప్ సొరంగాన్ని చూపిస్తుంది, మీ కోడ్ తనకు సొంతం కాని ఇంటర్ఫేస్ డిస్క్రిప్టర్ను పట్టుకుని ఉంటుంది.

దశ 3: connect కు ముందు protect ను పిలవండి

ఇంటర్ఫేస్ ఉనికిలో ఉన్నప్పుడు, మీ యాప్ తెరిచే సాకెట్లు డిఫాల్ట్గా సొరంగంలోకి మళ్లించబడతాయి. బాహ్య రవాణా ఆ నియమాన్ని పాటించలేదు, లేకపోతే కెప్సూల్ చేసిన ప్యాకెట్ ఇంటర్ఫేస్లోకి తిరిగి వస్తుంది, కాబట్టి VpnService protect ఒక సాకెట్ను VPN ను దాటవేసి అండర్లైయింగ్ నెట్వర్క్ ఉపయోగించేలా గుర్తిస్తుంది. పిలుపు boolean తిరిగి ఇస్తుంది, దాన్ని పట్టించుకోకపోవడమే ఆరోగ్యకరంగా కనిపిస్తూ ఏమీ మోసుకెళ్లని సాకెట్ను చేరుకునే మార్గం.

connect లేదా bind కు ముందు protect ను పిలవండి, ఎప్పుడూ తర్వాత కాదు. సాకెట్ కనెక్ట్ లేదా బైండ్ కావడానికి ముందే రక్షణ ఉండాలి, ఎందుకంటే కనెక్ట్ అయిన సాకెట్ తన మార్గాన్ని ఇప్పటికే ఎంచుకుంది, తర్వాతి protect దాన్ని నమ్మదగిన విధంగా కదిలించదు. protect false తిరిగి ఇస్తే, ఆగి యాజమాన్యాన్ని మళ్లీ తనిఖీ చేయండి: ఇంటర్ఫేస్ మీ యాప్ది కానప్పుడు అది విఫలమవుతుంది, అదే మరో VPN వదిలివేసే స్థితి. false తిరిగి రావడం దశ 1 కు తిరిగి వెళ్లడానికి సంకేతం, అదే సాకెట్ను మళ్లీ ప్రయత్నించడానికి కాదు.

DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
    return;
}
socket.connect(serverAddress, serverPort);

దశ 4: సాకెట్ ఇబ్బందిగా ఉన్నప్పుడు ప్రక్రియను బైండ్ చేయండి

కొన్ని రవాణాలు ఒకే సాకెట్ కావు: లైబ్రరీ అనేకాన్ని తెరవవచ్చు, లేదా సహాయక ప్రక్రియలోని ప్రతి కనెక్షన్ ఒకే నిష్క్రమణను ఉపయోగించాలని మీరు కోరుకోవచ్చు. ConnectivityManager.bindProcessToNetwork ప్రక్రియను ఎంచుకున్న నెట్వర్క్కు బైండ్ చేస్తుంది, పాత setProcessDefaultNetwork కూడా అది వాడుకలో లేనిదిగా ప్రకటించబడే ముందు అదే పని చేసింది. అండర్లైయింగ్ కనెక్షన్ను NET_CAPABILITY_NOT_VPN తో అడగండి, బైండింగ్ మీ సొరంగం క్రింది నెట్వర్క్ను ఎంచుకునేలా, సొరంగాన్ని కాదు.

NetworkRequest request = new NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build();

ప్రక్రియను బైండ్ చేయడం రెండో VPN కాదు. అది ఆ ప్రక్రియకు నిష్క్రమణను ఎంచుకుంటుంది, ఇది మీ రవాణాకు ఉపయోగకరం, ఒకేసారి రెండు సొరంగాలు నడపడానికి పనికిరాదు.

కోడ్ మార్గాన్ని కాదు, వినియోగదారు పరికరాన్ని సరిచేయండి

రెండు యాప్లు VPN స్లాట్ను పంచుకోవడానికి అనుమతించే API లేదు, కాబట్టి సవరణ పరికర స్థితికి చెందుతుంది. వినియోగదారునికి రెండు స్పష్టమైన మార్గాలు ఇవ్వండి: మరో యాప్ కనెక్షన్ను తెంచండి లేదా దాని ఎల్లప్పుడూ ఆన్ను తొలగించండి, మీ prepare స్వాధీనం చేసుకోగలదు, లేదా ఆ యాప్ యాప్ వారీ సెట్టింగ్లను తెరిచి మీ యాప్ను దాని సొరంగం నుండి మినహాయించండి. మినహాయింపు మిగతా అన్నింటికీ ఫిల్టర్ నడుస్తూ ఉండేలా చేసి మీ యాప్ సాధారణ కనెక్షన్ ఉపయోగించడానికి అనుమతిస్తుంది, ఇది తరచుగా వినియోగదారు నిజంగా కోరుకునే ఫలితం.

రెండు మార్గాలను మీ మద్దతు పత్రాలలో రాయండి, ఎందుకంటే ఏ యాప్ VPN కలిగి ఉందో వినియోగదారులు అరుదుగా తెలుసుకుంటారు. సెట్టింగ్ల నుండి సక్రియ VPN పేరు మరియు మీ లాగ్ల నుండి prepare, establish, protect ఫలితాలను పంపమని కోరండి, ఒక నిమిషంలో ఏ దశ విఫలమైందో చెప్పగలరు. ఆపై నిజమైన ట్రాఫిక్తో ధృవీకరించండి: పేరు శోధన, TCP కనెక్షన్ మరియు సొరంగం ద్వారా ఒక అభ్యర్థన, కేవలం కనెక్ట్ అయిన ఐకాన్ కాదు. చెల్లుబాటు అయిన డిస్క్రిప్టర్ మరియు ఆకుపచ్చ సూచిక గరిష్ఠంగా యాజమాన్యాన్ని రుజువు చేస్తాయి, రవాణా రూటింగ్ నియమాల నుండి బయటపడిందని ఎప్పుడూ కాదు.

నాలుగు తనిఖీలు దాటినా ట్రాఫిక్ ఇప్పటికీ చనిపోతే, యాజమాన్యం ఇక మీ సమస్య కాదు. రూటింగ్ మరియు సర్వర్ చేరుకోగలిగే స్థాయికి వెళ్లండి, VPN యాప్ ఇన్స్టాల్ లేని పరికరం నుండి అదే ఆధారాలను పరీక్షించండి.

సంబంధిత వ్యాసాలు