context.getdir("engine_bin",
context.mode_private)
< /blockquote>
Код: Выделить всё
/data/user/0/com.example.myapp/app_engine_bin/< /code> < /p>
и < /p>
file(context.filesdir, "Engine_bin") < /p>
< /blockquote>
/data/user/0/com.example.myapp/files/engine_bin/После копирования я использую функцию jni для
call chmod на двоичном.
Код: Выделить всё
#include
#include
#include
#include
#include
#define LOG_TAG_NATIVE "NativeUtils"
#define LOGI_NATIVE(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG_NATIVE, __VA_ARGS__)
#define LOGE_NATIVE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG_NATIVE, __VA_ARGS__)
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_myapp_EngineManager_nativeChmod(
JNIEnv *env,
jobject /* this */,
jstring filePathJStr) {
const char *filePath = env->GetStringUTFChars(filePathJStr, nullptr);
if (filePath == nullptr) {
LOGE_NATIVE("nativeChmod: GetStringUTFChars failed for filePath.");
return JNI_FALSE;
}
// Using 0744 equivalent (rwxr--r--)
mode_t target_mode = S_IRWXU | S_IRGRP | S_IROTH;
LOGI_NATIVE("nativeChmod: Attempting to chmod path '%s' to mode 0%o (octal)", filePath, target_mode);
int result = chmod(filePath, target_mode);
if (result != 0) {
LOGE_NATIVE("nativeChmod: chmod failed for path '%s'. errno: %d, error: %s", filePath, errno, strerror(errno));
} else {
LOGI_NATIVE("nativeChmod: chmod successful for path '%s'", filePath);
}
env->ReleaseStringUTFChars(filePathJStr, filePath);
return (result == 0) ? JNI_TRUE : JNI_FALSE;
Код: Выделить всё
class EngineManager(private val context: Context) {
private external fun nativeChmod(filePath: String): Boolean
private lateinit var engineFile: File
private val engineExecutableName = "my_engine_arm64-v8a" // Generalized
init { System.loadLibrary("native_engine_utils") }
suspend fun initialize(): Boolean = withContext(Dispatchers.IO) {
// ... (code to determine engineDir, e.g., File(context.filesDir, "engine_bin"))
// val engineDir = File(context.filesDir, "engine_bin")
val engineDir = context.getDir("engine_bin", Context.MODE_PRIVATE) // Also tried this
if (!engineDir.exists()) engineDir.mkdirs()
engineFile = File(engineDir, engineExecutableName)
// Copy from assets to engineFile.path
context.assets.open(engineExecutableName).use { input ->
FileOutputStream(engineFile).use { output ->
input.copyTo(output)
}
}
Log.i("EngineManager", "Engine copied to ${engineFile.absolutePath}")
if (nativeChmod(engineFile.absolutePath)) {
Log.i("EngineManager", "nativeChmod successful for ${engineFile.absolutePath}")
} else {
Log.e("EngineManager", "nativeChmod failed for ${engineFile.absolutePath}")
return@withContext false
}
if (engineFile.canExecute()) {
Log.i("EngineManager", "File.canExecute() is TRUE for ${engineFile.absolutePath}")
} else {
Log.e("EngineManager", "File.canExecute() is FALSE for ${engineFile.absolutePath}")
// This case is NOT being hit in my logs
}
// ...
return@withContext true
}
private suspend fun startEngineProcess(): Boolean = withContext(Dispatchers.IO) {
// ... (Pre-checks)
Log.i("EngineManager", "Attempting to start: ${engineFile.absolutePath}")
try {
val processBuilder = ProcessBuilder(engineFile.absolutePath)
val engineProcess = processBuilder.start() //
Проблема и журналы: < /strong> < /p>
Функция инициализации (), кажется, работает: < /p>
[list]
[*] Корпинга копируется. true.
[*] EngineFile.canexecute () возвращает true.
[/list]
Однако, когда startengineprocess () [info] EngineManager: двигатель успешно скопирован. />'/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a'.
mode 0744 (rwxr-r--) будет применяться изначально.
(из c ++) />'/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a'
to mode 0744 (окт)
(от c ++) />'/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a'
[info] EngineManager: успешно установить исполнительные разрешения с использованием
native chmod.
[info] enginemanager: verification: Enginefute.cree.C. /> Возврат
true после nativechmod. < /p>
[info] EngineManager: инициализация двигателя успешна (используя Native
чмод).
< /blockquote>
позже, когда пытается получить намек (который вызывает startEnginPocess) < /strong> < /strong>, когда вы пытаетесь получить намек (который вызывает eManGineProcess) />
[info] EngineManager: Pre-Start Проверка: EngineFile.canexeCute () IS true
для
/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a.br/> />/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a
[error] EngineManager: критическое ioException во время процесса двигателя
start
(путь: /DATA/USER/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a):
не может запустить программу "/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-V8a"! /> Java.io.ioexception: невозможно запустить программу
"/data/user/0/com.example.myapp/app_engine_bin/my_engine_arm64-v8a"! />ком. /> < /blockquote>
Это «разрешение отказано (error = 13)», несмотря на то, что CHMOD и CanExeCute (), преуспевание, часто указывает на флаги Mount Mount Selinux или Noexec. (rwxr-r--) через s_irwxu | S_IRGRP | S_IROTH в C ++. Также попробовал 0700 (rwx ------).
[*] Также попробована использовать 0O0700.
/> context.getDir("engine_bin",
context.mode_private)
< /blockquote>
`/data/user/0/com.example.myapp/app_engine_bin/`
and
< /code>
file(context.filesdir, "Engine_bin") < /p>
< /blockquote>
`/data/user/0/com.example.myapp/files/engine_bin/`
< /code>
Оба местоположения приводят к одной и той же ошибке = 13. < /p>
target sdk: < /strong> 34, min sdk: 30. Протестировано на Android 11 и 14. < /p>
< /li>
< /li>
Проверенный Abifilters 'arm64-v8a' in build.gradle. < /p>
< /li>
Вдохновленная Droidfish, которая также использует нативный CHMOD для его двигателя. Их CHMOD использует 0744, и они обычно помещают двигатель в каталог внутренних файлов приложения. /> Учитывая, что традиционные разрешения файлов, по -видимому, устанавливаются правильно (как предполагают chmod и canexecute (), что еще может привести к тому, что это «разрешение отказано (ошибку = 13)», особенно на стадии процесса. Start ()? Как я могу сделать скопированный бинарный исполняемый файл с помощью собственного процесса приложения на современных версиях Android? Есть ли конкретные контексты Selinux или манифестные объявления, которые мне не хватает?
Подробнее здесь: https://stackoverflow.com/questions/796 ... despite-ch
Мобильная версия