Comment puis-je faire référence aux ressources Android dans d'autres répertoires?

9

Mon projet n'était initialement pas destiné à Android, et ses ressources sont organisées selon la structure de répertoires suivante (j'espère que l'art ASCII se rend assez bien):

/
+- engine/
 |    +- src/
 |     |      enginefile1.cpp
 |     |      ...
 |     `- textures/
 |            texture1.tex
 |            ...
+- game/
 |    +- src/
 |     |      gamefile1.cpp
 |     |      ...
 |    +- textures/
 |     |      gametexture1.tex
 |     |      ...
 |    +- ios/
 |     |      [various iOS-specific files]
 |     `- android/
 |           | build.xml
 |           | AndroidManifest.xml
 |           +- jni/
 |           |     Android.mk
 |           +- assets/
 |             [other Android-specific files]
 `- othergame/

Mon game/android/jnirépertoire est presque vide car Android.mkpointe vers les chemins relatifs des fichiers source dans engine/srcet game/src. En fait, il inclut même les Makefiles appropriés afin que je n'ai jamais à modifier Android.mklorsque j'ajoute ou supprime un fichier source au projet.

Les deux engineet gamefournissent des actifs qui doivent être livrés avec la version Android. Je voudrais build.xmlfaire référence à ces actifs sans avoir à les copier manuellement. Une règle qui copie les actifs au moment de la construction puis les supprime serait acceptable, mais bien sûr, je préférerais une solution sans copie. Est-ce que ça a du sens? Comment les autres ont-ils résolu ce problème de construction multiplateforme?

sam hocevar
la source

Réponses:

1

Oui, vous pouvez absolument utiliser des fichiers dans d'autres répertoires. Placez les actifs que vous avez dans le assetsrépertoire (frère du resrépertoire) et utilisez le AssetManagerpour y accéder.

Pour charger des bitmaps, vous aurez besoin de la BitmapFactory, et vous devrez faire un travail supplémentaire si vous avez l'intention de charger des images dépendantes de la résolution.

Soyez prudent lors du chargement de bitmaps plusieurs fois. Parce que vous aurez affaire à des descripteurs de fichiers bruts, vous voudrez probablement implémenter un gestionnaire de ressources / mémoire qui vous permet de rechercher rapidement des références à des objets Bitmap existants et similaires. Selon votre architecture, vous devrez peut-être le faire avec WeakReferencespour ne pas vous retrouver avec toutes les données du jeu en mémoire. (Avec les ressources Android normales, le ResourceManagergère tout cela pour vous.)

Anm
la source
Placer les actifs dans le même répertoire (que ce ressoit ou assets) est précisément ce que je ne veux pas faire. Comme je l'ai dit dans la question, à la fois engineet gamefournir les actifs que je veux expédier.
sam hocevar
Ajoutez un script de précompilation pour lier ou copier des ressources dans le assetsrépertoire, vous permettant de conserver toute structure de répertoire spécifique au jeu. Pour ce qui est de Windows symlinks: windows7home.net/how-to-create-symbolic-link-in-windows-7
Anm
Bien qu'un script de pré-compilation soit probablement la solution la plus simple, ce serait bien si votre réponse le mentionnait, peut-être avec un court exemple, afin qu'il puisse être accepté. (notez que je fais exactement le même commentaire dans l'autre réponse)
sam hocevar
1

La propriété de génération Ant "asset.dir" est chargée de fournir le nom du répertoire des actifs. Il s'agit de "actifs" par défaut, mais vous pouvez le remplacer par quelque chose comme "../assets". Cela modifie le chemin du répertoire entier, mais si vous avez des ressources spécifiques à Android, vous pouvez toujours utiliser le répertoire "res".

Krzysiek K.
la source
1

Comme c'est étrange que les autres réponses ici ne répondent pas à votre question ... elles supposent toutes que vous ne voulez qu'un seul répertoire d'actifs, ou référez-vous à res / au lieu d'actifs /.

J'ai également besoin de plus d'un répertoire d'actifs.

J'ai combattu avec le <aapt>module des fourmis pendant des heures et des heures et j'ai finalement abandonné et j'ai réalisé qu'il y avait un moyen beaucoup plus facile.

J'ai copié la <target name="-package-resources"...>balise du fichier de construction principal qui antutilise android_sdk_dir/tools/ant/build.xmlet collé la balise dans mon projet build.xml(vous devez coller la balise juste avant que le maître ne build.xmlsoit inclus, comme l' build.xmlexpliquent les commentaires à la fin du projet prédéfini ), puis ajouté une deuxième section pour simplement exécuter zippour ajouter les actifs au fichier .ap_ (qui est ${out.absolute.dir}/${resource.package.file.name}à ce point dans le fichier ant):

    <target name="-package-resources" depends="-crunch">
        <!-- only package resources if *not* a library project -->
        <do-only-if-not-library elseText="Library project: do not package resources..." >
            <aapt executable="${aapt}"
                    command="package"
                    versioncode="${version.code}"
                    versionname="${version.name}"
                    debug="${build.is.packaging.debug}"
                    manifest="${out.manifest.abs.file}"
                    assets="${asset.absolute.dir}"
                    androidjar="${project.target.android.jar}"
                    apkfolder="${out.absolute.dir}"
                    nocrunch="${build.packaging.nocrunch}"
                    resourcefilename="${resource.package.file.name}"
                    resourcefilter="${aapt.resource.filter}"
                    libraryResFolderPathRefid="project.library.res.folder.path"
                    libraryPackagesRefid="project.library.packages"
                    libraryRFileRefid="project.library.bin.r.file.path"
                    previousBuildType="${build.last.target}"
                    buildType="${build.target}"
                    ignoreAssets="${aapt.ignore.assets}">
                <res path="${out.res.absolute.dir}" />
                <res path="${resource.absolute.dir}" />
                <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
                <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
            </aapt>
<!--
NEW XML STARTS HERE
-->
            <exec executable="zip" failonerror="true">
                <arg value="-r" />
                <arg value="${out.absolute.dir}/${resource.package.file.name}" />
                <arg value="my_assets_directory_1" />
                <arg value="my_assets_directory_2" />
                <arg value="my_assets_directory_3" />
            </exec>
<!--
NEW XML ENDS HERE
-->
        </do-only-if-not-library>
    </target>

Cette méthode a l'avantage que vous êtes plus libre de définir la structure de répertoires de vos actifs dans l'arborescence source et dans l'apk (car vous pouvez exec zipplusieurs fois avec des arguments différents, et même encapsuler zipdans un script qui s'exécute à zippartir de plusieurs répertoires actuels dans votre arbre source). Vous avez également un contrôle de compression par fichier (zip a une option -0 pour supprimer la compression) et vous n'avez pas besoin d'utiliser la balise nocompress limitée par extension uniquement.

Notez que ce antxml vient AVANT zipalign dans le processus de construction de fourmi, nous obtenons donc toujours une archive "compatible zip" qui répond aux besoins d'alignement des APK et Android Java.

Dans mon cas, j'ai une application basée sur NDK et je veux accéder à ces actifs à partir du code C uniquement (où tout chemin apk est OK). Si vous devez utiliser les appels d'actifs Java Android standard pour accéder à ces éléments, je ne sais pas s'ils doivent se trouver ou non dans un chemin à l'intérieur du fichier zip nommé actifs. Si tel est le cas, vous pouvez adapter l'astuce ci-dessus en execinsérant un script cddans le dossier d'arborescence source approprié, puis en l'exécutant zip.

Louis Semprini
la source
0

Du haut de ma tête, je ne pense pas que vous puissiez utiliser quoi que ce soit en dehors de res /, mais si vous cherchez à éviter des coûts supplémentaires pour votre cycle de développement avec une copie, vous pouvez essayer de les déplacer à la place ou peut-être même d'utiliser un lien symbolique ...

notlesh
la source
Je ne peux certainement pas déplacer les fichiers car certains d'entre eux sont partagés entre les jeux et doivent rester dans le enginerépertoire, qui se trouve dans un référentiel séparé. Les liens symboliques peuvent être acceptables, mais je ne suis pas sûr qu'ils fonctionneraient bien sous Windows et il y a toujours le problème de les synchroniser automatiquement avec build.xml.
sam hocevar
2
@Sam - Vous pouvez laisser les fichiers en place dans votre référentiel, mais créez une étape de pré-compilation dans votre framework de build (un fichier Ant build.xml apparent) pour copier les fichiers aux emplacements nécessaires à votre projet Android. C'est une pratique courante lorsque vous partagez des actifs dans un jeu multi-plateforme. Voir la tâche de copie Ant: ant.apache.org/manual/Tasks/copy.html
Anm
Bien qu'un script de pré-compilation soit probablement la solution la plus simple, ce serait bien si votre réponse le mentionnait, peut-être avec un court exemple, afin qu'il puisse être accepté. (notez que je fais exactement le même commentaire dans l'autre réponse)
sam hocevar
0

Si vous utilisiez un projet Maven par opposition à un projet Ant, vous pourriez facilement redéfinir le dossier res pour qu'il soit ce que vous vouliez via l' option de configuration resourceDirectory de l' androïde: apk mojo dans le plugin android-maven .

  <plugin>
    <groupId>com.jayway.maven.plugins.android.generation2</groupId>
    <artifactId>android-maven-plugin</artifactId>
    <version>${android.maven.version}</version>
    <configuration>
      <resourceDirectory>${project.basedir}/res</resourceDirectory>
    </configuration>
    <extensions>true</extensions>
  </plugin>

Malheureusement, à moins que vous ne souhaitiez migrer de Ant à Maven, cette réponse pourrait ne pas vous aider beaucoup ...

hatboyzero
la source
0

Si vous utilisez un système d'exploitation Unix, vous pouvez les lier en dur et dire à votre contrôle de version d'ignorer le res/répertoire.

o0 '.
la source