diff --git a/app/build.gradle b/app/build.gradle
index ac5df08627..f86a4d0c73 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,6 +11,7 @@ android {
implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.drawerlayout:drawerlayout:1.1.0"
implementation project(":terminal-view")
+ implementation project(":native-entrypoint")
}
defaultConfig {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2347586652..910f95726a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -94,6 +94,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/native-entrypoint/.gitignore b/native-entrypoint/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/native-entrypoint/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/native-entrypoint/build.gradle b/native-entrypoint/build.gradle
new file mode 100644
index 0000000000..d1405bc5cc
--- /dev/null
+++ b/native-entrypoint/build.gradle
@@ -0,0 +1,51 @@
+plugins {
+ id "com.jfrog.bintray" version "1.7.3"
+ id "com.github.dcendents.android-maven" version "2.0"
+}
+
+apply plugin: 'com.android.library'
+
+ext {
+ bintrayName = 'native-entrypoint'
+ publishedGroupId = 'com.termux'
+ libraryName = 'NativeEntryPoint'
+ artifact = 'native-entrypoint'
+ libraryDescription = 'The terminal view used in Termux'
+ siteUrl = 'https://github.com/termux/termux'
+ gitUrl = 'https://github.com/termux/termux.git'
+ libraryVersion = '0.50'
+}
+
+android {
+ compileSdkVersion project.properties.compileSdkVersion.toInteger()
+ ndkVersion project.properties.ndkVersion
+
+ dependencies {
+ implementation "androidx.annotation:annotation:1.1.0"
+ }
+
+ defaultConfig {
+ minSdkVersion project.properties.minSdkVersion.toInteger()
+ targetSdkVersion project.properties.targetSdkVersion.toInteger()
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ externalNativeBuild {
+ ndkBuild {
+ path "src/main/jni/Android.mk"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+apply from: '../scripts/bintray-publish.gradle'
diff --git a/native-entrypoint/proguard-rules.pro b/native-entrypoint/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/native-entrypoint/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/native-entrypoint/src/main/AndroidManifest.xml b/native-entrypoint/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..281f254520
--- /dev/null
+++ b/native-entrypoint/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/native-entrypoint/src/main/jni/Android.mk b/native-entrypoint/src/main/jni/Android.mk
new file mode 100644
index 0000000000..01a0ea3aa1
--- /dev/null
+++ b/native-entrypoint/src/main/jni/Android.mk
@@ -0,0 +1,6 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libnative-entrypoint
+LOCAL_SRC_FILES:= main.cpp
+LOCAL_LDLIBS:= -llog -landroid -ldl
+include $(BUILD_SHARED_LIBRARY)
diff --git a/native-entrypoint/src/main/jni/main.cpp b/native-entrypoint/src/main/jni/main.cpp
new file mode 100644
index 0000000000..213c4a5826
--- /dev/null
+++ b/native-entrypoint/src/main/jni/main.cpp
@@ -0,0 +1,85 @@
+#include
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ *
+ */
+
+//BEGIN_INCLUDE(all)
+#include
+#include
+
+#include
+#include
+
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
+
+jstring ANativeActivity_getIntent(ANativeActivity* activity, const char* intentName) {
+ JNIEnv* env = activity->env;
+ jobject me = activity->clazz;
+
+ jclass acl = env->GetObjectClass(me); //class pointer of NativeActivity
+ jmethodID giid = env->GetMethodID(acl, "getIntent", "()Landroid/content/Intent;");
+ jobject intent = env->CallObjectMethod(me, giid); //Got our intent
+
+ jclass icl = env->GetObjectClass(intent); //class pointer of Intent
+ jmethodID gseid = env->GetMethodID(icl, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
+
+ return (jstring)env->CallObjectMethod(intent, gseid, env->NewStringUTF(intentName));
+}
+
+void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
+ JNIEnv* env = activity->env;
+ jstring dylib_path = ANativeActivity_getIntent(activity, "DYLIB_PATH");
+
+ const char *path = env->GetStringUTFChars(dylib_path, 0);
+ void* handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
+
+ env->ReleaseStringUTFChars(dylib_path, path);
+
+ {
+ if (handle == NULL) {
+ char* errorText = dlerror();
+ LOGW("ERROR!!! %s\n", errorText);
+ printf("%s\n", errorText);
+ ANativeActivity_finish(activity);
+ return;
+ }
+
+ void* entryPoint = dlsym(handle, "ANativeActivity_onCreate");
+
+ if (entryPoint) {
+ LOGI("%s found.\n", "ANativeActivity_onCreate");
+ } else {
+ entryPoint = dlsym(handle, __func__);
+
+ if (entryPoint) {
+ LOGI("%s found.\n", __func__);
+ }
+ }
+
+ if (entryPoint) {
+ LOGI("calling main...\n");
+ (*(void(*)(ANativeActivity*, void*, size_t))entryPoint)(activity, savedState, savedStateSize);
+ LOGI("exited!...\n");
+ } else {
+ char* errorText = dlerror();
+ LOGW("ERROR!!! %s\n", errorText);
+ printf("%s\n", errorText);
+ }
+
+ dlclose(handle);
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 2cfc62326b..bdbf0720cc 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':app', ':terminal-emulator', ':terminal-view'
+include ':app', ':terminal-emulator', ':terminal-view', ':native-entrypoint'