ಅಪ್ಲಿಕೇಶನ್ 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 ಸೆಟ್ಟಿಂಗ್ ಒಟ್ಟಿಗೆ ನೀಡಿ; ಒಂದನ್ನು ಬದಲಿಸಿ ಉಳಿದವನ್ನು ಮರೆತರೆ ನೀವು ಅದೇ ಕ್ರ್ಯಾಶ್ಗೆ ಮರಳುತ್ತೀರಿ. ಶಾಶ್ವತ ಪರಿಹಾರ ಎಂದರೆ ಪ್ಯಾಚ್ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ಹೊತ್ತುಕೊಳ್ಳುವ ಬದಲು ನಿರ್ವಹಿಸಲ್ಪಡುವ ಕೋರ್ ಬಿಡುಗಡೆಗೆ ಹೋಗುವುದು.

ಸಂಬಂಧಿತ ಲೇಖನಗಳು