4 votes

Comment exécuter mon binaire packagé dans mon application Android ?

J'ai une application Android qui doit exécuter une application binaire personnalisée que j'ai écrite. J'ai déjà construit le binaire en utilisant ndk et je l'ai empaqueté dans l'apk sous res/raw.

J'ai procédé de la manière suivante pour lancer le processus su.

Process process;
process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());

Que dois-je faire ensuite pour exécuter le binaire à partir des ressources ? Une autre question ici suggérait l'utilisation d'AssetManager mais je ne comprends pas comment faire exactement. J'ai vérifié quelques applications opensource (Android-wifi-tether, etc.) qui ont des binaires emballés avec eux et je ne vois pas AssetManager n'importe où dans leur source et je ne comprends pas comment ils le font exactement.

2voto

David Given Points 4935

Il y a un moyen très astucieux de tromper Android pour qu'il le fasse à votre place (ce que j'ai fait, avec succès).

Lors de l'installation de l'application, Android copiera les bibliothèques appropriées à votre architecture dans le répertoire libs/$ARCH/libfoo.so en /data/data/$PACKAGE/libs pour vous. Le plus difficile, c'est qu'il seulement copier des fichiers de la forme lib$SOMETHING.so . Il conservera même les autorisations d'exécution.

Ainsi, si vous renommez votre su à l'exécutable libsu.so Android fera tout le travail pour vous. Vous pouvez ensuite le trouver en utilisant les chemins disponibles à partir d'Activity.

Mais attention ! Android est non conçu pour exécuter des applications autonomes et Zygote ne s'accommode vraiment pas d'être forké. J'ai constaté que Runtime.exec() présente des conditions de concurrence et peut se bloquer. La seule technique fiable que j'ai trouvée consiste à utiliser JNI pour implémenter une petite bibliothèque qui effectue un fork et un exec sans toucher à aucune autre donnée entre le fork et l'exec. J'avais une question ici à ce sujet avec tous les détails, mais je ne l'ai pas retrouvée.

Je n'ai pas accès au code pour l'instant, mais si vous le souhaitez, je peux en trouver pour vous lundi.

2voto

Pour compléter la réponse de David Given, qui est excellente, voici ce que j'utilise à la fin de Android.mk pour renommer automatiquement le binaire. Cela peut être utile à d'autres personnes qui essaient de faire la même chose :

...
LOCAL_MODULE := yourbinarynamehere

include $(BUILD_EXECUTABLE)

all: $(LOCAL_MODULE)
    $(shell (mv libs/$(TARGET_ARCH_ABI)/$< libs/$(TARGET_ARCH_ABI)/lib$<.so))

Attention, le TAB avant $(shell.... espaces ne fonctionnera pas selon le standard GNU Make.

0voto

SaintKnight Points 74

Il y a un répertoire déjà défini comme un dossier nommé 'jniLibs' par jniLibs.srcDirs dans le fichier build.gradle.

src/main/jniLibs/arm64-v8a
src/main/jniLibs/armeabi-v7a
src/main/jniLibs/x86
src/main/jniLibs/x86_64

Vous pouvez changer le chemin en le définissant dans le fichier build.gradle de votre application :

sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X