I have an AsyncTask which acts as a client and get a string from a server and puts it in a String. After the task I use the response from the server but the data haven't changed yet - it's null.
connectBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
Client myClient = new Client(responseTV);
myClient.execute();
if (responseStr.charAt(0) == '1') { <----- responseStr is null
changeBrightness(Integer.parseInt(responseStr.substring(1)));
}
}
});
I assume the code keeps going after .execute() which is not very good in my situation.
Update: Added code for Client class.
public class Client extends AsyncTask<Void, Void, Void> {
String response = "";
TextView responseTV;
public Client(TextView responseTV) {
this.responseTV = responseTV;
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = null;
try {
socket = new Socket(IP, PORT);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(BUFFER_SIZE);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
InputStream inputStream = socket.getInputStream();
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
e.printStackTrace();
response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
//Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show();
responseTV.setText(response);
responseStr = response;
super.onPostExecute(aVoid);
}
}
if (responseStr.charAt(0) == '1') { <----- responseStr is null
changeBrightness(Integer.parseInt(responseStr.substring(1)));
}
Use this code in onPostExecute() method of AsyncTask. It runs on the UI thread and is exactly the method you need after finishing work in doInBackground().
Related
I'm simply trying to send String text from my android app to Nodemcu esp8266 and the esp8266 response with another text.
I can receive the text on esp8266 but on android app I'm not get any response text! and I don't knew what is the problem.
my android code is
public class MainActivity extends Activity {
TextView textResponse;
Button buttonConnect;
EditText welcomeMsg;
String IpAddress = "192.168.0.117";
int Port = 8090;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonConnect = (Button) findViewById(R.id.connect);
textResponse = (TextView) findViewById(R.id.response);
welcomeMsg = (EditText)findViewById(R.id.welcomemsg);
buttonConnect.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
MyClientTask myClientTask = new MyClientTask(welcomeMsg.getText().toString());
myClientTask.execute();
}
});
}
#SuppressLint("StaticFieldLeak")
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String response = "";
String msgToServer;
MyClientTask(String msgTo) {
msgToServer = msgTo;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(IpAddress, Port);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
if(!msgToServer.equals(""))
dataOutputStream.writeUTF(msgToServer + "$");
response = dataInputStream.readUTF();
} catch (IOException e) { }
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
my esp8266 code is
#include <ESP8266WiFi.h>
WiFiServer server(8090);
IPAddress ip(192, 168, 0, 117);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
void setup() {
Serial.begin(115200);
WiFi.config(ip, gateway, subnet);
WiFi.begin("TP-LINK", "55555555");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
server.begin();
Serial.println("Connected");
}
void loop() {
WiFiClient client = server.available();
if (!client) {
return;
}
Serial.println(client.readStringUntil('$'));
String x = "esp8266";
client.println(x);
delay(100);
client.flush();
}
and this is how my app locks like
anyone have any idea?
use the code bellow to send data:
example: sendData("http://192.168.0.117:8090/data");
private void sendData(final String requestURL) {
reply = "";
new AsyncTask<Object, Void, String>() {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Object... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(requestURL);
try {
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputstream = entity.getContent();
BufferedReader bufferedreader =
new BufferedReader(new InputStreamReader(inputstream));
StringBuilder stringbuilder = new StringBuilder();
String currentline = null;
while ((currentline = bufferedreader.readLine()) != null) {
stringbuilder.append(currentline + "\n");
}
String result = stringbuilder.toString();
reply = result;
inputstream.close();
}
} catch (NetworkOnMainThreadException ne) {
String err = (ne.getMessage() == null) ? "Network" : ne.getMessage();
reply = err;
} catch (MalformedURLException me) {
String err = (me.getMessage() == null) ? "Malform" : me.getMessage();
reply = err;
} catch (ProtocolException pe) {
String err = (pe.getMessage() == null) ? "Protocol" : pe.getMessage();
reply = err;
} catch (IOException ioe) {
String err = (ioe.getMessage() == null) ? "IOError" : ioe.getMessage();
reply = err;
}
return reply;
}
#Override
protected void onPostExecute(String result) {
Log.v(reply);
}
}.execute();
}
Basically as stated above. I have 2 AsyncTasks, and Thread.sleep() crashes in one but works in the other when I add it.
here is the task that it works in
public class createConnection extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params){
try{
socket = new Socket(ip, port);
PrintWriter out = new PrintWriter(socket.getOutputStream());
InputStream is = socket.getInputStream();
}
catch (UnknownHostException e){
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
The task that makes it crash:
public class SR extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... params) {
out.write(messageToSend);
out.flush();
msg.setText("message sent!");
try{
Thread.sleep(1000);
msg.setText("before attempt:");
byte[] buffer = new byte[4096];
baos = new ByteArrayOutputStream(4096);
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1){
baos.write(buffer, 0, bytesRead);
}
String response = baos.toString("UTF-8");
msg.setText(response);
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
My code consists of one button that creates a TCP connection with a Python server (on a Pi), and a second button which sends and receives text between the two. In the msg textbox, the app displays "message sent!" before it crashes, but does not reach "before attempt", which leads me to think that it is Thread.sleep() crashing the application. Does anyone have any idea why it's crashing or why it's working in one function but not the other?
You can't call msg.setText(...) from inside doInBackground(). That will definitely cause an exception. You can use the progress mechanism of AsyncTask to post progress updates:
public class SR extends AsyncTask<Void,String,Void> { // <- NOTE TYPE CHANGE
#Override
protected Void doInBackground(Void... params) {
out.write(messageToSend);
out.flush();
publishProgress("message sent!");
try{
Thread.sleep(1000);
publishProgress("before attempt:");
byte[] buffer = new byte[4096];
baos = new ByteArrayOutputStream(4096);
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1){
baos.write(buffer, 0, bytesRead);
}
String response = baos.toString("UTF-8");
publishProgress(response);
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public void onProgressUpdate(String... progress) {
msg.setText(progress[0]);
}
}
Hi i have a requirement of calling a web service when application goes to background and come back to foreground.I tried both Volley and HttpURLConnection but unfortunately both of them are not working for me. Some times it gives result but some times it is not.Below is my code
#Override
protected void onResume() {
try {
super.onResume();
// app.activityResumed();
// Toast.makeText(this, "QuizActivity Resumed", Toast.LENGTH_LONG).show();
/* if (session.getAreaName()!= null) {
if (GetGeoCodingTask.mAutoCompText != null)
autoCompView.setText(GetGeoCodingTask.mAutoCompText);
}*/
if (GetGeoCodingTask.mAutoCompText != null) {
autoCompView.setText(GetGeoCodingTask.mAutoCompText);
}
autoCompView.post(new Runnable() {
public void run() {
autoCompView.dismissDropDown();
}
});
LoadFoodListData();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
and my Method using HttpURLConnection is
private void LoadFoodListData() {
try {
StringBuffer chaine = new StringBuffer("");
URL url = new URL(myUrl);
connectionOpp = (HttpURLConnection) url.openConnection();
//connection.setReadTimeout(15000);
//connection.setConnectTimeout(15000);
connectionOpp.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connectionOpp.setRequestMethod("POST");
connectionOpp.setDoInput(true);
connectionOpp.setDoOutput(true);
Log.d("Tag", "Webservice after connect");
OutputStream os = connectionOpp.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(child.toString());
writer.flush();
writer.close();
os.close();
connectionOpp.connect();
int responseCode = connectionOpp.getResponseCode();
Log.d("Tag", String.valueOf(responseCode));
if (responseCode == HttpsURLConnection.HTTP_OK) {
// Toast.makeText(mContext, "Httpok",Toast.LENGTH_SHORT).show();
InputStream inputStream = connectionOpp.getInputStream();
Log.d("Tag", "Webservice httpok");
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = rd.readLine()) != null) {
chaine.append(line);
}
}
String readJSON = chaine.toString();
} catch (Exception e) {
e.printStackTrace();
}
}
and Using Volley is
private void LoadFoodListData() {
final ProgressDialog ringProgressDialog = ProgressDialog.show(QuizActivity.this, "Please wait ...", "Fetching data nearby you ...", true);
ringProgressDialog.setCancelable(false);
JsonObjectRequest jsObjRequest = null;
try {
jsObjRequest = new JsonObjectRequest(Request.Method.POST, myurl, child,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
ongoing = response.getJSONArray("Listongoing");
if (ongoing != null) {
if (ongoing.length() != 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
livecount.setText("(" + ongoing.length() + ")");
}
});
}
}
upcoming = response.getJSONArray("ListUpcoming");
Expire = response.getJSONArray("ListExpire");
if (Expire != null) {
if (Expire.length() != 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
expiredcount.setText("(" + Expire.length() + ")");
}
});
}
}
}
catch (JSONException e) {
e.printStackTrace();
ringProgressDialog.dismiss();
}
// dialogPro.cancel();
ringProgressDialog.dismiss();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ringProgressDialog.dismiss();
}
});
} catch (Exception e) {
ringProgressDialog.dismiss();
}
if (jsObjRequest != null) {
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(0, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
AppController.getInstance().addToRequestQueue(jsObjRequest);
}
Any help would be very thankfull.
i've done an application in which the android application send datas to java desktop swing application as well as send datas from desktop to android using TCP socket programming through wifi.
Th application is a Hotel Kitchen order booking system
The problem describes that Dine_Tables class contains buttons which represents each tables in a hotel, on clicking table1 button for example it starts the BackgroundServers Asyntask which runs a server for receiving desktop application datas also it takes the activity from Dinein_Tables.java to Food_Customizer.java.
In Food_Customizer.java on clicking submit button it starts ServersendAsyncAction Asyntask which sends some datas to desktop swing application.
The desktop application after processing sends some datas to android application, The server that runs in the android application on receiving the datas goes again from Food_Customizer.java to Dinein_Tables.java activity in the BackgroundServers Asyntask onPostExecute method.
The problem is that when i do this process a two or three times the application stop due to address-in use and Null-Pointer exception at socket = serverSocket.accept(); in the BackgroundServers Asyntask.
Can anyone please tell me some solution for this problem
Dinein_Tables.java
public class Dinein_Tables extends Activity {
:
:
table1.setOnClickListener(new OnClickListener() {
public void onClick(final View v) {
new Handler().postDelayed(new Runnable() {
public void run() {
Food_Customizer.BackgroundServers ob = new Food_Customizer().new BackgroundServers(contexts);
ob.execute("");
Intent toAnotherActivity = new Intent(v.getContext(), Food_Customizer.class);
startActivity(toAnotherActivity);
finish();
}
}, 100L);
}
});
}
Food_Customizer.java
public class Food_Customizer extends Activity {
:
:
submit= (Button)findViewById(R.id.submit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pd = ProgressDialog.show(contexts, "Sending to Server...","Please Wait...", true, false);
new ServersendAsyncAction().execute();
}
});
:
:
/****************************** AsyncTask ********************************************************/
private class ServersendAsyncAction extends AsyncTask<String, Void, String> {
/****************************** AsyncTask doInBackground() ACTION ********************************/
protected String doInBackground(String... args) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
boolean flag = true;
while (flag) /******** If data is send flag turn to be false *******/
{
try {
socket = new Socket("192.168.1.74", 4444);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(datastosend);
flag = false;
} catch (UnknownHostException e) {
flag = true;
e.printStackTrace();
} catch (IOException e) {
flag = true;
e.printStackTrace();
}
/******** CLOSING SOCKET *****************/
finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/******** CLOSING DATAOUTPUTSTREAM *******/
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/******** CLOSING DATAINPUTSTREAM ********/
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
/******** returns what you want to pass to the onPostExecute() *******/
}
/****************************** AsyncTask onPostExecute() ACTION *********************************/
protected void onPostExecute(String result) {
}
/********************* ENDING OF ASYN TASK CLASS ServersendAsyncAction ***************************/
}
public Context con;
public static ServerSocket serverSocket = null;
public class BackgroundServers extends AsyncTask<String, Void, String> {
public BackgroundServers(Context context) {
con=context;
}
/****************************** AsyncTask doInBackground() ACTION ********************************/
protected String doInBackground(String... args) {
Socket socket = null;
DataInputStream dataInputStream = null;
DataOutputStream dataOutputStream = null;
try {
serverSocket = new ServerSocket(9999);
System.out.println("Listening :9999");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(
socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
String incoming_message=(dataInputStream.readUTF());
incoming_message=incoming_message.replace("/", "");
String recdatas[]=incoming_message.split("#");
if(recdatas[0].equalsIgnoreCase("success"))
{
DatabaseConnection dbs=new DatabaseConnection(con);
int status=dbs.update("UPDATE hotel_pub_tables SET status='occupied' WHERE tableno='"+recdatas[1]+"'");
if(status>0)
{
tabelstatus=1;
//msg.obj="Table status changed!!!";
System.out.println("Table status changed!!!");
if (true) {
System.out.println("entered 222");
System.out.println(tabelstatus);
if(tabelstatus==1)
{
System.out.println(tabelstatus);
Food_Customizer.pd.dismiss();
System.out.println("success");
}
else if(tabelstatus==2)
{
Food_Customizer.pd.dismiss();
Intent intent = new Intent(Food_Customizer.this, Dinein_Tables.class);
startActivity(intent);
finish();
}
}
}
else
tabelstatus=2;
dbs.close();
}
dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
/******** returns what you want to pass to the onPostExecute() *******/
}
/****************************** AsyncTask onPostExecute() ACTION *********************************/
#Override
protected void onPostExecute(String result) {
System.out.println("eneterd on posttttttttttttttt");
con.startActivity(new Intent(con, Dinein_Tables.class));
finish();
}
}
}
/********************* ENDING OF ASYN TASK CLASS BackgroundServers ***************************/
}
Well it's obvious that you setup your server on port 9999:
serverSocket = new ServerSocket(9999);
But you connect with the server on port 4444:
socket = new Socket("192.168.1.74", 4444);
Make sure you connect to the correct port-number otherwise it wont work. Hope this helps.
I'm new to android application development. I tried to develop an android server client chat
for my first project. This is the code for the client side. When the client press btnJoin,
it will connect to the server and send a string. I've read many example and many of them
looks like this. I got a networkOnMainThreadException. How do I make an asyncTask to prevent
this problem? Any help would be much appreciated.
btnJoin = (Button) findViewById(R.id.buttonJoin);
btnJoin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
txtIP.append(dataInputStream.readUTF() + "\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
Change your code as:
btnJoin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view){
new LongOperation().execute("");
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
Socket socket = null;
String strresult="";
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
#Override
protected String doInBackground(String... params) {
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
strresult.append(dataInputStream.readUTF() + "\n");
// txtIP.append(dataInputStream.readUTF() + "\n");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return strresult;
}
#Override
protected void onPostExecute(String result) {
TextView txtIP= (TextView) findViewById(R.id.txtIP);
// txtIP.append(result + "\n");
txtIP.setText(result + "\n");
}
#Override
protected void onPreExecute() {
}
}
Use AsyncTask like this :
First have it nested in your class, it should look similar to :
private class Communicator extends AsyncTask<Void, Void, Boolean> {
String tmp;
String err;
#Override
protected Boolean doInBackground() {
try {
socket = new Socket("192.168.1.4", 9092);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF("Hello server!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(Boolean result) {
txtIP.append(dataInputStream.readUTF() + "\n");
}
}
When you have AsyncTask,you can start it like this :
...
#Override
public void onClick(View v) {
Communicator c=new Communicator();
c.execute();
}
....
try to implement this code in your app
private class LongOperation extends AsyncTask<Object, Integer, Object> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
//do hard work here
return params;
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
}
}
AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)
Here is an example of subclassing:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Once created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
for more details refer below links...
http://www.vogella.com/articles/AndroidPerformance/article.html
http://developer.android.com/reference/android/os/AsyncTask.html