how to link process output to textview and automatically update in realtime? - android

I'm not the best programmer, actually, I'm pretty bad :(
I need help with something thats driving my crazy. basically I have a tcpdump process, I want to extract the output and put it into a textview which is updated every few milliseconds, I've tried everything and just cant get it to work.
I don't get any errors and it seems to work in the background, but only displays chunks of text only after I go to the homescreen and return back into the app. however, it doesnt constantly update the textview, and sometimes hangs and crashes.
I've created a simple handler which can update the textview with plain text without problems, but then i faced major problems getting it to read the process.
Begin button
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.capture);
this.LiveTraffic = (TextView) findViewById(R.id.LiveTraffic);
this.CaptureText = (TextView) findViewById(R.id.CaptureText);
((TextView) findViewById(R.id.ipv4)).setText(getLocalIpv4Address());
((TextView) findViewById(R.id.ipv6)).setText(getLocalIpv6Address());
//Begin button
final Button startButton = (Button) findViewById(R.id.start);
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "Now Capturing Packets", Toast.LENGTH_LONG).show();
try {
process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("/data/local/tcpdump -q\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
os.close();
inputStream = new DataInputStream(process.getInputStream());
Thread.sleep(1000);
Process process2 = Runtime.getRuntime().exec("ps tcpdump");
DataInputStream in = new DataInputStream(process2.getInputStream());
String temp = in.readLine();
temp = in.readLine();
temp = temp.replaceAll("^root *([0-9]*).*", "$1");
pid = Integer.parseInt(temp);
Log.e("MyTemp", "" + pid);
process2.destroy();
CaptureActivity.this.thisActivity.CaptureText.setText("Active");
} catch (Exception e) {
}
ListenThread thread = new ListenThread(new BufferedReader(new InputStreamReader(inputStream)));
thread.start();
}
});
}
ListenThread class
public class ListenThread extends Thread {
public ListenThread(BufferedReader reader) {
this.reader = reader;
}
private BufferedReader reader = null;
#Override
public void run() {
reader = new BufferedReader(new InputStreamReader(inputStream));
while (true) {
try {
CaptureActivity.this.thisActivity.CaptureText.setText("exec");
int a = 1;
String received = reader.readLine();
while (a == 1) {
CaptureActivity.this.thisActivity.LiveTraffic.append(received);
CaptureActivity.this.thisActivity.LiveTraffic.append("\n");
received = reader.readLine();
CaptureActivity.this.thisActivity.CaptureText.setText("in loop");
}
CaptureActivity.this.thisActivity.CaptureText.setText("out loop");
} catch (Exception e) {
Log.e("FSE", "", e);
}
}
}
}

I am not an android expert but I notice that:
you are running I/O operations in the UI thread - that will freeze your GUI until the I/O operation finishes ==> run them in a separate thread.
you update the UI from outside the UI thread in ListenThread, which can lead to unexpected results
You can read more about it in this tutorial (make sure you read the 2 examples as the first one is broken (on purpose)).
EDIT
In conclusion you should have something like this in your first piece of code:
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "Now Capturing Packets", Toast.LENGTH_LONG).show();
new Thread(new Runnable() {
public void run() {
try {
process = Runtime.getRuntime().exec("su");
...
CaptureActivity.this.runOnUiThread(new Runnable() {
public void run() {
CaptureActivity.this.thisActivity.CaptureText.setText("Active");
}
});
} catch (Exception e) {
}
ListenThread thread = new ListenThread(new BufferedReader(new InputStreamReader(inputStream)));
thread.start();
}
}).start();
}
});
and in the second:
while (true) {
try {
CaptureActivity.this.runOnUiThread(new Runnable() {
public void run() {
CaptureActivity.this.thisActivity.CaptureText.setText("exec");
}
});
int a = 1;
String received = reader.readLine();
while (a == 1) {
CaptureActivity.this.runOnUiThread(new Runnable() {
public void run() {
CaptureActivity.this.thisActivity.LiveTraffic.append(received);
CaptureActivity.this.thisActivity.LiveTraffic.append("\n");
CaptureActivity.this.thisActivity.CaptureText.setText("in loop");
}
});
received = reader.readLine();
}
CaptureActivity.this.runOnUiThread(new Runnable() {
public void run() {
CaptureActivity.this.thisActivity.CaptureText.setText("out loop");
}
});
} catch (Exception e) {
Log.e("FSE", "", e);
}
}
That should solve the specific UI interaction issue. But there are other logic problems in your code which go beyond this question (for example the fact that you never test if you have reached the end of the file you are reading, the fact that while(a==1) is an infinite loop because you never change the value of a etc.).

Related

Android edittext loses and repeats texts received via TCP socket

I have a problem with a edittext in Android Studio.
Normally, log.d reports the messages received via TCP socket and
those appears in the textedit mySocketrx. When there is a fast
message burst log.d is still working fine but textedit loses and repeats
messages.
protected void onCreate(Bundle savedInstanceState) {
final EditText mySocketrx = (EditText) findViewById(R.id.Socketrx);
new Thread(new Runnable() { // Client TCP socket thread
public void run() {
try {
s = new Socket("192.168.1.161",6000);
p = new PrintStream(s.getOutputStream());
b = new BufferedReader ( new InputStreamReader( s.getInputStream() ) );
} catch(Exception ex) { }
while (true) {
try {
status = b.readLine();
Log.d("DEBUG", status);
runOnUiThread(new Runnable() {
public void run() {
mySocketrx.append(status + "\n");
}
} );
} catch(Exception ex) { }
}
}
}).start();
}
Instead of append() use the setText() method.

How to make an Image View flash in sequence on a separate thread?

I am in the process of making a simple practice Morse code application.
I am trying to make an Image View flash between black and white in the SOS sequence based on Morse. When researching how to achieve this i realized i would have to do this on a separate thread in order to not block the UI thread.
The problem is that i am currently updating the Image View from outside of the UI thread which is stated to be a bad idea. At the moment i am trying to pass the Image View to the worker thread class that contains the logic for the screen flash.
I am new to multi-threading and i am pretty sure i am doing this completely backwards/incorrectly. Does anyone have an advice or ideas as of the best method to go about this?
new Thread(new Runnable() {
public void run() {
sf = new ScreenFlash("...---...", imgV);
sf.flashScreen();
}
}).start();
public ScreenFlash(String message, ImageView imgV){
this.message = message.replaceAll(".(?!$)", "$0 ");
this.imgV = imgV;
}
public void flashScreen() {
int offIntervalTime = 50;
char[] cArray = message.toCharArray();
for (int i = 0; i < cArray.length; i++) {
if (cArray[i] == '.') {
imgV.setBackgroundColor(Color.WHITE);
try {
Thread.sleep(50);
}catch(Exception e)
{
}
imgV.setBackgroundColor(Color.BLACK);
try {
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
} else if(cArray[i] == ' ')
{
try{
Thread.sleep(100);
}catch(Exception e)
{
}
}
else {
try{
imgV.setBackgroundColor(Color.WHITE);
Thread.sleep(dash);
}catch(Exception e)
{
}
try{
imgV.setBackgroundColor(Color.BLACK);
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
}
}
Take a look at the Handler class documentation and how to communicate with the UI thread from a background thread:
http://developer.android.com/training/multiple-threads/communicate-ui.html
You can update your imageView in onHandleMessage()
#Override
public void handleMessage(Message inputMessage) {
imageView.setBackgroundColor(android.R.color.white)
...
}

Get website source code from WebView

I'm trying to get HTML source but it's freezing the app.
I don't know what the problem is and I added Internet Permission
I took this code from a site but it's not working with me. It works until I press the button and then it just freezes.
I hope some one can help me with this, here is the code I'm using:
public class MainActivity extends Activity {
private String HTML = "";
EditText tv;
private ProgressDialog m_ProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button)findViewById(R.id.button1);
tv = (EditText)findViewById(R.id.editText1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
getHTML("http://m.Facebook.com/");
}
});
}
public void getHTML(String paramString)
{
try
{
BufferedInputStream localBufferedInputStream = new BufferedInputStream(new URL(paramString).openConnection().getInputStream());
ByteArrayBuffer localByteArrayBuffer = new ByteArrayBuffer(50);
while (true)
{
int i = localBufferedInputStream.read();
if (i == -1)
{
HTML = new String(localByteArrayBuffer.toByteArray());
handler.sendEmptyMessage(0);
return;
}
i = (byte)i;
localByteArrayBuffer.append(i);
}
}
catch (Exception localException)
{
while (true)
this.HTML = "Error!";
}
}
private Handler handler = new Handler()
{
public void handleMessage(Message paramMessage)
{
EditText localEditText = (EditText)MainActivity.this.findViewById(R.id.editText1);
MainActivity.this.m_ProgressDialog.dismiss();
localEditText.setText(MainActivity.this.HTML);
}
};
}
What does this have to to with a WebView? You have a NetworkOnMainThreadExeption. You have to put your code in an AsyncTask or Thread to prevent this.
In addition to doing network work on your main thread (a big no-no in Android - use an AsyncTask), your error is probably happening here:
public void getHTML(String paramString) {
try {
BufferedInputStream localBufferedInputStream = new BufferedInputStream(new URL(paramString).openConnection().getInputStream());
ByteArrayBuffer localByteArrayBuffer = new ByteArrayBuffer(50);
while (true) {
int i = localBufferedInputStream.read();
if (i == -1) {
HTML = new String(localByteArrayBuffer.toByteArray());
handler.sendEmptyMessage(0);
return;
}
i = (byte) i;
localByteArrayBuffer.append(i);
}
} catch (Exception localException) {
while (true) // <<< this will create an infinite loop when an error occurs
this.HTML = "Error!";
}
}
Try removing while (true) from your catch statement.

