I am trying to make something from this simple example :
SSH, execute remote commands with Android
I just want to see if I can connect from my android phone to a linux server using SSH but it doesn't work...
Here is my main code :
package com.example.ssh;
import java.util.Properties;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try
{
JSch jsch = new JSch();
Session session = jsch.getSession("root","192.168.0.26", 22);
session.setPassword("xxxxx");
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
What did I do wrong ? I have no error messages and I don't see any SSH connection on my Linux. I added the libraries jsch and jzlib. I have no problem to get connect with a putty session.
EDIT1 : In fact, I found an error which explain why it doesn't work even if I don't know how to resolve the problem. The error is :
android.os.NetworkOnMainThreadException
so it seems to mean that the app can't perform a networking operation on its main thread...
You have to execute that code in another thread so you don't hang the UI thread is what that exception means. If the UI thread is executing a network call it can't repaint the UI so your users sees a frozen UI that doesn't respond to them while the app is waiting on the network call to finish. Android wants to avoid bad user experiences like this so it prevents you from doing things like this by throwing this exception.
Your onCreate() method should invoke another thread (I'd suggest using an AsyncTask over a raw thread) to perform the SSH connection. Then when it's done it can post the results back to the UI thread and safely update your application's UI from the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
chubbsondubs's solution is perfect. I just want to share the code that I made for this problem too for people who want a quick solution:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AsyncTask<Integer, Void, Void>(){
#Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("root", "myPW","192.168.0.26", 22);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}.execute(1);
}
public static String executeRemoteCommand(String username,String password,String hostname,int port)
throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)
session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand("lsusb > /home/pi/test.txt");
channelssh.connect();
channelssh.disconnect();
return baos.toString();
}
A Kotlin solution:
import android.os.AsyncTask
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import java.io.ByteArrayOutputStream
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
SshTask().execute()
}
class SshTask : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg p0: Void?): String {
val output = executeRemoteCommand("demo", "password", "test.rebex.net")
print(output)
return output
}
}
}
fun executeRemoteCommand(username: String,
password: String,
hostname: String,
port: Int = 22): String {
val jsch = JSch()
val session = jsch.getSession(username, hostname, port)
session.setPassword(password)
// Avoid asking for key confirmation.
val properties = Properties()
properties.put("StrictHostKeyChecking", "no")
session.setConfig(properties)
session.connect()
// Create SSH Channel.
val sshChannel = session.openChannel("exec") as ChannelExec
val outputStream = ByteArrayOutputStream()
sshChannel.outputStream = outputStream
// Execute command.
sshChannel.setCommand("ls")
sshChannel.connect()
// Sleep needed in order to wait long enough to get result back.
Thread.sleep(1_000)
sshChannel.disconnect()
session.disconnect()
return outputStream.toString()
}
In build.gradle add:
dependencies {
...
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}
Related
Not able to start appium from code made a function and called before desired capability, post desired capability.
Getting error while running below code: C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium\lib\appium.js:1
import _ from 'lodash';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Object.compileFunction (node:vm:352:18)
//Option 1
public static void runAppiumService(String portNumber) {
//Build parameters for appium server:
AppiumServiceBuilder appiumServiceBuilder = new AppiumServiceBuilder();
appiumServiceBuilder.usingPort(Integer.parseInt(portNumber))
.withIPAddress("127.0.0.1")
.withAppiumJS(new File("C:\\Users\\Ritesh Mittal\\AppData\\Roaming\\npm\\node_modules\\appium\\lib\\appium.js"))
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withLogFile(new File(System.getProperty("user.dir") + "/target/resources/appium_server_logs" + Thread.currentThread().getId()));
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(appiumServiceBuilder);
service.start();
}
//Option 2
DesiredCapabilities dc = new DesiredCapabilities();
dc.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
//dc.setCapability(MobileCapabilityType.PLATFORM_VERSION,platformVersion);
dc.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
dc.setCapability(MobileCapabilityType.APP, System.getProperty("user.dir")+"/src/test/resources/apps/CRMNextNative 6.29.0-release_screenshot_enabled.apk");
dc.setCapability("automationName","UiAutomator2");
dc.setCapability("appPackage", "com.crmnextmobile.crmnextofflineplay");
dc.setCapability("appActivity", "com.crmnextmobile.crmnextofflineplay.qr.QrScannerActivity");
dc.setCapability("enforceAppInsall", true);
URL url = new URL("http://127.0.0.1:"+portNumber+"/wd/hub");
AppiumDriverLocalService service;
service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder()
.usingPort(Integer.parseInt(portNumber))
.usingDriverExecutable(new File("C:\\Program Files\\nodejs\\node.exe"))
.withAppiumJS(new File("C:\\Users\\Ritesh Mittal\\AppData\\Roaming\\npm\\node_modules\\appium\\lib\\appium.js"))
.withArgument(GeneralServerFlag.RELAXED_SECURITY)
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withArgument(GeneralServerFlag.LOG_LEVEL, "error")
.withCapabilities(dc));
service.start();
logger.info("Appium started ......");
Thread.sleep(10000);
driver = new AppiumDriver(url,dc);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
System.out.println("CRMNext automation start..");
please try this code:
public void startServer() throws IOException, InterruptedException {
Properties prop = new Properties();
InputStream input = null;
input = getClass().getClassLoader().getResourceAsStream("config.properties");
try {
prop.load(input);
} catch (IOException e) {
e.printStackTrace();
}
Map<String, String> env = new HashMap<>(System.getenv());
env.put("PATH", prop.getProperty("Local_Path") + env.get("PATH"));
env.put("ANDROID_HOME", prop.getProperty("Android_Home"));
int port = Integer.parseInt(prop.getProperty("port"));
System.out.println("port--> "+port);
service = AppiumDriverLocalService.buildService(
new AppiumServiceBuilder().usingDriverExecutable(new File(prop.getProperty("DriverExecutable")))
.withAppiumJS(new File(prop.getProperty("AppiumJS"))).withIPAddress(prop.getProperty("IP"))
.usingPort(port).withLogFile(new File("AppiumLog.text")).withEnvironment(env));
service.start();
Thread.sleep(20000);
}
I solved it. I was doing two mistakes
Appium Path was not correct.
Incorrect path was
builder.withAppiumJS(new File("C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium\lib\appium.js"));
corrected:
builder.withAppiumJS(new File("C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium"));
added arguments
builder.withArgument(() -> "--base-path", "/wd/");
I am trying to make something from this simple example :
SSH, execute remote commands with Android
i am trying to control my raspberry pi through ssh with simple command execution, everything ok except , it doesn't work! the command i am trying is to make empty text.txt, but when i check on the raspberry, there is no such file created. also tried a sudo reboot command , still doesn't work
Here is my main code:
package com.example.thesacredhaven.samplessh;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
executeRemoteCommand("pi","root","192.168.219.178",22);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void executeRemoteCommand(
String username,
String password,
String hostname,
int port) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, 22);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.setTimeout(10000);
session.connect();
// SSH Channel
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("lsusb > /home/pi/test.txt");
channel.connect();
channel.disconnect();
}
}
What did I do wrong ? I have no error messages and I don't see any SSH connection on my Linux. is there any library ? or some missing step?
I have such a problem: on device with Android OS, I am executing action script code. And I have a method, which must to send some data to sever. But!!! Even if I stop my application before sending some data to server - it still somehow sends that data. I don't understand how it can be?? Anyone faced with this problem? Please help me. Thanks.
public class VerifyCommand extends SimpleCommand
{
override public function execute(notification:INotification):void
{
//here is the place, where I put breakpoint and stop the program
trace("here is the place, where I put breakpoint and stop the program");
verify();
}
private function verify():void
{
var tempError:Error = new Error();
var stackTrace:String = tempError.getStackTrace();
trace(stackTrace);
var request : URLRequest = new URLRequest();
request.url = "http://www.somesite.com";
request.method = URLRequestMethod.POST;
request.contentType = "application/x-www-form-urlencoded; charset=utf-8";
request.data = variables;
request.useCache = false;
request.cacheResponse = false;
var call_loader:URLLoader = new URLLoader();
call_loader.dataFormat = URLLoaderDataFormat.TEXT;
call_loader.addEventListener(Event.COMPLETE, onVerificationResult);
call_loader.addEventListener(IOErrorEvent.IO_ERROR, onVerificationError);
call_loader.load(request);
}
private function onVerificationResult(event:Event):void
{
trace("all ok");
}
private function onVerificationError( event:Event):void
{
trace("all failed");
}
}
It was a debugger fault , it doesn't stop exactly where I think it should.
I am trying to send an object to a server i wrote. I have only just learnt about AsyncTask and am trying to use it in order to keep networking tasks off the main thread. It is currently making the connection but is not receiving the object. I know the server is fine because I have tested it using code written to send the object from my laptop. Also I am not receiving any error messages.
Code:
private class sendToServer extends AsyncTask<UserObject, Integer, Double> {
#Override
protected Double doInBackground(UserObject...userObjects) {
ObjectOutputStream oos = null;
String Header = "GPSUpdate";
String Userid = "07000000001";
String Latitude = "6.00";
String Longitude = "6.00";
try{
Socket socket = new Socket("igor.gold.ac.uk", 3000);
oos = new ObjectOutputStream(socket.getOutputStream());
UserObject [] userObject = new UserObject[1];
userObject[0] = new UserObject();
userObject[0].setHeader(Header);
userObject[0].setUserid(Userid);
userObject[0].setLatitude(Latitude);
userObject[0].setLongitude(Longitude);
oos.writeObject(userObject[0]);
oos.flush();
oos.close();
}
catch(Exception e){
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onPostExecute(Double result) {
}
}
Also the code to send the object works when ran from my laptop. Do I have to set permissions or anything different if I'm using AsyncTask to handle network operations.
Thanks for any help given.
You have an empty block catching all exceptions! At least log what's going on in there...
Does your app have the INTERNET permission declared in its manifest?
Does UserObject implement Serializable?
I found the problem it was my own simple mistake. All the code was fine but the Object being sent was in a different package on the server than the one being sent. Updated them so they are both in the same package in their respective location.
I have a problem detecting zero class bluetooth devices with my Galaxy Tab using the Android Bluetooth API. It simply does not "see" some devices although I can detect them with my phone or computer. Has anyone run into this problem? I´m writing an app which depends on pairing with a device through bluetooth and some help in this regard would be most appreciated.
Note: This solution will only work with old Android OSs, due to it's need for access to the device logs.
Yes! I have exactly the same problem, abeit on a Samsung Galaxy S, and LG Optimus One. I wrote a class you can reuse to fix this, no idea if it will work on the Galaxy Tab, but you can try:
package com.yourpackagename;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
// This class exists due to a bug in the Broadcomm bluetooth stack, which is
// used by many Android smart-phone manufacturers (LG, Samsung HTC etc.). That
// bug prevents discovery of ALL bluetooth devices that report their Class of Device (CoD)
// code as 0x00, which prevent many SPP (Serial Port Profile) devices from working.
//
// See: http://www.google.com/codesearch/p?hl=en#4hzE-Xyu5Wo/vendor/brcm/adaptation/dtun/dtunc_bz4/dtun_hcid.c&q=%22Device%20[%25s]%20class%20is%200x00%20-%20skip%20it.%22&sa=N&cd=1&ct=rc
// And: http://stackoverflow.com/questions/4215398/bluetooth-device-not-discoverable
// And: http://www.reddit.com/r/Android/comments/hao6p/my_experience_with_htc_support_eu_anyone_has/
//
// How to use (from your Activity class):
//
// (new BluetoothClassZeroDiscoveryTask(this, new BluetoothDiscoveryCallback())).execute();
//
// Where BluetoothDiscoveryCallback is a class defined e.g. in your Activity. The call method
// will be called after the discovery task completes, and is passed the complete list
// of paired bluetooth devices, including those that are undiscoverable due to the above bug.
//
// private class BluetoothDiscoveryCallback implements Action<ArrayList<BluetoothDevice>>
// {
// public void call(ArrayList<BluetoothDevice> devices)
// {
// // Now you have the list of ALL available devices,
// // including those that report class 0x00.
// }
// }
//
// // Java equivalent of the built-in Action from C#.
// public interface Action<T>
// {
// void call(T target);
// }
//
public class BluetoothClassZeroDiscoveryTask extends AsyncTask<Void, Void, Void>
{
// This is the well-known ID for bluetooth serial port profile (SPP) devices.
public static final UUID BluetoothSerialUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private Activity _parent;
private boolean _discoveryComplete = false;
private Action<ArrayList<BluetoothDevice>> _callback;
private ArrayList<BluetoothDevice> _devices = new ArrayList<BluetoothDevice>();
private Calendar _discoveryStartTime;
private SimpleDateFormat _logDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
private BluetoothAdapter _adapter;
private ProgressDialog _progressDialog;
public BluetoothClassZeroDiscoveryTask(Activity parent, Action<ArrayList<BluetoothDevice>> callback)
{
_callback = callback;
_parent = parent;
_adapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
_parent.registerReceiver(mReceiver, foundFilter);
IntentFilter finishedFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
_parent.registerReceiver(mReceiver, finishedFilter);
// This task performs a scan for bluetooth devices, which
// takes ~ 12 seconds, so show an indeterminate progress bar.
_progressDialog = ProgressDialog.show(_parent, "", "Discovering bluetooth devices...", true);
}
// Kicks off bluetooth discovery.
#Override
protected Void doInBackground(Void... params)
{
_discoveryStartTime = Calendar.getInstance();
_adapter.startDiscovery();
while (!_discoveryComplete)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e) { }
}
_adapter.cancelDiscovery();
return null;
}
// Provide notification of results to client.
#Override
protected void onPostExecute(Void result)
{
_progressDialog.dismiss();
_parent.unregisterReceiver(mReceiver);
_callback.call(_devices);
}
// Handler for bluetooth discovery events.
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, (we'll add it after the scan completes).
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
{
_devices.add(device);
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
// Add all already-paired devices to the list.
for (BluetoothDevice device : _adapter.getBondedDevices())
{
_devices.add(device);
}
// Trawl through the logs to find any devices that were skipped >:(
try
{
Process process = Runtime.getRuntime().exec("logcat -d -v time *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
Pattern pattern = Pattern.compile("(.{18}).*\\[(.+)\\] class is 0x00 - skip it.");
while ((line = bufferedReader.readLine()) != null)
{
Matcher matcher = pattern.matcher(line);
if (matcher.find())
{
// Found a blocked device, check if it was newly discovered.
// Android log timestamps don't contain the year!?
String logTimeStamp = Integer.toString(_discoveryStartTime.get(Calendar.YEAR)) + "-" + matcher.group(1);
Date logTime = null;
try
{
logTime = _logDateFormat.parse(logTimeStamp);
}
catch (ParseException e) { }
if (logTime != null)
{
if (logTime.after(_discoveryStartTime.getTime()))
{
// Device was discovered during this scan,
// now we want to get the name of the device.
String deviceAddress = matcher.group(2);
BluetoothDevice device = _adapter.getRemoteDevice(deviceAddress);
// In order to get the name, we must attempt to connect to the device.
// This will attempt to pair with the device, and will ask the user
// for a PIN code if one is required.
try
{
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(BluetoothSerialUuid);
socket.connect();
socket.close();
_devices.add(device);
}
catch (IOException e) { }
}
}
}
}
}
catch (IOException e) {}
_discoveryComplete = true;
}
}
};
}
See also:
http://zornsoftware.codenature.info/blog/pairing-spp-bluetooth-devices-with-android-phones.html