Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e76162346 | ||
|
|
5fa4f2647b | ||
|
|
81b5889a26 | ||
|
|
514f59258a | ||
|
|
9f79393aa5 | ||
|
|
e49d514236 | ||
|
|
4e1462326c | ||
|
|
b0f1773a92 | ||
|
|
af9f28c010 | ||
|
|
fef0c66868 | ||
|
|
7a5da83ce2 | ||
|
|
97f01387b9 | ||
|
|
012ff83a06 | ||
|
|
a082c63849 |
@@ -14,8 +14,8 @@ android {
|
|||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 68
|
versionCode 72
|
||||||
versionName "0.68"
|
versionName "0.72"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -38,25 +38,14 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
|
<meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="com.termux.app.TermuxFailsafeActivity"
|
|
||||||
android:label="@string/app_failsafe_mode" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.termux.app.TermuxHelpActivity"
|
android:name="com.termux.app.TermuxHelpActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
|||||||
@@ -103,11 +103,17 @@ public final class BackgroundJob {
|
|||||||
environment.add("TERM=xterm-256color");
|
environment.add("TERM=xterm-256color");
|
||||||
environment.add("HOME=" + TermuxService.HOME_PATH);
|
environment.add("HOME=" + TermuxService.HOME_PATH);
|
||||||
environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
|
environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
|
||||||
|
environment.add("BOOTCLASSPATH" + System.getenv("BOOTCLASSPATH"));
|
||||||
environment.add("ANDROID_ROOT=" + System.getenv("ANDROID_ROOT"));
|
environment.add("ANDROID_ROOT=" + System.getenv("ANDROID_ROOT"));
|
||||||
environment.add("ANDROID_DATA=" + System.getenv("ANDROID_DATA"));
|
environment.add("ANDROID_DATA=" + System.getenv("ANDROID_DATA"));
|
||||||
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
||||||
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
||||||
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
||||||
|
String androidRuntimeRoot = System.getenv("ANDROID_RUNTIME_ROOT");
|
||||||
|
// ANDROID_RUNTIME_ROOT is required for `am` to run on Android Q
|
||||||
|
if (androidRuntimeRoot != null) {
|
||||||
|
environment.add("ANDROID_RUNTIME_ROOT=" + androidRuntimeRoot);
|
||||||
|
}
|
||||||
if (failSafe) {
|
if (failSafe) {
|
||||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||||
environment.add("PATH= " + System.getenv("PATH"));
|
environment.add("PATH= " + System.getenv("PATH"));
|
||||||
|
|||||||
63
app/src/main/java/com/termux/app/BellUtil.java
Normal file
63
app/src/main/java/com/termux/app/BellUtil.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package com.termux.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.os.Vibrator;
|
||||||
|
|
||||||
|
public class BellUtil {
|
||||||
|
private static BellUtil instance = null;
|
||||||
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
|
public static BellUtil with(Context context) {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new BellUtil((Vibrator) context.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long DURATION = 50;
|
||||||
|
private static final long MIN_PAUSE = 3 * DURATION;
|
||||||
|
|
||||||
|
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
private long lastBell = 0;
|
||||||
|
private final Runnable bellRunnable;
|
||||||
|
|
||||||
|
private BellUtil(final Vibrator vibrator) {
|
||||||
|
bellRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (vibrator != null) {
|
||||||
|
vibrator.vibrate(DURATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void doBell() {
|
||||||
|
long now = now();
|
||||||
|
long timeSinceLastBell = now - lastBell;
|
||||||
|
|
||||||
|
if (timeSinceLastBell < 0) {
|
||||||
|
// there is a next bell pending; don't schedule another one
|
||||||
|
} else if (timeSinceLastBell < MIN_PAUSE) {
|
||||||
|
// there was a bell recently, scheudle the next one
|
||||||
|
handler.postDelayed(bellRunnable, MIN_PAUSE - timeSinceLastBell);
|
||||||
|
lastBell = lastBell + MIN_PAUSE;
|
||||||
|
} else {
|
||||||
|
// the last bell was long ago, do it now
|
||||||
|
bellRunnable.run();
|
||||||
|
lastBell = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long now() {
|
||||||
|
return SystemClock.uptimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -83,6 +83,8 @@ import androidx.viewpager.widget.ViewPager;
|
|||||||
*/
|
*/
|
||||||
public final class TermuxActivity extends Activity implements ServiceConnection {
|
public final class TermuxActivity extends Activity implements ServiceConnection {
|
||||||
|
|
||||||
|
public static final String TERMUX_FAILSAFE_SESSION_ACTION = "com.termux.app.failsafe_session";
|
||||||
|
|
||||||
private static final int CONTEXTMENU_SELECT_URL_ID = 0;
|
private static final int CONTEXTMENU_SELECT_URL_ID = 0;
|
||||||
private static final int CONTEXTMENU_SHARE_TRANSCRIPT_ID = 1;
|
private static final int CONTEXTMENU_SHARE_TRANSCRIPT_ID = 1;
|
||||||
private static final int CONTEXTMENU_PASTE_ID = 3;
|
private static final int CONTEXTMENU_PASTE_ID = 3;
|
||||||
@@ -400,7 +402,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f);
|
mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f);
|
||||||
break;
|
break;
|
||||||
case TermuxPreferences.BELL_VIBRATE:
|
case TermuxPreferences.BELL_VIBRATE:
|
||||||
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(50);
|
BellUtil.with(TermuxActivity.this).doBell();
|
||||||
break;
|
break;
|
||||||
case TermuxPreferences.BELL_IGNORE:
|
case TermuxPreferences.BELL_IGNORE:
|
||||||
// Ignore the bell character.
|
// Ignore the bell character.
|
||||||
@@ -478,9 +480,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
Bundle bundle = getIntent().getExtras();
|
Bundle bundle = getIntent().getExtras();
|
||||||
boolean launchFailsafe = false;
|
boolean launchFailsafe = false;
|
||||||
if (bundle != null) {
|
if (bundle != null) {
|
||||||
launchFailsafe = bundle.getBoolean(TermuxFailsafeActivity.TERMUX_FAILSAFE_SESSION_ACTION, false);
|
launchFailsafe = bundle.getBoolean(TERMUX_FAILSAFE_SESSION_ACTION, false);
|
||||||
}
|
}
|
||||||
clearTemporaryDirectory();
|
|
||||||
addNewSession(launchFailsafe, null);
|
addNewSession(launchFailsafe, null);
|
||||||
} catch (WindowManager.BadTokenException e) {
|
} catch (WindowManager.BadTokenException e) {
|
||||||
// Activity finished - ignore.
|
// Activity finished - ignore.
|
||||||
@@ -494,8 +495,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
if (i != null && Intent.ACTION_RUN.equals(i.getAction())) {
|
if (i != null && Intent.ACTION_RUN.equals(i.getAction())) {
|
||||||
// Android 7.1 app shortcut from res/xml/shortcuts.xml.
|
// Android 7.1 app shortcut from res/xml/shortcuts.xml.
|
||||||
clearTemporaryDirectory();
|
boolean failSafe = i.getBooleanExtra(TERMUX_FAILSAFE_SESSION_ACTION, false);
|
||||||
addNewSession(false, null);
|
addNewSession(failSafe, null);
|
||||||
} else {
|
} else {
|
||||||
switchToSession(getStoredCurrentSessionOrLast());
|
switchToSession(getStoredCurrentSessionOrLast());
|
||||||
}
|
}
|
||||||
@@ -833,18 +834,4 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearTemporaryDirectory() {
|
|
||||||
if (mTermService.getSessions().size() == 0 && !mTermService.isWakelockEnabled()) {
|
|
||||||
File termuxTmpDir = new File(TermuxService.PREFIX_PATH + "/tmp");
|
|
||||||
if (termuxTmpDir.exists()) {
|
|
||||||
try {
|
|
||||||
TermuxInstaller.deleteFolder(termuxTmpDir);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
termuxTmpDir.mkdirs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.termux.app;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
public final class TermuxFailsafeActivity extends Activity {
|
|
||||||
|
|
||||||
public static final String TERMUX_FAILSAFE_SESSION_ACTION = "com.termux.app.failsafe_session";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle bundle) {
|
|
||||||
super.onCreate(bundle);
|
|
||||||
Intent intent = new Intent(TermuxFailsafeActivity.this, TermuxActivity.class);
|
|
||||||
intent.putExtra(TERMUX_FAILSAFE_SESSION_ACTION, true);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -214,7 +214,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
builder.setShowWhen(false);
|
builder.setShowWhen(false);
|
||||||
|
|
||||||
// Background color for small notification icon:
|
// Background color for small notification icon:
|
||||||
builder.setColor(0xFF000000);
|
builder.setColor(0xFF607D8B);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
|
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
|
||||||
@@ -237,6 +237,18 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
File termuxTmpDir = new File(TermuxService.PREFIX_PATH + "/tmp");
|
||||||
|
|
||||||
|
if (termuxTmpDir.exists()) {
|
||||||
|
try {
|
||||||
|
TermuxInstaller.deleteFolder(termuxTmpDir.getCanonicalFile());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(EmulatorDebug.LOG_TAG, "Error while removing directory " + termuxTmpDir.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
termuxTmpDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
if (mWakeLock != null) mWakeLock.release();
|
if (mWakeLock != null) mWakeLock.release();
|
||||||
if (mWifiLock != null) mWifiLock.release();
|
if (mWifiLock != null) mWifiLock.release();
|
||||||
|
|
||||||
@@ -250,14 +262,6 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
return mTerminalSessions;
|
return mTerminalSessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWakelockEnabled() {
|
|
||||||
if (mWakeLock == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return mWakeLock.isHeld();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminalSession createTermSession(String executablePath, String[] arguments, String cwd, boolean failSafe) {
|
TerminalSession createTermSession(String executablePath, String[] arguments, String cwd, boolean failSafe) {
|
||||||
new File(HOME_PATH).mkdirs();
|
new File(HOME_PATH).mkdirs();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="application_name">Termux</string>
|
<string name="application_name">Termux</string>
|
||||||
<string name="shared_user_label">Termux user</string>
|
<string name="shared_user_label">Termux user</string>
|
||||||
<string name="app_failsafe_mode">Termux (failsafe)</string>
|
|
||||||
<string name="new_session">New session</string>
|
<string name="new_session">New session</string>
|
||||||
<string name="new_session_failsafe">Failsafe</string>
|
<string name="new_session_failsafe">Failsafe</string>
|
||||||
<string name="toggle_soft_keyboard">Keyboard</string>
|
<string name="toggle_soft_keyboard">Keyboard</string>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<shortcuts xmlns:tools="http://schemas.android.com/tools"
|
<shortcuts xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<shortcut
|
<shortcut
|
||||||
android:shortcutId="new_session"
|
android:shortcutId="new_session"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
@@ -11,4 +12,19 @@
|
|||||||
android:targetPackage="com.termux"
|
android:targetPackage="com.termux"
|
||||||
android:targetClass="com.termux.app.TermuxActivity"/>
|
android:targetClass="com.termux.app.TermuxActivity"/>
|
||||||
</shortcut>
|
</shortcut>
|
||||||
|
|
||||||
|
<shortcut
|
||||||
|
android:shortcutId="new_failsafe_session"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_new_session"
|
||||||
|
android:shortcutShortLabel="@string/new_session_failsafe"
|
||||||
|
tools:targetApi="n_mr1">
|
||||||
|
<intent
|
||||||
|
android:action="android.intent.action.RUN"
|
||||||
|
android:targetPackage="com.termux"
|
||||||
|
android:targetClass="com.termux.app.TermuxActivity">
|
||||||
|
<extra android:name="com.termux.app.failsafe_session" android:value="true" />
|
||||||
|
</intent>
|
||||||
|
</shortcut>
|
||||||
|
|
||||||
</shortcuts>
|
</shortcuts>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user