Updating CPU frequency on textView (howto?)

private String ReadCPUMhz()
{
ProcessBuilder cmd;
String result="";
int resultshow = 0;
try{
String[] args = {"/system/bin/cat", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"};
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1)
{
result = result + new String(re);
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
I used setText to write the value from result to a textView.
So it read out the current cpu frequency when app was started and write it to this textView. The app shows f.e. 1200Mhz the whole time the app is opened. It didn't update the value.
How can I use Timer or other methods to update the current value after 1s or 250ms and write it to the textView?
It should display the current CPU frequency. F.e.: 300Mhz - 1200Mhz.. updating after 1s or 250ms..
Please help me :-)
Best regards
Marcus
Try using runOnUiThread for updating Textview from Thread as:
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
while(true)
{
Thread.sleep(100L); //SET INTERVAL TO UPDATE TEXTVIEW TEXT
Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
String str=ReadCPUMhz(); //CALL YOUR METHOD HERE
tvnn.setText(str); SET TEXT HERE
});
}
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
//....YOUR CODE
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myThread();
//YOUR CODE..

Scale a bitmap and upload to server, ui thread blocking

I'm working on an Android app where I need to upload an image to a server.
Before I upload the image, I'm scaling it to a max width/height of 500 with Bitmap.createScaledBitmap()
The problem I have is that the UI thread get's stuck even though I do both steps in a background thread.
My code looks like this:
dialog = ProgressDialog.show(this, "", "Loading...", true);
// upload the image to the server
Thread t = new Thread() {
#Override
public void run() {
bmp = BitmapHelper.scaleBmp(bmp, 500);//bmp is a private class Bitmap
try {
HttpResponse response = Helper.uploadBitmap(bmp);
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("\n");
}
finalResult = new JSONObject(builder.toString());
} catch (Exception e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
handleData();
}
});
}
};
t.run();
Any help on how to do this correctly would be really appreciated!
EDIT: adding handleData() function
public void handleData() {
take.setVisibility(View.VISIBLE);
select.setVisibility(View.VISIBLE);
process.setVisibility(View.GONE);
select_new.setVisibility(View.GONE);
message = "An error occured! Please try again.";
boolean success = false;
try {
success = finalResult.getBoolean("success");
url = "http://url";
url += finalResult.getString("path");
thumbnail = finalResult.getString("thumbnail");
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
if (success) {
message = "Picture was uploaded successfuly!";
}
dialog.dismiss();
Config.toast(this, message);
Thread t = new Thread() {
#Override
public void run() {
final Bitmap b = HttpHelper.getBitmapFromURL(thumbnail);
preview_image.post(new Runnable() {
#Override
public void run() {
preview_image.setImageBitmap(b);
preview_image.setVisibility(View.VISIBLE);
preview_image.setOnClickListener(context);
}
});
}
};
t.run();
}
You are not starting new threads. You are creating thread objects but you never start new threads. Instead, you just execute the method run in the current thread. For reference how to start a new thread see Defining and Starting a Thread.
As #LuxuryMode says, AsyncTask is a very good alternative on Android for long running operations that should not block the ui thread.
I think the problem is you are starting a new thread and then inside of it you're using Handler to post another runnable. So, the Handler is associated with this new Thread and you cannot manipulate the UI thread from that thread. It seems to me that you really should be using an AsyncTask, which provides a convenience for switching from background threads to the UI thread very easily.
http://developer.android.com/reference/android/os/AsyncTask.html
aside from what the others posters said, running a thread is done by calling start() not run().

Categories

Resources