Open In App

How to Execute Commands Remotely via SSH in Android?

Last Updated : 23 Feb, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

The SSH protocol uses encryption to secure the connection between a client and a server. All user authentication, commands, output, and file transfers are encrypted to protect against attacks in the network. More often than not you would need to SSH into your cloud Virtual Machines or a remote shell. Usually, we need an SSH client to establish an SSH connection. For Windows, the free (libre) GUI client PuTTY is used for this purpose. Here is how it looks like accessing a remote Linux shell in PuTTY:

The following tutorial illustrates how the same can be achieved in android. Note that we are going to implement this project using the Java language. Library: Apache MINA SSHD

Step by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Adding dependencies

Now we need to add the required dependencies in order to use the apache mina sshd library. Open app/src/build.gradle file in your project directory and add the following under dependencies:

// Adding implementations required for apache mina library

implementation ‘org.apache.mina:mina-core:3.0.0-M2’

implementation ‘org.apache.sshd:sshd-core:2.1.0’

implementation ‘org.apache.sshd:sshd-putty:2.1.0’

implementation ‘org.apache.sshd:sshd-common:2.1.0’

implementation ‘org.slf4j:slf4j-api:1.7.5’

implementation ‘org.slf4j:slf4j-simple:1.6.4’

Step 3: Add permission to the internet in your AndroidManifest.xml file

Add below two lines inside your src/res/AndroidManifest.xml file inside <manifest></manifest> tags.

<uses-permission android:name=”android.permission.INTERNET” />

Step 4: Modify the strings.xml file

Open app > src > main > res > values > strings.xml and add the following code:

XML




<resources>
    <string name="app_name">gfg_ssh</string>
    <string name="host">Host</string>
    <string name="port">Port</string>
    <string name="defaultPort">22</string>
    <string name="username">Username</string>
    <string name="password">Password</string>
    <string name="button_send">SEND</string>
</resources>


Step 5: Building the UI

We are going to have two activities in our app.

  • MainActivity: Here, we’ll enter the login details
  • sshActivity: Here, we’ll see the shell output.

Working with the activity_main.xml file:

Now, Navigate to the app > src > main > res > layout > activity_main.xml and add the below code to the file.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".MainActivity">
  
    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="270dp"
        android:layout_height="413dp"
        android:layout_margin="50dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent=".8">
  
        <EditText
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:autofillHints="host"
            android:background="@color/white"
            android:ems="10"
            android:hint="@string/host"
            android:inputType="textPersonName"
            android:padding="10dp"
            android:textColor="@color/black"
            android:textColorHint="@color/black"
            app:layout_constraintWidth_percent=".8" />
  
        <EditText
            android:id="@+id/portField"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="22dp"
            android:autofillHints="port"
            android:background="@color/white"
            android:ems="10"
            android:hint="@string/port"
            android:inputType="textPersonName"
            android:padding="10dp"
            android:textColor="@color/black"
            android:textColorHint="@color/black"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintWidth_percent=".8"
            tools:text="@string/defaultPort" />
  
        <EditText
            android:id="@+id/usernameField"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="22dp"
            android:autofillHints="username"
            android:background="@color/white"
            android:ems="10"
            android:hint="@string/username"
            android:inputType="textPersonName"
            android:padding="10dp"
            android:textColor="@color/black"
            android:textColorHint="@color/black"
            app:layout_constraintBottom_toTopOf="@+id/passwordField"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/portField"
            app:layout_constraintWidth_percent=".8" />
  
        <EditText
            android:id="@+id/passwordField"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="22dp"
            android:autofillHints="password"
            android:background="@color/white"
            android:ems="10"
            android:hint="@string/password"
            android:inputType="textPassword"
            android:padding="10dp"
            android:textColor="@color/black"
            android:textColorHint="@color/black"
            app:layout_constraintWidth_percent=".8" />
  
        <Button
            android:id="@+id/button"
            android:layout_width="194dp"
            android:layout_height="61dp"
            android:layout_gravity="center"
            android:layout_marginTop="69dp"
            android:layout_marginBottom="373dp"
            android:background="#594FAA"
            android:onClick="authenticate"
            android:text="@string/button_send"
            android:textColor="@android:color/background_light"
            tools:text="@string/button_send" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>


