I am using Jsoup to parse a part of a website and then put it into a string. I want to visualize this string into a textView, but since only the thread that had created the textView can modify it i need to pass the value of the string into the main thread. how?
This is the code: (ignore the tabhost stuff)
public class NewsAndAnnouncements extends Activity {
TabHost host;
FlyOutContainer container;
Button bttoggle;
Button bt1;
String loggity;
TextView tv1;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.container = (FlyOutContainer) this.getLayoutInflater().inflate(
R.layout.newsandannouncements, null);
this.setContentView(container);
host = (TabHost) findViewById(R.id.tabhost);
host.setup();
TabSpec specs = host.newTabSpec("TAGGITY EINZ");
specs.setContent(R.id.tab1);
specs.setIndicator("News");
host.addTab(specs);
specs = host.newTabSpec("TAGGITY ZWEI");
specs.setContent(R.id.tab2);
specs.setIndicator("Notices");
host.addTab(specs);
specs = host.newTabSpec("TAGGITY DREI");
specs.setContent(R.id.tab3);
specs.setIndicator("Events");
host.addTab(specs);
tv1 = (TextView) findViewById(R.id.textView1);
/*
* bttoggle = (Button) findViewById(R.id.bttoggle); bt1 = (Button)
* findViewById(R.id.Button1);
*
* bttoggle.setOnClickListener(new OnClickListener() {
*
* #Override public void onClick(View v) { // TODO Auto-generated method
* container.toggleMenu(); } });
*
* bt1.setOnClickListener(new OnClickListener() {
*
* #Override public void onClick(View v) { // TODO Auto-generated method
* container.toggleMenu(); } });
*/
Thread newsThread = new Thread() {
public void run() {
Document doc = null;
try {
doc = Jsoup
.connect(
"http://acs.bg/Home/About_ACS/News_and_Events/News.aspx")
.get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Elements myin = doc.getElementsByClass("news_list");
loggity = myin.toString();
Log.i("ELEMENTS HTML", loggity);
}
};
newsThread.start();
tv1.setText(loggity);
}
}
Try using AsyncTask instead of the Thread. To modify views on your ui thread use the runOnUiThread() method in your activity.
runOnUiThread(new Runnable() {
#Override
public void run() {
tv1.setText("...");
}
});
Use an AsyncTask instead of a raw Thread:
new AsyncTask<URL, Object, Document>() {
protected Document doInBackground(URL... urls) {
// parse URL and return document
}
protected void onPostExecute(Document result) {
// this runs in UI thread
// show document in UI
}
}).execute(myURL);
There are two ways to d it-
1)- Using AsyncTask
2)- Using Handler
Thread newsThread = new Thread()
{
public void run()
{
Document doc = null;
try {
doc = Jsoup
.connect(
"http://acs.bg/Home/About_ACS/News_and_Events/News.aspx")
.get();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Elements myin = doc.getElementsByClass("news_list");
loggity = myin.toString();
mHandler.post(new Runnable()
{
#Override
public void run()
{
try
{
tv1.setText(loggity);
} catch (Exception e)
{
e.printStackTrace();
}
}
});
Log.i("ELEMENTS HTML", loggity);
}
};
newsThread.start();
You can initialize the Hanlder in the start.
try this sample code, don't know if this is the better way:
public class MainThread {
public static void main(String args[]) {
Thread2 t2 = new Thread2();
Thread nextThread = new Thread(t2);
nextThread.start();
try {
nextThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
System.out.println(t2.getStr());
}
private static class Thread2 implements Runnable{
private String str;
#Override
public void run() {
setStr("T2 Thread String");
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
}
Related
I am having a problem which is I think that I can't access th,e ListView from the asyncTask
Actually, I really don't know the real problem here
Let me show you what is happening
I have an activity which is executing AsyncTask and creates HttpURLConnection. Sometimes I get an exception (ProtocolException) because the stream un-expectedly ends.
So, I created a handler for this exception that calls a function or a method inside the class of the activity to display a message to the user
Here is a picture so you understand what is my project.
image
the problem here whenever the exception is thrown, the same function/method that I use to add the text to the listView is called, but after it called the listView disappear, but when I minimize the soft keyboard manually the everything becomes fine.
the structure of my class is
public class MainActivity extends AppCompatActivity
{
protected void onCreate(Bundle savedInstanceState)
{
addMessageToListView()//works fin here
}
protected void addMessage(String message, int userMessage, ListView listView) // the function
{
try
{
messages.add(new Message(message,userMessage));
MessagesAdapter messagesAdapter = new MessagesAdapter(messages, getBaseContext());
messagesAdapter.notifyDataSetChanged();
listView.setAdapter(messagesAdapter);
}
catch (Exception exception)
{
}
}
private class HttpPostAsyncTask extends AsyncTask<String, Void, String>
{
...
#Override
protected void onPostExecute(String result)
{
try
{
addMessageToListView()//works fin here
}
catch (Exception exception)
{
}
}
protected String doInBackground(String... params)
{
String result = "";
for (int i = 0; i <= 0; ++i)
{
result = this.invokePost(params[i], this.postData);
}
return result;
}
private String invokePost(String requestURL, HashMap<String, String> postDataParams)// called from doInBackground
{
try
{
addMessageToListView()//works fin here
}
catch (Exception exception)
{
addMessageToListView()//not orking here
}
}
}
}
I don't know how to explain more actually.
You can change Views only in mainthread of your app. The doInBackground doesn't run in mainthread of your app.
Solved by adding:
new Thread()
{
#Override
public void run()
{
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
addMessageToListView()//not orking here
}
});
super.run();
}
}.start();
Editing the previous code in my question:
public class MainActivity extends AppCompatActivity
{
protected void onCreate(Bundle savedInstanceState)
{
addMessageToListView()//works fin here
}
protected void addMessage(String message, int userMessage, ListView listView) // the function
{
try
{
messages.add(new Message(message,userMessage));
MessagesAdapter messagesAdapter = new MessagesAdapter(messages, getBaseContext());
messagesAdapter.notifyDataSetChanged();
listView.setAdapter(messagesAdapter);
}
catch (Exception exception)
{
}
}
private class HttpPostAsyncTask extends AsyncTask<String, Void, String>
{
...
#Override
protected void onPostExecute(String result)
{
try
{
addMessageToListView()//works fin here
}
catch (Exception exception)
{
}
}
protected String doInBackground(String... params)
{
String result = "";
for (int i = 0; i <= 0; ++i)
{
result = this.invokePost(params[i], this.postData);
}
return result;
}
private String invokePost(String requestURL, HashMap<String, String> postDataParams)// called from doInBackground
{
try
{
addMessageToListView()//works fin here
}
catch (Exception exception)
{
new Thread()
{
#Override
public void run()
{
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
addMessageToListView()//not orking here
}
});
super.run();
}
}.start();
}
}
}
}
I am working on an android app development and I am stuck in an issue. I have used ANSYNC TASK method but now it has stopped working.
It was working fine from last many years but now it is creating problem.
Also, doinbackground() and postExecute() methods are not working (they are not called) only preExecute() method is working for me.
I am attaching code here for the reference:
class MyAsyncTask extends AsyncTask<Void, ConversationModel, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
heading.setText("myheading");
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (ConversationModel model : dataList) {
if (flagStop)
break;
publishProgress(model);
long_time = Long.parseLong(model.sound_time) * 1000 + 500;
try {
Thread.sleep(long_time);
Thread.sleep(long_extraTime);
long_extraTime = 0;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i++;
Log.d("i", i + " -----------------");
}
return null;
}
protected void onProgressUpdate(ConversationModel... model) {
if (i % 2 == 0) {
View v = View.inflate(Conversation1.this, arrInt_resource[0], null);
v.setAnimation(null);
TextView txtV_spn = (TextView) v.findViewById(R.id.textView_spn);
TextView txtV_eng = (TextView) v.findViewById(R.id.textView_eng);
ImageView img_sound = (ImageView) v.findViewById(R.id.imgsound_conv_spn2eng);
RelativeLayout speak_layout = (RelativeLayout) v.findViewById(R.id.speaking_layout);
heading.setText(dataList.get(0).heading);
if (flag != 1) {
txtV_spn.setText(model[0].eng_txt);
txtV_eng.setText(model[0].spn_txt);
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (i >= dataList.size()) {
Log.d("i", i + " ------------------");
makingcontinueImageView();
}
}
}
i think you are using .execute() method of asynctask to start execute of asynctask, change that line of code with this one
asynctask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
My purpose is simple,I want to creat a countdown that count from 10 to 1.I have tried using countdown given by google but I can't make it as a thread,so I use this way to creat the same function but I had a problem with this code.My app getting crashed when I use this threads code.Please help me man.
public class MainActivity extends Activity {
TextView textView;
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
String string = textView.getText().toString();
int num = Integer.parseInt(string);
num = num-1;
string = Integer.toString(num);
textView.setText(string);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Thread myThread = new Thread(new Runnable(){
#Override
public void run() {
// TODO Auto-generated method stub
for(int i = 10; i>0;i--){
try {
Thread.sleep(1000);
//handler.sendMessage(handler.obtainMessage());
handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
myThread.start();
}
}
Your problem isnt with the thread, its with these lines
String string = textView.getText().toString();
int num = Integer.parseInt(string);
You probably have that textView starting out with some text in the XML("Large Text"). Remove it. "Large Text" isn't a number, so when you call parseInt() on that original string its trying to convert "Large Text" to a number.
Try this code:
try {
String string = textView.getText().toString();
int num = Integer.parseInt(string);
textView.setText(String.valueOf(--num));
catch(NumberFormatException ignored){
}
with a try/catch block
I am having problem in my code.I am trying to change the layout background of my app every second.I used Thread in this code.I've searched the site but I couldn't find anything useful.Here is the code.
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
//private Bitmap open, close;
private LinearLayout myL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myL = (LinearLayout) findViewById(R.id.LinearLayout2);
// myL=(LinearLayout) findViewById(R.id.LinearLayout2);
//close = BitmapFactory.decodeResource(getResources(), R.drawable.kapa);
//open = BitmapFactory.decodeResource(getResources(), R.drawable.ac);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Thread th = new Thread() {
public void run() {
while (true) {
myL.setBackgroundResource(R.drawable.kapa);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myL.setBackgroundResource(R.drawable.ac);
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
th.start();
}
}
From the answer to this question Change Layout background continuously...
Try using a Handler. Example...
public class MainActivity extends Activity {
final int CHANGE_BG_RES = 1;
final int RESOURCE_1 = R.drawable.kapa;
final int RESOURCE_2 = R.drawable.ac;
private LinearLayout myL;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (CHANGE_BG_RES == msg.what) {
int res = msg.arg1;
myL.setBackgroundResource(res);
int nextRes;
if (RESOURCE_1 == res)
nextRes = RESOURCE_2;
else
nextRes = RESOURCE_1;
Message m = obtainMessage (CHANGE_BG_RES, nextRes, 0, null);
sendMessageDelayed(m, 1000);
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myL = (LinearLayout) findViewById(R.id.LinearLayout2);
}
#Override
protected void onResume() {
super.onResume();
Message m = handler.obtainMessage(CHANGE_BG_RES, RESOURCE_1, 0, null);
handler.sendMessageDelayed(m, 1000);
}
}
Try this:
public class MainActivity extends Activity {
//private Bitmap open, close;
private LinearLayout myL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myL = (LinearLayout) findViewById(R.id.LinearLayout2);
// myL=(LinearLayout) findViewById(R.id.LinearLayout2);
//close = BitmapFactory.decodeResource(getResources(), R.drawable.kapa);
//open = BitmapFactory.decodeResource(getResources(), R.drawable.ac);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Runnable runnable = new Runnable() {
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
myL.setBackgroundResource(R.drawable.kapa);
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
myL.setBackgroundResource(R.drawable.ac);
}
});
}
}
};
new Thread(runnable).start();
}
}
I send a string from android to C# and from C# to android
it works on simulator but does't work on real android device
My phone using android 2.3
here is my code on Android:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
hienthi_lv_tab2 = (ListView) findViewById(R.id.lvhienthi);
chuoi = (EditText) findViewById(R.id.string);
ipserver = (EditText) findViewById(R.id.ipserver);
txt = (TextView) findViewById(R.id.Show);
quit = (Button) findViewById(R.id.quit);
connect = (Button) findViewById(R.id.Connect);
send = (Button) findViewById(R.id.Send);
quit.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
finish();
}
});
send.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
OUT_message = chuoi.getText().toString();
new Thread(new Runnable() {
final Handler handler = new Handler();
final Runnable updateUI2 = new Runnable() {
public void run() {
// TODO Auto-generated method stub
OUT_message = "Android: " + OUT_message;
add_chuoi(OUT_message);
}
};
public void run() {
// TODO Auto-generated method stub
PrintWriter out;
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream())), true);
out.println(OUT_message);
out.flush();
handler.post(updateUI2);
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
Thread C_thread = new Thread(new ClientThread());
C_thread.start();
}
});
connect.setVisibility(1);
connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
connect.setVisibility(v.GONE);
Thread C_thread = new Thread(new ClientThread());
C_thread.start();
}
});
}
public class ClientThread implements Runnable {
final Handler handler = new Handler();
final Runnable updateUI = new Runnable() {
public void run() {
// TODO Auto-generated method stub
txt.setText(IN_message);
IN_message = "Server: " + IN_message;
add_chuoi(IN_message);
}
};
public void run() {
// TODO Auto-generated method stub
try {
IP = ipserver.getText().toString();
serverAddr = InetAddress.getByName(IP);
state_connnect = true;
Scanner in;
while (state_connnect) {
s = new Socket(serverAddr, 4444);
in = new Scanner(s.getInputStream());
IN_message = in.nextLine();
handler.post(updateUI);
in.close();
s.close();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void add_chuoi(String chuoi) {
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array_operator);
array_operator.add(chuoi);
hienthi_lv_tab2.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
here is my code on C#:
private void Form1_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
String hostname = "";
System.Net.IPHostEntry ip = new IPHostEntry();
hostname = System.Net.Dns.GetHostName();
ip = System.Net.Dns.GetHostByName(hostname);
lblhostname.Text = "Tên Server : " + ip.HostName;
foreach (System.Net.IPAddress listip in ip.AddressList)
{
lblip.Text ="Địa Chỉ IP Server : "+listip.ToString();
IPAddress ipAd = IPAddress.Parse(listip.ToString());
myList = new TcpListener(ipAd, 4444);
myList.Start();
}
}
void connect()
{
txt_show.Text="Waitting for connect from android...";
while (true)
{
server_socket = myList.AcceptSocket();
byte[] data_rec = new byte[1024];
int k = server_socket.Receive(data_rec);
char cc;
String mes = null;
for (int i = 0; i < k - 1; i++)
{
cc = Convert.ToChar(data_rec[i]);
mes += cc.ToString();
}
if (mes != null)
{
string_rec = mes.ToString();
txt_show.Text += Environment.NewLine + "Android: " + mes;
}
}
}
private void btn_send_Click(object sender, EventArgs e)
{
String data_send = txt_send.Text;
ASCIIEncoding asen = new ASCIIEncoding();
server_socket.Send(asen.GetBytes(data_send));
txt_show.Text += Environment.NewLine + "Server : " + txt_send.Text;
txt_send.Text = "";
}
private void button1_Click(object sender, EventArgs e)
{
S_thread = new Thread(connect);
S_thread.Start();
}
and this is logcat:
FATAL EXCEPTION:Thread-10 java.util.NoSuchElementException
at java.util.Scanner.nextLine(Scanner.java:1417)
at iNET.Android.Thread_TCP.ThreadActivity$ClientThread.run(ThreadActivity.java:207)
at java.lang.Thread.run(Thread.java:1019)
thanks all!
Not fully sure, But my guess is you are using different private network in Mobile and Pc. That's why you can send data while using emulator ( because both in pc) but not able to send using mobile.
After your comments I think your pc is in a private network. So you can not send message from the android application using the entered ip.