OpenVPN உதவி பைனரி Android 10 இல் தோல்வியடைகிறது: அனுமதி மறுக்கப்பட்டது
Android 10, பயன்பாடு தன் சொந்த சேமிப்பகத்தில் எழுதிய உதவியை இயக்க மறுக்கிறது. logcat படிக்கவும், உதவியை சொந்த நூலகமாக வழங்கவும், bundle கட்டுமானங்களைச் சரிசெய்யவும்.
பயன்பாடு Android 9 இல் வேலை செய்தது, Android 10 புதுப்பிப்புக்குப் பிறகு அதே தொலைபேசியில் இறக்கிறது. உங்கள் சுயவிவரம் தொடப்படவில்லை, சான்றிதழ்கள் அதே தான், மேலும் எந்த அங்கீகாரப் போக்குவரத்துக்கும் முன்பே செயலிழப்பு வருகிறது. logcat முதலில் பூஜ்ய சுட்டியைக் காட்டுகிறது, அதற்கு சில வரிகளுக்கு மேலே உள்ளது Cannot run program ...: error=13, Permission denied. அந்தச் செய்தி ஒரு கோப்பை இயக்குவது பற்றியது, உங்கள் கட்டமைப்பைப் படிப்பது பற்றியது அல்ல.
பிழை 13 உண்மையில் எதை மறுக்கிறது
Android 10, API நிலை 29, பயன்பாடுகள் தம் தரவு கோப்பகத்தில் எழுதிய கோப்புகளை இயக்குவதை நிறுத்தியது. இந்த விதி முதலில் எழுதக்கூடிய, பின்னர் இயக்கக்கூடிய சேமிப்பகத்தை இலக்காகக் கொள்கிறது, அதைத்தான் assets இலிருந்து நகலெடுக்கும் துவக்கி உருவாக்குகிறது. 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> உறுப்பில் அமைக்கவும். manifest இணைப்பான் வேறு மதிப்பைக் கொண்டு வந்தால் அதற்கு அருகில் tools:replace="android:extractNativeLibs" சேர்க்கவும். application உறுப்பு குறிப்பு இந்தப் பண்பு எதைக் கட்டுப்படுத்துகிறது என்பதை ஆவணப்படுத்துகிறது.
துவக்கியை கைமுறையாக இணைக்கும்போது நகலெடுக்கப்பட்ட உள்ளூர் மாறியைக் கவனியுங்கள். பழைய மூலங்கள் அதே முறையில் பின்னர் nativeAPI என அறிவிக்கின்றன, இரண்டாவது அறிவிப்பு இயக்க நேரப் பிழை அல்ல, தொகுப்புப் பிழை, எனவே கட்டுமானம் விரைவாகத் தோல்வியடைகிறது, பிழையை எளிதில் காணலாம். Gradle தொகுதியில் உள்ள ABI பட்டியலை நீங்கள் சேர்க்கும் கோப்புறைகளுடன் ஒத்திசைவில் வைத்திருங்கள்.
வெளியீட்டு மூலப்பொருளை சோதனைக் கட்டுமானத்துடன் பொருத்தவும்
பிழைத்திருத்த APK சுரங்கப்பாதையை உயர்த்த முடியும், அதே நேரம் வெளியீட்டு bundle இன்னும் செயலிழக்கிறது, ஏனெனில் bundle சொந்த நூலகங்களை வேறு வடிவில் தொகுத்து அவற்றைக் காப்பகத்திலிருந்து சுருக்கியதாக வழங்கலாம். bundle இலிருந்து வந்த கட்டுமானங்கள் மட்டும் தோல்வியடைந்தால், இதை gradle.properties இல் சேர்க்கவும், மீண்டும் கட்டமைக்கவும்:
android.bundle.enableUncompressedNativeLibs=falseபின்னர் நிறுவப்பட்ட தொகுப்பு நீங்கள் எதிர்பார்க்கும் ABI ஐத் தெரிவிக்கிறதா என்பதை உறுதிப்படுத்தி, இரண்டையும் வழங்கினால் 32-பிட் மற்றும் 64-பிட் சாதனத்தில் சரிபார்ப்பை மீண்டும் செய்யவும். தொகுப்பு மேலாளர் தான் தேர்ந்தெடுத்த ABI ஐப் பெயரிடுகிறது, எனவே 32 பிட்டுக்குத் திரும்பிய சாதனம் செயலிழப்பு அறிக்கையில் அல்ல, இங்கே தோன்றும்:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbiஒரு ABI க்கு நூலகம் இல்லாதது அசல் அனுமதிப் பிழையை அந்தச் சாதனத்தில் மட்டுமே மீண்டும் உருவாக்குகிறது, எனவே ஒரு வெற்றிகரமான சோதனைத் தொலைபேசி சான்று அல்ல. manifest கொடி, நூலகப் பெயர், bundle அமைப்பு ஆகியவற்றை ஒன்றாக வழங்கவும்; ஒன்றை மாற்றி மற்றவற்றை மறந்தால் அதே செயலிழப்புக்குத் திரும்புவீர்கள். நீடித்த தீர்வு, இணைப்பை என்றென்றும் சுமப்பதற்குப் பதிலாக பராமரிக்கப்படும் மைய வெளியீட்டுக்கு மாறுவதாகும்.