Skip to content

Commit 547c703

Browse files
committed
add support for 'android:hasCode="false"'
1 parent 17aa647 commit 547c703

File tree

5 files changed

+25
-24
lines changed

5 files changed

+25
-24
lines changed

examples/minimal/android/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
android:icon="@mipmap/ic_launcher"
88
android:label="@string/app_name"
99
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
10+
android:hasCode="false"
1011
tools:targetApi="31">
1112
<activity
1213
android:name="android.app.NativeActivity"

examples/minimal/android/src/NativeInvocationHandler.java

Lines changed: 0 additions & 15 deletions
This file was deleted.

examples/minimal/build.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ pub fn build(b: *std.Build) void {
3232
apk.addResourceDirectory(b.path("android/res"));
3333

3434
// Add Java files
35-
apk.addJavaSourceFile(.{ .file = b.path("android/src/NativeInvocationHandler.java") });
35+
// - If you have 'android:hasCode="false"' in your AndroidManifest.xml then no Java files are required
36+
// see: https://developer.android.com/ndk/samples/sample_na
37+
// apk.addJavaSourceFile(.{ .file = b.path("android/src/X.java") });
3638
break :blk apk;
3739
};
3840

examples/minimal/src/minimal.zig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,16 @@ fn nativeActivityOnCreate(activity: *androidbind.ANativeActivity, savedState: []
7272
log.debug("Successfully started the app.", .{});
7373
}
7474

75+
comptime {
76+
if (builtin.abi.isAndroid()) {
77+
@export(&NativeActivity_onCreate, .{ .name = "ANativeActivity_onCreate" });
78+
} else {
79+
@compileError("This example cannot run on targets other Android");
80+
}
81+
}
82+
7583
/// Android entry point
76-
export fn ANativeActivity_onCreate(activity: *androidbind.ANativeActivity, rawSavedState: ?[*]u8, rawSavedStateSize: usize) callconv(.C) void {
84+
fn NativeActivity_onCreate(activity: *androidbind.ANativeActivity, rawSavedState: ?[*]u8, rawSavedStateSize: usize) callconv(.C) void {
7785
const savedState: []const u8 = if (rawSavedState) |s|
7886
s[0..rawSavedStateSize]
7987
else

src/androidbuild/apk.zig

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,18 @@ fn doInstallApk(apk: *Apk) std.mem.Allocator.Error!*Step.InstallFile {
203203
}
204204
}
205205
}
206-
if (apk.java_files.items.len == 0) {
207-
// NOTE(jae): 2024-09-19
208-
// We can probably avoid this with a stub or something but for now error so that an "adb install"
209-
// doesn't give users:
210-
// - Scanning Failed.: Package /data/app/base.apk code is missing]
211-
try errors.append(b.fmt("must add at least one Java file to build", .{}));
212-
}
206+
// NOTE(jae): 2025-05-06
207+
// This validation rule has been removed because if you have `android:hasCode="false"` in your AndroidManifest.xml file
208+
// then you can have no Java files.
209+
//
210+
// If you do not provide Java files AND hasCode=false isn't set, then you may get the following error on "adb install"
211+
// - Scanning Failed.: Package /data/app/base.apk code is missing]
212+
//
213+
// 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
214+
// an error at compilation time. Similar to how we use it to extract the package name from AndroidManifest.xml below (ie. "aapt2 dump packagename")
215+
// if (apk.java_files.items.len == 0) {
216+
// 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'", .{}));
217+
// }
213218
if (errors.items.len > 0) {
214219
printErrorsAndExit("misconfigured Android APK", errors.items);
215220
}

0 commit comments

Comments
 (0)