Skip to content
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

Gh action publish apk #509

Merged
merged 7 commits into from
Dec 7, 2023
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
9 changes: 7 additions & 2 deletions .github/workflows/releases-android-binary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ jobs:
key: ${{ runner.os }}-go-docker-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-docker-
- name: Gradle cache
uses: actions/cache@v3
with:
path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle') }}
- name: Cache sdk root
id: ndk-cache
uses: actions/cache@v3
Expand Down Expand Up @@ -134,7 +139,7 @@ jobs:
echo "CXX=${{ github.workspace }}/third_party/llvm-build/Release+Asserts/bin/clang++" >> $GITHUB_ENV
- name: Build TGZ packages
run: |
./tools/build --variant gui --arch ${{ matrix.arch }} --system android -build-benchmark -build-test -nc
./tools/build --variant gui --arch ${{ matrix.arch }} --system android --cmake-build-type MinSizeRel -build-benchmark -build-test -android-sdk-dir "${ANDROID_HOME}"
- name: "Install dependency: android sysroot (test purpose)"
if: ${{ steps.sysroot-cache.outputs.cache-hit != 'true' }}
run: |
Expand Down Expand Up @@ -163,4 +168,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ github.event.release.tag_name }} yass*.tgz
gh release upload ${{ github.event.release.tag_name }} yass*.tgz yass*.apk
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.0'
classpath 'com.android.tools.build:gradle:7.4.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
Expand Down
3 changes: 0 additions & 3 deletions android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,4 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sun May 28 17:34:07 CST 2023
android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false
android.nonTransitiveRClass=false
org.gradle.jvmargs=-Xmx4096M
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Sat Jul 15 09:20:22 BST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
2 changes: 0 additions & 2 deletions android/yass/build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
apply plugin: 'com.android.application'

android {
// https://developer.android.com/build/configure-app-module#set-namespace
namespace = "it.gui.yass"
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId 'it.gui.yass'
Expand Down
1 change: 1 addition & 0 deletions android/yass/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

</manifest>
14 changes: 13 additions & 1 deletion android/yass/src/main/java/it/gui/yass/YassActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

import android.app.NativeActivity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;

import java.io.FileDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Formatter;
import java.util.concurrent.LinkedBlockingQueue;


Expand All @@ -37,14 +42,15 @@ public void hideSoftInput() {
}

// Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
private LinkedBlockingQueue<Integer> unicodeCharacterQueue = new LinkedBlockingQueue<Integer>();
private final LinkedBlockingQueue<Integer> unicodeCharacterQueue = new LinkedBlockingQueue<Integer>();

// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
// KeyEvent and not consumed by any View before it reaches here
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
unicodeCharacterQueue.offer(event.getUnicodeChar(event.getMetaState()));
notifyNativeThread();
}
return super.dispatchKeyEvent(event);
}
Expand All @@ -54,4 +60,10 @@ public int pollUnicodeChar() {
return poll != null ? poll.intValue() : 0;
}

public int getIpAddress() {
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getIpAddress();
}

private native void notifyNativeThread();
}
92 changes: 87 additions & 5 deletions src/android/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ static EGLSurface g_EglSurface = EGL_NO_SURFACE;
static EGLContext g_EglContext = EGL_NO_CONTEXT;
static struct android_app* g_App = nullptr;
static bool g_Initialized = false;
static char g_LogTag[] = "ImGuiExample";
static std::string g_IniFilename = "";
static int g_NotifyFd[2] = {-1, -1};

// Forward declarations of helper functions
static void Init(struct android_app* app);
Expand All @@ -47,8 +47,14 @@ static void MainLoopStep();
static int ShowSoftKeyboardInput();
static int PollUnicodeChars();
static int GetAssetData(const char* filename, void** out_data);
// returning in host byte order
static int32_t GetIpAddress();

extern "C"
JNIEXPORT void JNICALL Java_it_gui_yass_YassActivity_notifyNativeThread(JNIEnv *env, jobject obj);

static Worker g_worker;

