Skip to content

Commit

Permalink
First Release (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
silbinarywolf authored Sep 19, 2024
1 parent 4f111a3 commit 2ca003d
Show file tree
Hide file tree
Showing 20 changed files with 5,011 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ jobs:
with:
version: "0.13.0"

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
packages: 'tools platform-tools platforms;android-35 build-tools;35.0.0 ndk;27.0.12077973'

- name: Build
run: zig build -Dandroid=true --verbose
working-directory: examples/minimal
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) SilbinaryWolf and Zig Android SDK contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# <img src="examples/minimal/android/res/mipmap/ic_launcher.png" width="32" height="32"> Zig Android SDK

![Continuous integration](https://github.com/silbinarywolf/zig-android-sdk/actions/workflows/ci.yml/badge.svg)

⚠️ **WARNING:** This is a work-in-progress and will be updated as I improve it for my personal SDL2 / OpenXR project.

This library allows you to setup and build an APK for your Android devices. This project was mostly based off the work of [ikskuh](https://github.com/ikskuh) and wouldn't exist without the work they did on the [ZigAndroidTemplate](https://github.com/ikskuh/ZigAndroidTemplate) project.


```sh
# Target one Android architecture
zig build -Dtarget=x86_64-linux-android

# Target all Android architectures
zig build -Dandroid=true
```

```zig
// This is an overly simplified example to give you the gist
// of how this library works, see: examples/minimal/build.zig
const android = @import("zig-android-sdk");
pub fn build(b: *std.Build) !void {
const android_tools = android.Tools.create(b, ...);
const apk = android.APK.create(b, android_tools);
apk.setAndroidManifest(b.path("android/AndroidManifest.xml"));
apk.addResourceDirectory(b.path("android/res"));
apk.addJavaSourceFile(.{ .file = b.path("android/src/NativeInvocationHandler.java") });
for (android.standardTargets(b, b.standardTargetOptions(.{}))) |target| {
apk.addArtifact(b.addSharedLibrary(.{
.name = exe_name,
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}))
}
}
```

## Requirements

* [Zig](https://ziglang.org/download)
* Android Tools
* Option A: [Android Studio](https://developer.android.com/studio)
* Option B: [Android Command Line Tools](https://developer.android.com/studio#command-line-tools-only)
* [Java Development Kit](https://www.oracle.com/au/java/technologies/downloads/)

## Installation

Add the following to your build.zig.zon file and run `zig build`.

```zig
.{
.dependencies = .{
.@"zig-android-sdk" = .{
.path = "https://github.com/zigimg/zigimg/archive/REPLACE_WITH_WANTED_COMMIT.tar.gz",
// .hash = REPLACE_WITH_HASH_FROM_BUILD_ERROR
},
},
}
```

## Examples

* [minimal](examples/minimal): This is based off [ZigAndroidTemplate's minimal](https://github.com/ikskuh/ZigAndroidTemplate/tree/master/examples/minimal) example.

## Credits

- [ikskuh](https://github.com/ikskuh) This would not exist without their [ZigAndroidTemplate](https://github.com/ikskuh/ZigAndroidTemplate) repository to use as a baseline for figuring this all out and also being able to use their logic for the custom panic / logging functions.
- ikskuh gave a huge thanks to [@cnlohr](https://github.com/cnlohr) for [rawdrawandroid](https://github.com/cnlohr/rawdrawandroid)
26 changes: 26 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const std = @import("std");
const androidbuild = @import("src/androidbuild/androidbuild.zig");
const apk = @import("src/androidbuild/apk.zig");
const tools = @import("src/androidbuild/tools.zig");

// Expose Android build functionality for use in your build.zig

pub const ToolsOptions = tools.ToolsOptions;
pub const Tools = tools.Tools;
pub const APK = apk.APK;
pub const APILevel = androidbuild.APILevel;
pub const CreateKey = tools.CreateKey;
pub const standardTargets = androidbuild.standardTargets;

/// NOTE: As well as providing the "android" module this declaration is required so this can be imported by other build.zig files
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const module = b.addModule("android", .{
.root_source_file = b.path("src/android/android.zig"),
.target = target,
.optimize = optimize,
});
module.linkSystemLibrary("log", .{});
}
10 changes: 10 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.{
.name = "zig-android-sdk",
.version = "0.1.0",
.dependencies = .{},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
29 changes: 29 additions & 0 deletions examples/minimal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Minimal Example

As of 2024-09-19, this is a thrown together, very quick copy-paste of the minimal example from the original [ZigAndroidTemplate](https://github.com/ikskuh/ZigAndroidTemplate/blob/master/examples/minimal/main.zig) repository.

### Build and install to test one target against a local emulator

```sh
zig build -Dtarget=x86_64-linux-android
adb install ./zig-out/bin/minimal.apk
```

### Build and install for all supported Android targets

```sh
zig build -Dandroid=true
adb install ./zig-out/bin/minimal.apk
```

### View logs of application

Powershell
```sh
adb logcat | Select-String com.zig.minimal:
```

Bash
```sh
adb logcat --pid=`adb shell pidof -s com.zig.minimal`
```
23 changes: 23 additions & 0 deletions examples/minimal/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.zig.minimal">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
tools:targetApi="31">
<activity
android:name="android.app.NativeActivity"
android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions examples/minimal/android/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Pretty name of your app -->
<string name="app_name">Zig Minimal</string>
<!--
This is required for the APK name. This identifies your app, Android will associate
your signing key with this identifier and will prevent updates if the key changes.
-->
<string name="package_name">com.zig.minimal</string>
</resources>
15 changes: 15 additions & 0 deletions examples/minimal/android/src/NativeInvocationHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import java.lang.Object;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class NativeInvocationHandler implements InvocationHandler {
public NativeInvocationHandler(long ptr) { this.ptr = ptr; }

public Object invoke(Object proxy, Method method, Object[] args) {
return invoke0(proxy, method, args);
}

native private Object invoke0(Object proxy, Method method, Object[] args);

private long ptr;
}
90 changes: 90 additions & 0 deletions examples/minimal/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const std = @import("std");
const builtin = @import("builtin");
const android = @import("zig-android-sdk");

pub fn build(b: *std.Build) void {
const exe_name: []const u8 = "minimal";
const root_target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const android_targets = android.standardTargets(b, root_target);

var root_target_single = [_]std.Build.ResolvedTarget{root_target};
const targets: []std.Build.ResolvedTarget = if (android_targets.len == 0)
root_target_single[0..]
else
android_targets;

// If building with Android, initialize the tools / build
const android_apk: ?*android.APK = blk: {
if (android_targets.len == 0) {
break :blk null;
} else {
const android_tools = android.Tools.create(b, .{
.api_level = .android15,
.build_tools_version = "35.0.0",
.ndk_version = "27.0.12077973",
});
const apk = android.APK.create(b, android_tools);

const key_store_file = android_tools.createKeyStore(android.CreateKey.example());
apk.setKeyStore(key_store_file);
apk.setAndroidManifest(b.path("android/AndroidManifest.xml"));
apk.addResourceDirectory(b.path("android/res"));

// Add Java files
apk.addJavaSourceFile(.{ .file = b.path("android/src/NativeInvocationHandler.java") });

// Example of adding Java files from an external package
// const sdl_dep = b.dependency("sdl", .{
// .optimize = .ReleaseFast,
// .target = android_targets[0],
// });
// const sdl_java_files = sdl_dep.namedWriteFiles("sdljava");
// for (sdl_java_files.files.items) |file| {
// apk.addJavaSourceFile(.{ .file = file.getPath() });
// }

break :blk apk;
}
};

for (targets) |target| {
var exe: *std.Build.Step.Compile = if (target.result.isAndroid()) b.addSharedLibrary(.{
.name = exe_name,
.root_source_file = b.path("src/minimal.zig"),
.target = target,
.optimize = optimize,
}) else b.addExecutable(.{
.name = exe_name,
.root_source_file = b.path("src/minimal.zig"),
.target = target,
.optimize = optimize,
});

// if building as library for Android, add this target
// NOTE: Android has different CPU targets so you need to build a version of your
// code for x86, x86_64, arm, arm64 and more
if (target.result.isAndroid()) {
const apk: *android.APK = android_apk orelse @panic("Android APK should be initialized");
const android_dep = b.dependency("zig-android-sdk", .{
.optimize = optimize,
.target = target,
});
exe.root_module.addImport("android", android_dep.module("android"));

apk.addArtifact(exe);
} else {
b.installArtifact(exe);

// If only 1 target, add "run" step
if (targets.len == 1) {
const run_step = b.step("run", "Run the application");
const run_cmd = b.addRunArtifact(exe);
run_step.dependOn(&run_cmd.step);
}
}
}
if (android_apk) |ab| {
ab.installApk();
}
}
14 changes: 14 additions & 0 deletions examples/minimal/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.{
.name = "minimal",
.version = "0.0.0",
.dependencies = .{
.@"zig-android-sdk" = .{
.path = "../..",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
Loading

0 comments on commit 2ca003d

Please sign in to comment.