OpenVPN સહાયક બાઈનરી Android 10 પર નિષ્ફળ: પરવાનગી નકારી
Android 10 એ એપે તેના પોતાના સંગ્રહમાં લખેલી સહાયક ફાઇલ ચલાવવાનો ઇનકાર કરે છે. logcat વાંચો, સહાયકને નેટિવ લાઇબ્રેરી તરીકે મોકલો અને બંડલ બિલ્ડ ઠીક કરો.
એપ Android 9 પર કામ કરતી હતી અને Android 10 અપડેટ પછી એ જ ફોનમાં મરી જાય છે. તમારી પ્રોફાઇલ અકબંધ છે, પ્રમાણપત્રો એ જ છે, અને ક્રેશ કોઈપણ પ્રમાણીકરણ ટ્રાફિક પહેલાં આવે છે. logcat પહેલાં નલ પોઇન્ટર બતાવે છે, અને તેની થોડી લીટીઓ ઉપર છે Cannot run program ...: error=13, Permission denied. એ સંદેશ ફાઇલ ચલાવવા વિશે છે, તમારી ગોઠવણી વાંચવા વિશે નહીં.
ભૂલ 13 ખરેખર શું નકારે છે
Android 10, API સ્તર 29, એ એપ્સને તેમના પોતાના ડેટા ડિરેક્ટરીમાં લખેલી ફાઇલો ચલાવવાથી રોક્યું. નિયમ એ સંગ્રહને લક્ષ્ય કરે છે જે પહેલાં લખી શકાય અને પછી ચલાવી શકાય, અને તે બરાબર એ જ છે જે એસેટ્સમાંથી કોપી કરતું લોન્ચર બનાવે છે. ics-openvpn કોરના જૂના બિલ્ડ પ્રથમ વખત ચલાવતી વખતે APKમાંથી એક openvpn એક્ઝિક્યુટેબલ કાઢે છે અને તેને ProcessBuilder વડે શરૂ કરે છે. કાઢવાનું હજી સફળ થાય છે; નકારાય છે એ એક્ઝિક્યુશન. API 29 ને લક્ષ્ય કરતી એપ જૂની આવૃત્તિ સાથે આવેલા ઉપકરણ પર ચાલે ત્યારે પણ નિયમ વારસામાં મેળવે છે, તેથી એક અપડેટ એવું બિલ્ડ તોડી શકે છે જેને કોઈએ સ્પર્શ પણ કર્યો ન હોય.
નકારમાં કોઈ એક ફોલ્ડર નામ માટે કંઈ ખાસ નથી. એપે તેની ડેટા ડિરેક્ટરી હેઠળ બનાવેલી ફાઇલ પાથ ગમે તે હોય, બિન-ચલાવી શકાય તેમ ગણાય છે, તેથી getFilesDir(), getCacheDir() અને કસ્ટમ સબડિરેક્ટરી બધા એ જ રીતે નિષ્ફળ જાય છે.
સહાયક ક્રેશને પ્રોફાઇલ સમસ્યાથી અલગ કરો
ઉપરથી સ્ક્રોલ કરવાને બદલે પ્રક્રિયા શરૂ થવાની આસપાસનું લોગ વાંચો. તમારે શોધવાની સહી એ લીટી છે error=13, અને તેની ઉપરનો સ્ટેક ટ્રેસ સામાન્ય રીતે એ લોન્ચર પદ્ધતિનું નામ આપે છે જેણે ProcessBuilder ને કૉલ કર્યું:
adb logcat -d | grep -n -i -E "cannot run program|permission denied|startOpenVPN"જો સહાયક કદી શરૂ જ ન થયું હોય, તો તમને OpenVPN લોગ આઉટપુટ જરાય દેખાશે નહીં: ન સાઇફર વાટાઘાટ, ન ધકેલાયેલા રૂટ, ન DNS ગોઠવણી. જો એ લીટીઓ દેખાય અને નિષ્ફળતા પછી આવે, તો બાઈનરી ચાલી હતી અને સમસ્યા પ્રોફાઇલ, સર્વર કે રૂટિંગ સ્તરમાં છે. એ એક જ ભેદ .ovpn ફાઇલોને સંપાદિત કરવામાં વીતતો ઘણો સમય બચાવે છે જે કદી દોષિત ન હતી. તે એ પણ કહે છે કે નીચેના બે સુધારામાંથી તમને ખરેખર કયો જોઈએ.
તમે જે ઉપકરણ પરીક્ષણ કરી રહ્યા છો તેના પર API સ્તર પણ તપાસો, તમારા બિલ્ડ કન્ફિગમાંનું નહીં. API 28 પર એમ્યુલેટર ઇમેજ કંઈ પણ પુનઃઉત્પાદિત કરતી નથી, કારણ કે પ્રતિબંધ ફક્ત 29 થી ઉપર જ ડંખે છે. તે જ સમયે તમારી બિલ્ડ ફાઇલમાં લક્ષ્ય SDK તપાસો: તેને વધારવું એ જ આ નિયમને અંદર ખેંચે છે.
adb shell getprop ro.build.version.sdkબાઈનરીને બીજે કોપી કરવાથી કેમ મદદ નથી મળતી
સ્પષ્ટ ઉપાય, સહાયકને બીજી લખી શકાય તેવી ડિરેક્ટરીમાં લખવો, મૂળ જે કારણે નિષ્ફળ ગયો તે જ કારણે નિષ્ફળ જાય છે. Android હજી પણ એપની નેટિવ લાઇબ્રેરી ડિરેક્ટરીમાં સ્થાપિત શેર્ડ લાઇબ્રેરીઓ ચલાવવાની પરવાનગી આપે છે, કારણ કે તેમને ઇન્સ્ટોલર પેક કરે છે, રનટાઇમમાં લખાતી નથી. એ ડિરેક્ટરી એ જ એક જગ્યા છે જ્યાં લોન્ચરે નિર્દેશ કરવો જોઈએ. તમે રનટાઇમમાં જાતે કાઢો છો તે દરેક વસ્તુ, ગમે તે નામ આપો, નકારેલી શ્રેણીમાં જ રહે છે.
બાહ્ય સંગ્રહ વધુ ખરાબ છે: તે noexec સાથે માઉન્ટ થયેલ છે, અને ત્યાં મૂકેલી સહાયક ફાઇલ કોઈ પણ એપ શરૂ કરી શકતી નથી. એપ ડેટા સાફ કરવાથી પણ જૂનું વર્તન પાછું આવતું નથી, કારણ કે આગલી વખતે ચલાવતાં એ જ બિન-ચલાવી શકાય નકલ ફરી બને છે.
લોન્ચરને પેકેજ કરેલી લાઇબ્રેરી તરફ નિર્દેશ કરો
સહાયકનું નામ શેર્ડ-લાઇબ્રેરીના નામમાં બદલો અને તમે સમર્થન આપો છો તે દરેક ABI માટે તેને jniLibs હેઠળ મોકલો, પછી લોન્ચર API 28 થી આગળ સ્થાપિત લાઇબ્રેરીનો પાથ પરત આપે:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return new File(context.getApplicationInfo().nativeLibraryDir,
"libovpnexec.so").getPath();
}એ પાથમાં સાચી ફાઇલ હોવા માટે લાઇબ્રેરી ઇન્સ્ટોલ સમયે કાઢવી પડે, તેથી android:extractNativeLibs="true" ને <application> એલિમેન્ટ પર સેટ કરો. જો મેનિફેસ્ટ મર્જર બીજું મૂલ્ય લાવે, તો તેની બાજુમાં tools:replace="android:extractNativeLibs" ઉમેરો. એપ્લિકેશન એલિમેન્ટ સંદર્ભ દસ્તાવેજ કરે છે કે આ એટ્રિબ્યુટ શું નિયંત્રિત કરે છે.
લોન્ચરને હાથે પેચ કરતી વખતે ડુપ્લિકેટ લોકલ વેરિયેબલથી સાવધ રહો. જૂના સ્રોત એ જ પદ્ધતિમાં પછી nativeAPI જાહેર કરે છે, અને બીજી જાહેરાત રનટાઇમ નહીં પણ કમ્પાઇલ ભૂલ છે, તેથી બિલ્ડ ઝડપથી નિષ્ફળ જાય છે અને ભૂલ સહેલાઈથી દેખાય છે. Gradle બ્લોકમાંની ABI સૂચિને તમે ઉમેરો તે ફોલ્ડરો સાથે મેળમાં રાખો.
રિલીઝ આર્ટિફેક્ટને ટેસ્ટ બિલ્ડ સાથે મેળવો
ડિબગ APK ટનલ ઉપાડી શકે છે જ્યારે રિલીઝ બંડલ હજી ક્રેશ થાય છે, કારણ કે બંડલ નેટિવ લાઇબ્રેરીઓને અલગ આકારમાં પેક કરે છે અને તેમને આર્કાઇવમાંથી સંકુચિત રીતે પરોવી શકે છે. જો ફક્ત બંડલમાંથી બનેલા બિલ્ડ નિષ્ફળ જાય, તો આ gradle.properties માં ઉમેરો અને ફરી બિલ્ડ કરો:
android.bundle.enableUncompressedNativeLibs=falseપછી ખાતરી કરો કે સ્થાપિત પેકેજ તમે અપેક્ષા રાખો છો તે ABI જણાવે છે, અને જો બંને મોકલો તો 32-બિટ અને 64-બિટ ઉપકરણ પર ચકાસણીનું પુનરાવર્તન કરો. પેકેજ મેનેજર પોતે પસંદ કરેલ ABIનું નામ આપે છે, તેથી 32 બિટ પર પાછું ગયેલું ઉપકરણ ક્રેશ રિપોર્ટમાં નહીં, અહીં દેખાય છે:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbiએક ABI માટે ખૂટતી લાઇબ્રેરી મૂળ પરવાનગી ભૂલ ફક્ત તે જ ઉપકરણ પર પુનઃઉત્પાદિત કરે છે, તેથી એક સફળ પરીક્ષણ ફોન પુરાવો નથી. મેનિફેસ્ટ ફ્લેગ, લાઇબ્રેરીનું નામ અને બંડલ સેટિંગ સાથે મોકલો; એક બદલીને બાકીના ભૂલી જવાથી તમે એ જ ક્રેશ પર પાછા આવો છો. કાયમી ઉપાય એ છે કે પેચ કાયમ ઉપાડવાને બદલે જાળવાયેલી કોર આવૃત્તિ પર જવું.