Open nkoroste opened 4 years ago
Seems like this is going to be very important come this August, as without this you can't publish to the play store: https://android-developers.googleblog.com/2020/11/new-android-app-bundle-and-target-api.html
I asked about this issue on bazel discuss and didn't get anything back:
https://groups.google.com/g/bazel-discuss/c/z8Z3-tLcaCI/m/TCKUppYHBQAJ
Hi all,
Our approach to solving this issue is for us to provide a rule called android_application
that replaces android_binary
and supports building Android App bundles. The android_application
rule will support configuration splits, as well as feature splits for assets and native libraries. We anticipate publishing it with enough time for adoption before the Play Store deadline.
If you would like to switch to using android_application
and Bazel to generate an Android App Bundle from an existing Bazel target that uses android_binary
:
android_binary
with android_application
.srcs
(if any) to a new android_library
target, then add that library to the deps
of the android_application
(android_applcation
does not accept source files directly).bundle_config_file
to a .pb.json
bundle configuration, as per https://developer.android.com/studio/build/building-cmdline#bundleconfig to configure the splits for the application.We'll publish additional documentation and examples when we publish the android_applcation
rule.
@ahumesky How would this work for generating APKs from AAB files? Would we need to use bundletool or keep android_binary
alongside android_application
to be able to create APKs?
Good question. Yes, you'd keep android_binary
targets for development. To clarify, the "Replace android_binary with android_application" step was about android_binary targets you might be using for deployment to Play store.
Also, android_application will support bazel run
, which will use bundletool to install an APK to a connected device.
It should also be possible to invoke bundletool in a genrule that depends on the android_application and specifies the configuration you want for the APK.
@ahumesky any target when android_application
will be available?
@ajanuar I aim to publish at least a preview of the code later this week or next week.
Any update?
I have the code for android_application working and building bundles (for at least a very simple app), and I think we'll have everything in position to publish a preview tomorrow (i.e. to the pre-alpha branch), but there's a chance that might slip to Monday
Hi all, I've published the preview to the pre-alpha branch here: https://github.com/bazelbuild/rules_android/tree/pre-alpha
Note that to get the bundletool dependencies, you'll need to add rules_jvm_external
to your workspace file if it's not there already, and there's some workspace setup now in @rules_android//:defs.bzl
:
http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-fa73b1a8e4846cee88240d0019b8f80d39feb1c3",
url = "https://github.com/bazelbuild/rules_jvm_external/archive/fa73b1a8e4846cee88240d0019b8f80d39feb1c3.zip",
)
http_archive(
name = "rules_android",
urls = ["https://github.com/bazelbuild/rules_android/archive/5c8bdd44193894594fa01fd527c5cf3af17e7652.zip"],
strip_prefix = "rules_android-5c8bdd44193894594fa01fd527c5cf3af17e7652",
)
load("@rules_android//:defs.bzl", "rules_android_workspace")
rules_android_workspace()
Thanks Alex! I am glad to see that and am looking forward to seeing how this evolves. I hope that this is useful for people. Has anyone tried it yet?
One more note on how to use these, the starlark code relies on some features and other changes in bazel that haven't been released yet, but should be in the next rolling release (https://github.com/bazelbuild/bazel/issues/13505). (otherwise something like name 'JavaPluginInfo' is not defined
will happen). For now, a bazel built at head should work.
Are those changes able to be cherry-picked into 4.2.0?
Good question, I'm not sure. The immediate error is from refactorings to the Java rules, so I'm not sure off-hand what it would take to cherry pick those. In general though, the Android rules are being developed internally against head, and then exported here, so for the time being the Android rules will need a fairly recent version of Bazel.
Has anyone had a chance to try building a bundle with android_application?
@ahumesky We tested out the pre-alpha branch and hit this issue immediately so we are blocked at trying it out until we can find a workaround.
Thanks for testing this, I'll post an update on that issue.
@ahumesky We did another round of testing against the data bindings patches with the alpha branch of rules_android. We got further but hit a new failure case where custom styles that references Android resource attributes provided by 3rd party dependencies aren't being found during static linking.
Tested using rules_jvm_external
and bazel
HEAD.
Exception in thread "main" java.lang.RuntimeException: Error during Statically linking com.google.devtools.build.android.aapt2.CompiledResources@35aea049:
Command: bazel-out/host/bin/external/androidsdk/aapt2_binary\
link\
--static-lib\
--manifest\
/var/folders/ts/25b588x11_n7f1k_2361ybr80000gp/T/android_resources_tmp17478694338343542457/manifest-aapt-dummy/AndroidManifest.xml\
--no-static-lib-packages\
--no-version-vectors\
-R\
/var/folders/ts/25b588x11_n7f1k_2361ybr80000gp/T/android_resources_tmp17478694338343542457/filtered/bazel-out/darwin-fastbuild/bin/_migrated/lib_symbols/symbols.zip\
-I\
external/androidsdk/platforms/android-30/android.jar\
--auto-add-overlay\
-o\
/var/folders/ts/25b588x11_n7f1k_2361ybr80000gp/T/android_resources_tmp17478694338343542457/lib.apk\
--java\
/var/folders/ts/25b588x11_n7f1k_2361ybr80000gp/T/android_resources_tmp17478694338343542457/java\
--output-text-symbols\
/var/folders/ts/25b588x11_n7f1k_2361ybr80000gp/T/android_resources_tmp17478694338343542457/R.txt
Output:
res/values/styles.xml:5: error: style attribute 'attr/autoSizeMinTextSize (aka com.demo.app:attr/autoSizeMinTextSize)' not found.
error: failed linking references.
at com.google.devtools.build.android.CommandHelper.execute(CommandHelper.java:42)
at com.google.devtools.build.android.AaptCommandBuilder.execute(AaptCommandBuilder.java:297)
at com.google.devtools.build.android.aapt2.ResourceLinker.linkStatically(ResourceLinker.java:272)
at com.google.devtools.build.android.ValidateAndLinkResourcesAction.main(ValidateAndLinkResourcesAction.java:207)
at com.google.devtools.build.android.ResourceProcessorBusyBox$Tool$7.call(ResourceProcessorBusyBox.java:105)
at com.google.devtools.build.android.ResourceProcessorBusyBox.processRequest(ResourceProcessorBusyBox.java:234)
at com.google.devtools.build.android.ResourceProcessorBusyBox.main(ResourceProcessorBusyBox.java:177)
Target //:lib failed to build
BUILD
load("@rules_android//rules:rules.bzl", "android_library")
android_library(
name = "lib",
custom_package = "com.demo.app",
# ... manifest, visibility, ...
resource_files = glob(["res/**/*.xml"]),
deps = [
"@maven//:androidx_appcompat_appcompat",
"@maven//:androidx_appcompat_appcompat_resources",
],
)
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FooTextAppearance">
<item name="autoSizeMinTextSize">1sp</item>
</style>
</resources>
Thanks for testing this out. I was able to repro the problem with the style resource, could you file an issue about this? I'll investigate from there.
@ahumesky moved the issue over to here https://github.com/bazelbuild/rules_android/issues/39
FYI with help from @ahumesky I ended up rebuilding a minimalistic version of android_application for my team that works with Bazel 4.0 since we were having some difficulty getting the new rules_android changes working. Feel free to take a look if it's helpful: https://github.com/oppia/oppia-android/pull/3750. Note that there's a bunch of extra stuff in there, but folks in this thread will probably be specifically interested in: https://github.com/oppia/oppia-android/blob/d7945d56de9fd7a1ad7ff131953de296ffcf35cd/oppia_android_application.bzl.
I tried to build this in a way that would be easily swappable with rules_android once it's ready.
Hello, are there any updates to this aab support? It has been 3 months since last update. Are folks with APKs migrating off Bazel or simply waiting for the bazel android_application
rule to publish their aps?
We've been using https://github.com/oppia/oppia-android/blob/develop/oppia_android_application.bzl successfully to build aabs
@rockwotj Thanks for the link. I am using a modified version of the oppia_android_application.bzl
. But I am getting NullPointerException. Did you encounter a similar issue? If so, how did you solve it?
wsluser@DESKTOP-1:/mnt/c/Users/user1/Documents/Misc/Dev/custom-mediapipe-fork$ bazel build -c opt --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/hairsegmentationgpu:hairlight_application
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'com_google_absl' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'com_google_benchmark' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'pybind11_bazel' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'com_google_protobuf' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'com_google_googletest' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'com_github_gflags_gflags' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'build_bazel_rules_apple' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'build_bazel_rules_swift' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'build_bazel_apple_support' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'xctestrunner' because it already exists.
DEBUG: /home/wsluser/.cache/bazel/_bazel_wsluser/27576fa3ed0872646a64b44d0d0f4d1d/external/org_tensorflow/third_party/repo.bzl:122:14:
Warning: skipping import of repository 'pybind11' because it already exists.
WARNING: /mnt/c/Users/user1/Documents/Misc/Dev/custom-mediapipe-fork/mediapipe/framework/tool/BUILD:182:24: in cc_library rule //mediapipe/framework/tool:field_data_cc_proto: target '//mediapipe/framework/tool:field_data_cc_proto' depends on deprecated target '@com_google_protobuf//:cc_wkt_protos': Only for backward compatibility. Do not use.
WARNING: /mnt/c/Users/user1/Documents/Misc/Dev/custom-mediapipe-fork/mediapipe/framework/BUILD:54:24: in cc_library rule //mediapipe/framework:calculator_cc_proto: target '//mediapipe/framework:calculator_cc_proto' depends on deprecated target '@com_google_protobuf//:cc_wkt_protos': Only for backward compatibility. Do not use.
Analyzing: target //mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/hairsegmentationgpu:hairlight_application (171 packages loaded, 12409 targets configured)
currently loading: @org_tensorflow//tensorflow/core/kernels
FATAL: bazel crashed due to an internal error. Printing stack trace:
java.lang.RuntimeException: Unrecoverable error while evaluating node 'ConfiguredTargetKey{label=//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/hairsegmentationgpu:hairlight_application_binary, config=BuildConfigurationValue.Key[24c3d57be09409ec5b3d2c93fae5528ea0f5267d0a2f463c174db0f2ce0825d8]}' (requested by nodes 'ConfiguredTargetKey{label=//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/hairsegmentationgpu:hairlight_application_binary.apk, config=BuildConfigurationValue.Key[24c3d57be09409ec5b3d2c93fae5528ea0f5267d0a2f463c174db0f2ce0825d8]}')
at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:563)
at com.google.devtools.build.lib.concurrent.AbstractQueueVisitor$WrappedRunnable.run(AbstractQueueVisitor.java:398)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at com.google.devtools.build.lib.rules.java.JavaCompilationHelper.usesAnnotationProcessing(JavaCompilationHelper.java:530)
at com.google.devtools.build.lib.rules.java.JavaCompilationHelper.createOutputs(JavaCompilationHelper.java:187)
at com.google.devtools.build.lib.rules.android.AndroidCommon.initJava(AndroidCommon.java:580)
at com.google.devtools.build.lib.rules.android.AndroidCommon.init(AndroidCommon.java:517)
at com.google.devtools.build.lib.rules.android.AndroidBinary.init(AndroidBinary.java:311)
at com.google.devtools.build.lib.rules.android.AndroidBinary.create(AndroidBinary.java:118)
at com.google.devtools.build.lib.rules.android.AndroidBinary.create(AndroidBinary.java:96)
at com.google.devtools.build.lib.analysis.ConfiguredTargetFactory.createRule(ConfiguredTargetFactory.java:385)
at com.google.devtools.build.lib.analysis.ConfiguredTargetFactory.createConfiguredTarget(ConfiguredTargetFactory.java:195)
at com.google.devtools.build.lib.skyframe.SkyframeBuildView.createConfiguredTarget(SkyframeBuildView.java:940)
at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.createConfiguredTarget(ConfiguredTargetFunction.java:1031)
at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.compute(ConfiguredTargetFunction.java:371)
at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:477)
hairlight_android_application.bzl
"""
Macros pertaining to building & managing Android app bundles.
"""
def _convert_apk_to_aab_module_impl(ctx):
output_file = ctx.outputs.output_file
input_file = ctx.attr.input_file.files.to_list()[0]
# See aapt2 help documentation for details on the arguments passed here.
arguments = [
"convert",
"--output-format",
"proto",
"-o",
output_file.path,
input_file.path,
]
# Reference: https://docs.bazel.build/versions/master/skylark/lib/actions.html#run.
ctx.actions.run(
outputs = [output_file],
inputs = ctx.files.input_file,
tools = [ctx.executable._aapt2_tool],
executable = ctx.executable._aapt2_tool.path,
arguments = arguments,
mnemonic = "GenerateAndroidAppBundleModuleFromApk",
progress_message = "Generating deployable AAB",
)
return DefaultInfo(
files = depset([output_file]),
runfiles = ctx.runfiles(files = [output_file]),
)
def _convert_module_aab_to_structured_zip_impl(ctx):
output_file = ctx.outputs.output_file
input_file = ctx.attr.input_file.files.to_list()[0]
command = """
# Extract AAB to working directory.
WORKING_DIR=$(mktemp -d)
unzip -d $WORKING_DIR {0}
# Create the expected directory structure for an app bundle.
# Reference for copying all other files to root: https://askubuntu.com/a/951768.
mkdir -p $WORKING_DIR/assets $WORKING_DIR/dex $WORKING_DIR/manifest $WORKING_DIR/root
mv $WORKING_DIR/*.dex $WORKING_DIR/dex/
mv $WORKING_DIR/AndroidManifest.xml $WORKING_DIR/manifest/
ls -d $WORKING_DIR/* | grep -v -w -E "res|assets|dex|manifest|root|resources.pb" | xargs -I{{}} sh -c "mv \\$0 $WORKING_DIR/root/ || exit 255" {{}} 2>&1 || exit $?
# Zip up the result--this will be used by bundletool to build a deployable AAB. Note that these
# strange file path bits are needed because zip will always retain the directory structure
# passed via arguments (necessitating changing into the working directory).
DEST_FILE_PATH="$(pwd)/{1}"
cd $WORKING_DIR
zip -r $DEST_FILE_PATH .
""".format(input_file.path, output_file.path)
# Reference: https://docs.bazel.build/versions/main/skylark/lib/actions.html#run_shell.
ctx.actions.run_shell(
outputs = [output_file],
inputs = ctx.files.input_file,
tools = [],
command = command,
mnemonic = "ConvertModuleAabToStructuredZip",
progress_message = "Generating deployable AAB",
)
return DefaultInfo(
files = depset([output_file]),
runfiles = ctx.runfiles(files = [output_file]),
)
def _bundle_module_zip_into_deployable_aab_impl(ctx):
output_file = ctx.outputs.output_file
input_file = ctx.attr.input_file.files.to_list()[0]
config_file = ctx.attr.config_file.files.to_list()[0]
# Reference: https://developer.android.com/studio/build/building-cmdline#build_your_app_bundle_using_bundletool.
arguments = [
"build-bundle",
"--modules=%s" % input_file.path,
"--config=%s" % config_file.path,
"--output=%s" % output_file.path,
]
# Reference: https://docs.bazel.build/versions/master/skylark/lib/actions.html#run.
ctx.actions.run(
outputs = [output_file],
inputs = ctx.files.input_file + ctx.files.config_file,
tools = [ctx.executable._bundletool_tool],
executable = ctx.executable._bundletool_tool.path,
arguments = arguments,
mnemonic = "GenerateDeployAabFromModuleZip",
progress_message = "Generating deployable AAB",
)
return DefaultInfo(
files = depset([output_file]),
runfiles = ctx.runfiles(files = [output_file]),
)
def _package_metadata_into_deployable_aab_impl(ctx):
output_aab_file = ctx.outputs.output_aab_file
input_aab_file = ctx.attr.input_aab_file.files.to_list()[0]
proguard_map_file = ctx.attr.proguard_map_file.files.to_list()[0]
command = """
# Extract deployable AAB to working directory.
WORKING_DIR=$(mktemp -d)
echo $WORKING_DIR
cp {0} $WORKING_DIR/temp.aab || exit 255
# Change the permissions of the AAB copy so that it can be overwritten later.
chmod 755 $WORKING_DIR/temp.aab || exit 255
# Create directory needed for storing bundle metadata.
mkdir -p $WORKING_DIR/BUNDLE-METADATA/com.android.tools.build.obfuscation
# Copy over the Proguard map file.
cp {1} $WORKING_DIR/BUNDLE-METADATA/com.android.tools.build.obfuscation/proguard.map || exit 255
$ Repackage the AAB file into the destination.
DEST_FILE_PATH="$(pwd)/{2}"
cd $WORKING_DIR
zip -Dur temp.aab BUNDLE-METADATA || exit 255
cp temp.aab $DEST_FILE_PATH || exit 255
""".format(input_aab_file.path, proguard_map_file.path, output_aab_file.path)
# Reference: https://docs.bazel.build/versions/main/skylark/lib/actions.html#run_shell.
ctx.actions.run_shell(
outputs = [output_aab_file],
inputs = ctx.files.input_aab_file + ctx.files.proguard_map_file,
tools = [],
command = command,
mnemonic = "PackageMetadataIntoDeployableAAB",
progress_message = "Generating deployable AAB",
)
return DefaultInfo(
files = depset([output_aab_file]),
runfiles = ctx.runfiles(files = [output_aab_file]),
)
def _generate_apks_and_install_impl(ctx):
input_file = ctx.attr.input_file.files.to_list()[0]
debug_keystore_file = ctx.attr.debug_keystore.files.to_list()[0]
apks_file = ctx.actions.declare_file("%s_processed.apks" % ctx.label.name)
deploy_shell = ctx.actions.declare_file("%s_run.sh" % ctx.label.name)
# Reference: https://developer.android.com/studio/command-line/bundletool#generate_apks.
# See also the Bazel BUILD file for the keystore for details on its password and alias.
generate_apks_arguments = [
"build-apks",
"--bundle=%s" % input_file.path,
"--output=%s" % apks_file.path,
"--ks=%s" % debug_keystore_file.path,
"--ks-pass=pass:android",
"--ks-key-alias=androiddebugkey",
"--key-pass=pass:android",
]
# Reference: https://docs.bazel.build/versions/master/skylark/lib/actions.html#run.
ctx.actions.run(
outputs = [apks_file],
inputs = ctx.files.input_file + ctx.files.debug_keystore,
tools = [ctx.executable._bundletool_tool],
executable = ctx.executable._bundletool_tool.path,
arguments = generate_apks_arguments,
mnemonic = "BuildApksFromDeployAab",
progress_message = "Preparing AAB deploy to device",
)
# References: https://github.com/bazelbuild/bazel/issues/7390,
# https://developer.android.com/studio/command-line/bundletool#deploy_with_bundletool, and
# https://docs.bazel.build/versions/main/skylark/rules.html#executable-rules-and-test-rules.
# Note that the bundletool can be executed directly since Bazel creates a wrapper script that
# utilizes its own internal Java toolchain.
ctx.actions.write(
output = deploy_shell,
content = """
#!/bin/sh
{0} install-apks --apks={1}
echo The APK should now be installed
""".format(ctx.executable._bundletool_tool.short_path, apks_file.short_path),
is_executable = True,
)
# Reference for including necessary runfiles for Java:
# https://github.com/bazelbuild/bazel/issues/487#issuecomment-178119424.
runfiles = ctx.runfiles(
files = [
ctx.executable._bundletool_tool,
apks_file,
],
).merge(ctx.attr._bundletool_tool.default_runfiles)
return DefaultInfo(
executable = deploy_shell,
runfiles = runfiles,
)
_convert_apk_to_module_aab = rule(
attrs = {
"input_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"output_file": attr.output(
mandatory = True,
),
"_aapt2_tool": attr.label(
executable = True,
cfg = "host",
default = "@androidsdk//:aapt2_binary",
),
},
implementation = _convert_apk_to_aab_module_impl,
)
_convert_module_aab_to_structured_zip = rule(
attrs = {
"input_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"output_file": attr.output(
mandatory = True,
),
},
implementation = _convert_module_aab_to_structured_zip_impl,
)
_bundle_module_zip_into_deployable_aab = rule(
attrs = {
"input_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"config_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"output_file": attr.output(
mandatory = True,
),
"_bundletool_tool": attr.label(
executable = True,
cfg = "host",
default = "//third_party:android_bundletool",
),
},
implementation = _bundle_module_zip_into_deployable_aab_impl,
)
_package_metadata_into_deployable_aab = rule(
attrs = {
"input_aab_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"proguard_map_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"output_aab_file": attr.output(
mandatory = True,
),
},
implementation = _package_metadata_into_deployable_aab_impl,
)
_generate_apks_and_install = rule(
attrs = {
"input_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"debug_keystore": attr.label(
allow_single_file = True,
mandatory = True,
),
"_bundletool_tool": attr.label(
executable = True,
cfg = "host",
default = "//third_party:android_bundletool",
),
},
executable = True,
implementation = _generate_apks_and_install_impl,
)
def hairlight_android_application(name, config_file, proguard_generate_mapping, **kwargs):
"""
Creates an Android App Bundle (AAB) binary with the specified name and arguments.
Args:
name: str. The name of the Android App Bundle to build. This will corresponding to the name
of the generated .aab file.
config_file: target. The path to the .pb.json bundle configuration file for this build.
proguard_generate_mapping: boolean. Whether to perform a Proguard optimization step &
generate Proguard mapping corresponding to the obfuscation step.
**kwargs: additional arguments. See android_binary for the exact arguments that are
available.
"""
binary_name = "%s_binary" % name
module_aab_name = "%s_module_aab" % name
module_zip_name = "%s_module_zip" % name
deployable_aab_name = "%s_deployable" % name
native.android_binary(
name = binary_name,
tags = ["manual"],
proguard_generate_mapping = proguard_generate_mapping,
**kwargs
)
_convert_apk_to_module_aab(
name = module_aab_name,
input_file = ":%s.apk" % binary_name,
output_file = "%s.aab" % module_aab_name,
tags = ["manual"],
)
_convert_module_aab_to_structured_zip(
name = module_zip_name,
input_file = ":%s.aab" % module_aab_name,
output_file = "%s.zip" % module_zip_name,
tags = ["manual"],
)
# No extra package step is needed if there's no Proguard map file.
_bundle_module_zip_into_deployable_aab(
name = name,
input_file = ":%s.zip" % module_zip_name,
config_file = config_file,
output_file = "%s.aab" % name,
tags = ["manual"],
)
def declare_deployable_application(name, aab_target):
"""
Creates a new target that can be run with 'bazel run' to install an AAB file.
Example:
declare_deployable_application(
name = "install_oppia_prod",
aab_target = "//:oppia_prod",
)
$ bazel run //:install_oppia_prod
This will build (if necessary) and install the correct APK derived from the Android app bundle
on the locally attached emulator or device. Note that this command does not support targeting a
specific device so it will not work if more than one device is available via 'adb devices'.
Args:
name: str. The name of the runnable target to install an AAB file on a local device.
aab_target: target. The target (declared via oppia_android_application) that should be made
installable.
"""
_generate_apks_and_install(
name = name,
input_file = aab_target,
debug_keystore = "@bazel_tools//tools/android:debug_keystore",
tags = ["manual"],
)
BUILD
# Copyright 2019 The MediaPipe Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
licenses(["notice"])
load("//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/hairsegmentationgpu:hairlight_android_application.bzl", "declare_deployable_application", "hairlight_android_application")
package(default_visibility = ["//visibility:private"])
cc_binary(
name = "libmediapipe_jni.so",
linkshared = 1,
linkstatic = 1,
deps = [
"//mediapipe/graphs/hair_segmentation:mobile_calculators",
"//mediapipe/java/com/google/mediapipe/framework/jni:mediapipe_framework_jni",
],
)
cc_library(
name = "mediapipe_jni_lib",
srcs = [":libmediapipe_jni.so"],
alwayslink = 1,
)
android_binary(
name = "hairlight_binary",
srcs = glob(["*.java"]),
assets = [
"//mediapipe/graphs/hair_segmentation:mobile_gpu.binarypb",
"//mediapipe/models:hair_segmentation.tflite",
],
assets_dir = "",
manifest = "//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/basic:AndroidManifest.xml",
manifest_values = {
"applicationId": "com.hairlight.hairsegmentation.apps.hairsegmentationgpu",
"mainActivity": "com.hairlight.hairsegmentation.apps.basic.MainActivity"
},
multidex = "native",
deps = [
":mediapipe_jni_lib",
"//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/basic:basic_lib",
]
)
hairlight_android_application(
name = "hairlight_application",
custom_package = "org.oppia.android",
testonly = False,
enable_data_binding = True,
config_file = ":bundle_config.pb.json",
manifest = "//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/basic:AndroidManifest.xml",
manifest_values = {
"applicationId": "com.hairlight.hairsegmentation.apps.hairsegmentationgpu",
"mainActivity": "com.hairlight.hairsegmentation.apps.basic.MainActivity"
},
proguard_generate_mapping = False,
proguard_specs = [],
shrink_resources = False,
multidex = "native",
deps = [
":mediapipe_jni_lib",
"//mediapipe/examples/android/src/java/com/hairlight/hairsegmentation/apps/basic:basic_lib",
],
)
I am on bazel version 4.2.1
@ya332 you should re-run the command with sandbox_debug and verbose_failures to see what the specific sandbox command is that went wrong (you should be able to re-run that specific command and produce the same failure, plus the sandbox directories will stick around with sandbox_debug so you can inspect them to figure out what's going wrong).
Description of the problem / feature request:
Add the ability to build and publish Android APKs using the new App Bundles / Dynamic Delivery android features. See:
https://developer.android.com/platform/technology/app-bundle https://developer.android.com/guide/app-bundle/dynamic-delivery
Feature requests: what underlying problem are you trying to solve with this feature?
Use Bazel with App Bundles / Dynamic Delivery
What operating system are you running Bazel on?
MacOs or Linux
What's the output of
bazel info release
?Any
Have you found anything relevant by searching the web?
https://developer.android.com/platform/technology/app-bundle https://developer.android.com/guide/app-bundle/dynamic-delivery