Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bce65f7db1 | ||
|
|
e18579164f | ||
|
|
16273a1981 | ||
|
|
ce82979e2b | ||
|
|
625aeab398 | ||
|
|
bad6712338 | ||
|
|
b54c7909bd | ||
|
|
4ccc703fcf | ||
|
|
7348820caf | ||
|
|
525985b1f2 | ||
|
|
ab3852d2e4 | ||
|
|
9928073e48 | ||
|
|
3091da64bc | ||
|
|
74dca95101 | ||
|
|
2a6a3b76b7 | ||
|
|
0e4ea95d74 | ||
|
|
7389dbb56f | ||
|
|
d982c71efe | ||
|
|
1b36c684d6 | ||
|
|
a6a83b1fcd | ||
|
|
d6f01bfe9a | ||
|
|
271dd7dcee | ||
|
|
95fbb810e2 | ||
|
|
1aa439311b | ||
|
|
12ddaccaf7 | ||
|
|
09fe7e5941 | ||
|
|
36cc010a87 | ||
|
|
b1aaf5abe5 | ||
|
|
9b3dc57447 | ||
|
|
f7ce206212 | ||
|
|
0deacd8fc6 | ||
|
|
65cfcffa6f | ||
|
|
463b927813 | ||
|
|
09ecd14764 | ||
|
|
89912be500 | ||
|
|
3b4e3b0e42 | ||
|
|
7a726c035c | ||
|
|
430a98e9ad | ||
|
|
01de6b4d18 | ||
|
|
1652c1dcf3 | ||
|
|
7db3200c13 | ||
|
|
9e7ca8b689 | ||
|
|
cb42c19d76 |
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Copying and distribution of this file, with or without modification,
|
||||||
|
# are permitted in any medium without royalty provided this notice is
|
||||||
|
# preserved. This file is offered as-is, without any warranty.
|
||||||
|
|
||||||
|
# EditorConfig
|
||||||
|
# http://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
# Built application files
|
# Built application files
|
||||||
build/
|
build/
|
||||||
|
*.apk
|
||||||
|
|
||||||
# Crashlytics configuations
|
# Crashlytics configuations
|
||||||
com_crashlytics_export_strings.xml
|
com_crashlytics_export_strings.xml
|
||||||
|
|||||||
229
.idea/codeStyleSettings.xml
generated
Normal file
229
.idea/codeStyleSettings.xml
generated
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectCodeStyleSettingsManager">
|
||||||
|
<option name="PER_PROJECT_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="android" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="com" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="junit" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="org" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="java" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
<emptyLine />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="RIGHT_MARGIN" value="100" />
|
||||||
|
<AndroidXmlCodeStyleSettings>
|
||||||
|
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||||
|
</AndroidXmlCodeStyleSettings>
|
||||||
|
<Objective-C-extensions>
|
||||||
|
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
|
||||||
|
<option name="RELEASE_STYLE" value="IVAR" />
|
||||||
|
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
|
||||||
|
<file>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
|
</file>
|
||||||
|
<class>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
|
</class>
|
||||||
|
<extensions>
|
||||||
|
<pair source="cpp" header="h" />
|
||||||
|
<pair source="c" header="h" />
|
||||||
|
</extensions>
|
||||||
|
</Objective-C-extensions>
|
||||||
|
<XML>
|
||||||
|
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||||
|
</XML>
|
||||||
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<rules>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_NAMESPACE>Namespace:</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="TermuxCodeStyle" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
15
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
15
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="AndroidLintGoogleAppIndexingWarning" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="EmptyStatementBody" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="m_reportEmptyBlocks" value="true" />
|
||||||
|
<option name="commentsAreContent" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
@@ -11,9 +11,9 @@ android:
|
|||||||
components:
|
components:
|
||||||
- platform-tools
|
- platform-tools
|
||||||
- tools
|
- tools
|
||||||
- build-tools-23.0.1
|
- build-tools-23.0.2
|
||||||
- android-23
|
- android-23
|
||||||
- sys-img-x86-android-23
|
- extra-android-m2repository
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ./gradlew testDebugUnitTest
|
- ./gradlew testDebugUnitTest
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ Termux app
|
|||||||
|
|
||||||
Termux is an Android terminal app and Linux environment.
|
Termux is an Android terminal app and Linux environment.
|
||||||
|
|
||||||
* [Termux on Google Play](http://play.google.com/store/apps/details?id=com.termux)
|
* [Termux on Google Play Store](https://play.google.com/store/apps/details?id=com.termux)
|
||||||
|
* [Termux on F-Droid](https://f-droid.org/repository/browse/?fdid=com.termux)
|
||||||
* [termux.com](http://termux.com)
|
* [termux.com](http://termux.com)
|
||||||
* [Termux Help](http://termux.com/help/)
|
* [Termux Help](http://termux.com/help/)
|
||||||
* [Termux app on GitHub](https://github.com/termux/termux-app)
|
* [Termux app on GitHub](https://github.com/termux/termux-app)
|
||||||
@@ -14,7 +15,7 @@ Termux is an Android terminal app and Linux environment.
|
|||||||
|
|
||||||
License
|
License
|
||||||
=======
|
=======
|
||||||
Released under the GPLv3 license. Contains code from `Terminal Emulator for Android` which is released under the Apache License.
|
Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). Contains code from `Terminal Emulator for Android` which is released under [the Apache License 2.0](https://www.apache.org/licenses/).
|
||||||
|
|
||||||
Building JNI libraries
|
Building JNI libraries
|
||||||
======================
|
======================
|
||||||
@@ -29,9 +30,9 @@ Terminal resources
|
|||||||
Terminal emulators
|
Terminal emulators
|
||||||
==================
|
==================
|
||||||
* VTE (libvte): Terminal emulator widget for GTK+, mainly used in gnome-terminal. [Source](https://github.com/GNOME/vte), [Open Issues](https://bugzilla.gnome.org/buglist.cgi?quicksearch=product%3A%22vte%22+), and [All (including closed) issues](https://bugzilla.gnome.org/buglist.cgi?bug_status=RESOLVED&bug_status=VERIFIED&chfield=resolution&chfieldfrom=-2000d&chfieldvalue=FIXED&product=vte&resolution=FIXED).
|
* VTE (libvte): Terminal emulator widget for GTK+, mainly used in gnome-terminal. [Source](https://github.com/GNOME/vte), [Open Issues](https://bugzilla.gnome.org/buglist.cgi?quicksearch=product%3A%22vte%22+), and [All (including closed) issues](https://bugzilla.gnome.org/buglist.cgi?bug_status=RESOLVED&bug_status=VERIFIED&chfield=resolution&chfieldfrom=-2000d&chfieldvalue=FIXED&product=vte&resolution=FIXED).
|
||||||
* iTerm 2: Mac terminal application. [Source](https://github.com/gnachman/iTerm2), [Issues](https://gitlab.com/gnachman/iterm2/issues) and [Documentation](http://www.iterm2.com/documentation.html) (which includes [iTerm2 proprietary escape codes](http://www.iterm2.com/documentation-escape-codes.html)).
|
* iTerm 2: OS X terminal application. [Source](https://github.com/gnachman/iTerm2), [Issues](https://gitlab.com/gnachman/iterm2/issues) and [Documentation](http://www.iterm2.com/documentation.html) (which includes [iTerm2 proprietary escape codes](http://www.iterm2.com/documentation-escape-codes.html)).
|
||||||
* Konsole: KDE terminal application. [Source](https://projects.kde.org/projects/kde/applications/konsole/repository), in particular [tests](https://projects.kde.org/projects/kde/applications/konsole/repository/revisions/master/show/tests), [Bugs](https://bugs.kde.org/buglist.cgi?bug_severity=critical&bug_severity=grave&bug_severity=major&bug_severity=crash&bug_severity=normal&bug_severity=minor&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole) and [Wishes](https://bugs.kde.org/buglist.cgi?bug_severity=wishlist&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole).
|
* Konsole: KDE terminal application. [Source](https://projects.kde.org/projects/kde/applications/konsole/repository), in particular [tests](https://projects.kde.org/projects/kde/applications/konsole/repository/revisions/master/show/tests), [Bugs](https://bugs.kde.org/buglist.cgi?bug_severity=critical&bug_severity=grave&bug_severity=major&bug_severity=crash&bug_severity=normal&bug_severity=minor&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole) and [Wishes](https://bugs.kde.org/buglist.cgi?bug_severity=wishlist&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole).
|
||||||
* hterm: Javascript terminal implementation from chromium. [Source](https://github.com/chromium/hterm), including [tests](https://github.com/chromium/hterm/blob/master/js/hterm_vt_tests.js), and [google group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-hterm).
|
* hterm: JavaScript terminal implementation from Chromium. [Source](https://github.com/chromium/hterm), including [tests](https://github.com/chromium/hterm/blob/master/js/hterm_vt_tests.js), and [Google group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-hterm).
|
||||||
* xterm: The grandfather of terminal emulators. [Source](http://invisible-island.net/datafiles/release/xterm.tar.gz).
|
* xterm: The grandfather of terminal emulators. [Source](http://invisible-island.net/datafiles/release/xterm.tar.gz).
|
||||||
* Connectbot: Android SSH client. [Source](https://github.com/connectbot/connectbot)
|
* Connectbot: Android SSH client. [Source](https://github.com/connectbot/connectbot)
|
||||||
* Android Terminal Emulator: Android terminal app which Termux terminal handling is based on. Inactive. [Source](https://github.com/jackpal/Android-Terminal-Emulator).
|
* Android Terminal Emulator: Android terminal app which Termux terminal handling is based on. Inactive. [Source](https://github.com/jackpal/Android-Terminal-Emulator).
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ apply plugin: 'com.android.application'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 23
|
||||||
buildToolsVersion "23.0.1"
|
buildToolsVersion "23.0.2"
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'com.android.support:support-annotations:23.1.1'
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
@@ -13,32 +17,15 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 22
|
targetSdkVersion 23
|
||||||
versionCode 17
|
versionCode 22
|
||||||
versionName "0.17"
|
versionName "0.22"
|
||||||
}
|
|
||||||
|
|
||||||
signingConfigs {
|
|
||||||
release {
|
|
||||||
if (System.getenv("TRAVIS")) {
|
|
||||||
storeFile rootProject.file('travis.keystore')
|
|
||||||
storePassword 'abcdef'
|
|
||||||
keyAlias 'travis'
|
|
||||||
keyPassword 'abcdef'
|
|
||||||
} else {
|
|
||||||
storeFile new File(TERMUX_KEYSTORE_FILE)
|
|
||||||
storePassword TERMUX_KEYSTORE_PASSWORD
|
|
||||||
keyAlias TERMUX_KEYSTORE_ALIAS
|
|
||||||
keyPassword TERMUX_KEYSTORE_PASSWORD
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.release
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="22" />
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
@@ -16,11 +14,13 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:fullBackupContent="@xml/backupscheme"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:banner="@drawable/banner"
|
android:banner="@drawable/banner"
|
||||||
android:label="@string/application_name"
|
android:label="@string/application_name"
|
||||||
android:theme="@style/Theme.Termux"
|
android:theme="@style/Theme.Termux"
|
||||||
android:supportsRtl="false" >
|
android:supportsRtl="false" >
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.termux.app.TermuxActivity"
|
android:name="com.termux.app.TermuxActivity"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||||
@@ -35,13 +35,41 @@
|
|||||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.termux.app.TermuxHelpActivity"
|
android:name="com.termux.app.TermuxHelpActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/application_help" />
|
android:label="@string/application_help" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.termux.filepicker.TermuxFilePickerActivity"
|
||||||
|
android:label="@string/application_name"
|
||||||
|
android:theme="@android:style/Theme.Material"
|
||||||
|
android:noHistory="true">
|
||||||
|
<intent-filter>
|
||||||
|
<!--
|
||||||
|
http://stackoverflow.com/questions/6486716/using-intent-action-pick-for-specific-path
|
||||||
|
"That said, you should consider ACTION_PICK deprecated. The modern action is ACTION_GET_CONTENT
|
||||||
|
which is much better supported; you will find support of ACTION_PICK spotty and inconsistent.
|
||||||
|
Unfortunately ACTION_GET_CONTENT also does not let you specify a directory."
|
||||||
|
-->
|
||||||
|
<action android:name="android.intent.action.GET_CONTENT" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.OPENABLE" />
|
||||||
|
<data android:mimeType="*/*" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider android:authorities="com.termux.filepicker.provider"
|
||||||
|
android:readPermission="com.termux.filepickder.READ"
|
||||||
|
android:exported="true"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:name="com.termux.filepicker.TermuxFilePickerProvider" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="com.termux.app.TermuxService"
|
android:name="com.termux.app.TermuxService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import android.net.Uri;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -52,6 +54,7 @@ import android.view.View.OnClickListener;
|
|||||||
import android.view.View.OnKeyListener;
|
import android.view.View.OnKeyListener;
|
||||||
import android.view.View.OnLongClickListener;
|
import android.view.View.OnLongClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
@@ -86,7 +89,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
private static final String RELOAD_STYLE_ACTION = "com.termux.app.reload_style";
|
private static final String RELOAD_STYLE_ACTION = "com.termux.app.reload_style";
|
||||||
|
|
||||||
/** The main view of the activity showing the terminal. */
|
/** The main view of the activity showing the terminal. */
|
||||||
TerminalView mTerminalView;
|
@NonNull TerminalView mTerminalView;
|
||||||
|
|
||||||
final FullScreenHelper mFullScreenHelper = new FullScreenHelper(this);
|
final FullScreenHelper mFullScreenHelper = new FullScreenHelper(this);
|
||||||
|
|
||||||
@@ -142,6 +145,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
|
if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
|
||||||
|
|
||||||
final TerminalSession currentSession = getCurrentTermSession();
|
final TerminalSession currentSession = getCurrentTermSession();
|
||||||
|
if (currentSession == null) return false;
|
||||||
|
|
||||||
if (keyCode == KeyEvent.KEYCODE_ENTER && !currentSession.isRunning()) {
|
if (keyCode == KeyEvent.KEYCODE_ENTER && !currentSession.isRunning()) {
|
||||||
// Return pressed with finished session - remove it.
|
// Return pressed with finished session - remove it.
|
||||||
@@ -289,6 +293,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
|
|
||||||
mTerminalView.checkForTypeface();
|
mTerminalView.checkForTypeface();
|
||||||
mTerminalView.checkForColors();
|
mTerminalView.checkForColors();
|
||||||
|
|
||||||
|
TermuxInstaller.setupStorageSymlink(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,18 +420,22 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
TermuxInstaller.setupIfNeeded(TermuxActivity.this, new Runnable() {
|
TermuxInstaller.setupIfNeeded(TermuxActivity.this, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (TermuxPreferences.isShowWelcomeDialog(TermuxActivity.this)) {
|
try {
|
||||||
new AlertDialog.Builder(TermuxActivity.this).setTitle(R.string.welcome_dialog_title).setMessage(R.string.welcome_dialog_body)
|
if (TermuxPreferences.isShowWelcomeDialog(TermuxActivity.this)) {
|
||||||
.setCancelable(false).setPositiveButton(android.R.string.ok, null)
|
new AlertDialog.Builder(TermuxActivity.this).setTitle(R.string.welcome_dialog_title).setMessage(R.string.welcome_dialog_body)
|
||||||
.setNegativeButton(R.string.welcome_dialog_dont_show_again_button, new DialogInterface.OnClickListener() {
|
.setCancelable(false).setPositiveButton(android.R.string.ok, null)
|
||||||
@Override
|
.setNegativeButton(R.string.welcome_dialog_dont_show_again_button, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
@Override
|
||||||
TermuxPreferences.disableWelcomeDialog(TermuxActivity.this);
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
dialog.dismiss();
|
TermuxPreferences.disableWelcomeDialog(TermuxActivity.this);
|
||||||
}
|
dialog.dismiss();
|
||||||
}).show();
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
addNewSession(false, null);
|
||||||
|
} catch (WindowManager.BadTokenException e) {
|
||||||
|
// Activity finished - ignore.
|
||||||
}
|
}
|
||||||
addNewSession(false, null);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -456,7 +466,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalSession getCurrentTermSession() {
|
@Nullable TerminalSession getCurrentTermSession() {
|
||||||
return mTerminalView.getCurrentSession();
|
return mTerminalView.getCurrentSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,12 +585,11 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showUrlSelection() {
|
static LinkedHashSet<CharSequence> extractUrls(String text) {
|
||||||
String text = getCurrentTermSession().getEmulator().getScreen().getTranscriptText();
|
|
||||||
// Pattern for recognizing a URL, based off RFC 3986
|
// Pattern for recognizing a URL, based off RFC 3986
|
||||||
// http://stackoverflow.com/questions/5713558/detect-and-extract-url-from-a-string
|
// http://stackoverflow.com/questions/5713558/detect-and-extract-url-from-a-string
|
||||||
final Pattern urlPattern = Pattern.compile(
|
final Pattern urlPattern = Pattern.compile(
|
||||||
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)" + "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*" + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
|
"(?:^|[\\W])((ht|f)tp(s?)://|www\\.)" + "(([\\w\\-]+\\.)+?([\\w\\-.~]+/?)*" + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
|
||||||
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
|
||||||
LinkedHashSet<CharSequence> urlSet = new LinkedHashSet<>();
|
LinkedHashSet<CharSequence> urlSet = new LinkedHashSet<>();
|
||||||
Matcher matcher = urlPattern.matcher(text);
|
Matcher matcher = urlPattern.matcher(text);
|
||||||
@@ -590,7 +599,12 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
String url = text.substring(matchStart, matchEnd);
|
String url = text.substring(matchStart, matchEnd);
|
||||||
urlSet.add(url);
|
urlSet.add(url);
|
||||||
}
|
}
|
||||||
|
return urlSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void showUrlSelection() {
|
||||||
|
String text = getCurrentTermSession().getEmulator().getScreen().getTranscriptText();
|
||||||
|
LinkedHashSet<CharSequence> urlSet = extractUrls(text);
|
||||||
if (urlSet.isEmpty()) {
|
if (urlSet.isEmpty()) {
|
||||||
new AlertDialog.Builder(this).setMessage(R.string.select_url_no_found).show();
|
new AlertDialog.Builder(this).setMessage(R.string.select_url_no_found).show();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,16 +1,5 @@
|
|||||||
package com.termux.app;
|
package com.termux.app;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipInputStream;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
@@ -21,10 +10,22 @@ import android.content.DialogInterface.OnDismissListener;
|
|||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import com.termux.R;
|
import com.termux.R;
|
||||||
import com.termux.terminal.EmulatorDebug;
|
import com.termux.terminal.EmulatorDebug;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the Termux bootstrap packages if necessary by following the below steps:
|
* Install the Termux bootstrap packages if necessary by following the below steps:
|
||||||
*
|
*
|
||||||
@@ -138,27 +139,35 @@ final class TermuxInstaller {
|
|||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new AlertDialog.Builder(activity).setTitle(R.string.bootstrap_error_title).setMessage(R.string.bootstrap_error_body)
|
try {
|
||||||
.setNegativeButton(R.string.bootstrap_error_abort, new OnClickListener() {
|
new AlertDialog.Builder(activity).setTitle(R.string.bootstrap_error_title).setMessage(R.string.bootstrap_error_body)
|
||||||
@Override
|
.setNegativeButton(R.string.bootstrap_error_abort, new OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
@Override
|
||||||
dialog.dismiss();
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
activity.finish();
|
dialog.dismiss();
|
||||||
}
|
activity.finish();
|
||||||
}).setPositiveButton(R.string.bootstrap_error_try_again, new OnClickListener() {
|
}
|
||||||
@Override
|
}).setPositiveButton(R.string.bootstrap_error_try_again, new OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
@Override
|
||||||
dialog.dismiss();
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
TermuxInstaller.setupIfNeeded(activity, whenDone);
|
dialog.dismiss();
|
||||||
}
|
TermuxInstaller.setupIfNeeded(activity, whenDone);
|
||||||
}).show();
|
}
|
||||||
|
}).show();
|
||||||
|
} catch (WindowManager.BadTokenException e) {
|
||||||
|
// Activity already dismissed - ignore.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
progress.dismiss();
|
try {
|
||||||
|
progress.dismiss();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Activity already dismissed - ignore.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -191,4 +200,36 @@ final class TermuxInstaller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setupStorageSymlink(final Context context) {
|
||||||
|
final File[] dirs = context.getExternalFilesDirs(null);
|
||||||
|
if (dirs == null || dirs.length < 2) return;
|
||||||
|
new Thread() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
final File externalDir = dirs[1];
|
||||||
|
File homeDir = new File(TermuxService.HOME_PATH);
|
||||||
|
homeDir.mkdirs();
|
||||||
|
File externalLink = new File(homeDir, "storage");
|
||||||
|
|
||||||
|
if (externalLink.exists()) {
|
||||||
|
if (externalLink.getCanonicalPath().equals(externalDir.getPath())) {
|
||||||
|
// Keeping existing link.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Removing old link to give place to new.
|
||||||
|
if (!externalLink.delete()) {
|
||||||
|
Log.e("termux", "Unable to remove old $HOME/storage to give place for new");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Os.symlink(externalDir.getAbsolutePath(), externalLink.getAbsolutePath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("termux", "Error setting up link", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -768,16 +768,10 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
// or pick a magic number from thin air otherwise.
|
// or pick a magic number from thin air otherwise.
|
||||||
// TODO Better communication with tools of this bogus state.
|
// TODO Better communication with tools of this bogus state.
|
||||||
// It will crash on a real device.
|
// It will crash on a real device.
|
||||||
if (widthMode == MeasureSpec.AT_MOST) {
|
if (widthMode == MeasureSpec.UNSPECIFIED) {
|
||||||
widthMode = MeasureSpec.EXACTLY;
|
|
||||||
} else if (widthMode == MeasureSpec.UNSPECIFIED) {
|
|
||||||
widthMode = MeasureSpec.EXACTLY;
|
|
||||||
widthSize = 300;
|
widthSize = 300;
|
||||||
}
|
}
|
||||||
if (heightMode == MeasureSpec.AT_MOST) {
|
if (heightMode == MeasureSpec.UNSPECIFIED) {
|
||||||
heightMode = MeasureSpec.EXACTLY;
|
|
||||||
} else if (heightMode == MeasureSpec.UNSPECIFIED) {
|
|
||||||
heightMode = MeasureSpec.EXACTLY;
|
|
||||||
heightSize = 300;
|
heightSize = 300;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -934,10 +928,7 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
|
|
||||||
private static boolean hasOpaqueBackground(View v) {
|
private static boolean hasOpaqueBackground(View v) {
|
||||||
final Drawable bg = v.getBackground();
|
final Drawable bg = v.getBackground();
|
||||||
if (bg != null) {
|
return bg != null && bg.getOpacity() == PixelFormat.OPAQUE;
|
||||||
return bg.getOpacity() == PixelFormat.OPAQUE;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1114,7 +1105,6 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
mRightDragger.processTouchEvent(ev);
|
mRightDragger.processTouchEvent(ev);
|
||||||
|
|
||||||
final int action = ev.getAction();
|
final int action = ev.getAction();
|
||||||
boolean wantTouchEvents = true;
|
|
||||||
|
|
||||||
switch (action & MotionEvent.ACTION_MASK) {
|
switch (action & MotionEvent.ACTION_MASK) {
|
||||||
case MotionEvent.ACTION_DOWN: {
|
case MotionEvent.ACTION_DOWN: {
|
||||||
@@ -1154,7 +1144,7 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wantTouchEvents;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1317,10 +1307,7 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
*/
|
*/
|
||||||
public boolean isDrawerOpen(int drawerGravity) {
|
public boolean isDrawerOpen(int drawerGravity) {
|
||||||
final View drawerView = findDrawerWithGravity(drawerGravity);
|
final View drawerView = findDrawerWithGravity(drawerGravity);
|
||||||
if (drawerView != null) {
|
return drawerView != null && isDrawerOpen(drawerView);
|
||||||
return isDrawerOpen(drawerView);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1350,10 +1337,7 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
*/
|
*/
|
||||||
public boolean isDrawerVisible(int drawerGravity) {
|
public boolean isDrawerVisible(int drawerGravity) {
|
||||||
final View drawerView = findDrawerWithGravity(drawerGravity);
|
final View drawerView = findDrawerWithGravity(drawerGravity);
|
||||||
if (drawerView != null) {
|
return drawerView != null && isDrawerVisible(drawerView);
|
||||||
return isDrawerVisible(drawerView);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPeekingDrawer() {
|
private boolean hasPeekingDrawer() {
|
||||||
@@ -1776,10 +1760,7 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
|
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
|
||||||
if (CAN_HIDE_DESCENDANTS || includeChildForAccessibility(child)) {
|
return (CAN_HIDE_DESCENDANTS || includeChildForAccessibility(child)) && super.onRequestSendAccessibilityEvent(host, child, event);
|
||||||
return super.onRequestSendAccessibilityEvent(host, child, event);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1796,4 +1777,4 @@ public class DrawerLayout extends ViewGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1485,10 +1485,7 @@ public class ViewDragHelper {
|
|||||||
* @return true if the supplied view is under the given point, false otherwise
|
* @return true if the supplied view is under the given point, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isViewUnder(View view, int x, int y) {
|
public boolean isViewUnder(View view, int x, int y) {
|
||||||
if (view == null) {
|
return view != null && x >= view.getLeft() && x < view.getRight() && y >= view.getTop() && y < view.getBottom();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return x >= view.getLeft() && x < view.getRight() && y >= view.getTop() && y < view.getBottom();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1522,4 +1519,4 @@ public class ViewDragHelper {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.termux.filepicker;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.ListActivity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import com.termux.R;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Activity allowing picking files from the $HOME folder. */
|
||||||
|
public class TermuxFilePickerActivity extends ListActivity {
|
||||||
|
|
||||||
|
@SuppressLint("SdCardPath")
|
||||||
|
final String TERMUX_HOME = "/data/data/com.termux/files/home";
|
||||||
|
|
||||||
|
private File mCurrentDirectory;
|
||||||
|
private final List<File> mFiles = new ArrayList<>();
|
||||||
|
private final List<String> mFileNames = new ArrayList<>();
|
||||||
|
private ArrayAdapter mAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.file_picker);
|
||||||
|
|
||||||
|
mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mFileNames);
|
||||||
|
|
||||||
|
enterDirectory(new File(TERMUX_HOME));
|
||||||
|
setListAdapter(mAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
if (id == android.R.id.home) {
|
||||||
|
enterDirectory(mCurrentDirectory.getParentFile());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
super.onListItemClick(l, v, position, id);
|
||||||
|
File requestFile = mFiles.get(position);
|
||||||
|
if (requestFile.isDirectory()) {
|
||||||
|
enterDirectory(requestFile);
|
||||||
|
} else {
|
||||||
|
Uri returnUri = Uri.withAppendedPath(Uri.parse("content://com.termux.filepicker.provider/"), requestFile.getAbsolutePath());
|
||||||
|
Intent returnIntent = new Intent().setData(returnUri);
|
||||||
|
returnIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
setResult(Activity.RESULT_OK, returnIntent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enterDirectory(File directory) {
|
||||||
|
getActionBar().setDisplayHomeAsUpEnabled(!directory.getAbsolutePath().equals(TERMUX_HOME));
|
||||||
|
|
||||||
|
String title = directory.getAbsolutePath() + "/";
|
||||||
|
if (title.startsWith(TERMUX_HOME)) {
|
||||||
|
title = "~" + title.substring(TERMUX_HOME.length(), title.length());
|
||||||
|
}
|
||||||
|
setTitle(title);
|
||||||
|
|
||||||
|
mCurrentDirectory = directory;
|
||||||
|
mFiles.clear();
|
||||||
|
mFileNames.clear();
|
||||||
|
mFiles.addAll(Arrays.asList(mCurrentDirectory.listFiles()));
|
||||||
|
|
||||||
|
Collections.sort(mFiles, new Comparator<File>() {
|
||||||
|
@Override
|
||||||
|
public int compare(File f1, File f2) {
|
||||||
|
final String n1 = f1.getName();
|
||||||
|
final String n2 = f2.getName();
|
||||||
|
// Display dot folders last:
|
||||||
|
if (n1.startsWith(".") && !n2.startsWith(".")) {
|
||||||
|
return 1;
|
||||||
|
} else if (n2.startsWith(".") && !n1.startsWith(".")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n1.compareToIgnoreCase(n2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (File file : mFiles) {
|
||||||
|
mFileNames.add(file.getName() + (file.isDirectory() ? "/" : ""));
|
||||||
|
}
|
||||||
|
mAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.termux.filepicker;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
/** Provider of files content uris picked from {@link com.termux.filepicker.TermuxFilePickerActivity}. */
|
||||||
|
public class TermuxFilePickerProvider extends ContentProvider {
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(@NonNull Uri uri) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||||
|
File file = new File(uri.getPath());
|
||||||
|
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1444,7 +1444,7 @@ public final class TerminalEmulator {
|
|||||||
final int linesToScrollArg = getArg0(1);
|
final int linesToScrollArg = getArg0(1);
|
||||||
final int linesBetweenTopAndBottomMargins = mBottomMargin - mTopMargin;
|
final int linesBetweenTopAndBottomMargins = mBottomMargin - mTopMargin;
|
||||||
final int linesToScroll = Math.min(linesBetweenTopAndBottomMargins, linesToScrollArg);
|
final int linesToScroll = Math.min(linesBetweenTopAndBottomMargins, linesToScrollArg);
|
||||||
mScreen.blockCopy(0, mTopMargin, mColumns, linesBetweenTopAndBottomMargins - linesToScroll, 0, linesToScroll);
|
mScreen.blockCopy(0, mTopMargin, mColumns, linesBetweenTopAndBottomMargins - linesToScroll, 0, mTopMargin + linesToScroll);
|
||||||
blockClear(0, mTopMargin, mColumns, linesToScroll);
|
blockClear(0, mTopMargin, mColumns, linesToScroll);
|
||||||
} else {
|
} else {
|
||||||
// "${CSI}${func};${startx};${starty};${firstrow};${lastrow}T" - initiate highlight mouse tracking.
|
// "${CSI}${func};${startx};${starty};${firstrow};${lastrow}T" - initiate highlight mouse tracking.
|
||||||
@@ -2156,15 +2156,22 @@ public final class TerminalEmulator {
|
|||||||
|
|
||||||
final boolean autoWrap = isDecsetInternalBitSet(DECSET_BIT_AUTOWRAP);
|
final boolean autoWrap = isDecsetInternalBitSet(DECSET_BIT_AUTOWRAP);
|
||||||
final int displayWidth = WcWidth.width(codePoint);
|
final int displayWidth = WcWidth.width(codePoint);
|
||||||
|
final boolean cursorInLastColumn = mCursorCol == mRightMargin - 1;
|
||||||
|
|
||||||
if (autoWrap && (mCursorCol == mRightMargin - 1 && ((mAboutToAutoWrap && displayWidth == 1) || displayWidth == 2))) {
|
if (autoWrap) {
|
||||||
mScreen.setLineWrap(mCursorRow);
|
if (cursorInLastColumn && ((mAboutToAutoWrap && displayWidth == 1) || displayWidth == 2)) {
|
||||||
mCursorCol = mLeftMargin;
|
mScreen.setLineWrap(mCursorRow);
|
||||||
if (mCursorRow + 1 < mBottomMargin) {
|
mCursorCol = mLeftMargin;
|
||||||
mCursorRow++;
|
if (mCursorRow + 1 < mBottomMargin) {
|
||||||
} else {
|
mCursorRow++;
|
||||||
scrollDownOneLine();
|
} else {
|
||||||
|
scrollDownOneLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (cursorInLastColumn && displayWidth == 2) {
|
||||||
|
// The behaviour when a wide character is output with cursor in the last column when
|
||||||
|
// autowrap is disabled is not obvious - it's ignored here.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInsertMode && displayWidth > 0) {
|
if (mInsertMode && displayWidth > 0) {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
// Negated signal.
|
// Negated signal.
|
||||||
exitDescription += " with signal " + (-exitCode);
|
exitDescription += " with signal " + (-exitCode);
|
||||||
}
|
}
|
||||||
exitDescription += "]";
|
exitDescription += " - press Enter to close]";
|
||||||
|
|
||||||
byte[] bytesToWrite = exitDescription.getBytes(StandardCharsets.UTF_8);
|
byte[] bytesToWrite = exitDescription.getBytes(StandardCharsets.UTF_8);
|
||||||
mEmulator.append(bytesToWrite, bytesToWrite.length);
|
mEmulator.append(bytesToWrite, bytesToWrite.length);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.view.MotionEvent;
|
|||||||
import android.view.ScaleGestureDetector;
|
import android.view.ScaleGestureDetector;
|
||||||
|
|
||||||
/** A combination of {@link GestureDetector} and {@link ScaleGestureDetector}. */
|
/** A combination of {@link GestureDetector} and {@link ScaleGestureDetector}. */
|
||||||
public class GestureAndScaleRecognizer {
|
public final class GestureAndScaleRecognizer {
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
boolean onSingleTapUp(MotionEvent e);
|
boolean onSingleTapUp(MotionEvent e);
|
||||||
@@ -29,6 +29,7 @@ public class GestureAndScaleRecognizer {
|
|||||||
private final GestureDetector mGestureDetector;
|
private final GestureDetector mGestureDetector;
|
||||||
private final ScaleGestureDetector mScaleDetector;
|
private final ScaleGestureDetector mScaleDetector;
|
||||||
final Listener mListener;
|
final Listener mListener;
|
||||||
|
boolean isAfterLongPress;
|
||||||
|
|
||||||
public GestureAndScaleRecognizer(Context context, Listener listener) {
|
public GestureAndScaleRecognizer(Context context, Listener listener) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
@@ -52,6 +53,7 @@ public class GestureAndScaleRecognizer {
|
|||||||
@Override
|
@Override
|
||||||
public void onLongPress(MotionEvent e) {
|
public void onLongPress(MotionEvent e) {
|
||||||
mListener.onLongPress(e);
|
mListener.onLongPress(e);
|
||||||
|
isAfterLongPress = true;
|
||||||
}
|
}
|
||||||
}, null, true /* ignoreMultitouch */);
|
}, null, true /* ignoreMultitouch */);
|
||||||
|
|
||||||
@@ -88,8 +90,17 @@ public class GestureAndScaleRecognizer {
|
|||||||
public void onTouchEvent(MotionEvent event) {
|
public void onTouchEvent(MotionEvent event) {
|
||||||
mGestureDetector.onTouchEvent(event);
|
mGestureDetector.onTouchEvent(event);
|
||||||
mScaleDetector.onTouchEvent(event);
|
mScaleDetector.onTouchEvent(event);
|
||||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
switch (event.getAction()) {
|
||||||
mListener.onUp(event);
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
isAfterLongPress = false;
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (!isAfterLongPress) {
|
||||||
|
// This behaviour is desired when in e.g. vim with mouse events, where we do not
|
||||||
|
// want to move the cursor when lifting finger after a long press.
|
||||||
|
mListener.onUp(event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,4 +108,4 @@ public class GestureAndScaleRecognizer {
|
|||||||
return mScaleDetector.isInProgress();
|
return mScaleDetector.isInProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ final class TerminalRenderer {
|
|||||||
|
|
||||||
TerminalRow lineObject = screen.allocateFullLineIfNecessary(screen.externalToInternalRow(row));
|
TerminalRow lineObject = screen.allocateFullLineIfNecessary(screen.externalToInternalRow(row));
|
||||||
final char[] line = lineObject.mText;
|
final char[] line = lineObject.mText;
|
||||||
|
final int charsUsedInLine = lineObject.getSpaceUsed();
|
||||||
|
|
||||||
int lastRunStyle = 0;
|
int lastRunStyle = 0;
|
||||||
boolean lastRunInsideCursor = false;
|
boolean lastRunInsideCursor = false;
|
||||||
@@ -125,7 +126,7 @@ final class TerminalRenderer {
|
|||||||
measuredWidthForRun += measuredCodePointWidth;
|
measuredWidthForRun += measuredCodePointWidth;
|
||||||
column += codePointWcWidth;
|
column += codePointWcWidth;
|
||||||
currentCharIndex += charsForCodePoint;
|
currentCharIndex += charsForCodePoint;
|
||||||
while (WcWidth.width(line, currentCharIndex) <= 0) {
|
while (currentCharIndex < charsUsedInLine && WcWidth.width(line, currentCharIndex) <= 0) {
|
||||||
// Eat combining chars so that they are treated as part of the last non-combining code point,
|
// Eat combining chars so that they are treated as part of the last non-combining code point,
|
||||||
// instead of e.g. being considered inside the cursor in the next run.
|
// instead of e.g. being considered inside the cursor in the next run.
|
||||||
currentCharIndex += Character.isHighSurrogate(line[currentCharIndex]) ? 2 : 1;
|
currentCharIndex += Character.isHighSurrogate(line[currentCharIndex]) ? 2 : 1;
|
||||||
@@ -204,7 +205,10 @@ final class TerminalRenderer {
|
|||||||
final boolean strikeThrough = (effect & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0;
|
final boolean strikeThrough = (effect & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0;
|
||||||
final boolean dim = (effect & TextStyle.CHARACTER_ATTRIBUTE_DIM) != 0;
|
final boolean dim = (effect & TextStyle.CHARACTER_ATTRIBUTE_DIM) != 0;
|
||||||
|
|
||||||
int foreColorARGB = palette[foreColor];
|
// Let bold have bright colors if applicable (one of the first 8):
|
||||||
|
final int actualForeColor = foreColor + (bold && foreColor < 8 ? 8 : 0);
|
||||||
|
|
||||||
|
int foreColorARGB = palette[actualForeColor];
|
||||||
if (dim) {
|
if (dim) {
|
||||||
int red = (0xFF & (foreColorARGB >> 16));
|
int red = (0xFF & (foreColorARGB >> 16));
|
||||||
int green = (0xFF & (foreColorARGB >> 8));
|
int green = (0xFF & (foreColorARGB >> 8));
|
||||||
|
|||||||
21
app/src/main/res/layout/file_picker.xml
Normal file
21
app/src/main/res/layout/file_picker.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
|
<ListView android:id="@android:id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawSelectorOnTop="false"/>
|
||||||
|
|
||||||
|
<TextView android:id="@android:id/empty"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/empty_folder"/>
|
||||||
|
</LinearLayout>
|
||||||
@@ -56,4 +56,6 @@
|
|||||||
<string name="notification_action_wakelock">Wake</string>
|
<string name="notification_action_wakelock">Wake</string>
|
||||||
<string name="notification_action_wifilock">Wifi</string>
|
<string name="notification_action_wifilock">Wifi</string>
|
||||||
|
|
||||||
|
<string name="empty_folder">Empty folder.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
5
app/src/main/res/xml/backupscheme.xml
Normal file
5
app/src/main/res/xml/backupscheme.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<full-backup-content>
|
||||||
|
<!-- See https://developer.android.com/training/backup/autosyncapi.html -->
|
||||||
|
<include domain="file" path="home/backup" />
|
||||||
|
</full-backup-content>
|
||||||
25
app/src/test/java/com/termux/app/TermuxActivityTest.java
Normal file
25
app/src/test/java/com/termux/app/TermuxActivityTest.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package com.termux.app;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class TermuxActivityTest extends TestCase {
|
||||||
|
|
||||||
|
private void assertUrlsAre(String text, String... urls) {
|
||||||
|
LinkedHashSet<String> expected = new LinkedHashSet<>();
|
||||||
|
Collections.addAll(expected, urls);
|
||||||
|
assertEquals(expected, TermuxActivity.extractUrls(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExtractUrls() {
|
||||||
|
assertUrlsAre("hello http://example.com world", "http://example.com");
|
||||||
|
|
||||||
|
assertUrlsAre("http://example.com\nhttp://another.com", "http://example.com", "http://another.com");
|
||||||
|
|
||||||
|
assertUrlsAre("hello http://example.com world and http://more.example.com with secure https://more.example.com",
|
||||||
|
"http://example.com", "http://more.example.com", "https://more.example.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,21 +17,21 @@ public class ByteQueueTest extends TestCase {
|
|||||||
|
|
||||||
public void testCompleteWrites() throws Exception {
|
public void testCompleteWrites() throws Exception {
|
||||||
ByteQueue q = new ByteQueue(10);
|
ByteQueue q = new ByteQueue(10);
|
||||||
assertEquals(true, q.write(new byte[] { 1, 2, 3 }, 0, 3));
|
assertEquals(true, q.write(new byte[]{1, 2, 3}, 0, 3));
|
||||||
|
|
||||||
byte[] arr = new byte[10];
|
byte[] arr = new byte[10];
|
||||||
assertEquals(3, q.read(arr, true));
|
assertEquals(3, q.read(arr, true));
|
||||||
assertArrayEquals(new byte[] { 1, 2, 3 }, new byte[] { arr[0], arr[1], arr[2] });
|
assertArrayEquals(new byte[]{1, 2, 3}, new byte[]{arr[0], arr[1], arr[2]});
|
||||||
|
|
||||||
assertEquals(true, q.write(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 0, 10));
|
assertEquals(true, q.write(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 10));
|
||||||
assertEquals(10, q.read(arr, true));
|
assertEquals(10, q.read(arr, true));
|
||||||
assertArrayEquals(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, arr);
|
assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testQueueWraparound() throws Exception {
|
public void testQueueWraparound() throws Exception {
|
||||||
ByteQueue q = new ByteQueue(10);
|
ByteQueue q = new ByteQueue(10);
|
||||||
|
|
||||||
byte[] origArray = new byte[] { 1, 2, 3, 4, 5, 6 };
|
byte[] origArray = new byte[]{1, 2, 3, 4, 5, 6};
|
||||||
byte[] readArray = new byte[origArray.length];
|
byte[] readArray = new byte[origArray.length];
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
q.write(origArray, 0, origArray.length);
|
q.write(origArray, 0, origArray.length);
|
||||||
@@ -43,7 +43,7 @@ public class ByteQueueTest extends TestCase {
|
|||||||
public void testWriteNotesClosing() throws Exception {
|
public void testWriteNotesClosing() throws Exception {
|
||||||
ByteQueue q = new ByteQueue(10);
|
ByteQueue q = new ByteQueue(10);
|
||||||
q.close();
|
q.close();
|
||||||
assertEquals(false, q.write(new byte[] { 1, 2, 3 }, 0, 3));
|
assertEquals(false, q.write(new byte[]{1, 2, 3}, 0, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReadNonBlocking() throws Exception {
|
public void testReadNonBlocking() throws Exception {
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ package com.termux.terminal;
|
|||||||
* <pre>
|
* <pre>
|
||||||
* "CSI ? Pm h", DEC Private Mode Set (DECSET)
|
* "CSI ? Pm h", DEC Private Mode Set (DECSET)
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
* <p/>
|
||||||
* and
|
* and
|
||||||
*
|
* <p/>
|
||||||
* <pre>
|
* <pre>
|
||||||
* "CSI ? Pm l", DEC Private Mode Reset (DECRST)
|
* "CSI ? Pm l", DEC Private Mode Reset (DECRST)
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
* <p/>
|
||||||
* controls various aspects of the terminal
|
* controls various aspects of the terminal
|
||||||
*/
|
*/
|
||||||
public class DecSetTest extends TerminalTestCase {
|
public class DecSetTest extends TerminalTestCase {
|
||||||
@@ -59,4 +59,15 @@ public class DecSetTest extends TerminalTestCase {
|
|||||||
assertEquals("Terminal reset() should disable bracketed paste mode", "a", mOutput.getOutputAndClear());
|
assertEquals("Terminal reset() should disable bracketed paste mode", "a", mOutput.getOutputAndClear());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DECSET 7, DECAWM, controls wraparound mode. */
|
||||||
|
public void testWrapAroundMode() {
|
||||||
|
// Default with wraparound:
|
||||||
|
withTerminalSized(3, 3).enterString("abcd").assertLinesAre("abc", "d ", " ");
|
||||||
|
// With wraparound disabled:
|
||||||
|
withTerminalSized(3, 3).enterString("\033[?7labcd").assertLinesAre("abd", " ", " ");
|
||||||
|
enterString("efg").assertLinesAre("abg", " ", " ");
|
||||||
|
// Re-enabling wraparound:
|
||||||
|
enterString("\033[?7hhij").assertLinesAre("abh", "ij ", " ");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class KeyHandlerTest extends TestCase {
|
public class KeyHandlerTest extends TestCase {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import android.util.Base64;
|
|
||||||
|
|
||||||
/** "ESC ]" is the Operating System Command. */
|
/** "ESC ]" is the Operating System Command. */
|
||||||
public class OperatingSystemControlTest extends TerminalTestCase {
|
public class OperatingSystemControlTest extends TerminalTestCase {
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.termux.terminal;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ${CSI}${top};${bottom}r" - set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM).
|
* ${CSI}${top};${bottom}r" - set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM).
|
||||||
*
|
* <p/>
|
||||||
* "DECSTBM moves the cursor to column 1, line 1 of the page" (http://www.vt100.net/docs/vt510-rm/DECSTBM).
|
* "DECSTBM moves the cursor to column 1, line 1 of the page" (http://www.vt100.net/docs/vt510-rm/DECSTBM).
|
||||||
*/
|
*/
|
||||||
public class ScrollRegionTest extends TerminalTestCase {
|
public class ScrollRegionTest extends TerminalTestCase {
|
||||||
@@ -94,4 +94,8 @@ public class ScrollRegionTest extends TerminalTestCase {
|
|||||||
withTerminalSized(3, 3).enterString("\033[?69h\033[0;2sABCD\0339").assertLinesAre("B ", "D ", " ");
|
withTerminalSized(3, 3).enterString("\033[?69h\033[0;2sABCD\0339").assertLinesAre("B ", "D ", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testScrollDownWithScrollRegion() {
|
||||||
|
withTerminalSized(2, 5).enterString("1\r\n2\r\n3\r\n4\r\n5").assertLinesAre("1 ", "2 ", "3 ", "4 ", "5 ");
|
||||||
|
enterString("\033[3r").enterString("\033[2T").assertLinesAre("1 ", "2 ", " ", " ", "3 ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
public class TerminalRowTest extends TestCase {
|
public class TerminalRowTest extends TestCase {
|
||||||
|
|
||||||
/** The properties of these code points are validated in {@link #testStaticConstants()}. */
|
/** The properties of these code points are validated in {@link #testStaticConstants()}. */
|
||||||
@@ -96,7 +96,7 @@ public class TerminalRowTest extends TestCase {
|
|||||||
assertEquals(80, row.getSpaceUsed());
|
assertEquals(80, row.getSpaceUsed());
|
||||||
assertColumnCharIndicesStartsWith(0, 1, 2, 3);
|
assertColumnCharIndicesStartsWith(0, 1, 2, 3);
|
||||||
|
|
||||||
char[] someChars = new char[] { 'a', 'c', 'e', '4', '5', '6', '7', '8' };
|
char[] someChars = new char[]{'a', 'c', 'e', '4', '5', '6', '7', '8'};
|
||||||
|
|
||||||
char[] rawLine = new char[80];
|
char[] rawLine = new char[80];
|
||||||
Arrays.fill(rawLine, ' ');
|
Arrays.fill(rawLine, ' ');
|
||||||
@@ -373,13 +373,13 @@ public class TerminalRowTest extends TestCase {
|
|||||||
assertEquals(0, WcWidth.width(0x009F));
|
assertEquals(0, WcWidth.width(0x009F));
|
||||||
assertEquals(1, Character.charCount(0x009F));
|
assertEquals(1, Character.charCount(0x009F));
|
||||||
|
|
||||||
int[] points = new int[] { 0xC2541, 'a', '8', 0x73EE, 0x009F, 0x881F, 0x8324, 0xD4C9, 0xFFFD, 'B', 0x009B, 0x61C9, 'Z' };
|
int[] points = new int[]{0xC2541, 'a', '8', 0x73EE, 0x009F, 0x881F, 0x8324, 0xD4C9, 0xFFFD, 'B', 0x009B, 0x61C9, 'Z'};
|
||||||
// int[] expected = new int[] { TerminalEmulator.UNICODE_REPLACEMENT_CHAR, 'a', '8', 0x73EE, 0x009F, 0x881F, 0x8324, 0xD4C9, 0xFFFD,
|
// int[] expected = new int[] { TerminalEmulator.UNICODE_REPLACEMENT_CHAR, 'a', '8', 0x73EE, 0x009F, 0x881F, 0x8324, 0xD4C9, 0xFFFD,
|
||||||
// 'B', 0x009B, 0x61C9, 'Z' };
|
// 'B', 0x009B, 0x61C9, 'Z' };
|
||||||
int currentColumn = 0;
|
int currentColumn = 0;
|
||||||
for (int i = 0; i < points.length; i++) {
|
for (int point : points) {
|
||||||
row.setChar(currentColumn, points[i], 0);
|
row.setChar(currentColumn, point, 0);
|
||||||
currentColumn += WcWidth.width(points[i]);
|
currentColumn += WcWidth.width(point);
|
||||||
}
|
}
|
||||||
// assertLineStartsWith(points);
|
// assertLineStartsWith(points);
|
||||||
// assertEquals(Character.highSurrogate(0xC2541), line.mText[0]);
|
// assertEquals(Character.highSurrogate(0xC2541), line.mText[0]);
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -9,16 +12,10 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import com.termux.terminal.TerminalEmulator;
|
|
||||||
import com.termux.terminal.TerminalOutput;
|
|
||||||
|
|
||||||
public abstract class TerminalTestCase extends TestCase {
|
public abstract class TerminalTestCase extends TestCase {
|
||||||
|
|
||||||
public static class MockTerminalOutput extends TerminalOutput {
|
public static class MockTerminalOutput extends TerminalOutput {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
public final List<ChangedTitle> titleChanges = new ArrayList<>();
|
public final List<ChangedTitle> titleChanges = new ArrayList<>();
|
||||||
public final List<String> clipboardPuts = new ArrayList<>();
|
public final List<String> clipboardPuts = new ArrayList<>();
|
||||||
public int bellsRung = 0;
|
public int bellsRung = 0;
|
||||||
@@ -57,7 +54,7 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
public TerminalEmulator mTerminal;
|
public TerminalEmulator mTerminal;
|
||||||
public MockTerminalOutput mOutput;
|
public MockTerminalOutput mOutput;
|
||||||
|
|
||||||
public static class ChangedTitle {
|
public static final class ChangedTitle {
|
||||||
final String oldTitle;
|
final String oldTitle;
|
||||||
final String newTitle;
|
final String newTitle;
|
||||||
|
|
||||||
@@ -68,6 +65,7 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ChangedTitle)) return false;
|
||||||
ChangedTitle other = (ChangedTitle) o;
|
ChangedTitle other = (ChangedTitle) o;
|
||||||
return Objects.equals(oldTitle, other.oldTitle) && Objects.equals(newTitle, other.newTitle);
|
return Objects.equals(oldTitle, other.oldTitle) && Objects.equals(newTitle, other.newTitle);
|
||||||
}
|
}
|
||||||
@@ -115,8 +113,8 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LineWrapper {
|
private static final class LineWrapper {
|
||||||
TerminalRow mLine;
|
final TerminalRow mLine;
|
||||||
|
|
||||||
public LineWrapper(TerminalRow line) {
|
public LineWrapper(TerminalRow line) {
|
||||||
mLine = line;
|
mLine = line;
|
||||||
@@ -129,7 +127,7 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return ((LineWrapper) o).mLine == mLine;
|
return o instanceof LineWrapper && ((LineWrapper) o).mLine == mLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
public class TextStyleTest extends TestCase {
|
public class TextStyleTest extends TestCase {
|
||||||
|
|
||||||
private static final int[] ALL_EFFECTS = new int[] { 0, TextStyle.CHARACTER_ATTRIBUTE_BOLD, TextStyle.CHARACTER_ATTRIBUTE_ITALIC,
|
private static final int[] ALL_EFFECTS = new int[]{0, TextStyle.CHARACTER_ATTRIBUTE_BOLD, TextStyle.CHARACTER_ATTRIBUTE_ITALIC,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_UNDERLINE, TextStyle.CHARACTER_ATTRIBUTE_BLINK, TextStyle.CHARACTER_ATTRIBUTE_INVERSE,
|
TextStyle.CHARACTER_ATTRIBUTE_UNDERLINE, TextStyle.CHARACTER_ATTRIBUTE_BLINK, TextStyle.CHARACTER_ATTRIBUTE_INVERSE,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_INVISIBLE, TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH, TextStyle.CHARACTER_ATTRIBUTE_PROTECTED,
|
TextStyle.CHARACTER_ATTRIBUTE_INVISIBLE, TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH, TextStyle.CHARACTER_ATTRIBUTE_PROTECTED,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_DIM };
|
TextStyle.CHARACTER_ATTRIBUTE_DIM};
|
||||||
|
|
||||||
public void testEncodingSingle() {
|
public void testEncodingSingle() {
|
||||||
for (int fx : ALL_EFFECTS) {
|
for (int fx : ALL_EFFECTS) {
|
||||||
@@ -34,7 +34,7 @@ public class TextStyleTest extends TestCase {
|
|||||||
public void testEncodingStrikeThrough() {
|
public void testEncodingStrikeThrough() {
|
||||||
int encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
int encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
||||||
assertTrue((TextStyle.decodeEffect(encoded) | TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0);
|
assertTrue((TextStyle.decodeEffect(encoded) & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEncodingProtected() {
|
public void testEncodingProtected() {
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ public class UnicodeInputTest extends TerminalTestCase {
|
|||||||
// continue with valid successor bytes (see Table 3-7), it must not consume the successor bytes as part of the ill-formed
|
// continue with valid successor bytes (see Table 3-7), it must not consume the successor bytes as part of the ill-formed
|
||||||
// subsequence whenever those successor bytes themselves constitute part of a well-formed UTF-8 code unit subsequence."
|
// subsequence whenever those successor bytes themselves constitute part of a well-formed UTF-8 code unit subsequence."
|
||||||
withTerminalSized(5, 5);
|
withTerminalSized(5, 5);
|
||||||
mTerminal.append(new byte[] { (byte) 0b11101111, (byte) 'a' }, 2);
|
mTerminal.append(new byte[]{(byte) 0b11101111, (byte) 'a'}, 2);
|
||||||
assertLineIs(0, ((char) TerminalEmulator.UNICODE_REPLACEMENT_CHAR) + "a ");
|
assertLineIs(0, ((char) TerminalEmulator.UNICODE_REPLACEMENT_CHAR) + "a ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnassignedCodePoint() throws UnsupportedEncodingException {
|
public void testUnassignedCodePoint() throws UnsupportedEncodingException {
|
||||||
withTerminalSized(3, 3);
|
withTerminalSized(3, 3);
|
||||||
// UTF-8 for U+C2541, an unassigned code point:
|
// UTF-8 for U+C2541, an unassigned code point:
|
||||||
byte[] b = new byte[] { (byte) 0xf3, (byte) 0x82, (byte) 0x95, (byte) 0x81 };
|
byte[] b = new byte[]{(byte) 0xf3, (byte) 0x82, (byte) 0x95, (byte) 0x81};
|
||||||
mTerminal.append(b, b.length);
|
mTerminal.append(b, b.length);
|
||||||
enterString("Y");
|
enterString("Y");
|
||||||
assertEquals(1, Character.charCount(TerminalEmulator.UNICODE_REPLACEMENT_CHAR));
|
assertEquals(1, Character.charCount(TerminalEmulator.UNICODE_REPLACEMENT_CHAR));
|
||||||
@@ -26,10 +26,10 @@ public class UnicodeInputTest extends TerminalTestCase {
|
|||||||
|
|
||||||
public void testStuff() {
|
public void testStuff() {
|
||||||
withTerminalSized(80, 24);
|
withTerminalSized(80, 24);
|
||||||
byte[] b = new byte[] { (byte) 0xf3, (byte) 0x82, (byte) 0x95, (byte) 0x81, (byte) 0x61, (byte) 0x38, (byte) 0xe7, (byte) 0x8f,
|
byte[] b = new byte[]{(byte) 0xf3, (byte) 0x82, (byte) 0x95, (byte) 0x81, (byte) 0x61, (byte) 0x38, (byte) 0xe7, (byte) 0x8f,
|
||||||
(byte) 0xae, (byte) 0xc2, (byte) 0x9f, (byte) 0xe8, (byte) 0xa0, (byte) 0x9f, (byte) 0xe8, (byte) 0x8c, (byte) 0xa4,
|
(byte) 0xae, (byte) 0xc2, (byte) 0x9f, (byte) 0xe8, (byte) 0xa0, (byte) 0x9f, (byte) 0xe8, (byte) 0x8c, (byte) 0xa4,
|
||||||
(byte) 0xed, (byte) 0x93, (byte) 0x89, (byte) 0xef, (byte) 0xbf, (byte) 0xbd, (byte) 0x42, (byte) 0xc2, (byte) 0x9b,
|
(byte) 0xed, (byte) 0x93, (byte) 0x89, (byte) 0xef, (byte) 0xbf, (byte) 0xbd, (byte) 0x42, (byte) 0xc2, (byte) 0x9b,
|
||||||
(byte) 0xe6, (byte) 0x87, (byte) 0x89, (byte) 0x5a };
|
(byte) 0xe6, (byte) 0x87, (byte) 0x89, (byte) 0x5a};
|
||||||
mTerminal.append(b, b.length);
|
mTerminal.append(b, b.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +80,16 @@ public class UnicodeInputTest extends TerminalTestCase {
|
|||||||
public void testOverlongUtf8Encoding() throws Exception {
|
public void testOverlongUtf8Encoding() throws Exception {
|
||||||
// U+0020 should be encoded as 0x20, 0xc0 0xa0 is an overlong encoding
|
// U+0020 should be encoded as 0x20, 0xc0 0xa0 is an overlong encoding
|
||||||
// so should be replaced with the replacement char U+FFFD.
|
// so should be replaced with the replacement char U+FFFD.
|
||||||
withTerminalSized(5, 5).mTerminal.append(new byte[] { (byte) 0xc0, (byte) 0xa0, 'Y' }, 3);
|
withTerminalSized(5, 5).mTerminal.append(new byte[]{(byte) 0xc0, (byte) 0xa0, 'Y'}, 3);
|
||||||
assertLineIs(0, "\uFFFDY ");
|
assertLineIs(0, "\uFFFDY ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWideCharacterWithoutWrapping() throws Exception {
|
||||||
|
// With wraparound disabled. The behaviour when a wide character is output with cursor in
|
||||||
|
// the last column when autowrap is disabled is not obvious, but we expect the wide
|
||||||
|
// character to be ignored here.
|
||||||
|
withTerminalSized(3, 3).enterString("\033[?7l").enterString("枝枝枝").assertLinesAre("枝 ", " ", " ");
|
||||||
|
enterString("a枝").assertLinesAre("枝a", " ", " ");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
set -e -u
|
set -e -u
|
||||||
|
|
||||||
|
SRC_JNILIBS=app/src/main/jniLibs/
|
||||||
|
rm -Rf $SRC_JNILIBS
|
||||||
|
mkdir -p $SRC_JNILIBS
|
||||||
|
|
||||||
PROJECTDIR=`mktemp -d`
|
PROJECTDIR=`mktemp -d`
|
||||||
JNIDIR=$PROJECTDIR/jni
|
JNIDIR=$PROJECTDIR/jni
|
||||||
LIBSDIR=$PROJECTDIR/libs
|
LIBSDIR=$PROJECTDIR/libs
|
||||||
@@ -12,6 +16,6 @@ mkdir $JNIDIR
|
|||||||
cp app/src/main/jni/* $JNIDIR/
|
cp app/src/main/jni/* $JNIDIR/
|
||||||
|
|
||||||
ndk-build NDK_PROJECT_PATH=$PROJECTDIR
|
ndk-build NDK_PROJECT_PATH=$PROJECTDIR
|
||||||
cp -Rf $LIBSDIR/* app/src/main/jniLibs/
|
cp -Rf $LIBSDIR/* $SRC_JNILIBS
|
||||||
|
|
||||||
rm -Rf $PROJECTDIR
|
rm -Rf $PROJECTDIR
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:1.3.1'
|
classpath 'com.android.tools.build:gradle:1.5.0'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Thu Oct 22 22:50:58 CEST 2015
|
#Sat Nov 28 23:59:10 CET 2015
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip
|
||||||
|
|||||||
4
gradlew
vendored
4
gradlew
vendored
@@ -56,9 +56,9 @@ while [ -h "$PRG" ] ; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
SAVED="`pwd`"
|
||||||
cd "`dirname \"$PRG\"`/" >&-
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >&-
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user