Rewrite: Complete Release Tweaks
This commit is contained in:
parent
188bc459b1
commit
300fceae98
11 changed files with 45 additions and 51 deletions
|
|
@ -4,11 +4,11 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.vedroid"
|
namespace = "com.example.androidsshclient"
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.example.vedroid"
|
applicationId = "com.example.androidsshclient"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<application
|
<application
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="Vedroid SSH Client"
|
android:label="Android SSH Client"
|
||||||
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
|
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
|
||||||
<!-- Главный экран -->
|
<!-- Главный экран -->
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.example.vedroid
|
package com.example.androidsshclient
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.example.vedroid
|
package com.example.androidsshclient
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.Intent // ✅ Добавляем этот импорт
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
|
@ -13,7 +13,7 @@ import com.jcraft.jsch.ChannelExec
|
||||||
import com.jcraft.jsch.JSch
|
import com.jcraft.jsch.JSch
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import com.example.vedroid.model.SshProfile
|
import com.example.androidsshclient.model.SshProfile
|
||||||
|
|
||||||
class SshActivity : AppCompatActivity() {
|
class SshActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ class SshActivity : AppCompatActivity() {
|
||||||
private lateinit var profilesSpinner: Spinner
|
private lateinit var profilesSpinner: Spinner
|
||||||
private lateinit var saveProfileButton: Button
|
private lateinit var saveProfileButton: Button
|
||||||
private lateinit var deleteProfileButton: Button
|
private lateinit var deleteProfileButton: Button
|
||||||
private lateinit var terminalButton: Button // ✅ Добавляем terminalButton
|
private lateinit var terminalButton: Button
|
||||||
|
|
||||||
private val jsch = JSch()
|
private val jsch = JSch()
|
||||||
private lateinit var prefs: SharedPreferences
|
private lateinit var prefs: SharedPreferences
|
||||||
|
|
@ -55,7 +55,7 @@ class SshActivity : AppCompatActivity() {
|
||||||
profilesSpinner = findViewById(R.id.profilesSpinner)
|
profilesSpinner = findViewById(R.id.profilesSpinner)
|
||||||
saveProfileButton = findViewById(R.id.saveProfileButton)
|
saveProfileButton = findViewById(R.id.saveProfileButton)
|
||||||
deleteProfileButton = findViewById(R.id.deleteProfileButton)
|
deleteProfileButton = findViewById(R.id.deleteProfileButton)
|
||||||
terminalButton = findViewById(R.id.terminalButton) // ✅ Инициализируем terminalButton
|
terminalButton = findViewById(R.id.terminalButton)
|
||||||
|
|
||||||
executeButton.isEnabled = false
|
executeButton.isEnabled = false
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class SshActivity : AppCompatActivity() {
|
||||||
deleteCurrentProfile()
|
deleteCurrentProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
terminalButton.setOnClickListener { // ✅ Добавляем обработчик для terminalButton
|
terminalButton.setOnClickListener {
|
||||||
val position = profilesSpinner.selectedItemPosition
|
val position = profilesSpinner.selectedItemPosition
|
||||||
if (position > 0) {
|
if (position > 0) {
|
||||||
val profile = profiles[position - 1]
|
val profile = profiles[position - 1]
|
||||||
|
|
@ -160,14 +160,13 @@ class SshActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
prefs.edit().putString("profiles", jsonArray.toString()).apply()
|
prefs.edit().putString("profiles", jsonArray.toString()).apply()
|
||||||
loadProfiles() // Reload to update spinner
|
loadProfiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSaveProfileDialog() {
|
private fun showSaveProfileDialog() {
|
||||||
val dialogView = layoutInflater.inflate(R.layout.dialog_save_profile, null)
|
val dialogView = layoutInflater.inflate(R.layout.dialog_save_profile, null)
|
||||||
val nameInput = dialogView.findViewById<EditText>(R.id.profileNameInput)
|
val nameInput = dialogView.findViewById<EditText>(R.id.profileNameInput)
|
||||||
|
|
||||||
// Pre-fill with current connection details
|
|
||||||
nameInput.setText("${usernameInput.text}@${hostInput.text}")
|
nameInput.setText("${usernameInput.text}@${hostInput.text}")
|
||||||
|
|
||||||
AlertDialog.Builder(this)
|
AlertDialog.Builder(this)
|
||||||
|
|
@ -192,14 +191,13 @@ class SshActivity : AppCompatActivity() {
|
||||||
password = passwordInput.text.toString()
|
password = passwordInput.text.toString()
|
||||||
)
|
)
|
||||||
|
|
||||||
profiles.removeAll { it.name == name } // Remove existing with same name
|
profiles.removeAll { it.name == name }
|
||||||
profiles.add(profile)
|
profiles.add(profile)
|
||||||
saveProfiles()
|
saveProfiles()
|
||||||
|
|
||||||
// Select the newly saved profile
|
|
||||||
profilesSpinner.setSelection(adapter.getPosition(name))
|
profilesSpinner.setSelection(adapter.getPosition(name))
|
||||||
|
|
||||||
appendOutput("✅ Profile '$name' saved")
|
appendOutput("Profile '$name' saved")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteCurrentProfile() {
|
private fun deleteCurrentProfile() {
|
||||||
|
|
@ -213,7 +211,7 @@ class SshActivity : AppCompatActivity() {
|
||||||
profiles.removeAt(position - 1)
|
profiles.removeAt(position - 1)
|
||||||
saveProfiles()
|
saveProfiles()
|
||||||
profilesSpinner.setSelection(0) // Select "New Profile"
|
profilesSpinner.setSelection(0) // Select "New Profile"
|
||||||
appendOutput("🗑️ Profile '${profile.name}' deleted")
|
appendOutput("Profile '${profile.name}' deleted")
|
||||||
}
|
}
|
||||||
.setNegativeButton("Cancel", null)
|
.setNegativeButton("Cancel", null)
|
||||||
.show()
|
.show()
|
||||||
|
|
@ -226,7 +224,7 @@ class SshActivity : AppCompatActivity() {
|
||||||
usernameInput.setText(profile.username)
|
usernameInput.setText(profile.username)
|
||||||
passwordInput.setText(profile.password)
|
passwordInput.setText(profile.password)
|
||||||
|
|
||||||
appendOutput("📁 Loaded profile: ${profile.name}")
|
appendOutput("Loaded profile: ${profile.name}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun connectSsh() {
|
private fun connectSsh() {
|
||||||
|
|
@ -236,28 +234,28 @@ class SshActivity : AppCompatActivity() {
|
||||||
val password = passwordInput.text.toString()
|
val password = passwordInput.text.toString()
|
||||||
|
|
||||||
if (host.isEmpty() || username.isEmpty() || password.isEmpty()) {
|
if (host.isEmpty() || username.isEmpty() || password.isEmpty()) {
|
||||||
appendOutput("❌ Please fill all fields")
|
appendOutput("Please fill all fields")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
appendOutput("🔌 Connecting to $host:$port...")
|
appendOutput("Connecting to $host:$port...")
|
||||||
|
|
||||||
val session = jsch.getSession(username, host, port).apply {
|
val session = jsch.getSession(username, host, port).apply {
|
||||||
setPassword(password)
|
setPassword(password)
|
||||||
setConfig("StrictHostKeyChecking", "no") // ⚠️ Only for testing!
|
setConfig("StrictHostKeyChecking", "no")
|
||||||
connect(30000) // 30 second timeout
|
connect(30000) // 30 second timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
appendOutput("✅ Connected successfully!")
|
appendOutput("Connected successfully!")
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
executeButton.isEnabled = true
|
executeButton.isEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendOutput("❌ Connection failed: ${e.message}")
|
appendOutput("Connection failed: ${e.message}")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -270,13 +268,13 @@ class SshActivity : AppCompatActivity() {
|
||||||
val password = passwordInput.text.toString()
|
val password = passwordInput.text.toString()
|
||||||
|
|
||||||
if (host.isEmpty() || username.isEmpty() || password.isEmpty()) {
|
if (host.isEmpty() || username.isEmpty() || password.isEmpty()) {
|
||||||
appendOutput("❌ Please fill all fields")
|
appendOutput("Please fill all fields")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
appendOutput("💻 Executing: $command")
|
appendOutput("Executing: $command")
|
||||||
|
|
||||||
val session = jsch.getSession(username, host, port).apply {
|
val session = jsch.getSession(username, host, port).apply {
|
||||||
setPassword(password)
|
setPassword(password)
|
||||||
|
|
@ -300,16 +298,16 @@ class SshActivity : AppCompatActivity() {
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
if (output.isNotEmpty()) {
|
if (output.isNotEmpty()) {
|
||||||
appendOutput("📄 Output:\n$output")
|
appendOutput("Output:\n$output")
|
||||||
}
|
}
|
||||||
if (error.isNotEmpty()) {
|
if (error.isNotEmpty()) {
|
||||||
appendOutput("⚠️ Error:\n$error")
|
appendOutput("Error:\n$error")
|
||||||
}
|
}
|
||||||
appendOutput("🔚 Command completed")
|
appendOutput("Command completed")
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendOutput("❌ SSH operation failed: ${e.message}")
|
appendOutput("SSH operation failed: ${e.message}")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +321,6 @@ class SshActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Простой data class для профилей
|
|
||||||
data class SshProfile(
|
data class SshProfile(
|
||||||
val name: String,
|
val name: String,
|
||||||
val host: String,
|
val host: String,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.example.vedroid
|
package com.example.androidsshclient
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.method.ScrollingMovementMethod
|
import android.text.method.ScrollingMovementMethod
|
||||||
|
|
@ -113,7 +113,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
private fun connectToTerminal(host: String, port: Int, username: String, password: String) {
|
private fun connectToTerminal(host: String, port: Int, username: String, password: String) {
|
||||||
terminalScope.launch(Dispatchers.IO) {
|
terminalScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
appendToTerminal("🔌 Connecting to $host:$port...\n")
|
appendToTerminal("Connecting to $host:$port...\n")
|
||||||
|
|
||||||
val session = jsch.getSession(username, host, port).apply {
|
val session = jsch.getSession(username, host, port).apply {
|
||||||
setPassword(password)
|
setPassword(password)
|
||||||
|
|
@ -146,8 +146,8 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
|
|
||||||
isConnected = true
|
isConnected = true
|
||||||
|
|
||||||
appendToTerminal("✅ Connected to SSH terminal\n")
|
appendToTerminal("Connected to SSH terminal\n")
|
||||||
appendToTerminal("💡 Type commands in the input field below\n\n")
|
appendToTerminal("Type commands in the input field below\n\n")
|
||||||
|
|
||||||
// Запускаем чтение вывода
|
// Запускаем чтение вывода
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
|
|
@ -155,7 +155,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendToTerminal("❌ Connection failed: ${e.message}\n")
|
appendToTerminal("Connection failed: ${e.message}\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +175,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
appendToTerminal("\n❌ Connection lost\n")
|
appendToTerminal("\nConnection lost\n")
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
disconnect()
|
disconnect()
|
||||||
|
|
@ -213,7 +213,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
outputStream?.write("$command\n".toByteArray(StandardCharsets.UTF_8))
|
outputStream?.write("$command\n".toByteArray(StandardCharsets.UTF_8))
|
||||||
outputStream?.flush()
|
outputStream?.flush()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendToTerminal("❌ Error sending command\n")
|
appendToTerminal("Error sending command\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,7 +252,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
outputStream?.flush()
|
outputStream?.flush()
|
||||||
appendToTerminal("^C\n")
|
appendToTerminal("^C\n")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendToTerminal("❌ Error sending Ctrl+C\n")
|
appendToTerminal("Error sending Ctrl+C\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +266,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
outputStream?.flush()
|
outputStream?.flush()
|
||||||
appendToTerminal("^D\n")
|
appendToTerminal("^D\n")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
appendToTerminal("❌ Error sending Ctrl+D\n")
|
appendToTerminal("Error sending Ctrl+D\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
appendToTerminal("\n🔌 Disconnected\n")
|
appendToTerminal("\nDisconnected\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.example.vedroid.model
|
package com.example.androidsshclient.model
|
||||||
|
|
||||||
// Теперь не нужно Serializable
|
// Теперь не нужно Serializable
|
||||||
data class SshProfile(
|
data class SshProfile(
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="SSH Client with Profiles"
|
android:text="SSH Client"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginBottom="20dp" />
|
android:layout_marginBottom="20dp" />
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="💾"
|
android:text="Save Profile"
|
||||||
android:layout_marginEnd="4dp" />
|
android:layout_marginEnd="4dp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="🗑️"
|
android:text="Delete Profile"
|
||||||
android:layout_marginStart="4dp" />
|
android:layout_marginStart="4dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
@ -106,12 +106,11 @@
|
||||||
android:text="Execute: ls -la"
|
android:text="Execute: ls -la"
|
||||||
android:layout_marginTop="8dp" />
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
<!-- Добавляем после executeButton -->
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/terminalButton"
|
android:id="@+id/terminalButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="🖥️ Open Interactive Terminal"
|
android:text="Open Interactive Terminal"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:backgroundTint="#4CAF50" />
|
android:backgroundTint="#4CAF50" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="💡 Use ↑↓ for command history"
|
android:text="Use scroll for command history"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:textColor="#AAAAAA"
|
android:textColor="#AAAAAA"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Vedroid</string>
|
<string name="app_name">Android</string>
|
||||||
<string name="hello_world">Hello World!</string>
|
<string name="hello_world">Hello World!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.Vedroid" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="Theme.Android" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">#3F51B5</item>
|
<item name="colorPrimary">#3F51B5</item>
|
||||||
<item name="colorPrimaryVariant">#303F9F</item>
|
<item name="colorPrimaryVariant">#303F9F</item>
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,8 @@ dependencyResolutionManagement {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = uri("https://dl.bintray.com/termux/termux-packages/") }
|
|
||||||
maven { url = uri("https://grimler.se/termux-packages/") }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = "vedroid"
|
rootProject.name = "AndroidSSHClient"
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue