Skip to content

add support for 'android:hasCode="false"' and update "examples/minimal" to use it #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/minimal/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:hasCode="false"
tools:targetApi="31">
<activity
android:name="android.app.NativeActivity"
Expand Down
15 changes: 0 additions & 15 deletions examples/minimal/android/src/NativeInvocationHandler.java

This file was deleted.

8 changes: 7 additions & 1 deletion examples/minimal/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ pub fn build(b: *std.Build) void {
apk.addResourceDirectory(b.path("android/res"));

// Add Java files
apk.addJavaSourceFile(.{ .file = b.path("android/src/NativeInvocationHandler.java") });
// - If you have 'android:hasCode="false"' in your AndroidManifest.xml then no Java files are required
// see: https://developer.android.com/ndk/samples/sample_na
//
// WARNING: If you do not provide Java files AND android:hasCode="false" isn't explicitly set, then you may get the following error on "adb install"
// Scanning Failed.: Package /data/app/base.apk code is missing]
//
// apk.addJavaSourceFile(.{ .file = b.path("android/src/X.java") });
break :blk apk;
};

Expand Down
10 changes: 9 additions & 1 deletion examples/minimal/src/minimal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ fn nativeActivityOnCreate(activity: *androidbind.ANativeActivity, savedState: []
log.debug("Successfully started the app.", .{});
}

comptime {
if (builtin.abi.isAndroid()) {
@export(&NativeActivity_onCreate, .{ .name = "ANativeActivity_onCreate" });
} else {
@compileError("This example cannot run on targets other Android");
}
}

/// Android entry point
export fn ANativeActivity_onCreate(activity: *androidbind.ANativeActivity, rawSavedState: ?[*]u8, rawSavedStateSize: usize) callconv(.C) void {
fn NativeActivity_onCreate(activity: *androidbind.ANativeActivity, rawSavedState: ?[*]u8, rawSavedStateSize: usize) callconv(.C) void {
const savedState: []const u8 = if (rawSavedState) |s|
s[0..rawSavedStateSize]
else
Expand Down
23 changes: 13 additions & 10 deletions src/android/android.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const android_builtin = struct {
pub const package_name: [:0]const u8 = ab.package_name;
};

/// Writes the constant string text to the log, with priority prio and tag tag.
/// Returns: 1 if the message was written to the log, or -EPERM if it was not; see __android_log_is_loggable().
/// Source: https://developer.android.com/ndk/reference/group/logging
extern "log" fn __android_log_write(prio: c_int, tag: [*c]const u8, text: [*c]const u8) c_int;

/// Alternate panic implementation that calls __android_log_write so that you can see the logging via "adb logcat"
Expand Down Expand Up @@ -92,7 +95,7 @@ const LogWriter = struct {
/// logs with the package name.
///
/// To workaround this, we bake the package name into the Zig binaries.
var tag: [:0]const u8 = android_builtin.package_name;
const tag: [:0]const u8 = android_builtin.package_name;

level: Level,

Expand Down Expand Up @@ -166,6 +169,8 @@ const Panic = struct {
threadlocal var panic_stage: usize = 0;

fn panic(message: []const u8, ret_addr: ?usize) noreturn {
@branchHint(.cold);
if (comptime !builtin.abi.isAndroid()) @compileError("do not use Android panic for non-Android builds");
const first_trace_addr = ret_addr orelse @returnAddress();
panicImpl(first_trace_addr, message);
}
Expand Down Expand Up @@ -199,7 +204,12 @@ const Panic = struct {
// }
var act = posix.Sigaction{
.handler = .{ .handler = posix.SIG.DFL },
.mask = posix.empty_sigset,
.mask = if (builtin.zig_version.major == 0 and builtin.zig_version.minor == 14)
// Legacy 0.14.0
posix.empty_sigset
else
// 0.15.0-dev+
posix.sigemptyset(),
.flags = 0,
};
// To avoid a double-panic, do nothing if an error happens here.
Expand Down Expand Up @@ -236,14 +246,7 @@ const Panic = struct {
/// - Provide custom "io" namespace so we can easily customize getStdErr() to be our own writer
/// - Provide other functions from std.debug.*
fn panicImpl(first_trace_addr: ?usize, msg: []const u8) noreturn {
// NOTE(jae): 2024-09-22
// Cannot mark this as cold(true) OR setCold() depending on Zig version as we get an invalid builtin function
// comptime {
// if (builtin.zig_version.minor == 13)
// @setCold(true)
// else
// @cold(true);
// }
@branchHint(.cold);

if (enable_segfault_handler) {
// If a segfault happens while panicking, we want it to actually segfault, not trigger
Expand Down
19 changes: 12 additions & 7 deletions src/androidbuild/apk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,18 @@ fn doInstallApk(apk: *Apk) std.mem.Allocator.Error!*Step.InstallFile {
}
}
}
if (apk.java_files.items.len == 0) {
// NOTE(jae): 2024-09-19
// We can probably avoid this with a stub or something but for now error so that an "adb install"
// doesn't give users:
// - Scanning Failed.: Package /data/app/base.apk code is missing]
try errors.append(b.fmt("must add at least one Java file to build", .{}));
}
// NOTE(jae): 2025-05-06
// This validation rule has been removed because if you have `android:hasCode="false"` in your AndroidManifest.xml file
// then you can have no Java files.
//
// If you do not provide Java files AND android:hasCode="false" isn't set, then you may get the following error on "adb install"
// - Scanning Failed.: Package /data/app/base.apk code is missing]
//
// Ideally we may want to do something where we can utilize "aapt2 dump X" to determine if "hasCode" is set and if it isn't, throw
// an error at compilation time. Similar to how we use it to extract the package name from AndroidManifest.xml below (ie. "aapt2 dump packagename")
// if (apk.java_files.items.len == 0) {
// try errors.append(b.fmt("must add at least one Java file to build OR you must setup your AndroidManifest.xml to have 'android:hasCode=false'", .{}));
// }
if (errors.items.len > 0) {
printErrorsAndExit("misconfigured Android APK", errors.items);
}
Expand Down
Loading