Is there a way to ping a host (standard Android or via NDK implementation), and get detailed info on the response? (time, ttl, lost packages, etc..)
I was thinking of some open source app that has this feature but can't find any...
Thanks
Afaik, sending ICMP ECHO requests needs root (i.e. the app that does it needs to be setuid) - and that's not currently possible in "stock" Android (hell, even the InetAddress#isReachable() method in Android is a joke that doesn't work according to spec).
A very basic example using /usr/bin/ping & Process - reading the ping results, using an AsyncTask:
public class PingActivity extends Activity {
PingTask mTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onResume() {
super.onResume();
mTask = new PingTask();
// Ping the host "android.com"
mTask.execute("android.com");
}
#Override
protected void onPause() {
super.onPause();
mTask.stop();
}
class PingTask extends AsyncTask<String, Void, Void> {
PipedOutputStream mPOut;
PipedInputStream mPIn;
LineNumberReader mReader;
Process mProcess;
TextView mText = (TextView) findViewById(R.id.text);
#Override
protected void onPreExecute() {
mPOut = new PipedOutputStream();
try {
mPIn = new PipedInputStream(mPOut);
mReader = new LineNumberReader(new InputStreamReader(mPIn));
} catch (IOException e) {
cancel(true);
}
}
public void stop() {
Process p = mProcess;
if (p != null) {
p.destroy();
}
cancel(true);
}
#Override
protected Void doInBackground(String... params) {
try {
mProcess = new ProcessBuilder()
.command("/system/bin/ping", params[0])
.redirectErrorStream(true)
.start();
try {
InputStream in = mProcess.getInputStream();
OutputStream out = mProcess.getOutputStream();
byte[] buffer = new byte[1024];
int count;
// in -> buffer -> mPOut -> mReader -> 1 line of ping information to parse
while ((count = in.read(buffer)) != -1) {
mPOut.write(buffer, 0, count);
publishProgress();
}
out.close();
in.close();
mPOut.close();
mPIn.close();
} finally {
mProcess.destroy();
mProcess = null;
}
} catch (IOException e) {
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
try {
// Is a line ready to read from the "ping" command?
while (mReader.ready()) {
// This just displays the output, you should typically parse it I guess.
mText.setText(mReader.readLine());
}
} catch (IOException t) {
}
}
}
}
I found a way to execute ping command without root.
Spawns a 'sh' process first, and then execute 'ping' in that shell, the code:
p = new ProcessBuilder("sh").redirectErrorStream(true).start();
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("ping -c 10 " + host + '\n');
os.flush();
// Close the terminal
os.writeBytes("exit\n");
os.flush();
// read ping replys
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
It works fine on my HTC device with CyanogenMod 7.1.0 (Android 2.3.7)
Related
Is there any way to ping a url on Activity onDestroy event. I have tried to use AsyncTask as some tutorial said that it will execute after onDestroy but it doesn't work.
This is the class i ping on destroy
public class inactive extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String res = new String();
try {
BufferedReader reader = null;
URLConnection uc = null;
try {
URL urll = new URL(new StringBuilder()
.append("www.myuru.com").toString());
uc = urll.openConnection();
uc.connect();
reader = new BufferedReader(new InputStreamReader(uc.getInputStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
res = buffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
and this is the onDestroy method from my activity
#Override
protected void onDestroy() {
new inactive(this, sharedpreferences).execute();
super.onDestroy();
}
My tests have shown that this code breaks when it tries to open the connection (urll.openConnection()).
I have tried threads, async tasks and syncronously calling the url with multiple methods like: URLConnection, HttpGet
This is difficult since you have to run the network request in the background(asynchronously).
So even though you schedule the network request to happen in the background it might/probably fail since you then destroy the Activity that sent it.
A different approach might be to save the message you want to send on file(synchronously) and then fire it later when the user start the app again.
A more sophisticated approach might be to start a Service (can live without an Activity being present in the foreground) and let that handle any network request.
As a note, I would however avoid doing large amount of work via Services because then the user will notice degraded performance.
Easy approach:
#Override
onDestroy(){
new Thread(new Runnable() {
#Override
public void run() {
ping();//your ping code here!
}
}).start();
super.onDestroy();
}
I'm asking for a little help here..
I made a Android app in order to get messages from a server. The app just have to show the server's messages and nothing else.
the thing is nothing is shown in the UI, all the messages are shown when I disconnect the server.
It's frustrating because the app get the data's, just don't show them before the disconnection of the server.
Here is my code :
public class SlimpleTextClientActivity extends Activity {
private TextView textView;
private Socket client;
private PrintWriter printwriter;
private BufferedReader bufferedReader;
//Following is the IP address of the chat server. You can change this IP address according to your configuration.
// I have localhost IP address for Android emulator.
private String CHAT_SERVER_IP = "192.168.2.2";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slimple_text_client);
textView = (TextView) findViewById(R.id.textView1);
ChatOperator chatOperator = new ChatOperator();
chatOperator.execute();
}
/**
* This AsyncTask create the connection with the server and initialize the
* chat senders and receivers.
*/
private class ChatOperator extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
try {
client = new Socket(CHAT_SERVER_IP, 6666); // Creating the server socket.
if (client != null) {
printwriter = new PrintWriter(client.getOutputStream(), true);
InputStreamReader inputStreamReader = new InputStreamReader(client.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
} else {
System.out.println("Server has not bean started on port 4444.");
}
} catch (UnknownHostException e) {
System.out.println("Faild to connect server " + CHAT_SERVER_IP);
e.printStackTrace();
} catch (IOException e) {
System.out.println("Faild to connect server " + CHAT_SERVER_IP);
e.printStackTrace();
}
return null;
}
/**
* Following method is executed at the end of doInBackground method.
*/
#Override
protected void onPostExecute(Void result) {
Receiver receiver = new Receiver(); // Initialize chat receiver AsyncTask.
receiver.execute();
}
}
/**
* This AsyncTask continuously reads the input buffer and show the chat
* message if a message is availble.
*/
private class Receiver extends AsyncTask<Void, Void, Void> {
private String message;
#Override
protected Void doInBackground(Void... params) {
while (true) {
try {
if (bufferedReader.ready()) {
message = bufferedReader.readLine();
publishProgress(null);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
#Override
protected void onProgressUpdate(Void... values) {
textView.append( message + "\n");
}
}
}
Hope that someone have an idea because here... I don't x)
Simon !
EDIT :
So... I went to java to test my code (simplification with the System.out.println)
Here is my code :
public class MainClass {
public static void main(String[] args) throws Exception {
final Socket client;
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try{
client = new Socket("192.168.2.2", 6666);
InputStreamReader inputStreamReader = new InputStreamReader(client.getInputStream());
// create new buffered reader
br = new BufferedReader(inputStreamReader);
int value=0;
String monChar = null;
String maChaine = null;
//System.out.println(maChaine);
// reads to the end of the stream
while((value = br.read()) != -1)
{
// converts int to character
char c = (char) value;
maChaine = maChaine + c;
}
}catch(Exception e){
e.printStackTrace();
}finally{
// releases resources associated with the streams
if(is!=null)
is.close();
if(isr!=null)
isr.close();
if(br!=null)
br.close();
}
}
}
The thing is that I can't reach maChaine.
This does the same thing that before : I only can reach my String when the server is disconected.
If I put a "System.out.println(maChaine);" in my While it will print something at each rows and if I put it after it will only do something if the server is disconected.
This question was asked and answered some time ago link. However the answer did not help me yet. I am in sort of the same position as the OP of the other post:
I have an Asynctask in which I make a connection to a certain website, however, most of the time the connection will take some time due to a laggy internetconnection.
I want the user to be able to stop trying to connect at any time.
public class DownloadWebHtml extends AsyncTask<String, Void, Map<String,ArrayList<ArrayList<String>>>> {
HttpURLConnection con = null;
#Override
protected void onPreExecute(){
Button but = (Button) findViewById(301);
but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cancel(true);
con.disconnect();
}
});
}
#Override
protected Map<String, ArrayList<ArrayList<String>>> doInBackground(String... urlcodes) {
//stuff
BufferedReader in = null;
try {
URL url = new URL("some url");
con = (HttpURLConnection) url.openConnection();
in = new BufferedReader(new InputStreamReader(con.getInputStream(),Charset.forName("ISO-8859-1")));
String line = "";
while ((line = in.readLine()) != null && !isCancelled()) {
html.add(line);
}
in.close();
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
} finally {
con.disconnect();
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.d("gettxt", e.getMessage());
}
}
}
if(!html.isEmpty()) {
return //stuff;
}
return null;
}
#Override
protected void onCancelled(){
//cancellation
}
//onpostexecute doing stuff
}
Whenever the button is pressed the whole AsyncTask will by cancelled only after a connection has been made.
Is it possible to immediately stop the whole process on a button press?
Can it be done using the default httpurlconnection?
I tried using the disconnect to trigger an exception while the con.getInputStream is busy, but it failed to work.
I recommend switching to Apache's HTTP Components. It works a charm, and has a thread-safe abort method, as outlined here.
I'm working on a test project, something like a basic chat program using wi-fi connection.
I'm creating sockets to connect two different devices, but my problem is that when I send the first message, it's showing in the other device. But if I try to send again, I can see in the logs from the first one, that the message is sent, but it never shows up in the second device.
I've tried to implement the reading of the received data in another thread..or in Async Task, but the problem is still there. Here are both ways of my implementation :
Single Thread :
public void listenForSocket(){
thread = new Thread(new Runnable() {
public void run() {
Log.e("READDATAFROMSOCKET","READDATAFROMSOCKET");
try {
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
String line = "";
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
changeText(line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
And here is AsyncTask :
class ServerTask extends AsyncTask<Void, Void, Void>{
private String line = "";
#Override
protected Void doInBackground(Void... params) {
try {
Log.e("ASYNCTASK","ASYNCTASK");
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
changeText(line);
}
}
changeText(String); -
private void changeText(final String line) {
runOnUiThread(new Runnable() {
#Override
public void run() {
LinearLayout.LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.RIGHT;
TextView sendMsg = new TextView(MainActivity.this);
sendMsg.setText(DNSUtils.clientName+" : "+line);
sendMsg.setTextColor(Color.DKGRAY);
sendMsg.setTextSize(18);
layout.addView(sendMsg, params);
}
});
}
Any ideas how to fix this issue?
And another problem is that when I am reading the received data, the first letter of the sent string never shows. It always starts from the second letter.
Thanks in advance.
If i were you i will try to implement serverSocket = new ServerSocket(DNSUtils.port); only once with new; not in every thread.
I have an compiled executable that is supposed to copy itself from the res folder, and into the /data/data/package-name/ folder, and change the permissions, and then execute. Every step completes all the way to the end. The output stream seems to be writing, etc. Except when I go check the file system, nothing has been done. I first tried with 'sh' then with 'su' (I have a rooted Cyanogen rom).
Here is the code:
public class UnexecutableActivity extends Activity {
String executablePath;
TextView outputView;
private UnexecutableTask mUnexecutableTask;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
executablePath = getIntent().getData().getPath();
System.out.println(executablePath);
setContentView(R.layout.main);
outputView = (TextView)findViewById(R.id.outputView);
try {
Process process = Runtime.getRuntime().exec("su");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Runnable runexecutable = new Runnable(){
#Override
public void run() {
mUnexecutableTask = new UnexecutableTask();
mUnexecutableTask.execute("");
}
};
runOnUiThread(runexecutable);
}
private class UnexecutableTask extends AsyncTask<String, String, String> {
public UnexecutableTask() {
super();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
outputView.setText(outputView.getText() + "\n" + executablePath + "converted to ");
}
#Override
protected void onPreExecute() {
super.onPreExecute();
outputView.setText("About to un-executable " + executablePath + " ...");
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
outputView.setText(outputView.getText() + "\n" + values[0]);
}
#Override
protected String doInBackground(String... params) {
String bashEscapedPath = executablePath.replace(" ", "\\ ");
try{
String[] commands;
publishProgress("Loading unexecutable...");
InputStream unexecutableInputStream = getAssets().open("unexecutable");
FileOutputStream fos = new FileOutputStream(getDir("", MODE_WORLD_WRITEABLE) + "/unexecutable");
byte[] tmp = new byte[2048];
int l;
while ((l = unexecutableInputStream.read(tmp)) != -1) {
fos.write(tmp, 0, l);
}
fos.flush();
fos.close();
unexecutableInputStream.close();
publishProgress("Changing file permissions...");
commands = new String[] {"/system/bin/chmod","744", getDir("", MODE_WORLD_WRITEABLE) + "/unexecutable"};
Process process = Runtime.getRuntime().exec("su");
StringBuffer res = new StringBuffer();
DataOutputStream os = new DataOutputStream(process.getOutputStream());
DataInputStream osRes = new DataInputStream(new
BufferedInputStream(process.getInputStream()));
for (String single : commands) {
os.writeBytes(single + "\n");
os.flush();
//publishProgress(String.valueOf(osRes.readByte()));
}
os.writeBytes("exit\n");
os.flush();
process.waitFor();
publishProgress("Performing un-executable...");
commands = new String[] {"/data/data/" + getPackageName() + "/unexecutable", bashEscapedPath};
process = Runtime.getRuntime().exec("su");
res = new StringBuffer();
os = new DataOutputStream(process.getOutputStream());
osRes = new DataInputStream(process.getInputStream());
for (String single : commands) {
os.writeBytes(single + "\n");
os.flush();
}
os.writeBytes("exit\n");
os.flush();
publishProgress("Finishing...");
process.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "Success";
}
}
If anyone could fix this up for me, (and hopefully use sh!) I would be eternally grateful.
Not you should not use shell commands. The SDK does not include any shell commands, and you can not rely on these working consistently across devices. You definitely can't rely on su working across devices. :}
executablePath = getIntent().getData().getPath();
This line is giving a null pointer exception for me. Apparently the URI (java.net.Uri) returned by getIntent().getData is null. I am trying to work around it and see if I can create the file with the rest of your code.