Nabibigo ang pantulong na binary ng OpenVPN sa Android 10: tinanggihan ang pahintulot
Tumatanggi ang Android 10 na patakbuhin ang pantulong na isinulat ng app sa sarili nitong storage. Basahin ang logcat, ihatid ang pantulong bilang katutubong library at ayusin ang mga pagbuo ng bundle.
Gumagana ang app sa Android 9 at namamatay sa parehong telepono pagkatapos ng update sa Android 10. Hindi nagalaw ang profile mo, pareho ang mga sertipiko, at dumarating ang pag-crash bago ang anumang trapiko ng pagpapatotoo. Nagpapakita muna ang logcat ng null pointer, at ilang linya sa itaas nito ay naroon ang Cannot run program ...: error=13, Permission denied. Ang mensaheng iyon ay tungkol sa pagpapatakbo ng file, hindi sa pagbasa ng iyong configuration.
Ano ba talaga ang tinatanggihan ng error 13
Ang Android 10, antas ng API 29, ay pumigil sa mga app na patakbuhin ang mga file na isinulat nila sa sarili nilang direktoryo ng data. Ang tuntunin ay tumutukoy sa storage na naisusulat muna at pagkatapos ay naipapatupad, at ito mismo ang nililikha ng isang launcher na kumokopya mula sa assets. Ang mga lumang build ng core ng ics-openvpn ay nagbubukas ng executable openvpn mula sa APK sa unang pagtakbo at sinisimulan ito gamit ang ProcessBuilder. Nagtatagumpay pa rin ang pagbubukas; ang tinatanggihan ay ang pagpapatupad. Ang isang app na naglalayon sa API 29 ay nagmamana ng tuntunin kahit tumatakbo ito sa device na lumabas na may lumang bersyon, kaya nakakasira ang isang update ng build na walang gumalaw.
Walang anuman sa pagtanggi ang partikular sa isang pangalan ng folder. Ang file na ginawa ng app sa ilalim ng direktoryo ng data nito ay itinuturing na hindi maipapatupad anuman ang landas, kaya getFilesDir(), getCacheDir() at isang custom na subdirectory ay lahat nabibigo sa parehong paraan.
Ihiwalay ang crash ng helper mula sa problema sa profile
Basahin ang log sa paligid ng pagsisimula ng proseso sa halip na mag-scroll mula sa itaas. Ang pirma na hahanapin ay ang linyang error=13, at ang stack trace sa itaas nito ay karaniwang pinapangalanan ang paraan ng launcher na tumawag sa ProcessBuilder:
adb logcat -d | grep -n -i -E "cannot run program|permission denied|startOpenVPN"Kung hindi kailanman nagsimula ang helper, wala kang makikitang anumang output ng log ng OpenVPN: walang negosasyon ng cipher, walang itinulak na ruta, walang configuration ng DNS. Kung lumitaw ang mga linyang iyon at dumating ang kabiguan mamaya, tumakbo ang binary at ang problema ay nasa profile, server o layer ng pag-ruta. Ang nag-iisang pagkakaibang iyon ay nakakatipid ng maraming oras na sana ay napunta sa pag-edit ng mga file .ovpn na hindi naman kailanman may kasalanan. Sinasabi rin nito kung alin sa dalawang pag-aayos sa ibaba ang kailangan mo talaga.
Suriin din ang antas ng API sa device na sinusubok mo, hindi ang nasa configuration ng build mo. Walang muling ginagawa ang image ng emulator sa API 28, dahil ang paghihigpit ay kumakagat lamang mula 29 pataas. Suriin din ang target na SDK sa iyong build file: ang pagtataas nito ang humihila ng tuntuning ito papasok.
adb shell getprop ro.build.version.sdkBakit hindi nakakatulong ang pagkopya ng binary sa ibang lugar
Ang halatang paraan, ang pagsulat ng helper sa ibang naisusulat na direktoryo, ay nabibigo sa parehong dahilan na nabigo ang orihinal. Pinapayagan pa rin ng Android na patakbuhin ang mga shared library na naka-install sa native library directory ng app, dahil ang installer ang nag-package sa mga ito at hindi isinusulat sa oras ng pagtakbo. Ang direktoryong iyon ang nag-iisang lugar na dapat tularan ng launcher. Anumang binuksan mo mismo sa oras ng pagtakbo, anuman ang itawag mo, ay nananatili sa tinanggihang kategorya.
Mas malala ang external storage: naka-mount ito gamit ang noexec, at ang helper na inilagay doon ay hindi masisimulan ng anumang app. Ang pagbura ng data ng app ay hindi rin nagbabalik ng lumang ugali, dahil ang susunod na pagtakbo ay muling gumagawa ng parehong hindi maipapatupad na kopya.
Ituro ang launcher sa isang naka-package na library
Palitan ang pangalan ng helper sa pangalan ng shared library at ihatid ito sa ilalim ng jniLibs para sa bawat ABI na sinusuportahan mo, pagkatapos hayaang ibalik ng launcher ang landas ng naka-install na library mula API 28 pataas:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return new File(context.getApplicationInfo().nativeLibraryDir,
"libovpnexec.so").getPath();
}Kailangang mabuksan ang library sa oras ng pag-install para may totoong file ang landas na iyon, kaya itakda ang android:extractNativeLibs="true" sa elementong <application>. Kung may ibang value na dinala ang tagapagsanib ng manifest, idagdag ang tools:replace="android:extractNativeLibs" sa tabi nito. Ang sanggunian ng elementong application ay nagdodokumento kung ano ang kinokontrol ng attribute.
Mag-ingat sa nadobleng lokal na variable kapag manu-manong pinapatch ang launcher. Ang lumang source ay nagdedeklara ng nativeAPI mamaya sa parehong paraan, at ang pangalawang deklarasyon ay error sa pag-compile hindi sa pagtakbo, kaya mabilis na nabibigo ang build at madaling makita ang pagkakamali. Panatilihing tugma ang listahan ng ABI sa bloke ng Gradle sa mga folder na idinadagdag mo.
Gawing tugma ang release artifact sa test build
Maaaring itaas ng debug APK ang tunnel habang nag-crash pa rin ang release bundle, dahil ibang hugis ang packaging ng native library sa bundle at maaari nitong ihatid ang mga ito nang naka-compress mula sa archive. Kung ang mga build na nagmula sa bundle lang ang nabibigo, idagdag ito sa gradle.properties at i-build muli:
android.bundle.enableUncompressedNativeLibs=falsePagkatapos kumpirmahin na ang naka-install na package ay nag-uulat ng ABI na inaasahan mo, at ulitin ang pagsusuri sa 32-bit at 64-bit na device kung pareho ang ipinapadala mo. Pinapangalanan ng package manager ang ABI na pinili nito, kaya ang device na bumalik sa 32 bit ay lumilitaw dito at hindi sa ulat ng pag-crash:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbiAng kulang na library para sa isang ABI ay muling gumagawa ng orihinal na error sa pahintulot sa device na iyon lang, kaya ang isang matagumpay na test phone ay hindi patunay. Ihatid nang sabay ang flag ng manifest, pangalan ng library at setting ng bundle; ang palitan ang isa at kalimutan ang iba ay magbabalik sa iyo sa parehong crash. Ang pangmatagalang solusyon ay lumipat sa isang maintained na core release sa halip na buhatin ang patch magpakailanman.