I wrote this little application that take some datas from a web service and put them in a custom ListView:
SOAP CALL
public String getVoy(String voy) {
String SOAP_ACTION = "XXXXXXXXXX";
String METHOD_NAME = "XXXXXXXXXX";
String NAMESPACE = "urn:DefaultNamespace";
String URL = "http://xxxxxxxxxxxx/xxxxx.nsf/xxxxxxx?wsdl";
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("VOY", voy);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
final SoapObject result = (SoapObject) envelope.bodyIn;
rt = (result != null) ? result.getProperty(0).toString() : "Nessuna risposta 1";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Invio il webservice
return rt;
}
AsyncTask
private class LineCall extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
final String text = WebService.getInstance().getVoy(params[0]);
return text;
}
}
Call the AsyncTask and get the datas
LineCall line = new LineCall();
line.execute(voy);
try {
**string** = line.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Then I take the string variable, split my datas and put them in the custom list...
It works very well but the problem is that is very slow so I tried to create a ProgressDialog but there are some problems...
If I put it in the previous activity:
Button partenze = (Button) findViewById(R.id.partenze);
partenze.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
StartDeapartures call = new StartDeapartures();
call.execute();
}
});
}
private class StartDeapartures extends AsyncTask<Void, Void, Void> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dialog = new ProgressDialog(Home.this);
dialog.setTitle("Loading..");
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
Intent intent = new Intent(getApplicationContext(), Partenze.class);
startActivity(intent);
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.dismiss();
}
}
The progress image don't move and it seems freezed and if i put it in the LineCall asyncTask the ProgressDialog is not showed...
I found in google that this is dued to string = line.get(); that takes a long time to run...
So how can i put a ProgressDialog when get() is working ?
If you call AsyncTask.get(), it will block the main thread until the doInBackground completes. So, you should not call AsyncTask.get(), instead you should handle the result and do UI operations in AsyncTask.onPostExecute() method. This is the designed behaviour of AsyncTask.
In your StartDeapartures asynctask, why do you start an activity in doInBackground? What is the point of using an AsyncTask for starting an activity?
Related
I'm trying to implement an asynchronous access to internet using AsyncTask, but in log cat PID and TID of my logging are the same, because AsyncTask doesn't create a parallel queue, so my app crashes with a NetworkOnMainThreadException.
Here's my subclass code :
class BL_SimpleAsyncTask extends AsyncTask<Void, Void, Void> {
String requestServer;
HashMap<String, String> postRequestBody;
//------------------------// answer from http client
static DefaultHttpClient sharedClient = null;
boolean isPostRequest;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
System.out.println("bg started");
if (sharedClient == null) {
sharedClient = new DefaultHttpClient();
}
HttpPost post = new HttpPost(requestServer);
String postBody = new String();
postBody += "{";
for (String key : postRequestBody.keySet()) {
String result = String.format("\"%s\":\"%s\",", key, postRequestBody.get(key));
postBody += result;
}
System.out.println("body initialized");
postBody.substring(0, postBody.length() - 1);
postBody += "}";
try {
post.setEntity(new StringEntity(postBody));
} catch (UnsupportedEncodingException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("entity set");
try {
if (post != null) {
System.out.println("starting request....");
HttpResponse response = sharedClient.execute(post);
System.out.println("responce recieved");
} else {
System.out.println("null request");
}
// System.out.println(response) ;
} catch (ClientProtocolException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
So, to start post-request, I simply do the following :
BL_SimpleAsyncTask obj = new BL_SimpleAsyncTask() ;
obj.requestServer = "https://api.orbios.com/v1/auth/sign-in" ;
obj.postRequestBody = new HashMap<String, String> () ;
obj.postRequestBody.put ("password", password) ;
obj.postRequestBody.put("email", email ) ;
obj.isPostRequest = true ;
System.out.println("start bg thread") ;
obj.doInBackground() ;
What am I doing wrong?
You are not supposed to call doInBackground() yourself. Just call execute() and let the framework call your doInBackground() in a background thread.
Instead of calling directly doInBackground() you should be calling execute method.
I am getting GetVehicles method of SOAP WSDL from SOAP web services and call that GetVehicles result in TextView when clicking on a Button event.
there is one button and one TextView in my xml.
when I run program the data is shown in textview , I want to store or save that result shown in TextView in Sqlite database?.
I have created DatabaseHandler class extending SQLiteOpenHelper.
I am passing these two parameters which are for id and name,
HERE IS MY CODE:
public class GetVehiclesActivity extends Activity {
private static String SOAP_ACTION = "http://tempuri.org/GetServerVehicles";
private static String NAMESPACE = "http://tempuri.org/";
private static String METHOD_NAME = "GetServerVehicles";
private static String URL = "http://favouritehatfield.co.uk/Service1.asmx?";
private TextView txtV_vehicles;
private long clientid=46;
private String response;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.getvehicles);
/** Show Toast at the Start of Activity... **/
Toast.makeText(this, "WELCOME to GET VEHICLES ACTIVITY..", 1).show();
txtV_vehicles = (TextView) findViewById(R.id.txtV_lbl_vehicles);
DatabaseHandler db = new DatabaseHandler(this);
}//End onCreate()
private class vehiclesAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
txtV_vehicles.setText(response);
}//End onPostExecute()
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}//End onPreExecute()
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
SoapObject getVehiclesRequest = new SoapObject(NAMESPACE,METHOD_NAME);
// add paramaters and values
PropertyInfo pi = new PropertyInfo();
pi.setName("defaultclientId");
pi.type= PropertyInfo.LONG_CLASS;
getVehiclesRequest.addProperty(pi,46);
PropertyInfo pi2 = new PropertyInfo();
pi2.setName("hashKey");
pi2.type= PropertyInfo.STRING_CLASS;
getVehiclesRequest.addProperty(pi2,"464321orue");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);
envelope.setOutputSoapObject(getVehiclesRequest);
envelope.dotNet = true;
HttpTransportSE httpTransport = new HttpTransportSE(URL);
//httpTransport.debug = true;
try {
httpTransport.call(SOAP_ACTION, envelope);
} catch (HttpResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
SoapPrimitive result = (SoapPrimitive) envelope.getResponse();
response = result.toString();
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}//End doInBackground
}// End vehiclesAsyncTask
/** Called when the user clicks the GetVehicles button */
public void getVehicle(View v) {
String str = "You have clicked GetVehicles ...";
Toast.makeText(this, str, 0).show();
vehiclesAsyncTask vehiclesRequest = new vehiclesAsyncTask();
vehiclesRequest.execute();
//
}//End getVehicle()
/** Called when the user clicks the SAVEDATA button I want this buton to save the TextView result in SQLite Database*/
/** Called when the user clicks the SAVEDATA button */
public void saveData(View v) {
String str = "Save DAta Button Clicked ...";
Toast.makeText(this, str, 0).show();
String s1 = txtV_vehicles.getText().toString();
Objdbhandler.saveVehicles(s1, s1, s1, s1, s1);
// Objdbhandler.saveVehicles(Name, TotalPassengers, TotalHandLuggages, TotalLugages, SortOderNo)
}//End saveData(...) Method
}//End class GetVehiclesActivity
I have searched a lot but couldn't find any clue.
How can I do that?
I assume that DatabaseHandler() is working correctly. As per code sample, the problem I can see that you have written
cValues.put("defaultclientId", "clientidclientid");
db.insert("defaultclientId", null, cValues);
here you are passing databaseName same as columnName in insert query. The correct usage of insert query is as follows:
public long insert (String table, String nullColumnHack, ContentValues values)
where
table:=the table to insert the row into
nullColumnHack:=optional; may be null.
values:=this map contains the initial column values for the row. The keys should be the column names and the values the column values
So, you should insert in database by using below code:
ContentValues values = new ContentValues();
values.put("defaultclientId", "put_default_client_id_received_from_SOAP");
values.put("hashkey", "put_hashkey_received");
database.insert("database_name", null, values);
Hope this clears things!!
I want to load a data using JSON from php and then parsing it in android. I'm trying to implement asynctask in this process. And the return is in string. I got an error in
"Type mismatch : cannot convert from AsyncTask<String,String,String> to String in
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
The xResult is supposed to be the string value I got from php.
Here's the complete codes :
public void tampilkanData() {
try {
String nama = URLEncoder.encode(Login.usernameP, "utf-8");
urltampil += "?" + "&nama=" + nama;
txtNama.setText("");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
try {
parse();
} catch (Exception e) {
e.printStackTrace();
}
}
private void parse() throws Exception {
//jObject = new JSONObject(xResult);
JSONArray menuitemArray = new JSONArray(xResult);
jObject=menuitemArray.getJSONObject(0);
String sret="";
txtBerat.setText(jObject.getString("berat_badan"));
txtNama.setText(jObject.getString("username"));
// txtUsia.setText(jObject.getString("usia"));
txtTinggi.setText(jObject.getString("tinggi_badan"));
//System.out.println(jObject.getString("jenis_kelamin").equalsIgnoreCase("female"));
if(jObject.getString("jenis_kelamin").equalsIgnoreCase("female")){
radioFemale.setSelected(true);
radioMale.setSelected(false);
}else{
radioMale.setSelected(true);
radioFemale.setSelected(false);
}
}
public String getRequestData(String UrlTampil){
String sret="";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(UrlTampil);
try{
HttpResponse response = client.execute(request);
sret =request(response);
}catch(Exception ex){
Toast.makeText(this,"Gagal "+sret, Toast.LENGTH_SHORT).show();
}
System.out.println(sret);
return sret;
}
class ProsesTampil extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
return getRequestData(params[0]);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
I'm sorry for my bad english. thanks in advance
The propose of an AsyncTask is execute some code in a separate thread (different from UI thread), but the result from that code, when ready, will be delivered in onPostExecute.i.e. The method execute returns the AynscTask itself,not String so change your code as
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
to
ProsesTampil p = new ProsesTampil();
p.execute(urltampil);
And get xResult in onPostExecute method as
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
xResult = result;
}
First Thing You can not return value from onPostExecute() because return type is void
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
Second Your class doesn't Return any value...
So if you want to get value of result try to get value from onPostExecute().
I mean to say do as follow..
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
xResult = result;
super.onPostExecute();
}
You can't do it because AsyncTask works in background thread.
Your result will come in UI thread after background has done self work:
#Override
protected void onPostExecute(String result) {
//String result - that what you need
}
execute() doesn't return a string. So you can't assign it like that. AsyncTasks are asynchronous- they don't finish until later. Any code you'd want to run on the result of an AsyncTask should be placed in the onPostExecute() function of the AsyncTask.
Yo can use
String results = yourAsyntask.get() instead of using yourAsyntask.execut()e method, it will return you result. same as Result get you in onPostExecute method;
But it will block your main thread.
I can't explain why onPostExecute is not being called in my code. I have successfully used almost this exact code with a different app before. It prints 'onPreExecute' and the successful result of the JSON fetch from doInBackground just before return result; but then onPostExecute doesn't print anything - with the super call or not - and moreover doesn't return my string to the UI thread. Any ideas?
public class PrivateLoadFromServer extends AsyncTask<String, Integer, String> {
InputStream is = null;
String result = null;
String error_text="";
JSONObject j = null;
String url;
SQLiteOpenHelper helper;
CustomActivity activity;
private Context context;
private ProgressDialog dialog;
private int count;
String employee;
String text;
public PrivateLoadFromServer(CustomActivity activity,String employee,String url){
this.url=url;
this.employee=employee;
this.activity=activity;
}
#Override
protected void onPreExecute() {
system.out.println("onPreExecute");
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
System.out.println("onPostExecute");
activity.setJSONResult(result);
/*
if(result!=null){
System.out.println("Task reported successful");
taskHandler.taskSuccessful(this.result);
activity.setJSONResult(this.result);
} else {
taskHandler.taskFailed();
}
*/
//return;
}
#Override
protected String doInBackground(String... params) {
System.out.println("Running aSyncTask");
// Successful code to get JSON result string from server omitted.
System.out.println("Raw at doInBackground: " + result);
return result;
EDIT: Should've posted this originally, I call it as an inner class in CustomActivity like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
helper=new DBHelper(this);
loadBasicData();
}
private void loadBasicData() {
// If you can encode all of these into one JSON Object, cool.
String url="*****" //Omitted URL.
String employee=null;
PrivateLoadFromServer syncTask = new PrivateLoadFromServer(this,employee,url);
syncTask.execute();
try {
syncTask.get(15000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("JSONResult at Activity:"+jsonResult); // jsonResult is null
}
}
public void setJSONResult(String result){
System.out.println("setJSONResult"+result);
this.jsonResult=result; // jsonResult is a field in the Activity.
}
Because you are calling get, the JSON result is also returned from this method (see the source code of AsyncTask.java. So you can call your method directly on the output.
try {
setJSONResult(syncTask.get(15000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
Check if your are explicitly cancelling AsyncTask somewhere in the code before it could postExecute.
onPostExecute() is called on the main UI thread. If its not getting called, it means your UI thread is blocked doing something else.
I've an android application.
I need to execute a code on a separate task because it fives me android.os.NetworkOnMainThreadException .
This is my code:
public class AccesoCuentaActivity extends Activity{
public void validacion(View v) throws IOException, XmlPullParserException
{
try {
String usuario=((EditText)findViewById(R.id.etUsu)).getText().toString();
String pass=((EditText)findViewById(R.id.etPass)).getText().toString();
String[] pars = new String[2];
String[] = new String[2];
pars[0] = usuario;
pars[1] = pass;
new ValidacionThread().execute(pars);
Intent intent=new Intent(this, MainActivity.class);
intent.putExtra("idBoton",12);
intent.putExtra("usuario",usu);
startActivityForResult(intent, 0);
} }
Task:
public class ValidacionThread extends AsyncTask<String, Void, Usuario> {
private final String NAMESPACE = "http://webservices.pcp/";
private final String URL = "http://127.0.0.1:8080/webServices/pcpWS?wsdl";
private final String SOAPACTION = "";
private final String METHOD = "ValidarUsuario";
protected Usuario doInBackground(String[] pars) {
String user = pars[0];
String password = pars[1];
SoapObject request = new SoapObject(NAMESPACE, METHOD);
SoapSerializationEnvelope sobre = new SoapSerializationEnvelope(SoapEnvelope.VER11);
sobre.dotNet = false;
request.addProperty("login", user);
request.addProperty("password", password);
sobre.setOutputSoapObject(request);
HttpTransportSE transporte = new HttpTransportSE(URL);
try {
transporte.call(SOAPACTION, sobre);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SoapObject resultado = null;
try {
resultado = (SoapObject)sobre.getResponse();
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Usuario usu = new Usuario();
usu.IdUsuario= resultado.getProperty(0).toString();
usu.Nombre = resultado.getProperty(1).toString();
usu.Apellidos = resultado.getProperty(2).toString();
usu.Rol = resultado.getProperty(3).toString();
usu.Centro=resultado.getProperty(4).toString();
return usu;
}
protected void onPostExecute(ValidacionThread vt) {
}
}
It gives me two problems:
1) In class AccesoCuentaActivity :
I want to save the variable "usuario" return in ValidationThread.doInBackground(). But how do I do it?
Indeed if I just write: new ValidacionThread().execute(pars); it tells me that the variable "usu" (intent.putExtra("usuario",usu);) has not been initialized
while with code (in main code) Usuario usu = new ValidacionThread().execute(pars); it says type mismatch
2) In doInBackground() line eclipse gives the warning:
Varargs methods should only override or be overridden by other varargs methods unlike ValidacionThread.doInBackground(String[]) and AsyncTask<String,Void,Usuario>.doInBackground(String...)
Since this is Async task you need to create a return way for that data.
I would recomend creating an interface like:
interface{
public void parseData(Usuario data);
}
and implementing it in your activity class.
I would then pass and instance of activity to that async task in constructor.
Then in your ValidationThread:
protected void onPostExecute(Usuario vt) {
activityInstance.parseData(vt);
}
As for the second part change String[] to String..