I can't seem to get runtime.exec working in my android app. I've tried it with a host of shell utilities, here's the code I'm using:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
filesPrinter = (Button) findViewById(R.id.print_files);
filesPrinter.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
Process proc = Runtime.getRuntime().exec("ls");
out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while((line = in.readLine()) != null) {
System.out.println(line);
}
System.out.println("Done reading");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
I don't get an error, but also do not get anything in logcat.
The problem ended up being a bug with the eclipse logcat. Using adb logcat, I could see everything that was supposed to be outputted. For some reason, logcat on eclipse showed that it was connected but was not receiving any application level output from the emulator.
Maybe your current working directory (which is what ls scans without any parameters) simply contains no files. Try providing a path as a command argument.
Think you're missing a proc.waitFor()....
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
filesPrinter = (Button) findViewById(R.id.print_files);
filesPrinter.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
Process proc = Runtime.getRuntime().exec("ls");
out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while((line = in.readLine()) != null) {
System.out.println(line);
}
System.out.println("Done reading");
//
proc.waitFor(); // THIS!!!
//
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
Related
Hello I have wrote this code to read my csv and when I click a button I get an output. The thing is the only line that gets printed is the final row of the csv. How can I modify my code so with each and every click I get next line?
``InputStream inputStream;
String[] ids;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.textView);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
inputStream = getResources().openRawResource(R.raw.dating);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try{
String csvLine;
while((csvLine = reader.readLine())!=null){
ids = csvLine.split(",");
try{
textView.setText(ids[3]+ids[4]);
}catch (Exception e){
Log.e("Unknown exception", e.toString());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
Move the:
inputStream = getResources().openRawResource(R.raw.dating);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
out off the OnClickListener.
That's all.
To run the executable and get the real-time output I'm using the following code (with String[] command = new String[]{"/a.out"};):
public static void execute(String... command) {
try {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
final Process proc = builder.start();
new Thread(new Runnable() {
public void run() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
EventBus.getDefault().post(new MessageEvent(line+"\n"));
}
} catch (Exception e) {
// TODO
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// ignore
}
}
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
The command should be executed inside a service:
public class Service extends IntentService {
...
#Override
protected void onHandleIntent(Intent intent) {
String[] command = new String[]{"/a.out"};
Class.execute(command);
}
}
But I only get one line as an output, nothing more, but it should be hundreds of them. I already tried it on my computer by replacing EventBus.getDefault().post(new MessageEvent(line+"\n")); with System.out.println(line); and it works just fine.
Additional information: Subscriber handles EventBus through:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
tv.append(event.getMessage());
}
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
And tv is a TextView: TextView tv = (TextView)findViewById(R.id.TextView);
This structure was tested with a simple method, which in the following shown. It updated the TextView and there was more than one line passed to the TextView. So I guess it must be something inside my execution method.
public static void test() {
for(int i = 0; i<500000; i++)
EventBus.getDefault().post(new MessageEvent(i+"\n"));
}
Why does the EventBus only passes one line? What can I change to get the expected result?
Edit: Changing onMessageEvent() to:
public void onMessageEvent(MessageEvent event) {
Log.i("Activity",event.getMessage());
}
Also just one line.
Tested it with another executable, now it works just fine, any idea why it works now?
Is it passing only one line? It looks like your appending all the text into a single line by doing this -> tv.append(event.getMessage());
In your onMessageEvent() method try to System.out.println(event.getMessage()); to assert if the problem is really from EventBus.
adminpage.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_page);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mTextView = (TextView) findViewById(R.id.dataList);
Button button = (Button) findViewById(R.id.rf);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// new JSONTask().execute("https://jsonparsingdemo-cec5b.firebaseapp.com/jsonData/moviesDemoItem.txt");
new JSONTask().execute("https://jsonparsingdemo-cec5b.firebaseapp.com/jsonData/moviesDemoList.txt");
}
});
}
public static class JSONTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("movies");
StringBuffer finalBufferedData = new StringBuffer();
for (int i = 0; i < parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
String movieName = finalObject.getString("movie");
int year = finalObject.getInt("year");
finalBufferedData.append(movieName + " - " + year + "\n");
}
//JSONObject finalObject = parentArray.getJSONObject(0);
return finalBufferedData.toString();
//return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
mTextView.setText(result);
}
}
So base on this what i can conclude is.
1) JSONTASK will take the url and break them in to different string and link them together and return finalBufferedData.toString();
2) The onPostExecute will take the result and set it to mTextView.
3) onclicklistener will run the function and perform step 2 and display.
Question!
I don't see anywhere in the code that call the function onPostExecute(String result) <-- what is the result?? is it the return finalBufferedData.toString()?
I am running the same function in another activity, how do i display in TextView without the onClicklistener to execute it.
1. Yes.. it is the return value(finalBufferedData.toString()).It is the output (result/return) of doInBackground method.
2. Call in onCreate or onResume for executing without onClick. eg:-
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
// put the AsyncTask call here
I am trying to read all the text from server, I think that my code is not retrieving text from server will you please help me how can I fix this problem, I am new to android development. Thanks in advance
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv= (TextView)findViewById(R.id.my_text);
try {
URL url = new URL("http://www.google.com:80/");
StringBuilder content = new StringBuilder();
// read text returned by server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null) {
content.append(line +"\n");
}
tv.setText(content.toString());
setContentView(tv);
in.close();
}
catch (MalformedURLException e) {
System.out.println("Malformed URL: " + e.getMessage());
}
catch (IOException e) {
System.out.println("I/O Error: " + e.getMessage());
}
};
}
Take these lines
tv.setText(line);
setContentView(tv);
out of while loop
Use StringBuilder object (declared before loop) in while loop and append the strings in that.
After while loop take string from StringBuilder and do tv.setText(string)
May be you can try like this, just a thought only :
StringBuilder content = new StringBuilder();
// read text returned by server
BufferedReader in = new BufferedReader(new InputStreamReader(new URL("http://www.google.com:80/").openConnection().getInputStream()));
String line;
while ((line = in.readLine()) != null) {
content.append(line +"\n");
}
tv.setText(content.toString());
setContentView(tv);
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)