First, create a new activity sshActivity by right-clicking on the activity folder (com.example.gfg_ssh) and then select New > Activity > Empty Activity and Now add the below code to the activity_ssh.xml file for UI of this activity.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".sshActivity">
  
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="688dp"
        android:background="@android:color/black"
        android:textColor="@color/white"
        android:textSize="18sp" />
  
</androidx.coordinatorlayout.widget.CoordinatorLayout>


Step 6: Working with the MainActivity.java file

Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.

Java




import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
  
import androidx.appcompat.app.AppCompatActivity;
  
public class MainActivity extends AppCompatActivity {
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
  
    public void authenticate(View view) {
        
        // Create an intent for sshActivity
        Intent intent = new Intent(this, sshActivity.class);
  
        // Declare fields
        EditText editText = (EditText) findViewById(R.id.editText);
        EditText portField = (EditText) findViewById(R.id.portField);
        EditText usernameField = (EditText) findViewById(R.id.usernameField);
        EditText passwordField = (EditText) findViewById(R.id.passwordField);
          
        // Get input data from fields
        String host = editText.getText().toString();
        String port = portField.getText().toString();
        String username = usernameField.getText().toString();
        String password = passwordField.getText().toString();
  
        // Pass on data to sshActivity via intent
        intent.putExtra("host", host);
        intent.putExtra("port", port);
        intent.putExtra("username", username);
        intent.putExtra("password", password);
        startActivity(intent);
        finish();
    }
}


Step 7: Working with the sshActivity.java file

This is the activity where we import the Apache MINA SSHD library and connect to our remote machine via SSH. We obtain the login data from the intent. Below is the code for the sshActivity.java file. Comments are added inside the code to understand the code in more detail.

Java




import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
  
import androidx.appcompat.app.AppCompatActivity;
  
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
  
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
  
public class sshActivity extends AppCompatActivity {
  
    ClientChannel channel;
    TextView shellOutput;
    String host, username, password;
    Integer port;
    String command;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ssh);
  
        // set output field
        shellOutput = findViewById(R.id.textView);
  
        // Get user credentials from indent
        Intent intent = getIntent();
        host = intent.getStringExtra("host");
        port = Integer.parseInt(intent.getStringExtra("port"));
        username = intent.getStringExtra("username");
        password = intent.getStringExtra("password");
  
        // Command which will be executed
        command = "pwd\n";
          
        // Setting user.com property manually 
        // since isn't set by default in android
        String key = "user.home";
        Context Syscontext;
        Syscontext = getApplicationContext();
        String val = Syscontext.getApplicationInfo().dataDir;
        System.setProperty(key, val);
  
        // Creating a client instance
        SshClient client = SshClient.setUpDefaultClient();
        client.setForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
        client.start();
  
        // Starting new thread because network processes 
        // can interfere with UI if started in main thread
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // Connection establishment and authentication
                    try (ClientSession session = client.connect(username, host, port).verify(10000).getSession()) {
                        session.addPasswordIdentity(password);
                        session.auth().verify(50000);
                        System.out.println("Connection establihed");
  
                        // Create a channel to communicate
                        channel = session.createChannel(Channel.CHANNEL_SHELL);
                        System.out.println("Starting shell");
  
                        ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
                        channel.setOut(responseStream);
  
                        // Open channel
                        channel.open().verify(5, TimeUnit.SECONDS);
                        try (OutputStream pipedIn = channel.getInvertedIn()) {
                            pipedIn.write(command.getBytes());
                            pipedIn.flush();
                        }
  
                        // Close channel
                        channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
                                TimeUnit.SECONDS.toMillis(5));
  
                        // Output after converting to string type
                        String responseString = new String(responseStream.toByteArray());
                        System.out.println(responseString);
                        shellOutput.setText(responseString);
                          
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        client.stop();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }
}


Output:

Logging in:

SSH command execution:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads