I have a simple android project.
This commands compile resources and build apk without dex:
aapt2 compile project/res/values/strings.xml project/res/layout/activity_main.xml -o project/compiled_res
aapt2 link -o project/apk/unsigned_app.apk -I sdk/platforms/android-28/android.jar --manifest project/src/AndroidManifest.xml -R project/compiled_res/*.flat --java project/src --auto-add-overlay
Quote from documentation:
However, the generated APK does not contain DEX bytecode and is
unsigned
...
you can use other command line tools, such as d8 to
compile Java bytecode into DEX bytecode and apksigner to sign your
APK.
Ok. I can:
d8 project/compiled_classes/com/illuzor/buildtest/*.class --output project/dex
But how to pack this dex to apk? aapt2 can`t recognize classes.dex:
I can just add classes.dex to my apk by zipping:
zip -uj project/apk/unsigned_app.apk project/dex/classes.dex
And it works after aligning and signing. But must be another way, more proper.
I'm looking for a proper way too. But I have no luck even it is 2019 now, and I searched everywhere, for days.
I guess aapt add will get the job done, but your solution with zip is not bad.
Hope aapt won't be deprecated soon, or aapt2 should get enhanced before that happens.
Related
We have a great build system, so we're not looking to use gradle. Right now, we use appt to build an APK and it works great and the APK runs well. I see that aapt2 is the future, though, and so we'd like to move to it before we're forced to.
What we currently do:
We have a simple icon in res/mipmap/our_icon.png
We have our ./AndroidManifest.xml file
We have our libMyApp.so stored in apk/lib/armeabi-v7a/libMyApp.so
We build using the following command: aapt package -f -M AndroidManifest.xml -S ./res -I /opt/android-sdk/platforms/android-28/android.jar -F my app-unsigned.apk apk/
We then zipalign and sign using apksigner and the app loads just fine. As you can see, all very simple and gives us just what we need.
I've tried the following with aapt2, but of course it is incorrect:
aapt2 compile ./res/mipmap/our_icon.png -o ./compiled
aapt2 link -v -I /opt/android-sdk/platforms/android-28/android.jar -I compiled/mipmap_our_icon.png.flat --manifest AndroidManifest.xml -o MyApp-unsigned.apk
note: including compiled/minmap_our_icon.png.flat.
error: failed to open APK: Invalid file.
You're trying to provide the resources the way you'd provide an APK (e.g. android.jar):
-I compiled/mipmap_our_icon.png.flat
To pass compiled resources use the -R flag (per each resource or use the wildcard * if you want to pass the whole directory, e.g. compiled/*).
You can find more info on differences between aapt and aapt2 in my old answer here.
I'm running AAPT2 from the command line:
%PATH_AAPT2%\aapt2.exe compile -v --dir res -o build
Many resource files are compiled. But after a time aapt2 is aborting with the message
Check failed: node_stack.size() == 1u
The build output is:
>C:\Android\aapt2\aapt2.exe compile -v --dir res -o build
res\color\button_back.xml: note: compiling XML.
...
res\drawable\rectangle.xml: note: compiling XML.
res\drawable\row.xml: note: compiling XML.
res\drawable\splash_screen.xml: note: compiling XML.
res\menu\menu_main.xml: note: compiling XML.
aapt2.exe F 08-23 07:52:20 16152 15008 ResourceParser.cpp:346] Check failed: node_stack.size() == 1u
What is the reason?
The used AAPT2 version is 4.1.0 rc01, but the error occurs with other versions too.
The error seems not to be related to any resource. I removed the recently compiled resources like menu_main.xml, but the error occurs furthermore.
I Replaced one attribute of all of my .xml files by a mistake. so I undo all of them . now Android failed to compile the project because of internal files that does not belong to my project . look at this Error for example:
Android resource compilation failed
Output: C:\Users\andrew\.gradle\caches\transforms-1\files-1.1\support-
compat-28.0.0.aar\0f40d142e6b58b7fe15914d4ec5e3dc5\res\layout\notification_action.xml:24: error: duplicate attribute.
Command: C:\Users\andrew\.gradle\caches\transforms-1\files-1.1\aapt2-3.2.1-4818971-windows.jar\cacb99a92dc25d61ade7acbb3a469d02\aapt2-3.2.1-4818971-windows\aapt2.exe compile --legacy \
-o \
C:\Users\andrew\AndroidStudioProjects\clone\app\build\intermediates\res\merged\debug \
C:\Users\andrew\.gradle\caches\transforms-1\files-1.1\support-compat-28.0.0.aar\0f40d142e6b58b7fe15914d4ec5e3dc5\res\layout\notification_action.xml
Daemon: AAPT2 aapt2-3.2.1-4818971-windows Daemon #3
this happened for many .xml in internal files .
my IDE is Android Studio 3.2.1
This happened to me .Delete this file C:\Users\andrew.gradle\caches\transforms-1 form windows and build your project. this should solve your problem .
I'm working on some script for custom build system and i need to pack some .so files in android apk (aars with native libs are not yet supported).
I've invoked ./gradlew assembleDebug --debug for the apk project that depends on aar with native libraries (.so) to get full log but did not find any .so files paths passed to aapt or any other android build tool (though i've seen .so stripping commands with ndk strip tool).
How is it done in details? Does aapt tool do it? Are there any aapt arguments for this or they should be just stored on some specific paths (eg. libs).
Yes, aapt via an invocation like aapt add -v MyApp.apk lib/armeabi/libMyLib.so.
Use aapt --list MyApp.apk to ensure that it is in the apk with that directory structure (a lib folder, an armeabi subfolder, and MyApp.apk within that).
After installing the app, look in /data/app/com.Company/android/MyApp-X/lib/arm/ for libMyLib.so to ensure it got copied.
If problems, logcat output is actually really useful, telling you the path tried, the function tried, etc.
Obviously, replace the app name, company name, and armeabi architecture to fit your projects' parameters.
I have a kind of strange issue. In my bash script or Makefile, using aapt with absolute path does not work but if I am in the local directory it does.
If I do the following, it does not work:
aapt add $OUT/device.jar $OUT/classes.dex
The command does run and print this output:
'/homes/rsevile/CS307/bin/Device/classes.dex'...
But when trying to load the jar, the class that I am trying to load end up being not found.
The following does work though:
cd $OUT
aapt add device.jar classes.dex
Printing:
'classes.dex'...
This is the whole code being executed in the script (which works):
javac -d $(OUT)/classes -classpath ./layoutlib.jar src/com/device/client/*.java
jar cf $(OUT)/device.jar $(OUT)/classes $(OUT)/layoutlib
dx --dex --no-strict --output=$OUT/classes.dex $OUT/device.jar
cd $OUT
aapt add device.jar classes.dex
cd $ROOT
adb push $OUT/device.jar $ANDROID_OUT_DIR
I am confused why my class ends up being not found when using an absolute path with aapt.
Could anyone please explain to me why it is not working and how I could fix it to use a proper absolute path please?
Thank you.
I realized that aapt actually keeps the absolute path, there is no way around it.
I fixed the problem by reusing jar and using the -C option that lets me specify a directory.