enum StartState {
STOPPED = 0,
STOPPING,
Expand Down Expand Up @@ -108,7 +114,8 @@ static void WorkFunc() {
int events;
struct android_poll_source* source;

while ((ident=ALooper_pollAll(g_Initialized ? 0 : -1, nullptr, &events,
while ((ident=ALooper_pollAll(g_Initialized ? 67 /* limit to 15 fps */ : -1,
nullptr, &events,
(void**)&source)) >= 0) {

// Process this event.
Expand Down Expand Up @@ -153,15 +160,40 @@ static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent
return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
}

/* Invoked by ALooper to process a message */
static int messagepipe_cb(int fd, int events, void* user) {
while (true) {
char msg;
ssize_t ret = read(fd, &msg, sizeof(msg));
if (ret < 0 && errno == EINTR)
continue;
if (ret < 0) {
break;
}
}

return 1;
}

void Init(struct android_app* app) {
if (g_Initialized)
return;
LOG(INFO) << "imgui: Initialize";
g_App = app;
DCHECK_EQ(g_App, a_app);

config::ReadConfigFileOption(0, nullptr);
config::ReadConfig();

g_App = app;
DCHECK_EQ(g_App, a_app);
/* Call this from your main thread to set up the callback pipe. */
int ret = pipe2(g_NotifyFd, O_NONBLOCK | O_CLOEXEC);
CHECK_NE(ret, -1);

/* Register the file descriptor to listen on. */
ALooper_addFd(g_App->looper, g_NotifyFd[0], LOOPER_ID_USER,
ALOOPER_EVENT_INPUT, messagepipe_cb, nullptr);

LOG(INFO) << "imgui: Initialize";

ANativeWindow_acquire(g_App->window);

// Initialize EGL
Expand Down Expand Up @@ -308,6 +340,7 @@ CIPHER_METHOD_VALID_MAP(XX)
static char local_host[140];
static int local_port;
static int timeout;
static std::string ipaddress = asio::ip::make_address_v4(GetIpAddress()).to_string();
static bool _init = [&]() -> bool {
strcpy(server_host, absl::GetFlag(FLAGS_server_host).c_str());
server_port = absl::GetFlag(FLAGS_server_port);
Expand All @@ -332,6 +365,7 @@ CIPHER_METHOD_VALID_MAP(XX)
ImGui::InputText("local_host", local_host, IM_ARRAYSIZE(local_host));
ImGui::InputInt("local_port", &local_port);
ImGui::InputInt("timeout", &timeout);
ImGui::Text("Current Ip Address: %s", ipaddress.c_str());

ImGui::Checkbox("Option Window", &show_option_window);

Expand Down Expand Up @@ -416,6 +450,14 @@ void Shutdown()
g_EglSurface = EGL_NO_SURFACE;
ANativeWindow_release(g_App->window);

/* UnRegister the file descriptor to listen on. */
ALooper_removeFd(g_App->looper, g_NotifyFd[0]);

close(g_NotifyFd[0]);
close(g_NotifyFd[1]);
g_NotifyFd[0] = -1;
g_NotifyFd[1] = -1;

g_Initialized = false;
}

Expand Down Expand Up @@ -506,6 +548,46 @@ static int GetAssetData(const char* filename, void** outData)
return num_bytes;
}

static int32_t GetIpAddress()
{
JavaVM* java_vm = g_App->activity->vm;
JNIEnv* java_env = nullptr;

jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
if (jni_return == JNI_ERR)
return 0;

jni_return = java_vm->AttachCurrentThread(&java_env, nullptr);
if (jni_return != JNI_OK)
return 0;

jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
if (native_activity_clazz == nullptr)
return 0;

jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "getIpAddress", "()I");
if (method_id == nullptr)
return 0;

jint ip_address = java_env->CallIntMethod(g_App->activity->clazz, method_id);

jni_return = java_vm->DetachCurrentThread();
if (jni_return != JNI_OK)
return 0;

return ntohl(ip_address);
}

JNIEXPORT void JNICALL Java_it_gui_yass_YassActivity_notifyNativeThread(JNIEnv *env, jobject obj) {
while (g_Initialized) {
char byte;
ssize_t ret = write(g_NotifyFd[1], &byte, sizeof(byte));
if (ret < 0 && (errno == EINTR || errno == EAGAIN))
continue;
break;
}
}

void android_main(android_app* app) {
CHECK(app);
app->onAppCmd = handleAppCmd;
Expand Down
42 changes: 40 additions & 2 deletions tools/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ var msvcAllowXpFlag bool

var freebsdAbiFlag int

var androidSdkDir string

var systemNameFlag string
var subSystemNameFlag string
var sysrootFlag string
Expand Down Expand Up @@ -144,6 +146,7 @@ func InitFlag() {
flag.BoolVar(&msvcAllowXpFlag, "msvc-allow-xp", getEnvBool("MSVC_ALLOW_XP", false), "Enable Windows XP Build")

flag.IntVar(&freebsdAbiFlag, "freebsd-abi", getFreebsdABI(11), "Select FreeBSD ABI")
flag.StringVar(&androidSdkDir, "android-sdk-dir", "", "Android SDK Home Path")

flag.StringVar(&systemNameFlag, "system", runtime.GOOS, "Specify host system name")
flag.StringVar(&subSystemNameFlag, "subsystem", "", "Specify host subsystem name")
Expand Down Expand Up @@ -1124,7 +1127,7 @@ func archiveMainFile(output string, prefix string, paths []string) {
// Use this command line to update .DS_Store
// hdiutil convert -format UDRW -o yass.dmg yass-macos-release-universal-*.dmg
// hdiutil resize -size 1G yass.dmg
cmdCheckOutput([]string{"../scripts/pkg-dmg",
cmdRun([]string{"../scripts/pkg-dmg",
"--source", paths[0],
"--target", output,
"--sourcefile",
Expand All @@ -1133,7 +1136,39 @@ func archiveMainFile(output string, prefix string, paths []string) {
"--icon", "../src/mac/yass.icns",
"--copy", "../macos/.DS_Store:/.DS_Store",
"--copy", "../macos/.background:/",
"--symlink", "/Applications:/Applications"})
"--symlink", "/Applications:/Applications"}, true)
} else if systemNameFlag == "android" && variantFlag == "gui" {
androidDir := "../android"
err := os.Chdir(androidDir)
if err != nil {
glog.Fatalf("%v", err)
}
if (androidSdkDir != "") {
glog.Infof("android sdk dir to %s", androidSdkDir)
localProperties := fmt.Sprintf("sdk.dir=%s\n", androidSdkDir)
err = ioutil.WriteFile("local.properties", []byte(localProperties), 0666)
if err != nil {
glog.Fatalf("%v", err)
}
}
_, abi := getAndroidTargetAndAppAbi(archFlag)
if cmakeBuildTypeFlag == "Release" || cmakeBuildTypeFlag == "MinSizeRel" {
cmdRun([]string{"./gradlew", "yass:assembleRelease"}, true)
err = os.Rename(fmt.Sprintf("./yass/build/outputs/apk/release/yass-%s-release-unsigned.apk", abi), output)
if err != nil {
glog.Fatalf("%v", err)
}
} else {
cmdRun([]string{"./gradlew", "yass:assembleDebug"}, true)
err = os.Rename(fmt.Sprintf("./yass/build/outputs/apk/debug/yass-%s-release-unsigned.apk", abi), output)
if err != nil {
glog.Fatalf("%v", err)
}
}
err = os.Chdir(buildDir)
if err != nil {
glog.Fatalf("%v", err)
}
} else {
archiveFiles(output, prefix, paths)
}
Expand Down Expand Up @@ -1261,6 +1296,9 @@ func postStateArchives() map[string][]string {
archivePrefix := fmt.Sprintf(archiveFormat, strings.Replace(APPNAME, "_", "-", 1), "", "")
archiveSuffix := fmt.Sprintf(archiveFormat, "", "", "")
archiveSuffix = archiveSuffix[1:]
if systemNameFlag == "android" && variantFlag == "gui" {
archive = fmt.Sprintf(archiveFormat, APPNAME, archFlag, ".apk")
}
if systemNameFlag == "darwin" {
archive = fmt.Sprintf(archiveFormat, APPNAME, "", ".dmg")
}
Expand Down
Loading