Wie kann ich auf Android-Assets in anderen Verzeichnissen verweisen?


9

Mein Projekt war ursprünglich nicht für Android gedacht, und seine Assets sind in der folgenden Verzeichnisstruktur organisiert (ich hoffe, dass die ASCII-Grafik einigermaßen gut wiedergegeben wird):

/
+- 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/

Mein game/android/jniVerzeichnis ist fast leer, da es Android.mkauf die relativen Pfade der Quelldateien in engine/srcund verweist game/src. Tatsächlich enthält es sogar die richtigen Makefiles, sodass ich keine Änderungen vornehmen muss, Android.mkwenn ich dem Projekt eine Quelldatei hinzufüge oder entferne.

Beide engineund gamebieten Assets, die mit dem Android-Build ausgeliefert werden müssen. Ich möchte build.xmlauf diese Assets verweisen, ohne sie manuell kopieren zu müssen. Eine Regel, die die Assets beim Erstellen kopiert und dann löscht, wäre akzeptabel, aber natürlich würde ich eine Nullkopie-Lösung bevorzugen. Macht das Sinn? Wie haben andere dieses plattformübergreifende Build-Problem gelöst?

Antworten:


1

Ja, Sie können Dateien absolut in anderen Verzeichnissen verwenden. Platzieren Sie die vorhandenen Assets im assetsVerzeichnis (Geschwister des resVerzeichnisses) und verwenden Sie die, AssetManagerum auf sie zuzugreifen.

Um Bitmaps zu laden, BitmapFactorybenötigen Sie die und müssen zusätzliche Arbeit leisten, wenn Sie auflösungsabhängige Bilder laden möchten .

Seien Sie vorsichtig, wenn Sie Bitmaps mehrmals laden. Da Sie sich mit Rohdatei-Handles befassen, möchten Sie wahrscheinlich einen Ressourcen- / Speichermanager implementieren, mit dem Sie Verweise auf vorhandene Bitmap-Objekte und dergleichen nicht schnell nachschlagen können. Abhängig von Ihrer Architektur müssen Sie dies möglicherweise tun, WeakReferencesdamit nicht die gesamten Spieldaten im Speicher verbleiben. (Mit normalen Android-Ressourcen ResourceManagererledigt das alles für Sie.)


Das Platzieren der Assets in demselben Verzeichnis (sei es resoder assets) ist genau das, was ich nicht tun möchte. Wie ich in der Frage sagte, beides engineund gamestellen Vermögenswerte zur Verfügung, die ich versenden möchte.
Sam Hocevar

Fügen Sie ein vorkompiliertes Skript hinzu, um Assets zu verknüpfen oder in das assetsVerzeichnis zu kopieren , sodass Sie jede spielspezifische Verzeichnisstruktur beibehalten können. Wie für Windows-Symlinks: windows7home.net/how-to-create-symbolic-link-in-windows-7
Anm

Obwohl ein vorkompiliertes Skript wahrscheinlich die bequemste Lösung ist, wäre es schön, wenn Ihre Antwort es erwähnen würde, vielleicht zusammen mit einem kurzen Beispiel, damit es akzeptiert werden könnte. (Beachten Sie, dass ich genau den gleichen Kommentar in der anderen Antwort
mache

1

Die Ant-Build-Eigenschaft "asset.dir" ist für die Angabe des Namens des Assets-Verzeichnisses verantwortlich. Es ist standardmäßig "Assets", aber Sie können es in "../assets" ändern. Dadurch wird der Pfad des gesamten Verzeichnisses geändert. Wenn Sie jedoch über Android-spezifische Ressourcen verfügen, können Sie weiterhin das Verzeichnis "res" verwenden.


1

Wie seltsam, dass die anderen Antworten hier Ihre Frage nicht beantworten ... alle gehen davon aus, dass Sie nur ein Assets-Verzeichnis möchten, oder verweisen auf res / anstelle von Assets /.

Ich brauche auch mehr als ein Assets-Verzeichnis.

Ich habe <aapt>stundenlang mit dem Ameisenmodul gekämpft und schließlich aufgegeben und festgestellt, dass es einen viel einfacheren Weg gibt.

Ich kopierte den <target name="-package-resources"...>Tag aus der Master - Build - Datei , dass antAnwendungen, android_sdk_dir/tools/ant/build.xmlund den Tag in mein Projekt eingefügt build.xml(Sie müssen den Tag einfügen direkt vor dem Master build.xmlenthalten ist, wie die Kommentare am Ende des vorgefertigten Projektes build.xmlerklären) und fügte hinzu : Ein zweiter Abschnitt zum einfachen Ausführen zip, um die Assets zur AP_-Datei hinzuzufügen (die sich ${out.absolute.dir}/${resource.package.file.name}an diesem Punkt in der Ant-Datei befindet):

    <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>

Diese Methode hat den Vorteil, dass Sie die Verzeichnisstruktur Ihrer Assets im Quellbaum und in der apk freier definieren können (da Sie exec zipmehrere Male mit unterschiedlichen Argumenten arbeiten und sogar zipein Skript einschließen können, das zipvon mehreren aktuellen Verzeichnissen in Ihrem ausgeführt wird Quellbaum). Sie haben auch die Möglichkeit, die Komprimierung pro Datei zu steuern (zip verfügt über die Option -0, um die Komprimierung zu unterdrücken) und müssen nicht das eingeschränkte Nocompress-Tag verwenden, das nur für Erweiterungen gilt.

Beachten Sie, dass diese antXML-Datei VOR zipalign im Ant-Build-Prozess verfügbar ist, sodass wir weiterhin ein "zip-kompatibles" Archiv erhalten, das die Ausrichtungsanforderungen von APKs und Android Java erfüllt.

In meinem Fall habe ich eine NDK-basierte App und möchte nur über C-Code auf diese Assets zugreifen (wobei jeder APK-Pfad in Ordnung ist). Wenn Sie die Standardaufrufe für Android Java-Assets verwenden müssen, um auf diese Elemente zuzugreifen, bin ich mir nicht sicher, ob sie sich in einem Pfad innerhalb der Zip-Datei mit dem Namen Assets befinden müssen oder nicht. In diesem Fall können Sie den obigen Trick anpassen, indem execSie ein Skript cdfür den entsprechenden Quellbaumordner erstellen und dann ausführen zip.


0

Ich glaube nicht, dass Sie irgendetwas außerhalb von res / verwenden können, aber wenn Sie zusätzliche Kosten für Ihren Entwicklungszyklus mit einer Kopie vermeiden möchten, können Sie versuchen, sie stattdessen zu verschieben oder vielleicht sogar eine zu verwenden symlink ...


Ich kann die Dateien definitiv nicht verschieben, da einige von ihnen spielübergreifend gemeinsam genutzt werden und im engineVerzeichnis verbleiben müssen , das sich in einem separaten Repository befindet. Symlinks sind möglicherweise akzeptabel, aber ich bin nicht sicher, ob sie unter Windows gut funktionieren, und dann besteht immer noch das Problem, dass sie automatisch von synchronisiert werden build.xml.
Sam Hocevar

2
@Sam - Sie können die Dateien in Ihrem Repository belassen, aber einen Vorkompilierungsschritt in Ihrem Build-Framework erstellen (offensichtlich eine Ant build.xml-Datei), um die Dateien an die für Ihr Android-Projekt erforderlichen Stellen zu kopieren. Dies ist gängige Praxis, wenn Assets in einem Spiel mit mehreren Plattformen gemeinsam genutzt werden. Siehe die Ant- Kopieraufgabe
Anm

Obwohl ein vorkompiliertes Skript wahrscheinlich die bequemste Lösung ist, wäre es schön, wenn Ihre Antwort es erwähnen würde, vielleicht zusammen mit einem kurzen Beispiel, damit es akzeptiert werden könnte. (Beachten Sie, dass ich genau den gleichen Kommentar in der anderen Antwort
mache

0

Wenn Sie ein Maven-Projekt im Gegensatz zu einem Ant-Projekt verwenden, können Sie den res-Ordner über die Konfigurationsoption resourceDirectory des android: apk mojo im android-maven-plugin einfach so neu definieren, wie Sie es möchten .

  <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>

Leider hilft Ihnen diese Antwort möglicherweise nicht sehr, wenn Sie nicht bereit sind, von Ant auf Maven umzusteigen ...


0

Wenn Sie ein Unix-Betriebssystem verwenden, können Sie diese fest verknüpfen und Ihre Versionskontrolle anweisen, das res/Verzeichnis zu ignorieren .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.