diff --git a/NeoTermBridge/.gitignore b/NeoTermBridge/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/NeoTermBridge/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/NeoTermBridge/bintray.gradle b/NeoTermBridge/bintray.gradle
new file mode 100644
index 0000000..ef75194
--- /dev/null
+++ b/NeoTermBridge/bintray.gradle
@@ -0,0 +1,71 @@
+apply plugin: 'com.github.dcendents.android-maven'
+apply plugin: 'com.jfrog.bintray'
+
+def siteUrl = 'https://github.com/NeoTerm/NeoTerm.git'
+def gitUrl = 'https://github.com/NeoTerm/NeoTerm.git'
+def libraryGroup = "io.neoterm.bridge"
+def libraryRepoName = "neoterm-bridge"
+def libraryDesc = "Communicate with NeoTerm in an elegant way."
+def libraryVersionCode = 1
+def libraryVersionName = "1.0"
+def libraryLicences = ["MIT"]
+
+group = libraryGroup
+version = libraryVersionName + "-" + libraryVersionCode
+
+install {
+ repositories.mavenInstaller {
+ pom {
+ project {
+ packaging 'aar'
+ name libraryDesc
+ url siteUrl
+ licenses {
+ license {
+ name 'The MIT Software License'
+ url 'https://mit-license.org/'
+ }
+ }
+ developers {
+ developer {
+ id 'imkiva'
+ name 'imKiva'
+ email 'libkernelpanic@gmail.com'
+ }
+ }
+ scm {
+ connection gitUrl
+ developerConnection gitUrl
+ url siteUrl
+ }
+ }
+ }
+ }
+}
+
+task sourcesJar(type: Jar) {
+ from android.sourceSets.main.java.srcDirs
+ classifier = 'sources'
+}
+
+artifacts {
+ archives sourcesJar
+}
+
+Properties properties = new Properties()
+properties.load(project.file('../local.properties').newDataInputStream())
+bintray {
+ user = properties.getProperty("bintray.user")
+ key = properties.getProperty("bintray.apikey")
+ configurations = ['archives']
+ pkg {
+ repo = "maven"
+ name = libraryRepoName
+ websiteUrl = siteUrl
+ vcsUrl = gitUrl
+ dryRun = false
+ licenses = libraryLicences
+ publish = true
+ publicDownloadNumbers = true
+ }
+}
diff --git a/NeoTermBridge/build.gradle b/NeoTermBridge/build.gradle
new file mode 100644
index 0000000..efbda8c
--- /dev/null
+++ b/NeoTermBridge/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.library'
+
+def libraryVersionCode = 1
+def libraryVersionName = "1.0"
+
+android {
+ compileSdkVersion rootProject.ext.android.COMPILE_SDK_VERSION
+ buildToolsVersion '28.0.3'
+
+ defaultConfig {
+ minSdkVersion rootProject.ext.android.MIN_SDK_VERSION
+ targetSdkVersion rootProject.ext.android.TARGET_SDK_VERSION
+ versionCode libraryVersionCode
+ versionName libraryVersionName
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ testImplementation rootProject.ext.deps["junit"]
+}
+
+apply from: 'bintray.gradle'
diff --git a/NeoTermBridge/proguard-rules.pro b/NeoTermBridge/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/NeoTermBridge/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/NeoTermBridge/src/androidTest/java/io/neoterm/bridge/ExampleInstrumentedTest.java b/NeoTermBridge/src/androidTest/java/io/neoterm/bridge/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..3f02033
--- /dev/null
+++ b/NeoTermBridge/src/androidTest/java/io/neoterm/bridge/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package io.neoterm.bridge;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("io.neoterm.bridge.test", appContext.getPackageName());
+ }
+}
diff --git a/NeoTermBridge/src/main/AndroidManifest.xml b/NeoTermBridge/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8378b0b
--- /dev/null
+++ b/NeoTermBridge/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/NeoTermBridge/src/main/java/io/neoterm/bridge/Bridge.java b/NeoTermBridge/src/main/java/io/neoterm/bridge/Bridge.java
new file mode 100644
index 0000000..0a2bdaa
--- /dev/null
+++ b/NeoTermBridge/src/main/java/io/neoterm/bridge/Bridge.java
@@ -0,0 +1,60 @@
+package io.neoterm.bridge;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import java.util.Objects;
+
+/**
+ * @author kiva
+ */
+public class Bridge {
+ public static final String ACTION_EXECUTE = "neoterm.action.remote.execute";
+ public static final String ACTION_SILENT_RUN = "neoterm.action.remote.silent-run";
+ public static final String EXTRA_COMMAND = "neoterm.extra.remote.execute.command";
+ public static final String EXTRA_SESSION_ID = "neoterm.extra.remote.execute.session";
+ public static final String EXTRA_FOREGROUND = "neoterm.extra.remote.execute.foreground";
+ private static final String NEOTERM_PACKAGE = "io.neoterm";
+ private static final String NEOTERM_REMOTE_INTERFACE = "io.neoterm.ui.term.NeoTermRemoteInterface";
+ private static final ComponentName NEOTERM_COMPONENT = new ComponentName(NEOTERM_PACKAGE, NEOTERM_REMOTE_INTERFACE);
+
+ private Bridge() throws IllegalAccessException {
+ throw new IllegalAccessException();
+ }
+
+ public static Intent createExecuteIntent(SessionId sessionId,
+ String command,
+ boolean foreground) {
+ Objects.requireNonNull(command, "command");
+ Objects.requireNonNull(sessionId, "session id");
+
+ Intent intent = new Intent(ACTION_EXECUTE);
+ intent.setComponent(NEOTERM_COMPONENT);
+ intent.putExtra(EXTRA_COMMAND, command);
+ intent.putExtra(EXTRA_SESSION_ID, sessionId.getSessionId());
+ intent.putExtra(EXTRA_FOREGROUND, foreground);
+ return intent;
+ }
+
+ public static Intent createExecuteIntent(SessionId sessionId, String command) {
+ return createExecuteIntent(sessionId, command, true);
+ }
+
+ public static Intent createExecuteIntent(String command) {
+ return createExecuteIntent(SessionId.NEW_SESSION, command);
+ }
+
+ public static Intent createExecuteIntent(String command, boolean foreground) {
+ return createExecuteIntent(SessionId.NEW_SESSION, command, foreground);
+ }
+
+ public static SessionId parseResult(Intent data) {
+ Objects.requireNonNull(data, "data");
+
+ if (data.hasExtra(EXTRA_SESSION_ID)) {
+ String handle = data.getStringExtra(EXTRA_SESSION_ID);
+ return SessionId.of(handle);
+ }
+ return null;
+ }
+}
diff --git a/NeoTermBridge/src/main/java/io/neoterm/bridge/SessionId.java b/NeoTermBridge/src/main/java/io/neoterm/bridge/SessionId.java
new file mode 100644
index 0000000..ea3d11f
--- /dev/null
+++ b/NeoTermBridge/src/main/java/io/neoterm/bridge/SessionId.java
@@ -0,0 +1,50 @@
+package io.neoterm.bridge;
+
+import java.util.Objects;
+
+/**
+ * @author kiva
+ */
+public class SessionId {
+ /**
+ * Created a new session.
+ */
+ public static final SessionId NEW_SESSION = SessionId.of("new");
+
+ /**
+ * Presents current session in NeoTerm.
+ */
+ public static final SessionId CURRENT_SESSION = SessionId.of("current");
+
+ private final String sessionId;
+
+ SessionId(String sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ public String getSessionId() {
+ return sessionId;
+ }
+
+ @Override
+ public String toString() {
+ return "TerminalSession { id = " + sessionId + " }";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SessionId sessionId1 = (SessionId) o;
+ return Objects.equals(sessionId, sessionId1.sessionId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sessionId);
+ }
+
+ public static SessionId of(String sessionId) {
+ return new SessionId(sessionId);
+ }
+}
diff --git a/NeoTermBridge/src/main/res/values/strings.xml b/NeoTermBridge/src/main/res/values/strings.xml
new file mode 100644
index 0000000..f886376
--- /dev/null
+++ b/NeoTermBridge/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ NeoTermBridge
+
diff --git a/NeoTermBridge/src/test/java/io/neoterm/bridge/ExampleUnitTest.java b/NeoTermBridge/src/test/java/io/neoterm/bridge/ExampleUnitTest.java
new file mode 100644
index 0000000..b7e7724
--- /dev/null
+++ b/NeoTermBridge/src/test/java/io/neoterm/bridge/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package io.neoterm.bridge;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/NeoTermBridgeExample/.gitignore b/NeoTermBridgeExample/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/NeoTermBridgeExample/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/NeoTermBridgeExample/build.gradle b/NeoTermBridgeExample/build.gradle
new file mode 100644
index 0000000..bfd4313
--- /dev/null
+++ b/NeoTermBridgeExample/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 28
+
+
+
+ defaultConfig {
+ applicationId "io.neoterm.bridge.example"
+ minSdkVersion 21
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation project(':NeoTermBridge')
+}
diff --git a/NeoTermBridgeExample/proguard-rules.pro b/NeoTermBridgeExample/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/NeoTermBridgeExample/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/NeoTermBridgeExample/src/androidTest/java/io/neoterm/bridge/example/ExampleInstrumentedTest.java b/NeoTermBridgeExample/src/androidTest/java/io/neoterm/bridge/example/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..100d570
--- /dev/null
+++ b/NeoTermBridgeExample/src/androidTest/java/io/neoterm/bridge/example/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package io.neoterm.bridge.example;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("io.neoterm.bridge.example", appContext.getPackageName());
+ }
+}
diff --git a/NeoTermBridgeExample/src/main/AndroidManifest.xml b/NeoTermBridgeExample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1a94d0e
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NeoTermBridgeExample/src/main/java/io/neoterm/bridge/example/MainActivity.java b/NeoTermBridgeExample/src/main/java/io/neoterm/bridge/example/MainActivity.java
new file mode 100644
index 0000000..e6356bd
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/java/io/neoterm/bridge/example/MainActivity.java
@@ -0,0 +1,70 @@
+package io.neoterm.bridge.example;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import io.neoterm.bridge.Bridge;
+import io.neoterm.bridge.SessionId;
+
+public class MainActivity extends Activity {
+
+ private static final int REQUEST_CODE_RUN = 1;
+ private static final int REQUEST_CODE_APPEND = 2;
+ private static final int REQUEST_CODE_APPEND_SILENTLY = 3;
+ private static final String COMMAND = "echo \"hello world\"";
+
+ private SessionId lastSessionId;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+
+ public void onRunHelloWorld(View view) {
+ Intent intent = Bridge.createExecuteIntent(COMMAND);
+ startActivityForResult(intent, REQUEST_CODE_RUN);
+ }
+
+ public void onAppendHelloWorld(View view) {
+ if (lastSessionId == null) {
+ Toast.makeText(this, "Please run at least once",
+ Toast.LENGTH_SHORT).show();
+ }
+
+ Intent intent = Bridge.createExecuteIntent(lastSessionId, COMMAND);
+ startActivityForResult(intent, REQUEST_CODE_APPEND);
+ }
+
+ public void onAppendHelloWorldSilently(View view) {
+ if (lastSessionId == null) {
+ Toast.makeText(this, "Please run at least once",
+ Toast.LENGTH_SHORT).show();
+ }
+ Intent intent = Bridge.createExecuteIntent(lastSessionId, COMMAND, false);
+ startActivityForResult(intent, REQUEST_CODE_APPEND_SILENTLY);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != RESULT_OK) {
+ Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ switch (requestCode) {
+ case REQUEST_CODE_RUN:
+ lastSessionId = Bridge.parseResult(data);
+ break;
+ case REQUEST_CODE_APPEND:
+ Toast.makeText(this, "appended to " + lastSessionId.toString(), Toast.LENGTH_SHORT).show();
+ break;
+ case REQUEST_CODE_APPEND_SILENTLY:
+ Toast.makeText(this, "appended silently to " + lastSessionId.toString(), Toast.LENGTH_SHORT).show();
+ break;
+ }
+ }
+}
diff --git a/NeoTermBridgeExample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/NeoTermBridgeExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NeoTermBridgeExample/src/main/res/drawable/ic_launcher_background.xml b/NeoTermBridgeExample/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NeoTermBridgeExample/src/main/res/layout/activity_main.xml b/NeoTermBridgeExample/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..36c067f
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher.png b/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher.png b/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher.png b/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/NeoTermBridgeExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/NeoTermBridgeExample/src/main/res/values/colors.xml b/NeoTermBridgeExample/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/NeoTermBridgeExample/src/main/res/values/strings.xml b/NeoTermBridgeExample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..1563576
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ NeoTermBridgeExample
+
diff --git a/NeoTermBridgeExample/src/main/res/values/styles.xml b/NeoTermBridgeExample/src/main/res/values/styles.xml
new file mode 100644
index 0000000..9785e0c
--- /dev/null
+++ b/NeoTermBridgeExample/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/NeoTermBridgeExample/src/test/java/io/neoterm/bridge/example/ExampleUnitTest.java b/NeoTermBridgeExample/src/test/java/io/neoterm/bridge/example/ExampleUnitTest.java
new file mode 100644
index 0000000..4a3fc4b
--- /dev/null
+++ b/NeoTermBridgeExample/src/test/java/io/neoterm/bridge/example/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package io.neoterm.bridge.example;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 1953666..0817575 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,8 +9,8 @@ android {
applicationId "io.neoterm"
minSdkVersion rootProject.ext.android.MIN_SDK_VERSION
targetSdkVersion rootProject.ext.android.TARGET_SDK_VERSION
- versionCode 36
- versionName "2.0.3"
+ versionCode 37
+ versionName "2.1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resConfigs "zh-rCN", "zh-rTW"
externalNativeBuild {
@@ -74,6 +74,7 @@ dependencies {
implementation 'com.github.GrenderG:Color-O-Matic:1.1.5'
implementation project(':chrome-tabs')
- implementation project(path: ':NeoLang')
+ implementation project(':NeoLang')
+ implementation project(':NeoTermBridge')
implementation project(':Xorg')
}
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt b/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt
index 11798ee..76cabef 100644
--- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt
@@ -1,12 +1,13 @@
package io.neoterm.frontend.session.shell
import io.neoterm.backend.TerminalSession
+import io.neoterm.bridge.SessionId
/**
* @author kiva
*/
class ShellParameter {
- var sessionId: String? = null;
+ var sessionId: SessionId? = null
var executablePath: String? = null
var arguments: Array? = null
var cwd: String? = null
@@ -56,12 +57,12 @@ class ShellParameter {
return this
}
- fun session(sessionId: String?): ShellParameter {
+ fun session(sessionId: SessionId?): ShellParameter {
this.sessionId = sessionId
return this
}
fun willCreateNewSession(): Boolean {
- return sessionId == null
+ return sessionId?.equals(SessionId.NEW_SESSION) ?: true
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/services/NeoTermService.kt b/app/src/main/java/io/neoterm/services/NeoTermService.kt
index 2e74a55..a8a519c 100644
--- a/app/src/main/java/io/neoterm/services/NeoTermService.kt
+++ b/app/src/main/java/io/neoterm/services/NeoTermService.kt
@@ -13,6 +13,7 @@ import android.support.v4.app.NotificationCompat
import io.neoterm.R
import io.neoterm.backend.EmulatorDebug
import io.neoterm.backend.TerminalSession
+import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.session.shell.ShellParameter
import io.neoterm.frontend.session.xorg.XParameter
import io.neoterm.frontend.session.xorg.XSession
@@ -109,14 +110,16 @@ class NeoTermService : Service() {
private fun createOrFindSession(parameter: ShellParameter): TerminalSession {
if (parameter.willCreateNewSession()) {
+ NLog.d("createOrFindSession: creating new session")
val session = TerminalUtils.createSession(this, parameter)
mTerminalSessions.add(session)
return session
}
- // TODO: find session by id
val sessionId = parameter.sessionId!!
- val session = mTerminalSessions.find { it.mHandle == sessionId }
+ NLog.d("createOrFindSession: find session by id $sessionId")
+
+ val session = mTerminalSessions.find { it.mHandle == sessionId.sessionId }
?: throw IllegalArgumentException("cannot find session by given id")
session.write(parameter.initialCommand + "\n")
diff --git a/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
index e53c78f..0a9dcf0 100644
--- a/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
+++ b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
@@ -13,6 +13,8 @@ import android.widget.ArrayAdapter
import android.widget.ListView
import io.neoterm.App
import io.neoterm.R
+import io.neoterm.bridge.Bridge.*
+import io.neoterm.bridge.SessionId
import io.neoterm.component.userscript.UserScript
import io.neoterm.component.userscript.UserScriptComponent
import io.neoterm.frontend.component.ComponentManager
@@ -24,7 +26,6 @@ import io.neoterm.utils.MediaUtils
import io.neoterm.utils.TerminalUtils
import java.io.File
-
/**
* @author kiva
*/
@@ -80,17 +81,15 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
when (intent.action) {
ACTION_EXECUTE -> {
if (!intent.hasExtra(EXTRA_COMMAND)) {
- App.get().errorDialog(this, R.string.no_command_extra, { finish() })
+ App.get().errorDialog(this, R.string.no_command_extra)
+ { finish() }
return
}
val command = intent.getStringExtra(EXTRA_COMMAND)
val foreground = intent.getBooleanExtra(EXTRA_FOREGROUND, true)
- val session = if (intent.hasExtra(EXTRA_SESSION_ID)) {
- intent.getStringExtra(EXTRA_SESSION_ID)
- } else {
- null
- }
- openTerm(command, session, foreground)
+ val session = intent.getStringExtra(EXTRA_SESSION_ID)
+
+ openTerm(command, SessionId.of(session), foreground)
}
else -> openTerm(null, null)
@@ -199,6 +198,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
foreground: Boolean = true) {
val session = termService!!.createTermSession(parameter)
+ val data = Intent()
+ data.putExtra(EXTRA_SESSION_ID, session.mHandle)
+ setResult(Activity.RESULT_OK, data)
+
if (foreground) {
// Set current session to our new one
// In order to switch to it when entering NeoTermActivity
@@ -209,14 +212,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
-
- val data = Intent()
- data.putExtra(EXTRA_SESSION_ID, session.mHandle)
- setResult(Activity.RESULT_OK, data)
}
private fun openTerm(initialCommand: String?,
- sessionId: String? = null,
+ sessionId: SessionId? = null,
foreground: Boolean = true) {
val parameter = ShellParameter()
.initialCommand(initialCommand)
@@ -239,11 +238,4 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
private fun detectSystemShell(): Boolean {
return false
}
-
- companion object {
- const val ACTION_EXECUTE = "neoterm.action.remote.execute"
- const val EXTRA_COMMAND = "neoterm.extra.remote.execute.command"
- const val EXTRA_SESSION_ID = "neoterm.extra.remote.execute.session"
- const val EXTRA_FOREGROUND = "neoterm.extra.remote.execute.foreground"
- }
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 1f92e49..4f7b250 100644
--- a/build.gradle
+++ b/build.gradle
@@ -57,6 +57,9 @@ buildscript {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath rootProject.ext.deps["kotlin-gradle-plugin"]
+ classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
+ classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
+
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
diff --git a/settings.gradle b/settings.gradle
index 2a1adde..ec85a91 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':app', ':chrome-tabs', ':NeoLang', ':Xorg'
+include ':app', ':chrome-tabs', ':NeoLang', ':Xorg', ':NeoTermBridge', ':NeoTermBridgeExample'