I am trying to send an Object through Sockets using AsyncTask, but i'm getting this error (i just post the important part of it):
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3
Process: com.mitorapps.beberconmemes, PID: 6418
java.lang.RuntimeException: An error occurred while executing doInBackground()
Caused by: java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.mitorapps.beberconmemes.data.Persona[]
at com.mitorapps.beberconmemes.conexion.Enviar_Persona$MyATaskCliente.doInBackground(Enviar_Persona.java:47)
This is my Persona Class(The object that i want to send):
package com.mitorapps.beberconmemes.data;
import java.io.Serializable;
public class Persona implements Serializable{
private String Name_Persona;
String Mac_Address;
public Persona(String name_persona, String mac_address) {
this.Name_Persona = name_persona;
this.Mac_Address = mac_address;
}
public String getMac_Address() {
return this.Mac_Address;
}
public String getName_Persona() {
return this.Name_Persona;
}
public void setName_Persona(String name_Persona) {
this.Name_Persona = name_Persona;
}
}
This is my Client Class (named as Enviar_persona):
package com.mitorapps.beberconmemes.conexion;
public class Enviar_Persona extends Cliente{
private AsyncTask myATaskYW;
public Enviar_Persona(Context context){
super(context);//the client class forces to receive a context
SERVERPORT=5000;
}
#Override
public void enviar_persona(Persona p){//Method Called from view
this.myATaskYW = new MyATaskCliente();
this.myATaskYW.execute(p);
}
public void update_view(String s){//To update the State of an element on UI
TextView resp = (TextView) ((Activity)c).findViewById(R.id.resp);
resp.setText(s);
}
//AsyncTask class
class MyATaskCliente extends AsyncTask<Persona, Void, String> {
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("OnPreExecute");
progressDialog = new ProgressDialog(c);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setTitle("Connecting to server");
progressDialog.setMessage("Please wait...");
progressDialog.show();
}
#Override
protected String doInBackground(Persona... persona) {
try {
//here i'm using an static ip
Socket socket = new Socket("192.168.1.7", SERVERPORT);
//Object Send to server
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeObject(persona[0]);
//Response recivied from server
InputStream stream = socket.getInputStream();
byte[] len=new byte[256];
stream.read(len,0,256);
String received = new String(len,"UTF-8");
socket.close();
return received;
} catch (UnknownHostException ex) {
return ex.getMessage();
} catch (IOException ex) {
return ex.getMessage();
}
}
#Override
protected void onPostExecute(String value) {
progressDialog.dismiss();
update_view(value);
}
}
}
I did it using the AsyncTask On the main activity and it works perfectly, but now that I need group my code in different classes i got the error
Instead of using
AsyncTask myATaskYW;
use
MyATaskCliente myATaskYW;
because AsyncTask is generic so the signature is replaced with Object[] array but you need to work with the specific implementation.
Note : Person[] is not a child of Object[]
Related
I am busy with an application where i am getting data from my azure database with sql and storing it in an array. I created a separate class where i get my data and my main activity connects to this class and then displays it.
Here is my getData class:
public class GetData {
Connection connect;
String ConnectionResult = "";
Boolean isSuccess = false;
public List<Map<String,String>> doInBackground() {
List<Map<String, String>> data = null;
data = new ArrayList<Map<String, String>>();
try {
ConnectionHelper conStr=new ConnectionHelper();
connect =conStr.connectionclass(); // Connect to database
if (connect == null) {
ConnectionResult = "Check Your Internet Access!";
} else {
// Change below query according to your own database.
String query = "select * from cc_rail";
Statement stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
Map<String,String> datanum=new HashMap<String,String>();
datanum.put("NAME",rs.getString("RAIL_NAME"));
datanum.put("PRICE",rs.getString("RAIL_UNIT_PRICE"));
datanum.put("RANGE",rs.getString("RAIL_RANGE"));
datanum.put("SUPPLIER",rs.getString("RAIL_SUPPLIER"));
datanum.put("SIZE",rs.getString("RAIL_SIZE"));
data.add(datanum);
}
ConnectionResult = " successful";
isSuccess=true;
connect.close();
}
} catch (Exception ex) {
isSuccess = false;
ConnectionResult = ex.getMessage();
}
return data;
}
}
And in my Fragmentactivity.java I simply just call the class as shown here:
List<Map<String,String>> MyData = null;
GetValence mydata =new GetValence();
MyData= mydata.doInBackground();
String[] fromwhere = { "NAME","PRICE","RANGE","SUPPLIER","SIZE" };
int[] viewswhere = {R.id.Name_txtView , R.id.price_txtView,R.id.Range_txtView,R.id.size_txtView,R.id.supplier_txtView};
ADAhere = new SimpleAdapter(getActivity(), MyData,R.layout.list_valence, fromwhere, viewswhere);
list.setAdapter(ADAhere);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
HashMap<String,Object> obj=(HashMap<String,Object>)ADAhere.getItem(position);
String ID=(String)obj.get("A");
Toast.makeText(getActivity(), ID, Toast.LENGTH_SHORT).show();
}
});
My problem comes when I want to include the onPreExecute and onPostExecute because I am relatively new to android studio and I do not know where to put the following lines of code:
#Override
protected void onPreExecute() {
ProgressDialog progress;
progress = ProgressDialog.show(MainActivity.this, "Synchronising", "Listview Loading! Please Wait...", true);
}
#Override
protected void onPostExecute(String msg) {
progress.dismiss();
}
You need to get the data from your azure database using a background service or AsyncTask. However, you are defining a class GetData which does not extend AsyncTask and hence the whole operation is not asynchronous. And I saw you have implemented doInBackground method which is not applicable here as you are not extending AsyncTask. I would suggest an implementation like the following.
You want to get some data from your azure database and want to show them in your application. In these kind of situations, you need to do this using an AsyncTask to call the server api to get the data and pass the data to the calling activity using an interface. Let us have an interface like the following.
public interface HttpResponseListener {
void httpResponseReceiver(String result);
}
Now from your Activity while you want to get the data through an web service call, i.e. AsyncTask, just the pass the interface from the activity class to the AsyncTask. Remember that your AsyncTask should have an instance variable of that listener as well. So the overall implementation should look like the following.
public abstract class HttpRequestAsyncTask extends AsyncTask<Void, Void, String> {
public HttpResponseListener mHttpResponseListener;
private final Context mContext;
HttpRequestAsyncTask(Context mContext, HttpResponseListener listener) {
this.mContext = mContext;
this.mHttpResponseListener = listener;
}
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
// Your implementation of getting data from your server
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(final String result) {
mHttpResponseListener.httpResponseReceiver(result);
}
#Override
protected void onCancelled() {
mHttpResponseListener.httpResponseReceiver(null);
}
}
Now you need to have the httpResponseReceiver function implemented in the calling Activity. So the sample activity should look like.
public class YourActivity extends AppCompatActivity implements HttpResponseListener {
// ... Other code and overriden functions
public void callAsyncTaskForGettingData() {
// Pass the listener here
HttpRequestAsyncTask getDataTask = new HttpRequestGetAsyncTask(
YourActivity.this, this);
getDataTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
public void httpResponseReceiver(String result) {
// Get the response callback here
// Do your changes in UI elements here.
}
}
To read more about how to use AsyncTask, you might consider having a look at here.
I get the NullPointerException and I can't figure out what's wrong. I've tried only to bring the necessary code.
I have 3 classes: MainActivity, GoogleCommunicator and CustomAdapter.
The error is caused by following in CustomAdapter:
mActivity.updateBought(position, "1");
The errors I get are line 283 and 277 which are:
283: URL listFeedUrl = mWorksheet.getListFeedUrl();
277: private class UpdateBought extends AsyncTask<Void, Void, String>
The logcat:
3011-3026/com.example.andb.apop_l6_google_communicator_app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.andb.apop_l6_google_communicator_app, PID: 3011
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.net.URL com.google.gdata.data.spreadsheet.WorksheetEntry.getListFeedUrl()' on a null object reference
at com.example.andb.apop_l6_google_communicator_app.GoogleCommunicator$UpdateBought.doInBackground(GoogleCommunicator.java:283)
at com.example.andb.apop_l6_google_communicator_app.GoogleCommunicator$UpdateBought.doInBackground(GoogleCommunicator.java:277)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
MainActivity
public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener{
public GoogleCommunicator mGCom = new GoogleCommunicator(this,"torprode#gmail.com");
TextView tvStatus;
EditText etAdd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvStatus = (TextView) findViewById(R.id.tvStatus);
doSomeGoogleStuff();
buttonListener();
update();
}
private void doSomeGoogleStuff(){
mGCom.setupFeed("mandatoryProject","BuyMe");
}
private void drawListview() {
ListAdapter listAdapter = new CustomAdapter(this, mGCom.listItem, mGCom.listBought);
ListView listView = (ListView) findViewById(R.id.lv_items);
listView.setAdapter(listAdapter);
}
public void updateBought(int name, String bought) {
mGCom.updateBought(name, bought);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}
GoogleCommunicator
public class GoogleCommunicator {
//Spreadsheet communication
private static final String mScope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
private MainActivity mActivity;
private SpreadsheetService mSpreadSheetService;
private SpreadsheetFeed mFeed;
private String mSpreadsheetName;
private String mWorksheetName;
private SpreadsheetEntry mSpreadsheet;
private WorksheetEntry mWorksheet;
private String itemName;
private int itemNameIndex;
private String itemBought;
//Constructor
public GoogleCommunicator(MainActivity activity, String email) {
mEmail = email;
mActivity = activity; //possibility for callback to method in activity class
}
//Method to be called from your application.
//Creates an instance of SetupFeedTask (an AsyncTask) and executes it
public void setupFeed(String spreadsheet_name, String worksheet_name){
mSpreadsheetName = spreadsheet_name;
mWorksheetName = worksheet_name;
new SetupFeedTask().execute();
}
public void updateBought(int name, String bought) {
itemNameIndex = name;
itemBought = bought;
new UpdateBought().execute();
}
//AsyncTask that handles network comminucation e.t.c.
private class SetupFeedTask extends AsyncTask<Void, Void, String> {
//Executes in its own "worker thread" and doesnt block the main UI thread
#Override protected String doInBackground(Void... params) {
// Do work
mToken = fetchToken();
mSpreadSheetService = new SpreadsheetService("MySpreadsheetService");
mSpreadSheetService.setAuthSubToken(mToken);
URL feed_url;
try {
feed_url = new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full");
mFeed = mSpreadSheetService.getFeed(feed_url, SpreadsheetFeed.class);
}catch(MalformedURLException e){
//TODO: handle exception
Log.v(TAG, "MalformedURLException");
return null;
}catch(ServiceException e){
//TODO: handle exception
Log.v(TAG, "ServiceException");
return null;
}catch(IOException e){
//TODO: handle exception
Log.v(TAG, "IOException");
return null;
}
try{
List<SpreadsheetEntry> spreadsheets = mFeed.getEntries();
// Iterate through all of the spreadsheets returned
for (SpreadsheetEntry spreadsheet : spreadsheets) {
if (spreadsheet.getTitle().getPlainText().equals(mSpreadsheetName)) {
List<WorksheetEntry> worksheets = spreadsheet.getWorksheets();
//Iterate through worksheets
for (WorksheetEntry worksheet : worksheets) {
if (worksheet.getTitle().getPlainText().equals(mWorksheetName)) {
mSpreadsheet = spreadsheet;
mWorksheet = worksheet;
Log.v(TAG,"Spreadsheet and Worksheet is now setup.");
}
}
}
}
}catch(ServiceException e){
//TODO: handle exception
Log.v(TAG, "Service Exception");
return null;
}catch(IOException e){
//TODO: handle exception
Log.v(TAG, "IO Exception");
return null;
}
//Just for the example.. mToken not important to return
return mToken;
}
//Call back that is called when doInBackground has finished.
//Executes in main UI thread
#Override protected void onPostExecute(String result) {
//TODO: Notify rest of application, e.g.:
// * Send broadcast
// * Send message to a handler
// * Call method on Activity
}
//Helper method
private String fetchToken(){
try {
return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
} catch (UserRecoverableAuthException userRecoverableException) {
// GooglePlayServices.apk is either old, disabled, or not present, which is
// recoverable, so we need to show the user some UI through the activity.
//TODO:
if(mActivity instanceof MainActivity){
((MainActivity)mActivity).handleException(userRecoverableException);
if(D) Log.e(TAG,"UserRecoverableAuthException");
}
} catch (GoogleAuthException fatalException) {
//TODO:
//onError("Unrecoverable error " + fatalException.getMessage(), fatalException);
if(D) Log.e(TAG,"GoogleAuthException");
} catch (IOException ioException){
if(D) Log.e(TAG,"IOException");
}
return null;
}
}
private class UpdateBought extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
try {
URL listFeedUrl = mWorksheet.getListFeedUrl();
ListFeed listFeed = mSpreadSheetService.getFeed(listFeedUrl, ListFeed.class);
ListEntry row = listFeed.getEntries().get(itemNameIndex);
row.getCustomElements().setValueLocal("bought", itemBought);
row.update();
} catch (IOException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
return null;
}
}
}
CustomAdapter
class CustomAdapter extends ArrayAdapter<String> {
ArrayList boughtList;
MainActivity mActivity = new MainActivity();
CustomAdapter(Context context, ArrayList<String> item, ArrayList<String> bought) {
super(context, R.layout.custom_listview, item);
boughtList = bought;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
LayoutInflater listViewInflater = (LayoutInflater.from(getContext()));
final View customView = listViewInflater.inflate(R.layout.custom_listview, parent, false);
final String foodItem = getItem(position);
TextView foodText = (TextView) customView.findViewById(R.id.tv_Item);
final CheckBox checkBox = (CheckBox) customView.findViewById(R.id.cb_checked);
foodText.setText(foodItem);
String foodBought = String.valueOf(boughtList.get(position));
int foodBoughtInt = Integer.parseInt(foodBought);
if (foodBoughtInt == 1) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (checkBox.isChecked()) {
System.out.println("Jep");
mActivity.updateBought(position, "1");
} else {
System.out.println("Nope");
mActivity.updateBought(position, "0");
}
}
});
return customView;
}
}
You are encountering a race condition. You have to asynchronous tasks that execute, and the second asynchronous task depends on the first task to be done for it to work correctly. Because both tasks are done asynchronously, they are done in the background, on separate threads. Your setupFeed method is not done working, and then you start your updateBought method on a new thread. What happens is that updateBought begins while mWorksheet is still null. You will have to reorganize your code logic to avoid this race condition. What I have done in the past when I have two async tasks is to put the second asynchronous task in onPostExecute() of the first async task, because onPostExecute only occurs once doInBackground is finished.
Here is an execellent article on AsyncTasks and Threads from the developer guides.
I have called an async task from my button click.In the doInBackground I have called an API and It is returning me a Json object.I want to pass the Json object to another activity on the button click.How can I can get the return Json object value so that I can send it to other activity.
Thanks.
Create Interface
public interface Listener {
void success(BaseModel baseModel);
void fail(String message);
}
Create Base model class
public class BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
}
Call below method inside your onClick mehtod.
protected void userLoginData(final String userName) {
// if you want to pass multiple data to server like string or json you can pass in this constructor
UserLoginLoader userLoginLoader = new UserLoginLoader(LoginActivity.this, userName, "1234567899", new Listener() {
#Override
public void success(BaseModel baseModel) {
// here you got response in object you can use in your activity
UserLoginModel userLoginModel = (UserLoginModel) baseModel;
// you can get data from user login model
}catch(Exception exception){
exception.printStackTrace();
Utils.showAlertDialog(LoginActivity.this, "Server is not responding! Try Later.");
}
}
#Override
public void fail(String message) {
}
});
userLoginLoader.execute();
}
:- User Login Loader class
public class UserLoginLoader extends AsyncTask<String, Void, Boolean> {
private Dialog dialog;
private Listener listner;
private String deviceId;
Activity activity;
String message;
String userName;
boolean checkLoginStatus;
public UserLoginLoader(Activity activity,String userName, String deviceId, Listener listener) {
this.listner = listener;
this.userName =userName;
this.activity = activity;
this.deviceId = deviceId;
}
#Override
protected Boolean doInBackground(String... arg0) {
//User login web service is only for making connection to your API return data into message string
message = new UserLoginWebService().getUserId(userName, deviceId);
if (message != "null" && !message.equals("false")) {
return true;
}
return false;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new Dialog(activity, R.style.CustomDialogTheme);
dialog.setContentView(R.layout.progress);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
BaseModel baseModel = null;
if (!message.equals("null") && (!message.equals("false")) )
baseModel = parseData(message, result);
if (dialog.isShowing()) {
dialog.dismiss();
dialog.cancel();
dialog = null;
}
if (listner != null) {
if (result && baseModel != null)
listner.success(baseModel);
else
listner.fail("Server not responding! Try agian.");
} else
listner.fail("Server not responding! Try agian.");
}
//call parser for parsing data return data from the parser
private BaseModel parseData(String responseData, Boolean success) {
if (success == true && responseData != null
&& responseData.length() != 0) {
UserLoginParser loginParser = new UserLoginParser(responseData);
loginParser.parse();
return loginParser.getResult();
}
return null;
}
}
This is you Login parser class
public class UserLoginParser {
JSONObject jsonObject;
UserLoginModel userLoginModel;
/*stored data into json object*/
public UserLoginParser(String data) {
try {
jsonObject = new JSONObject(data);
} catch (JSONException e) {
Log.d("TAG MSG", e.getMessage());
e.printStackTrace();
}
}
public void parse() {
userLoginModel = new UserLoginModel();
try {
if (jsonObject != null) {
userLoginModel.setUser_name(jsonObject.getString("user_name")== null ? "": jsonObject.getString("user_name"));
userLoginModel.setUser_id(jsonObject.getString("user_id") == null ? "" : jsonObject.getString("user_id"));
userLoginModel.setFlag_type(jsonObject.getString("flag_type") == null ? "" : jsonObject.getString("flag_type"));
} else {
return;
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
/*return ship name list which is stored into model */
public UserLoginModel getResult() {
return userLoginModel;
}
}
Write a callback method in the Activity that takes in the argument that you wish to pass from AsyncTask to that Activity. Send reference to the Activity to AysncTask while creating it. From doInBackground() method make a call to this callback method with the data your API returns.
Code would be something like -
public class TestAsyncTask extends AsyncTask<Integer, Integer, String[]> {
Activity myActivity;
public TestAsyncTask(Activity activity) {
this.myActivity = activity;
}
#Override
protected String[] doInBackground(Integer... params) {
String data = yourApi();
myActivity.callback(data);
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
new TestAsyncTask(this).execute(someId);
}
public void callback(String data) {
//process data
}
}
Just for the record you can directly get return value from doInBackground() method by calling get() on it.
String data = new TestAsyncTask(this).execute(someId).get();
But note this may block your UI thread as it will wait for the doInBackground() method to complete it's execution.
public class SocketThread {
private boolean connect = false;
private String ip = "*********";
private int port = ****;
private Socket socket;
private SocketAsync socketAsync;
public SocketThread() {
socketAsync = new SocketAsync();
socketAsync.execute();
}
public void setMessenger(SocketServiceMessenger messenger) {
this.socketServiceMessenger = messenger;
}
public void setConnectFlag(boolean connect) {
this.connect = connect;
}
public void sentData(JSONObject json) {
socketAsync.sentData2(json);
}
private class SocketAsync extends AsyncTask<Void, Void, String> {
private PrintWriter printWriter;
#Override
protected String doInBackground(Void... params) {
String msgStr;
String type;
try {
socket = new Socket(InetAddress.getByName(ip),port);
OutputStreamWriter streamOut = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
printWriter = new PrintWriter(streamOut);
streamOut.flush();
BufferedReader streamIn = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
while(socket.isConnected()) {
msgStr = streamIn.readLine();
System.out.println(msgStr);
if(!connect) {
socket.close();
}
}
System.out.println("SocketDisconnected");
} catch (Exception e) {
System.out.println(e.toString());
}
return null;
}
public void sentData2(JSONObject json) {
if(socket.isConnected()) {
printWriter.println(json.toString());
printWriter.flush();
System.out.println("OUT : " + json);
}
}
}
I get android.os.NetworkOnMainThreadException when call sentData()
Now I use
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
to resolve the problem, but I want to know how to use asynctask in true way.
This code is for online game that receive message from server in realtime and it can also sent message to server from some activity by calling sentData().
Resolve
Example: Android bi-directional network socket using AsyncTask
You should set the class to be public and no outer class needed.
public class SocketAsync extends AsyncTask<String, String, String> {
private PrintWriter printWriter;
#Override
protected String doInBackground(String... params) {
//You do things here.
}
}
This is how you set up the class and in the Activity class, you simply call this by code like :
new SocketAsync(this).execute(/*Put parameters here.*/);
Hope this will help.
The method SocketAsync.sentData2() calls socket.isConnected(). This is being called on the main thread because something calls SocketThread.sendData2() on the main thread.
Code executes on the thread it is called from. Just because you put that code in your AsyncTask class does not mean it will be on a background thread. Only the code in doInBackground() is guaranteed to be executed in the background, because the Android framework takes care to call that method from a background thread. If you called it yourself, it would execute on whatever thread called it. sentData2() is no different.
You are using Asynctask wrong. When you call the execute method the doInBackground is called which runs on a different thread. You use the onPostExecute method from AsyncTask to get your data back to the main thread (a kind of callback method). This method runs on the main ui thread.
The sendData method would require a new AsyncTask, with a new doInbackground and a new call to execute.
I have a common class say for eg Class A which extends AsyncTask and has all the methods implemented i.e. onPreExecute, doinbackground and onPostExecute.
Now, there are other classes which want to use Class A object.
Say Class B uses class A in the below manner
A a = new A(context)
a.execute(url)
Then i fetch the result in get method. But get method is not the proper way of using AsyncTask. I will like to get the result in onPostExecute. For that i tried using a boolean parameter which will get true only in onpostexecute. The class B will check till it gets true and when it gets true it will fetch the result.
But this is somehow blocking the application.
I have placed the code for asynctask below.
'
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
public class A extends AsyncTask<String, Void, String>
{
private Context context = null;
private final HttpClient httpClient = new DefaultHttpClient();
private String content = null;
//private String error = null;
private String finalResult = null;
private static boolean isResult = false;
private ProgressDialog progressDialog = null;
public BabbleVilleSyncTask(Context context)
{
this.context = context;
progressDialog = new ProgressDialog(this.context);
}
protected void onPreExecute()
{
progressDialog.setMessage("Please Wait....");
progressDialog.show();
}
protected String doInBackground(String... urls)
{
try
{
//urls[0] = URLEncoder.encode(urls[0], "UTF-8");
HttpGet httpget = new HttpGet(urls[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
content = httpClient.execute(httpget, responseHandler);
}
/*catch(UnsupportedEncodingException ue)
{
error = ue.getMessage();
}*/
catch (ClientProtocolException e)
{
//error = e.getMessage();
cancel(true);
}
catch (IOException e)
{
//error = e.getMessage();
cancel(true);
}
httpClient.getConnectionManager().shutdown();
return content;
}
protected void onPostExecute(String result)
{
finalResult = result;
progressDialog.dismiss();
System.out.println("on Post execute called");
isResult = true;
}
public boolean getIsResult()
{
return isResult;
}
public void setIsResult(boolean flag)
{
isResult = flag;
}
public String getResult()
{
return finalResult;
}
}
'
Can someone let me know what the issue may be?
Regards
Sunil
A clean way to use AsyncTask to get a result would be to use a callback interface.
Here is a simple example of this concept:
interface AsyncTaskCompleteListener<T> {
public void onTaskComplete(T result);
}
then in your B class :
class B implements AsyncTaskCompleteListener<String> {
public void onTaskComplete(String result) {
// do whatever you need
}
public void launchTask(String url) {
A a = new A(context, this);
a.execute(url);
}
}
you should now add the following code to your A class:
class A extends AsyncTask<String, Void, String> {
private AsyncTaskCompleteListener<String> callback;
public A(Context context, AsyncTaskCompleteListener<String> cb) {
this.context = context;
this.callback = cb;
}
protected void onPostExecute(String result) {
finalResult = result;
progressDialog.dismiss();
System.out.println("on Post execute called");
callback.onTaskComplete(result);
}
}
This way, you don't need to wait explicitely for your task to complete, instead, your main code (which is probably the main UI thread), is waiting in the normal android event loop, and the onTaskComplete method will be automatically called, allowing to handle the task result there.
public abstract class BaseTask<T> extends AsyncTask<Object, Void, T> {
public Context context;
public ProgressDialog dialog;
public Exception exception;
protected BaseTask() {
}
public BaseTask(Context context) {
this.context = context;
this.dialog = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
this.dialog.setMessage(context.getResources().getString(R.string.loading));
this.dialog.show();
}
#Override
protected T doInBackground(Object... objects) {
try {
return doWork(objects);
} catch (Exception e) {
exception = e;
}
return null;
}
#Override
protected void onPostExecute(T result) {
if (dialog.isShowing()) dialog.dismiss();
if (exception == null) {
onResult(result);
} else {
onError();
}
}
public abstract T doWork(Object... objects) throws Exception;
public abstract void onResult(T result);
public abstract void onError();
}
I would make class A a private class embedded in parent class, and once it's done with the work it should update the parent class properties, that's possible onPostExecute.