OpenVPN ਸਹਾਇਕ ਬਾਈਨਰੀ Android 10 'ਤੇ ਫੇਲ੍ਹ: ਇਜਾਜ਼ਤ ਰੱਦ
Android 10 ਉਸ ਸਹਾਇਕ ਫਾਈਲ ਨੂੰ ਚਲਾਉਣ ਤੋਂ ਇਨਕਾਰ ਕਰਦਾ ਹੈ ਜੋ ਐਪ ਨੇ ਆਪਣੇ ਹੀ ਸਟੋਰੇਜ ਵਿੱਚ ਲਿਖੀ ਸੀ। logcat ਪੜ੍ਹੋ, ਸਹਾਇਕ ਨੂੰ ਨੇਟਿਵ ਲਾਇਬ੍ਰੇਰੀ ਵਜੋਂ ਭੇਜੋ ਅਤੇ ਬੰਡਲ ਬਿਲਡ ਠੀਕ ਕਰੋ।
ਐਪ 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 ਟਨਲ ਚੁੱਕ ਸਕਦਾ ਹੈ ਜਦਕਿ ਰਿਲੀਜ਼ ਬੰਡਲ ਅਜੇ ਵੀ ਕ੍ਰੈਸ਼ ਹੁੰਦਾ ਹੈ, ਕਿਉਂਕਿ ਬੰਡਲ ਨੇਟਿਵ ਲਾਇਬ੍ਰੇਰੀਆਂ ਨੂੰ ਵੱਖਰੀ ਸ਼ਕਲ ਵਿੱਚ ਪੈਕ ਕਰਦਾ ਹੈ ਅਤੇ ਉਹਨਾਂ ਨੂੰ ਆਰਕਾਈਵ ਵਿੱਚੋਂ ਸੰਕੁਚਿਤ ਰੂਪ ਵਿੱਚ ਦੇ ਸਕਦਾ ਹੈ। ਜੇ ਸਿਰਫ਼ ਬੰਡਲ ਤੋਂ ਬਣੇ ਬਿਲਡ ਫੇਲ੍ਹ ਹੁੰਦੇ ਹਨ, ਤਾਂ ਇਹ gradle.properties ਵਿੱਚ ਜੋੜੋ ਅਤੇ ਦੁਬਾਰਾ ਬਿਲਡ ਕਰੋ:
android.bundle.enableUncompressedNativeLibs=falseਫਿਰ ਪੁਸ਼ਟੀ ਕਰੋ ਕਿ ਸਥਾਪਿਤ ਪੈਕੇਜ ਤੁਹਾਡੀ ਉਮੀਦ ਵਾਲੀ ABI ਦੱਸਦਾ ਹੈ, ਅਤੇ ਜੇ ਦੋਵੇਂ ਭੇਜਦੇ ਹੋ ਤਾਂ 32-ਬਿਟ ਅਤੇ 64-ਬਿਟ ਡਿਵਾਈਸ 'ਤੇ ਜਾਂਚ ਦੁਹਰਾਓ। ਪੈਕੇਜ ਮੈਨੇਜਰ ਆਪਣੀ ਚੁਣੀ ABI ਦਾ ਨਾਮ ਦੱਸਦਾ ਹੈ, ਇਸ ਲਈ 32 ਬਿਟ 'ਤੇ ਵਾਪਸ ਆਇਆ ਡਿਵਾਈਸ ਕ੍ਰੈਸ਼ ਰਿਪੋਰਟ ਵਿੱਚ ਨਹੀਂ, ਇੱਥੇ ਦਿਖਦਾ ਹੈ:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbiਇੱਕ ABI ਲਈ ਗੁੰਮ ਲਾਇਬ੍ਰੇਰੀ ਅਸਲੀ ਇਜਾਜ਼ਤ ਗਲਤੀ ਸਿਰਫ਼ ਉਸੇ ਡਿਵਾਈਸ 'ਤੇ ਦੁਬਾਰਾ ਬਣਾਉਂਦੀ ਹੈ, ਇਸ ਲਈ ਇੱਕ ਸਫਲ ਟੈਸਟ ਫ਼ੋਨ ਸਬੂਤ ਨਹੀਂ ਹੈ। manifest ਫਲੈਗ, ਲਾਇਬ੍ਰੇਰੀ ਦਾ ਨਾਮ ਅਤੇ ਬੰਡਲ ਸੈਟਿੰਗ ਇਕੱਠੇ ਭੇਜੋ; ਇੱਕ ਬਦਲ ਕੇ ਬਾਕੀ ਭੁੱਲਣ ਨਾਲ ਤੁਸੀਂ ਉਸੇ ਕ੍ਰੈਸ਼ 'ਤੇ ਵਾਪਸ ਆ ਜਾਂਦੇ ਹੋ। ਟਿਕਾਊ ਹੱਲ ਇਹ ਹੈ ਕਿ ਪੈਚ ਨੂੰ ਹਮੇਸ਼ਾ ਢੋਣ ਦੀ ਬਜਾਏ ਸੰਭਾਲੀ ਜਾਂਦੀ ਕੋਰ ਰਿਲੀਜ਼ 'ਤੇ ਜਾਓ।