When i click on an item in my listview, I would like to have a new thread start and execute the desired tasks I have defined for it in the Connect2 class, however, as far as I can tell the thread is not starting or showing any indication of as why it isn't starting. If anybody could help diagnose a problem in the code or point me in the right direction to fix this issue I would greatly appreciate it. Thanks!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_directory);
final ListView fileDirectory=(ListView) findViewById(R.id.DirectoryView);
final ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1, SocketConnection.remoteList);
fileDirectory.setAdapter(adapter);
fileDirectory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(FileDirectory.this, "The click works", Toast.LENGTH_SHORT).show();
FileDirectory.listItem=i;
new Connect2().execute("");
adapter.notifyDataSetChanged();
}
});
}
public class Connect2 extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params){
runConnectCode();
return null;
}
}
public void runConnectCode(){
String itemTemp=SocketConnection.remoteList.toArray()[FileDirectory.listItem].toString();
SocketConnection.PW.write(itemTemp);
//SocketConnection.DOS.flush();
SocketConnection.currentF.concat("\\"+itemTemp);
SocketConnection.PW.write(SocketConnection.currentF);
//SocketConnection.DOS.flush();
try{
Object object=SocketConnection.OIS.readObject();
SocketConnection.remoteList=(ArrayList<String>) object;
} catch(IOException e){
System.out.println(e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}//run()
Try to run your thread using runOnUiThread();
Try to create class extend Asynctask and call your code in doinbackground() method like this:
public class Connect2 extends AsyncTask<String , String , String>
{
#Override
protected String doInBackground(String... params) {
runConnectCode();
return null;
}
}
public void runConnectCode ()
{
String itemTemp = SocketConnection.remoteList.toArray() [FileDirectory.listItem].toString();
try {
SocketConnection.DOS.writeUTF(itemTemp);
SocketConnection.DOS.flush();
} catch (IOException e) {
System.out.println(e);
}
try {
SocketConnection.currentF.concat("\\" + itemTemp);
SocketConnection.DOS.writeUTF(SocketConnection.currentF);
SocketConnection.DOS.flush();
} catch (IOException e) {
System.out.println(e);
}
try {
Object object = SocketConnection.OIS.readObject();
SocketConnection.remoteList = (ArrayList<String>) object;
} catch (IOException e) {
System.out.println(e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Finally, call this whenever you want:
new Connect2().execute("");
Related
Recent study utilizing Asynctask to establish socket connections, but encountered some situation
now I can use to press the button to establish a connection, , but I do not know how to make the button text from "unconnected" to "Connected ".Compile no problem but it can not be executed on the simulator, press the button, I can see a text from "unconnected" to "Connected", but the next second forced off the APP.
The following is my code fragment:
public class MainActivity extends Activity {
public static Button Btn_Wifi,Btn_Power,Btn_Flame;
public static Boolean connected=false;
public static DataOutputStream dataOutputStream = null;
public static DataInputStream dataInputStream = null ;
public static Socket socket;
AsyncTask:
static class SocketTask extends AsyncTask<Void, Void, Void > {
#Override
protected Void doInBackground(Void ... parms) {
try {
socket = new Socket("ip", port);//
dataOutputStream = new DataOutputStream(socket.getOutputStream());//and stream
changeConnectionStatus(true);//change the connection status
}catch (UnknownHostException e) {
}catch (IOException e) {
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
};
Button.OnClickListener:
Button.OnClickListener BtnWifiOnClickListener = new Button.OnClickListener(){
#Override
public void onClick(View view) {
//SocketTask sockettask = new SocketTask();
new SocketTask().execute();
}
};
changeConnectionStatus:
public static void changeConnectionStatus(Boolean isConnected) {
connected=isConnected;//change variable
if(isConnected){//if connection established
Btn_Wifi.setText("connected");
Btn_Power.setEnabled(true);
}else{
Btn_Wifi.setText("unconnected");
Btn_Power.setText("POWER OFF");
Btn_Power.setEnabled(false);
PowerStatus(false);
}
}
Positive solutions
#Override
protected void onPostExecute(Void result) {
changeConnectionStatus(true);
}
you can't touch UI from doInBackground()
you need to use onPostExecute()
move the call of changeConnectionStatus(true) from doInBackground() as following:
#Override
protected void onPostExecute() {
changeConnectionStatus(true);
}
In my AsyncTask I do a quite a long operation inside doInBackground() which assigns a value to a variable after completion of doInBackground().
I use the value of that variable to setup a part of the user interface in postExecute().
The problem is that doinbackground() is quite a long operation and postExecute() finishes first. That way I fail to obtain the value.
Here's what the problem is
private class bigwork extends AsyncTask<String, Void, Boolean> {
String foo = null;
#Override
protected void onPreExecute() {
}
#Override
protected Boolean doInBackground(final String... args) {
// Long operation sets variable 'foo' a new value
}
#Override
protected void onPostExecute(final Boolean success) {
// Make use of foo here
}
The problem is the value of foo I get in postExecute() is still null.
Usually you would pass the String directly to onPostExecute:
private class bigwork extends AsyncTask<String, Void, String>
{
#Override
protected void onPreExecute() {
}
#Override
protected Boolean doInBackground(final String... args) {
// Long operation
set variable 'foo' a new value
return foo;
}
#Override
protected void onPostExecute(String foo) {
if (foo != null) {
// success
}
// Make use of foo here
}
Override onPostExecute() function to perform some task after doInBackground() function has finished.Like this:
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
ServiceHandler sh = new ServiceHandler();
jsonStr=sh.makeServiceCall(arg0[0], ServiceHandler.GET);
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.i("jsin", jsonStr);
if(pd.isShowing()){
pd.dismiss();
}
try {
js = new JSONObject(jsonStr);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONArray results =null;
try {
results = js.getJSONArray("results");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i< results.length();i++)
{
JSONObject c = null;
try {
c = results.getJSONObject(i);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
placeName = c.getString(TAG_NAME);
ratings = c.getDouble(TAG_RATING);
HashMap<String, String> rest = new HashMap<String, String>();
rest.put(TAG_NAME, placeName);
rest.put(TAG_RATING, ratings+"");
placeList.add(rest);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ListAdapter adapter = new SimpleAdapter(getActivity().getApplicationContext(), placeList, R.layout.list_item, new String[]{TAG_NAME}, new int[]{R.id.list_text});
lv.setAdapter(adapter);
}
I am making http request in my doInBackground and after successful reply i am parsing json in onPostExecute() and displaying in a listview and obviously this code is in class extending AsyncTask class.
You should pass the parameter directly to onPostExecute. Quoting from the Android Developer Reference:
protected void onPostExecute (Result result)
Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).
In case you need to pass more than one parameter wrap them in a class like:
public class MyClass
{
public String string1;
public String string2;
public MyClass(String a, String b){
string1 = a;
string2 = b;
}
}
Hope this helps.
Best regards.
I am trying to implement simple internal data storage code.In it I want to show ProgressDialog for some background process which will increment by 5 while calling publishProgress(). But it gives me error like the following,
The method publishProgress(R.integer...) in the type AsyncTask<String,R.integer,String> is not applicable for the arguments (int)
following is the code.
public class loadSomeStuff extends AsyncTask<String, integer, String>
{
ProgressDialog dailog;
protected void onPreExecute()
{
//example of setting up something
dailog=new ProgressDialog(MainActivity.this);
dailog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dailog.setMax(100);
dailog.show();
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String collected=null;
FileInputStream fis=null;
for(int i=1; i<=20; i++)
{
publishProgress(5);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
dailog.dismiss();
try {
fis=openFileInput(FileName);
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!= -1)
{
collected=new String(dataArray);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
return collected;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer...progress)
{
dailog.incrementProgressBy(5);
}
protected void onPostExecute(String result)
{
DataResults.setText(result);
}
}
Generics cannot use value types so your AsyncTask needs to use Integer:
extends AsyncTask<String, Integer, String>
try this :
extends AsyncTask<String, Integer, String>
Integer with a capital I
I have tried your code on my machine and its working fine without any error.
You can check now with my code.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadSomeStuff objSomeStuff = new loadSomeStuff();
objSomeStuff.execute();
}
public class loadSomeStuff extends AsyncTask<String, Integer, String>
{
ProgressDialog dailog;
protected void onPreExecute()
{
//example of setting up something
dailog=new ProgressDialog(MainActivity.this);
dailog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dailog.setMax(100);
dailog.show();
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String collected=null;
FileInputStream fis=null;
for(int i=1; i<=20; i++)
{
publishProgress(5);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
dailog.dismiss();
try {
fis=openFileInput("");
byte[] dataArray = new byte[fis.available()];
while(fis.read(dataArray)!= -1)
{
collected=new String(dataArray);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
return collected;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer...progress)
{
dailog.incrementProgressBy(5);
}
protected void onPostExecute(String result)
{
//DataResults.setText(result);
Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG).show();
}
}
}
Alright I think you may have messed up with some namespaces. Here is what you need to do
Organize your imports Ctrl+Shift+O. make sure there is no invalid import. it may have happned if you copy & paste code from any other source.
Clean your project.
AsyncTask should look like this:
public class LoadSomeStuff extends AsyncTask<String, Integer, String>
Let me know if you still cant resolve it .
simple answer is that
in the Question Code Mention is
AsyncTask< String, integer, String>
But change that for progress updated
AsyncTask< String, Integer, String>
if use AsyncTask**< String, String, String>** then should be Cast into Interger for
progress update.
I have an android application that is a client for a simple chat server. I am able to connect to the server and my ObjectStreams. The problem is when I receive a message, the thread that handles my server connection calls upon my display message which updates the list view.
I am getting the error "only the original thread that created a view hierarchy can touch its views."
I am pretty sure its because I'm calling my displayMessage() method from my connect thread, but I am not sure how to organize my threads to have a connection to the server and dynamically update my listview.
Here is my main activity.
public class MainActivity extends Activity {
private Connection serverConnection;
private ArrayList<String> listItems = new ArrayList<String>();
private ArrayAdapter<String> adapter;
/**
* Sets the ArrayAdaptor, and starts the connectThread.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runOnUiThread(new Runnable() {
public void run() {
ListView listview = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,
listItems);
listview.setAdapter(adapter);
}
});
/**
* Starts a new connection Thread
*/
Thread connectThread = new Thread(new Runnable(){
public void run(){
serverConnection = new Connection(MainActivity.this);
serverConnection.run();
}
});
connectThread.start();
}
/**
* Adds a message to the list view.
* #param string - message to be added.
*/
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
}
Here is my connection thread class.
public class Connection extends Thread {
private Socket client;
private ObjectOutputStream output;
private ObjectInputStream input;
private MainActivity mainActivity;
private String message;
/**
* Constructor starts the socket and ObjectStreams
*
* #param mainActivity - reference to the MainActivity
*/
public Connection(MainActivity mainActivity) {
this.mainActivity = mainActivity;
try {
client = new Socket("192.168.1.105", 50499);
mainActivity.displayMessage("Connected to: "
+ client.getInetAddress().getHostName());
output = new ObjectOutputStream(client.getOutputStream());
output.flush();
input = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Run method for the Thread.
*/
public void run() {
for (;;) {
try {
message = (String) input.readObject();
mainActivity.displayMessage(message);
} catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You are updating Ui on the background thread. You should update ui on the ui thread. Move your code that updates ui in the background thread. You are refreshing your listview on the background thread.
mainActivity.displayMessage("Connected to: "
+ client.getInetAddress().getHostName());
mainActivity.displayMessage(message);
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
The above should be outside the thread or You can use runonuithread inside the thread to update ui.
runOnUiThread(new Runnable() {
#Override
public void run() {
// update ui
}
});
Another way would be to use asynctask. Do all your network related operation in doInbackground() and update ui in onPostExecute().
Async Task
Edit: Not sure what you are trying to do.
public class MainActivity extends Activity {
private Connection serverConnection;
private ArrayList<String> listItems = new ArrayList<String>();
private ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview = (ListView) findViewById(R.id.lv);
adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,
listItems);
listview.setAdapter(adapter);
// use a button and on button click start the thread.
Thread connectThread = new Thread(new Runnable(){
public void run(){
serverConnection = new Connection(MainActivity.this);
serverConnection.run();
}
});
connectThread.start();
}
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
class Connection extends Thread {
private Socket client;
private ObjectOutputStream output;
private ObjectInputStream input;
private MainActivity mainActivity;
private String message;
public Connection(MainActivity mainActivity) {
this.mainActivity = mainActivity;
try {
client = new Socket("192.168.1.105", 50499);
runOnUiThread(new Runnable() {
#Override
public void run() {
displayMessage("Connected to: "
);
}
});
output = new ObjectOutputStream(client.getOutputStream());
output.flush();
input = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
for (;;) {
try {
message = (String) input.readObject();
runOnUiThread(new Runnable() {
#Override
public void run() {
displayMessage(message);
}
});
} catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
I am missing something very crucial but I can't quite see what. Can someone please assist. It's probably something really silly that I have missed but I cannot initiate my onItemClick.
onCreate....
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
actu_ip = intent.getStringExtra(IPEntry.ACTUALSMARTIP);
setContentView(R.layout.act_ipcontrol);
mainListView = (ListView) findViewById( R.id.mainListView );
String[] options = new String[] { "All in to 1", "Spare"};
ArrayList<String> optionsList = new ArrayList<String>();
optionsList.addAll( Arrays.asList(options) );
listAdapter = new ArrayAdapter<String>(this, R.layout.simplerow, optionsList);
mainListView.setAdapter( listAdapter );
try {
Toast.makeText(IPControl.this, "Please wait...Connecting...", Toast.LENGTH_SHORT).show();
new AsyncAction().execute();
} catch(Exception e) {
e.printStackTrace();
}
}
private class AsyncAction extends AsyncTask<String, Void, String> {
protected String doInBackground(String... args) {
try {
InetAddress serverAddr = InetAddress.getByName(actu_ip);
socket = new Socket(serverAddr, REDIRECTED_SERVERPORT);
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bw = new BufferedWriter(osw);
out = new PrintWriter(bw, true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (! in .ready());
readBuffer();
out.println("root\r\n");
while (! in .ready());
readBuffer();
out.println("root\r\n");
while (! in .ready());
readBuffer();
out.println("[verbose,off\r\n");
while (! in .ready());
String msg = "";
while ( in .ready()) {
msg = msg + (char) in .read();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;//returns what you want to pass to the onPostExecute()
}
protected void onPostExecute(String result) {
Toast.makeText(IPControl.this, "Connected", Toast.LENGTH_SHORT).show();
//results the data returned from doInbackground
IPControl.this.data = result;
}
}
private String readBuffer() throws IOException {
String msg = "";
while(in.ready()) {
msg = msg + (char)in.read();
}
//System.out.print(msg);
if(msg.indexOf("SNX_COM> ") != -1) return msg.substring(0, msg.indexOf("SNX_COM> "));
else if(msg.indexOf("SCX_COM> ") != -1) return msg.substring(0, msg.indexOf("SCX_COM> "));
else return msg;
}
}
What I want to initiate...
public void onItemClick(AdapterView<?> arg0, View arg1, int pos,
long arg3) {
try {
new AsyncAction1().execute();
} catch(Exception e) {
e.printStackTrace();
}
}
private class AsyncAction1 extends AsyncTask<String, Void, String> {
protected String doInBackground(String... args) {
try {
out.println("[c,l#,i1,o*\r\n");
//System.out.print("root\r\n");
while(! in .ready());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;//returns what you want to pass to the onPostExecute()
}
protected void onPostExecute(String result) {
//results the data returned from doInbackground
Toast.makeText(IPControl.this, "Command Sent", Toast.LENGTH_SHORT).show();
IPControl.this.data = result;
}
}
I haven't seen setOnItemClickListener method for listview in your code. Have you implemented it?
Try following
mainListView.setAdapter( listAdapter );
mainListView.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
try {
new AsyncAction1().execute();
}catch(Exception e) {
e.printStackTrace();
}
});
Thanks for all your help, I fixed my problem.
I just wasn't doing things in the correct order.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
actu_ip = intent.getStringExtra(IPEntry.ACTUALSMARTIP);
setContentView(R.layout.act_ipcontrol);
mainListView = (ListView) findViewById( R.id.mainListView );
final String[] options = new String[] { "All in to 1", "Spare"};
ArrayList<String> optionsList = new ArrayList<String>();
optionsList.addAll( Arrays.asList(options) );
listAdapter = new ArrayAdapter<String>(this, R.layout.simplerow, optionsList);
mainListView.setAdapter( listAdapter );
mainListView.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
try {
if(pos == 0) {
AsyncAction1 a = new AsyncAction1();
a.setCmd("[c,l#,i1,o*\r\n");
a.execute();
}
} catch(Exception e) {
e.printStackTrace();
}
}
});
Then....
private class AsyncAction1 extends AsyncTask<String, Void, String> {
String cmd;
public void setCmd(String c) {
cmd = c;
}
protected String doInBackground(String... args) {
try {
out.println(cmd);
//System.out.print("root\r\n");
while(! in .ready());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;//returns what you want to pass to the onPostExecute()
}
protected void onPostExecute(String result) {
//results the data returned from doInbackground
Toast.makeText(IPControl.this, "Command Sent", Toast.LENGTH_SHORT).show();
IPControl.this.data = result;
}
}
}