તમારી એપ 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 હોય કે પહેલેથી બંધ હોય તેવું ડિસ્ક્રિપ્ટર એટલે ઇન્ટરફેસ ક્યારેય બન્યું જ નહીં, ભલે કોઈ અપવાદ દેખાયો ન હોય. બિલ્ડરનું ઇન્ટરફેસ નામ સિસ્ટમ સક્રિય 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 નથી. તે તે પ્રક્રિયા માટે એક્ઝિટ પસંદ કરે છે, જે તમારા ટ્રાન્સપોર્ટ માટે ઉપયોગી છે અને એકસાથે બે ટનલ ચલાવવા માટે નકામું છે.

વપરાશકર્તાનું ઉપકરણ સુધારો, કોડનો માર્ગ નહીં

એવી કોઈ API નથી જે બે એપને VPN સ્લોટ વહેંચવા દે, તેથી સુધારો ઉપકરણની સ્થિતિમાં છે. વપરાશકર્તાને બે નક્કર માર્ગ આપો: બીજી એપનું જોડાણ કાપો અથવા તેનું હંમેશા-ચાલુ ભૂંસો જેથી તમારું prepare કબજો લઈ શકે, અથવા તે એપની એપ-વાર સેટિંગ્સ ખોલીને તમારી એપને તેની ટનલમાંથી બાકાત કરો. બાકાત રાખવાથી બાકીની બધી બાબતો માટે ફિલ્ટર ચાલુ રહે છે અને તમારી એપને સામાન્ય જોડાણ વાપરવા દે છે, જે ઘણી વાર વપરાશકર્તા ખરેખર ઈચ્છે તે પરિણામ હોય છે.

બંને માર્ગ તમારા સહાયતા દસ્તાવેજમાં લખો, કારણ કે વપરાશકર્તાઓ ભાગ્યે જ જાણે છે કે કઈ એપ VPNની માલિક છે. તેમને સેટિંગ્સમાંથી સક્રિય VPN નામ અને તમારા લોગમાંથી prepare, establish અને protectના પરિણામો મોકલવા કહો, અને તમે એક મિનિટમાં કહી શકો કે કયું પગલું નિષ્ફળ ગયું. પછી વાસ્તવિક ટ્રાફિકથી ચકાસો: નામ શોધ, TCP જોડાણ અને ટનલ દ્વારા એક વિનંતી, ફક્ત જોડાયેલ આઇકન નહીં. માન્ય ડિસ્ક્રિપ્ટર અને લીલું સૂચક વધુમાં વધુ માલિકી સાબિત કરે છે, ક્યારેય નહીં કે ટ્રાન્સપોર્ટ રૂટિંગ નિયમોથી બચી ગયું.

જો ચારેય તપાસ પાસ થાય અને ટ્રાફિક તોપણ મરે, તો માલિકી હવે તમારી સમસ્યા નથી. રૂટિંગ અને સર્વર સુલભતા તરફ આગળ વધો, અને VPN એપ ઇન્સ્ટોલ ન હોય તેવા ઉપકરણથી એ જ ઓળખપત્રો ચકાસો.

સંબંધિત લેખો