├── .gitattributes ├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml └── vcs.xml ├── LICENSE ├── MODULE_LICENSE_APACHE2 ├── NOTICE ├── README.md ├── artwork ├── Feature Graphic.xcf ├── android-terminal-emulator-512.png └── android-terminal-emulator.svg ├── build.gradle ├── docs ├── Building.md ├── UTF-8-SMP-chars-demo.txt ├── UTF-8-demo.txt ├── atari_small_notice.txt ├── notification icon source.png └── releaseChecklist.md ├── emulatorview ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── jackpal │ │ └── androidterm │ │ └── emulatorview │ │ ├── BaseTextRenderer.java │ │ ├── Bitmap4x8FontRenderer.java │ │ ├── ByteQueue.java │ │ ├── ColorScheme.java │ │ ├── EmulatorDebug.java │ │ ├── EmulatorView.java │ │ ├── GrowableIntArray.java │ │ ├── PaintRenderer.java │ │ ├── Screen.java │ │ ├── StyleRow.java │ │ ├── TermKeyListener.java │ │ ├── TermSession.java │ │ ├── TerminalEmulator.java │ │ ├── TextRenderer.java │ │ ├── TextStyle.java │ │ ├── TranscriptScreen.java │ │ ├── UnicodeTranscript.java │ │ ├── UpdateCallback.java │ │ ├── compat │ │ ├── AndroidCharacterCompat.java │ │ ├── AndroidCompat.java │ │ ├── ClipboardManagerCompat.java │ │ ├── ClipboardManagerCompatFactory.java │ │ ├── ClipboardManagerCompatV1.java │ │ ├── ClipboardManagerCompatV11.java │ │ ├── KeyCharacterMapCompat.java │ │ ├── KeycodeConstants.java │ │ └── Patterns.java │ │ └── package.html │ └── res │ ├── drawable-nodpi │ └── atari_small_nodpi.png │ └── drawable │ └── atari_small.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libtermexec ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── jackpal │ │ └── androidterm │ │ └── libtermexec │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── aidl │ └── jackpal │ │ └── androidterm │ │ └── libtermexec │ │ └── v1 │ │ └── ITerminal.aidl │ ├── java │ └── jackpal │ │ └── androidterm │ │ └── TermExec.java │ └── jni │ ├── process.cpp │ └── process.h ├── samples ├── intents │ ├── .gitignore │ ├── build.gradle │ ├── lint.xml │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── jackpal │ │ │ └── androidterm │ │ │ └── sample │ │ │ └── intents │ │ │ └── IntentSampleActivity.java │ │ └── res │ │ ├── layout │ │ └── main.xml │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-ko │ │ └── strings.xml │ │ └── values │ │ └── strings.xml ├── pathbroadcasts │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ ├── hello │ │ └── ls │ │ ├── java │ │ └── jackpal │ │ │ └── androidterm │ │ │ └── sample │ │ │ └── pathbroadcasts │ │ │ └── PathReceiver.java │ │ └── res │ │ └── values │ │ └── strings.xml └── telnet │ ├── .gitignore │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── jackpal │ │ └── androidterm │ │ └── sample │ │ └── telnet │ │ ├── LaunchActivity.java │ │ ├── TelnetSession.java │ │ └── TermActivity.java │ └── res │ ├── layout │ ├── launch_activity.xml │ └── term_activity.xml │ ├── values-ko │ └── strings.xml │ └── values │ └── strings.xml ├── settings.gradle ├── term ├── .gitignore ├── build.gradle ├── lint.xml └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── jackpal │ │ └── androidterm │ │ ├── BoundSession.java │ │ ├── Exec.java │ │ ├── GenericTermSession.java │ │ ├── RemoteInterface.java │ │ ├── RunScript.java │ │ ├── RunShortcut.java │ │ ├── ShellTermSession.java │ │ ├── Term.java │ │ ├── TermDebug.java │ │ ├── TermPreferences.java │ │ ├── TermService.java │ │ ├── TermView.java │ │ ├── TermViewFlipper.java │ │ ├── WindowList.java │ │ ├── WindowListAdapter.java │ │ ├── compat │ │ ├── ActionBarCompat.java │ │ ├── ActivityCompat.java │ │ ├── AlertDialogCompat.java │ │ ├── AndroidCompat.java │ │ ├── Base64.java │ │ ├── FileCompat.java │ │ ├── MenuItemCompat.java │ │ ├── PRNGFixes.java │ │ └── ServiceForegroundCompat.java │ │ ├── shortcuts │ │ ├── AddShortcut.java │ │ ├── ColorValue.java │ │ ├── FSNavigator.java │ │ └── TextIcon.java │ │ └── util │ │ ├── SessionList.java │ │ ├── ShortcutEncryption.java │ │ └── TermSettings.java │ ├── jni │ ├── common.cpp │ ├── common.h │ ├── fileCompat.cpp │ ├── fileCompat.h │ ├── termExec.cpp │ └── termExec.h │ └── res │ ├── drawable-hdpi-v11 │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-hdpi-v9 │ └── ic_stat_service_notification_icon.png │ ├── drawable-hdpi │ ├── btn_close_window.png │ ├── ic_launcher.png │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ ├── ic_menu_windows.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-ldpi-v11 │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-ldpi-v9 │ └── ic_stat_service_notification_icon.png │ ├── drawable-ldpi │ ├── ic_launcher.png │ ├── ic_menu_add.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_preferences.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-mdpi-v11 │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-mdpi-v9 │ └── ic_stat_service_notification_icon.png │ ├── drawable-mdpi │ ├── btn_close_window.png │ ├── ic_launcher.png │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ ├── ic_menu_windows.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-xhdpi-v11 │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-xhdpi-v9 │ └── ic_stat_service_notification_icon.png │ ├── drawable-xhdpi │ ├── ic_launcher.png │ └── ic_stat_service_notification_icon.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_launcher.png │ ├── drawable │ ├── btn_close_window.png │ ├── close_background.xml │ ├── ic_folder.png │ ├── ic_folderup.png │ ├── ic_launcher.png │ ├── ic_menu_add.png │ ├── ic_menu_back.png │ ├── ic_menu_close_clear_cancel.png │ ├── ic_menu_forward.png │ ├── ic_menu_preferences.png │ ├── ic_menu_windows.png │ └── ic_stat_service_notification_icon.png │ ├── layout │ ├── term_activity.xml │ ├── window_list_item.xml │ └── window_list_new_window.xml │ ├── menu │ └── main.xml │ ├── values-cs │ ├── arrays.xml │ └── strings.xml │ ├── values-de │ ├── arrays.xml │ └── strings.xml │ ├── values-es │ ├── arrays.xml │ └── strings.xml │ ├── values-eu │ ├── arrays.xml │ └── strings.xml │ ├── values-fr │ ├── arrays.xml │ └── strings.xml │ ├── values-hu │ ├── arrays.xml │ └── strings.xml │ ├── values-it │ ├── arrays.xml │ └── strings.xml │ ├── values-iw │ ├── arrays.xml │ └── strings.xml │ ├── values-ja │ ├── arrays.xml │ └── strings.xml │ ├── values-ka │ ├── arrays.xml │ └── strings.xml │ ├── values-ko │ ├── arrays.xml │ └── strings.xml │ ├── values-nb │ ├── arrays.xml │ └── strings.xml │ ├── values-nl │ ├── arrays.xml │ └── strings.xml │ ├── values-pl │ ├── arrays.xml │ └── strings.xml │ ├── values-pt-rPT │ ├── arrays.xml │ └── strings.xml │ ├── values-pt │ ├── arrays.xml │ └── strings.xml │ ├── values-ro │ ├── arrays.xml │ └── strings.xml │ ├── values-ru │ ├── arrays.xml │ └── strings.xml │ ├── values-sk │ ├── arrays.xml │ └── strings.xml │ ├── values-sr │ ├── arrays.xml │ └── strings.xml │ ├── values-sv │ ├── arrays.xml │ └── strings.xml │ ├── values-tr │ ├── arrays.xml │ └── strings.xml │ ├── values-uk │ ├── arrays.xml │ └── strings.xml │ ├── values-v11 │ └── styles.xml │ ├── values-v21 │ ├── colors.xml │ └── styles.xml │ ├── values-zh-rCN │ ├── arrays.xml │ └── strings.xml │ ├── values-zh-rTW │ ├── arrays.xml │ └── strings.xml │ ├── values │ ├── arrays.xml │ ├── arraysNoLocalize.xml │ ├── attrs.xml │ ├── defaults.xml │ ├── id.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── preferences.xml ├── tests ├── controlSequences │ ├── 256color.txt │ ├── combiningCharReplacement.txt │ ├── combiningChars.txt │ ├── hideCursor.txt │ ├── setTitle.txt │ ├── showCursor.txt │ └── textStyle.txt ├── emulatorview-test │ ├── AndroidManifest.xml │ ├── ant.properties │ ├── proguard-project.txt │ ├── project.properties │ ├── res │ │ ├── drawable-hdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-ldpi │ │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ │ └── ic_launcher.png │ │ └── values │ │ │ └── strings.xml │ └── src │ │ └── jackpal │ │ └── androidterm │ │ └── emulatorview │ │ ├── InputConnectionTest.java │ │ ├── ModifierKeyTest.java │ │ └── TermKeyListenerTest.java ├── fullWidthText ├── issue145 │ ├── README.md │ ├── fuzzer.go │ ├── issue145repro-2.txt │ └── issue145repro.txt ├── issue149 │ └── colors.go └── wideChars │ ├── combining-chars.txt │ ├── last-column-wrapping.txt │ ├── linkification.txt │ ├── overwriting1.txt │ ├── overwriting2.txt │ ├── overwriting3.txt │ ├── overwriting4.txt │ ├── overwriting5.txt │ └── sip-chars.txt └── tools ├── build-debug ├── build-release ├── import-icons ├── increment-version-number ├── install-sdk-packages ├── push-and-run-debug ├── push-and-run-release ├── push-samples-debug └── sign-release-build /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize line endings for text files. 2 | # This only affects how files are stored within the repo. Git will 3 | # automatically convert line endings to the platform choice when checking out, 4 | # and automatically convert them back to the normal form when checking in. 5 | 6 | * text=auto 7 | 8 | # Ensure XML files are treated a text files. 9 | 10 | *.xml text 11 | 12 | # Use java diff syntax for java files. 13 | 14 | *.java diff=java 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | *.iml 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Android-Terminal-Emulator -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MODULE_LICENSE_APACHE2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/MODULE_LICENSE_APACHE2 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terminal Emulator for Android 2 | 3 | *Note:* Terminal Emulator for Android development has ended. I am not 4 | accepting pull requests any more. 5 | 6 | Terminal Emulator for Android is a terminal emulator for communicating with the 7 | built-in Android shell. It emulates a reasonably large subset of Digital 8 | Equipment Corporation VT-100 terminal codes, so that programs like "vi", "Emacs" 9 | and "NetHack" will display properly. 10 | 11 | This application was previously named "Android Terminal Emulator". Same great 12 | application, just with a new name. (The change was made at the request of the 13 | Android trademark owner.) 14 | 15 | This code is based on the "Term" application which is included in the Android 16 | Open Source Project. (Which I also wrote. :-) ) 17 | 18 | [Download the Terminal Emulator for Android from Google Play](https://play.google.com/store/apps/details?id=jackpal.androidterm) 19 | 20 | If you are unable to use the Play Store, you can also 21 | [download from GitHub](https://jackpal.github.io/Android-Terminal-Emulator/) 22 | 23 | See [Building](docs/Building.md) for build instructions. 24 | 25 | Got questions? Please check out the 26 | [FAQ](http://github.com/jackpal/Android-Terminal-Emulator/wiki/Frequently-Asked-Questions). Thanks! 27 | 28 | Please see the 29 | [Recent Updates](http://github.com/jackpal/Android-Terminal-Emulator/wiki/Recent-Updates) 30 | page for recent updates. 31 | -------------------------------------------------------------------------------- /artwork/Feature Graphic.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/artwork/Feature Graphic.xcf -------------------------------------------------------------------------------- /artwork/android-terminal-emulator-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/artwork/android-terminal-emulator-512.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | task wrapper (type:Wrapper) { 3 | gradleVersion = '2.2.1' 4 | distributionUrl = 'https://services.gradle.org/distributions/gradle-2.2.1-all.zip' 5 | } 6 | 7 | buildscript { 8 | repositories { 9 | jcenter() 10 | mavenCentral() 11 | } 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:1.0.0' 14 | classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0' 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | jcenter() 21 | } 22 | } 23 | 24 | subprojects { 25 | def androidHome 26 | 27 | if ((androidHome = System.env.'ANDROID_HOME') 28 | && (androidHome = androidHome as File).exists() 29 | && androidHome.canWrite()) 30 | apply plugin: 'android-sdk-manager' 31 | } -------------------------------------------------------------------------------- /docs/Building.md: -------------------------------------------------------------------------------- 1 | Building 2 | ======== 3 | 4 | To keep from typing "Terminal Emulator for Android" over and over again, this 5 | document will use the abbreviation "TEA" to stand for "Terminal 6 | Emulator for Android". 7 | 8 | 9 | Download the Software Needed to Build Terminal Emulator for Android 10 | ------------------------------------------------------------------- 11 | 12 | TEA is built using: 13 | 14 | + [Android Studio](http://developer.android.com/sdk) 1.0 or newer 15 | + [Android NDK](http://developer.android.com/tools/sdk/ndk/) r10d or newer 16 | 17 | 18 | Telling Gradle where to find the Android NDK and SDK 19 | ---------------------------------------------------- 20 | 21 | Android Studio and the gradle build tool need to know where to find the NDK and 22 | SDK on your computer. 23 | 24 | Create a file local.properties in the root directiory of the TEA project that 25 | contains this text: 26 | 27 | ndk.dir=path/to/ndk 28 | sdk.dir=path/to/sdk 29 | 30 | On my personal dev machine the file looks like this, but of course it will 31 | be different on your machine, depending upon your OS, user name, directory 32 | tree, and version of the NDK that you have installed. 33 | 34 | ndk.dir=/Users/jack/code/android-ndk-r10d 35 | sdk.dir=/Users/jack/Library/Android/sdk 36 | 37 | In addition, if you are building from the command line, the scripts in the 38 | "tools" directory expect the environment variable ANDROID_SDK_ROOT to be 39 | defined. 40 | 41 | On my personal dev machine I have this line in my .profile: 42 | 43 | export ANDROID_SDK_ROOT=/Users/jack/Library/Android/sdk 44 | 45 | Installing required SDK Packages 46 | -------------------------------- 47 | 48 | In order to build, in addition to a current SDK version, 49 | TEA requires the Android 3.0 (API 11) version of the Android SDK 50 | to be installed. 51 | 52 | You can install it by running the following command-line script: 53 | 54 | tools/install-sdk-packages 55 | 56 | Or you can run Android Studio and choose Configure > SDK Manager, then 57 | choose the "Android 3.0 (API 11) > SDK Platform" package. 58 | 59 | Building TEA 60 | ------------ 61 | 62 | You can build TEA two ways: 63 | 64 | 1. Using the Android Studio IDE 65 | 2. Using the "gradlew" command line tool 66 | 67 | Using Android Studio is convenient for development. Using "gradlew" is 68 | convenient for automated testing and publishing. 69 | 70 | 71 | Building TEA with Android Studio 72 | -------------------------------- 73 | 74 | 1. Open Android Studio 75 | 2. Choose "Open an existing Android Studio project" from the "Quick Start" 76 | wizard. 77 | 3. Choose the top-level TEA directory. (If you installed the source code from 78 | github, this directory will be named Android-Terminal-Emulator). 79 | 4. Use the Android Studio menu "Run : Run 'term'" to build and run the app. 80 | 81 | 82 | Building TEA from the command line 83 | ---------------------------------- 84 | 85 | 0. Make sure a file local.properties exists at the root of the TEA source 86 | tree. Android Studio will create this file automaticaly. If you don't 87 | want to run Android Studio, you can create this file manually with the 88 | paths of your local sdk and ndk installations. For my machine that's: 89 | 90 | sdk.dir=/Users/jack/Library/Android/sdk 91 | ndk.dir=/Users/jack/code/android-ndk-r10d 92 | 93 | 1. Open a command line shell window and navigate to the main TEA directory. 94 | 95 | 2. Build 96 | 97 | $ ./tools/build-debug 98 | 99 | 3. Copy the built executable to a device: 100 | 101 | $ ./tools/push-and-run-debug 102 | -------------------------------------------------------------------------------- /docs/UTF-8-SMP-chars-demo.txt: -------------------------------------------------------------------------------- 1 | These are some characters in the Supplementary Multilingual Plane: 2 | 𝄞 𝄴𝅘𝅥𝅯𝅗𝅥 𝑥𝄽 3 | -------------------------------------------------------------------------------- /docs/atari_small_notice.txt: -------------------------------------------------------------------------------- 1 | COMMENT Copyright (c) 1999, Thomas A. Fine 2 | COMMENT 3 | COMMENT License to copy, modify, and distribute for both commercial and 4 | COMMENT non-commercial use is herby granted, provided this notice 5 | COMMENT is preserved. 6 | COMMENT 7 | COMMENT Email to my last name at head.cfa.harvard.edu 8 | COMMENT http://hea-www.harvard.edu/~fine/ 9 | COMMENT 10 | COMMENT Produced with bdfedit, a tcl/tk font editing program 11 | COMMENT written by Thomas A. Fine -------------------------------------------------------------------------------- /docs/notification icon source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/docs/notification icon source.png -------------------------------------------------------------------------------- /docs/releaseChecklist.md: -------------------------------------------------------------------------------- 1 | ## Terminal Emulator for Android Release Checklist 2 | 3 | # Test on 1.6 Donut API 4 4 | 5 | (Lowest supported level -- will be dropped soon.) 6 | 7 | # Test on 2.1 Eclair API 7 8 | 9 | # Test on 2.2 Froyo API 8 10 | 11 | # Test on 2.3 Gingerbread API 10 12 | 13 | (Still popular with cheap phones.) 14 | 15 | # Test on 4.3 Jelly Bean API 18 16 | 17 | # Test on 4.4 Kit Kat API 19 18 | 19 | # Test on 5.1 Lollipop API 22 20 | 21 | (Or whatever latest is.) 22 | 23 | # Test with Swype 24 | 25 | (Has to be on a real device, Swype beta won't run on an emulator.) 26 | 27 | # Update ./term/src/main/AndroidManifest.xml version number 28 | 29 | tools/increment-version-number 30 | 31 | # Commit changes 32 | 33 | git commit -a -m "Increment version number to v1.0.xx" 34 | 35 | # Tag git branch with version number 36 | 37 | git tag v1.0.xx 38 | 39 | # Push git to repository 40 | 41 | git push 42 | git push --tags 43 | 44 | # Build release apk 45 | 46 | tools/build-release 47 | 48 | (Will only work if you have the signing keys for the app.) 49 | 50 | # Publish to the Google Play Store 51 | 52 | open https://play.google.com/apps/publish 53 | 54 | The Android Developer Console Publishing UI is error prone: 55 | 56 | 1) Click on the "Terminal Emulator for Android" link. 57 | 58 | 2) Click on the APK files tab 59 | 60 | 3) Upload your new APK. 61 | 62 | 4) Activate it by clicking on the Activate link 63 | 64 | 5) Click on the "Save" button. 65 | 66 | 6) Click on the "Product Details button". 67 | 68 | 7) Fill in the "Listing Details" for the new version. 69 | 70 | 8) Click on the "Save" button 71 | 72 | 9) Visit https://play.google.com/apps/publish and verify that the new version is listed as the current version. 73 | 74 | 10) Verify that Google Play Store is serving the new version 75 | (check the "What's New" portion.) 76 | 77 | https://play.google.com/store/apps/details?id=jackpal.androidterm 78 | 79 | (Note, it can take several hours for the app to appear in the store.) 80 | 81 | # Update the Terminal Emulator for Android Wiki 82 | 83 | open https://github.com/jackpal/Android-Terminal-Emulator/wiki/Recent-Updates 84 | 85 | # Publish a new pre-compiled version of the APK for people who can't access Market. 86 | 87 | Github serves pages out of branch gh-pages , directory downloads/Term.apk 88 | Also update the version number in index.html 89 | 90 | cp ./term/build/outputs/apk/Term.apk /tmp 91 | git checkout gh-pages 92 | mv /tmp/Term.apk downloads/Term.apk 93 | git add downloads/Term.apk 94 | subl index.html 95 | # Update version save index.html 96 | git add index.html 97 | git commit -m "Update to version v1.0.xx" 98 | git push 99 | git checkout master 100 | 101 | Public URL is http://jackpal.github.com/Android-Terminal-Emulator/downloads/Term.apk 102 | 103 | 104 | -------------------------------------------------------------------------------- /emulatorview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /emulatorview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 4 9 | targetSdkVersion 22 10 | } 11 | 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /emulatorview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/EmulatorDebug.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jackpal.androidterm.emulatorview; 18 | 19 | /** 20 | * Debug settings. 21 | */ 22 | 23 | class EmulatorDebug { 24 | /** 25 | * Set to true to add debugging code and logging. 26 | */ 27 | public static final boolean DEBUG = false; 28 | 29 | /** 30 | * Set to true to log IME calls. 31 | */ 32 | public static final boolean LOG_IME = DEBUG & false; 33 | 34 | /** 35 | * Set to true to log each character received from the remote process to the 36 | * android log, which makes it easier to debug some kinds of problems with 37 | * emulating escape sequences and control codes. 38 | */ 39 | public static final boolean LOG_CHARACTERS_FLAG = DEBUG & false; 40 | 41 | /** 42 | * Set to true to log unknown escape sequences. 43 | */ 44 | public static final boolean LOG_UNKNOWN_ESCAPE_SEQUENCES = DEBUG & false; 45 | 46 | /** 47 | * The tag we use when logging, so that our messages can be distinguished 48 | * from other messages in the log. Public because it's used by several 49 | * classes. 50 | */ 51 | public static final String LOG_TAG = "EmulatorView"; 52 | 53 | public static String bytesToString(byte[] data, int base, int length) { 54 | StringBuilder buf = new StringBuilder(); 55 | for (int i = 0; i < length; i++) { 56 | byte b = data[base + i]; 57 | if (b < 32 || b > 126) { 58 | buf.append(String.format("\\x%02x", b)); 59 | } else { 60 | buf.append((char)b); 61 | } 62 | } 63 | return buf.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/GrowableIntArray.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview; 2 | 3 | class GrowableIntArray { 4 | GrowableIntArray(int initalCapacity) { 5 | mData = new int[initalCapacity]; 6 | mLength = 0; 7 | } 8 | 9 | void append(int i) { 10 | if (mLength + 1 > mData.length) { 11 | int newLength = Math.max((mData.length * 3) >> 1, 16); 12 | int[] temp = new int[newLength]; 13 | System.arraycopy(mData, 0, temp, 0, mLength); 14 | mData = temp; 15 | } 16 | mData[mLength++] = i; 17 | } 18 | 19 | int length() { 20 | return mLength; 21 | } 22 | 23 | int at(int index) { 24 | return mData[index]; 25 | } 26 | 27 | int[] mData; 28 | int mLength; 29 | } 30 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/StyleRow.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview; 2 | 3 | /** 4 | * Utility class for dealing with text style lines. 5 | * 6 | * We pack color and formatting information for a particular character into an 7 | * int -- see the TextStyle class for details. The simplest way of storing 8 | * that information for a screen row would be to use an array of int -- but 9 | * given that we only use the lower three bytes of the int to store information, 10 | * that effectively wastes one byte per character -- nearly 8 KB per 100 lines 11 | * with an 80-column transcript. 12 | * 13 | * Instead, we use an array of bytes and store the bytes of each int 14 | * consecutively in big-endian order. 15 | */ 16 | final class StyleRow { 17 | private int mStyle; 18 | private int mColumns; 19 | /** Initially null, will be allocated when needed. */ 20 | private byte[] mData; 21 | 22 | StyleRow(int style, int columns) { 23 | mStyle = style; 24 | mColumns = columns; 25 | } 26 | 27 | void set(int column, int style) { 28 | if (style == mStyle && mData == null) { 29 | return; 30 | } 31 | ensureData(); 32 | setStyle(column, style); 33 | } 34 | 35 | int get(int column) { 36 | if (mData == null) { 37 | return mStyle; 38 | } 39 | return getStyle(column); 40 | } 41 | 42 | boolean isSolidStyle() { 43 | return mData == null; 44 | } 45 | 46 | int getSolidStyle() { 47 | if (mData != null) { 48 | throw new IllegalArgumentException("Not a solid style"); 49 | } 50 | return mStyle; 51 | } 52 | 53 | void copy(int start, StyleRow dst, int offset, int len) { 54 | // fast case 55 | if (mData == null && dst.mData == null && start == 0 && offset == 0 56 | && len == mColumns) { 57 | dst.mStyle = mStyle; 58 | return; 59 | } 60 | // There are other potentially fast cases, but let's just treat them 61 | // all the same for simplicity. 62 | ensureData(); 63 | dst.ensureData(); 64 | System.arraycopy(mData, 3*start, dst.mData, 3*offset, 3*len); 65 | 66 | } 67 | 68 | void ensureData() { 69 | if (mData == null) { 70 | allocate(); 71 | } 72 | } 73 | 74 | private void allocate() { 75 | mData = new byte[3*mColumns]; 76 | for (int i = 0; i < mColumns; i++) { 77 | setStyle(i, mStyle); 78 | } 79 | } 80 | 81 | private int getStyle(int column) { 82 | int index = 3 * column; 83 | byte[] line = mData; 84 | return line[index] & 0xff | (line[index+1] & 0xff) << 8 85 | | (line[index+2] & 0xff) << 16; 86 | } 87 | 88 | private void setStyle(int column, int value) { 89 | int index = 3 * column; 90 | byte[] line = mData; 91 | line[index] = (byte) (value & 0xff); 92 | line[index+1] = (byte) ((value >> 8) & 0xff); 93 | line[index+2] = (byte) ((value >> 16) & 0xff); 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/TextRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jackpal.androidterm.emulatorview; 18 | 19 | import android.graphics.Canvas; 20 | 21 | /** 22 | * Text renderer interface 23 | */ 24 | 25 | interface TextRenderer { 26 | public static final int MODE_OFF = 0; 27 | public static final int MODE_ON = 1; 28 | public static final int MODE_LOCKED = 2; 29 | public static final int MODE_MASK = 3; 30 | 31 | public static final int MODE_SHIFT_SHIFT = 0; 32 | public static final int MODE_ALT_SHIFT = 2; 33 | public static final int MODE_CTRL_SHIFT = 4; 34 | public static final int MODE_FN_SHIFT = 6; 35 | 36 | void setReverseVideo(boolean reverseVideo); 37 | float getCharacterWidth(); 38 | int getCharacterHeight(); 39 | /** @return pixels above top row of text to avoid looking cramped. */ 40 | int getTopMargin(); 41 | /** 42 | * Draw a run of text 43 | * @param canvas The canvas to draw into. 44 | * @param x Canvas coordinate of the left edge of the whole line. 45 | * @param y Canvas coordinate of the bottom edge of the whole line. 46 | * @param lineOffset The screen character offset of this text run (0..length of line) 47 | * @param runWidth 48 | * @param text 49 | * @param index 50 | * @param count 51 | * @param selectionStyle True to draw the text using the "selected" style (for clipboard copy) 52 | * @param textStyle 53 | * @param cursorOffset The screen character offset of the cursor (or -1 if not on this line.) 54 | * @param cursorIndex The index of the cursor in text chars. 55 | * @param cursorIncr The width of the cursor in text chars. (1 or 2) 56 | * @param cursorWidth The width of the cursor in screen columns (1 or 2) 57 | * @param cursorMode The cursor mode (used to show state of shift/control/alt/fn locks. 58 | */ 59 | void drawTextRun(Canvas canvas, float x, float y, 60 | int lineOffset, int runWidth, char[] text, 61 | int index, int count, boolean selectionStyle, int textStyle, 62 | int cursorOffset, int cursorIndex, int cursorIncr, int cursorWidth, int cursorMode); 63 | } 64 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/TextStyle.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview; 2 | 3 | final class TextStyle { 4 | // Effect bitmasks: 5 | final static int fxNormal = 0; 6 | final static int fxBold = 1; // Originally Bright 7 | //final static int fxFaint = 2; 8 | final static int fxItalic = 1 << 1; 9 | final static int fxUnderline = 1 << 2; 10 | final static int fxBlink = 1 << 3; 11 | final static int fxInverse = 1 << 4; 12 | final static int fxInvisible = 1 << 5; 13 | 14 | // Special color indices 15 | final static int ciForeground = 256; // VT100 text foreground color 16 | final static int ciBackground = 257; // VT100 text background color 17 | final static int ciCursorForeground = 258; // VT100 text cursor foreground color 18 | final static int ciCursorBackground = 259; // VT100 text cursor background color 19 | 20 | final static int ciColorLength = ciCursorBackground + 1; 21 | 22 | final static int kNormalTextStyle = encode(ciForeground, ciBackground, fxNormal); 23 | 24 | static int encode(int foreColor, int backColor, int effect) { 25 | return ((effect & 0x3f) << 18) | ((foreColor & 0x1ff) << 9) | (backColor & 0x1ff); 26 | } 27 | 28 | static int decodeForeColor(int encodedColor) { 29 | return (encodedColor >> 9) & 0x1ff; 30 | } 31 | 32 | static int decodeBackColor(int encodedColor) { 33 | return encodedColor & 0x1ff; 34 | } 35 | 36 | static int decodeEffect(int encodedColor) { 37 | return (encodedColor >> 18) & 0x3f; 38 | } 39 | 40 | private TextStyle() { 41 | // Prevent instantiation 42 | throw new UnsupportedOperationException(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/UpdateCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jackpal.androidterm.emulatorview; 18 | 19 | /** 20 | * Generic callback to be invoked to notify of updates. 21 | */ 22 | public interface UpdateCallback { 23 | /** 24 | * Callback function to be invoked when an update happens. 25 | */ 26 | void onUpdate(); 27 | } 28 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/AndroidCharacterCompat.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | import android.text.AndroidCharacter; 4 | 5 | /** 6 | * Definitions related to android.text.AndroidCharacter 7 | */ 8 | public class AndroidCharacterCompat { 9 | public static final int EAST_ASIAN_WIDTH_NEUTRAL = 0; 10 | public static final int EAST_ASIAN_WIDTH_AMBIGUOUS = 1; 11 | public static final int EAST_ASIAN_WIDTH_HALF_WIDTH = 2; 12 | public static final int EAST_ASIAN_WIDTH_FULL_WIDTH = 3; 13 | public static final int EAST_ASIAN_WIDTH_NARROW = 4; 14 | public static final int EAST_ASIAN_WIDTH_WIDE = 5; 15 | 16 | private static class Api8OrLater { 17 | public static int getEastAsianWidth(char c) { 18 | return AndroidCharacter.getEastAsianWidth(c); 19 | } 20 | } 21 | 22 | public static int getEastAsianWidth(char c) { 23 | if (AndroidCompat.SDK >= 8) { 24 | return Api8OrLater.getEastAsianWidth(c); 25 | } else { 26 | return EAST_ASIAN_WIDTH_NARROW; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/AndroidCompat.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | /** 4 | * The classes in this package take advantage of the fact that the VM does 5 | * not attempt to load a class until it's accessed, and the verifier 6 | * does not run until a class is loaded. By keeping the methods which 7 | * are unavailable on older platforms in subclasses which are only ever 8 | * accessed on platforms where they are available, we can preserve 9 | * compatibility with older platforms without resorting to reflection. 10 | * 11 | * See http://developer.android.com/resources/articles/backward-compatibility.html 12 | * and http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html 13 | * for further discussion of this technique. 14 | */ 15 | 16 | public class AndroidCompat { 17 | public final static int SDK = getSDK(); 18 | 19 | private final static int getSDK() { 20 | int result; 21 | try { 22 | result = AndroidLevel4PlusCompat.getSDKInt(); 23 | } catch (VerifyError e) { 24 | // We must be at an SDK level less than 4. 25 | try { 26 | result = Integer.valueOf(android.os.Build.VERSION.SDK); 27 | } catch (NumberFormatException e2) { 28 | // Couldn't parse string, assume the worst. 29 | result = 1; 30 | } 31 | } 32 | return result; 33 | } 34 | } 35 | 36 | class AndroidLevel4PlusCompat { 37 | static int getSDKInt() { 38 | return android.os.Build.VERSION.SDK_INT; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/ClipboardManagerCompat.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | public interface ClipboardManagerCompat { 4 | CharSequence getText(); 5 | 6 | boolean hasText(); 7 | 8 | void setText(CharSequence text); 9 | } 10 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/ClipboardManagerCompatFactory.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | import android.content.Context; 4 | 5 | public class ClipboardManagerCompatFactory { 6 | 7 | private ClipboardManagerCompatFactory() { 8 | /* singleton */ 9 | } 10 | 11 | public static ClipboardManagerCompat getManager(Context context) { 12 | if (AndroidCompat.SDK < 11) { 13 | return new ClipboardManagerCompatV1(context); 14 | } else { 15 | return new ClipboardManagerCompatV11(context); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/ClipboardManagerCompatV1.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | import android.content.Context; 4 | import android.text.ClipboardManager; 5 | 6 | @SuppressWarnings("deprecation") 7 | public class ClipboardManagerCompatV1 implements ClipboardManagerCompat { 8 | private final ClipboardManager clip; 9 | 10 | public ClipboardManagerCompatV1(Context context) { 11 | clip = (ClipboardManager) context.getApplicationContext() 12 | .getSystemService(Context.CLIPBOARD_SERVICE); 13 | } 14 | 15 | @Override 16 | public CharSequence getText() { 17 | return clip.getText(); 18 | } 19 | 20 | @Override 21 | public boolean hasText() { 22 | return clip.hasText(); 23 | } 24 | 25 | @Override 26 | public void setText(CharSequence text) { 27 | clip.setText(text); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/ClipboardManagerCompatV11.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.emulatorview.compat; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.ClipData; 5 | import android.content.ClipDescription; 6 | import android.content.Context; 7 | import android.content.ClipboardManager; 8 | 9 | @SuppressLint("NewApi") 10 | public class ClipboardManagerCompatV11 implements ClipboardManagerCompat { 11 | private final ClipboardManager clip; 12 | 13 | public ClipboardManagerCompatV11(Context context) { 14 | clip = (ClipboardManager) context.getApplicationContext() 15 | .getSystemService(Context.CLIPBOARD_SERVICE); 16 | } 17 | 18 | @Override 19 | public CharSequence getText() { 20 | ClipData.Item item = clip.getPrimaryClip().getItemAt(0); 21 | return item.getText(); 22 | } 23 | 24 | @Override 25 | public boolean hasText() { 26 | return (clip.hasPrimaryClip() && clip.getPrimaryClipDescription() 27 | .hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)); 28 | } 29 | 30 | @Override 31 | public void setText(CharSequence text) { 32 | ClipData clipData = ClipData.newPlainText("simple text", text); 33 | clip.setPrimaryClip(clipData); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/KeyCharacterMapCompat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Jack Palevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jackpal.androidterm.emulatorview.compat; 18 | 19 | import android.view.KeyCharacterMap; 20 | 21 | public abstract class KeyCharacterMapCompat { 22 | public static final int MODIFIER_BEHAVIOR_CHORDED = 0; 23 | public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1; 24 | 25 | public static KeyCharacterMapCompat wrap(Object map) { 26 | if (map != null) { 27 | if (AndroidCompat.SDK >= 11) { 28 | return new KeyCharacterMapApi11OrLater(map); 29 | } 30 | } 31 | return null; 32 | } 33 | 34 | private static class KeyCharacterMapApi11OrLater 35 | extends KeyCharacterMapCompat { 36 | private KeyCharacterMap mMap; 37 | public KeyCharacterMapApi11OrLater(Object map) { 38 | mMap = (KeyCharacterMap) map; 39 | } 40 | public int getModifierBehaviour() { 41 | return mMap.getModifierBehavior(); 42 | } 43 | } 44 | 45 | public abstract int getModifierBehaviour(); 46 | } 47 | -------------------------------------------------------------------------------- /emulatorview/src/main/java/jackpal/androidterm/emulatorview/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

This package provides a fairly complete VT100 terminal emulator {@link 4 | jackpal.androidterm.emulatorview.TermSession TermSession} and a corresponding 5 | Android view {@link jackpal.androidterm.emulatorview.EmulatorView EmulatorView}. 6 | 7 |

Most users will create a TermSession, connect it to an {@link 8 | java.io.InputStream InputStream} and {@link java.io.OutputStream OutputStream} 9 | from the emulation client, then instantiate the EmulatorView and 10 | add it to an activity's layout. 11 | 12 | 13 | -------------------------------------------------------------------------------- /emulatorview/src/main/res/drawable-nodpi/atari_small_nodpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/emulatorview/src/main/res/drawable-nodpi/atari_small_nodpi.png -------------------------------------------------------------------------------- /emulatorview/src/main/res/drawable/atari_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/emulatorview/src/main/res/drawable/atari_small.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackpal/Android-Terminal-Emulator/35188f8a8b57989a4a4ec9485e11187b46be26d9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /libtermexec/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libtermexec/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | dependencies { 6 | classpath 'com.android.tools.build:gradle:1.0.0' 7 | } 8 | } 9 | apply plugin: 'com.android.library' 10 | 11 | repositories { 12 | jcenter() 13 | } 14 | 15 | android { 16 | compileSdkVersion 22 17 | buildToolsVersion "22.0.1" 18 | 19 | defaultConfig { 20 | minSdkVersion 4 21 | targetSdkVersion 22 22 | versionCode 1 23 | versionName "1.0" 24 | 25 | ndk { 26 | moduleName 'libjackpal-termexec2' 27 | abiFilters 'all' 28 | ldLibs 'log', 'c' 29 | } 30 | } 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_7 34 | targetCompatibility JavaVersion.VERSION_1_7 35 | } 36 | 37 | buildTypes { 38 | release { 39 | minifyEnabled false 40 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 41 | } 42 | } 43 | } 44 | 45 | // by default recent plugin version does not copy any AIDL files "to avoid publishing too much" 46 | android.libraryVariants.all { variant -> 47 | Sync packageAidl = project.tasks.create("addPublic${variant.name.capitalize()}Aidl", Sync) { sync -> 48 | from "$project.projectDir/src/main/aidl/" 49 | into "$buildDir/intermediates/bundles/${variant.dirName}/aidl/" 50 | } 51 | 52 | variant.javaCompile.dependsOn packageAidl 53 | } 54 | 55 | dependencies { 56 | compile fileTree(dir: 'libs', include: ['*.jar']) 57 | 58 | compile 'com.android.support:support-annotations:21.0.0' 59 | } 60 | -------------------------------------------------------------------------------- /libtermexec/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/uniqa/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /libtermexec/src/androidTest/java/jackpal/androidterm/libtermexec/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.libtermexec; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /libtermexec/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /libtermexec/src/main/aidl/jackpal/androidterm/libtermexec/v1/ITerminal.aidl: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.libtermexec.v1; 2 | 3 | import android.content.IntentSender; 4 | import android.os.ParcelFileDescriptor; 5 | import android.os.ResultReceiver; 6 | 7 | // see also: 8 | // the (clumsy) way to handle object inheritance with Binder: 9 | // https://kevinhartman.github.io/blog/2012/07/23/inheritance-through-ipc-using-aidl-in-android/ 10 | // some (possibly outdated) notes on preserving backward compatibility: 11 | // https://stackoverflow.com/questions/18197783/android-aidl-interface-parcelables-and-backwards-compatibility 12 | /** 13 | * An interface for interacting with Terminal implementation. 14 | * 15 | * The version of the interface is encoded in Intent action and the AIDL package name. New versions 16 | * of this interface may be implemented in future. Those versions will be made available 17 | * in separate packages and older versions will continue to work. 18 | */ 19 | interface ITerminal { 20 | /** 21 | * Start a new Terminal session. A session will remain hosted by service, that provides binding, 22 | * but no gurantees of process pesistence as well as stability of connection are made. You 23 | * should keep your ParcelFileDescriptor around and allow ServiceConnection to call this method 24 | * again, when reconnection happens, in case service hosting the session is killed by system. 25 | * 26 | * Allows caller to be notified of terminal session events. Multiple calls can happen on each, 27 | * and new call types can be introduced, so prepare to ignore unknown event codes. 28 | * 29 | * So far only notifications about session end (code 0) are supported. This notification is 30 | * issued after abovementioned file descriptor is closed and the session is ended from 31 | * Terminal's standpoint. 32 | * 33 | * @param pseudoTerminalMultiplexerFd file descriptor, obtained by opening /dev/ptmx. 34 | * @param a callback 35 | * 36 | * @return IntentSender, that can be used to start corresponding Terminal Activity. 37 | */ 38 | IntentSender startSession(in ParcelFileDescriptor pseudoTerminalMultiplexerFd, in ResultReceiver callback); 39 | } 40 | -------------------------------------------------------------------------------- /libtermexec/src/main/jni/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Steven Luo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _JACKPAL_PROCESS_H 18 | #define _JACKPAL_PROCESS_H 1 19 | 20 | #include 21 | #include "jni.h" 22 | #include 23 | 24 | #define LOG_TAG "jackpal-termexec" 25 | 26 | extern "C" { 27 | JNIEXPORT jint JNICALL Java_jackpal_androidterm_TermExec_createSubprocessInternal 28 | (JNIEnv *, jclass, jstring, jobjectArray, jobjectArray, jint); 29 | 30 | JNIEXPORT jint JNICALL Java_jackpal_androidterm_TermExec_waitFor 31 | (JNIEnv *, jclass, jint); 32 | } 33 | 34 | #endif /* !defined(_JACKPAL_PROCESS_H) */ 35 | -------------------------------------------------------------------------------- /samples/intents/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /samples/intents/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "jackpal.androidterm.sample.intents" 9 | minSdkVersion 4 10 | targetSdkVersion 22 11 | } 12 | 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/intents/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/intents/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/intents/src/main/java/jackpal/androidterm/sample/intents/IntentSampleActivity.java: -------------------------------------------------------------------------------- 1 | package jackpal.androidterm.sample.intents; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.view.View.OnClickListener; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | 11 | public class IntentSampleActivity extends Activity 12 | { 13 | private String mHandle; 14 | private static final int REQUEST_WINDOW_HANDLE = 1; 15 | 16 | /** Called when the activity is first created. */ 17 | @Override 18 | public void onCreate(Bundle savedInstanceState) 19 | { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.main); 22 | addClickListener(R.id.openNewWindow, new OnClickListener() { 23 | public void onClick(View v) { 24 | // Intent for opening a new window without providing script 25 | Intent intent = 26 | new Intent("jackpal.androidterm.OPEN_NEW_WINDOW"); 27 | intent.addCategory(Intent.CATEGORY_DEFAULT); 28 | startActivity(intent); 29 | }}); 30 | 31 | final EditText script = (EditText) findViewById(R.id.script); 32 | script.setText(getString(R.string.default_script)); 33 | addClickListener(R.id.runScript, new OnClickListener() { 34 | public void onClick(View v) { 35 | /* Intent for opening a new window and running the provided 36 | script -- you must declare the permission 37 | jackpal.androidterm.permission.RUN_SCRIPT in your manifest 38 | to use */ 39 | Intent intent = 40 | new Intent("jackpal.androidterm.RUN_SCRIPT"); 41 | intent.addCategory(Intent.CATEGORY_DEFAULT); 42 | String command = script.getText().toString(); 43 | intent.putExtra("jackpal.androidterm.iInitialCommand", command); 44 | startActivity(intent); 45 | }}); 46 | addClickListener(R.id.runScriptSaveWindow, new OnClickListener() { 47 | public void onClick(View v) { 48 | /* Intent for running a script in a previously opened window, 49 | if it still exists 50 | This will open another window if it doesn't find a match */ 51 | Intent intent = 52 | new Intent("jackpal.androidterm.RUN_SCRIPT"); 53 | intent.addCategory(Intent.CATEGORY_DEFAULT); 54 | String command = script.getText().toString(); 55 | intent.putExtra("jackpal.androidterm.iInitialCommand", command); 56 | if (mHandle != null) { 57 | // Identify the targeted window by its handle 58 | intent.putExtra("jackpal.androidterm.window_handle", 59 | mHandle); 60 | } 61 | /* The handle for the targeted window -- whether newly opened 62 | or reused -- is returned to us via onActivityResult() 63 | You can compare it against an existing saved handle to 64 | determine whether or not a new window was opened */ 65 | startActivityForResult(intent, REQUEST_WINDOW_HANDLE); 66 | }}); 67 | } 68 | 69 | private void addClickListener(int buttonId, OnClickListener onClickListener) { 70 | ((Button) findViewById(buttonId)).setOnClickListener(onClickListener); 71 | } 72 | 73 | protected void onActivityResult(int request, int result, Intent data) { 74 | if (result != RESULT_OK) { 75 | return; 76 | } 77 | 78 | if (request == REQUEST_WINDOW_HANDLE && data != null) { 79 | mHandle = data.getStringExtra("jackpal.androidterm.window_handle"); 80 | ((Button) findViewById(R.id.runScriptSaveWindow)).setText( 81 | R.string.run_script_existing_window); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /samples/intents/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 |