I Googled alot, but no chance for this.
For now, i a have an Inner AsyncTask class that i want to use the return values in the upper class.
And it successfully work, cause i have put a Log.e() and it shows my value, Here is my code :
public class Consume extends AsyncTask<Void, Void, Void> {
private List<LatLng> latLngs = new ArrayList<>();
private List<ContactModel> contacts = new ArrayList<>();
InputStream inputStream = null;
String result = "";
#Override
protected Void doInBackground(Void... params) {
String URL = "http://x.x.x.x/MYWCF/Service1.svc/Json/getContact";
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
post.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(post);
HttpEntity httpEntity = httpResponse.getEntity();
inputStream = httpEntity.getContent();
} catch (UnsupportedEncodingException e1) {
Log.e("UnsupportedEncoding", e1.toString());
e1.printStackTrace();
} catch (ClientProtocolException e2) {
Log.e("ClientProtocolException", e2.toString());
e2.printStackTrace();
} catch (IllegalStateException e3) {
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
} catch (IOException e4) {
Log.e("IOException", e4.toString());
e4.printStackTrace();
}
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding", "Error converting result " + e.toString());
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
List<ContactModel> contactModels;
List<LatLng> myLatLngs = new ArrayList<>();
try {
JSONObject object = new JSONObject(result);
JSONArray jArray = object.getJSONArray("getContactResult");
Type listType = new TypeToken<List<ContactModel>>() {
}.getType();
contactModels = new Gson().fromJson(String.valueOf(jArray), listType);
setContacts(contactModels);
setContacts(contactModels);
for(ContactModel contactModel : contactModels) {
Double latitude = Double.valueOf(contactModel.getLatitude());
Double longitude = Double.valueOf(contactModel.getLongitude());
LatLng latLong = new LatLng(latitude, longitude);
myLatLngs.add(latLong);
}
setLatLngs(myLatLngs);
Log.e("SizeOfArray", myLatLngs.size()+"");
} catch (JSONException e) {
e.printStackTrace();
}
}
public void setContacts(List<ContactModel> contacts) {
this.contacts = contacts;
}
public List<ContactModel> getContacts() {
return contacts;
}
public void setLatLngs(List<LatLng> latLngs) {
this.latLngs = latLngs;
}
public List<LatLng> getLatLngs() {
return latLngs;
}
And in my Activity Class :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.osmdroid_map);
Consume consume = new Consume();
consume.execute();
When i run the app, cause of the line :
Log.e("SizeOfArray", myLatLngs.size()+"");
it returns me the correct int number of array size in logcat, But i want to use that in my App,
I even do all stuff in doInBackground method, and even make a static variable,
No chance.
Can any one give a real sample by my code?
Thx
As far as your AsyncTask class is an inner class. It can directly access objects of outer class.
Create an object of below at your outer class level.
List<LatLng> myLatLngs = new ArrayList<>();
And remove same from inner class so that single object instance will be their.
Another approach will be to use callback from your inner asyntask you need to have interface callback to outer class to start further process.
interface CallBack {
public void processingDone();
}
Consume consume = new Consume(new CallBack() {
#Override
public void processingDone(List<LatLng> mLatLngs) {
// Do your stuff here
}
});
consume.execute();
And inside your Consume constructor store callback to pass data back to outer class.
class Consume {
private Callback mCallback;
public Consume(Callback callback) {
mCallback = callback;
}
}
And from below link you can do
if (mCallback != null) {
mCallback.processingDone(myLatLngs);
}
Log.e("SizeOfArray", myLatLngs.size()+"");
First of all I will say that you should use static inner class instead of non-static inner class to avoid memory leaks as non-static inner class holds reference to the outer class. Another thing is that you can pass a WeakReference of outer parent class so that you can return the value from onPostExecute() of AsyncTask like
public static class Consume extends AsyncTask<Void, Void, Void> {
WeakReference<MainActivity> mActivity;
public Consume(MainActivity activity){
mActivity = new WeakReference<SampleActivity>(activity);
}
}
In your AsyncTask's onPostExecute method it will be
mActivity.response(latLngs);
And in your other class it will be like
private static void response(List<LatLng> latLngs){
// handle response here in your outer class
}
Update: Here is how you can pass WeakReference of Activity to Inner or Anonymous class and use it.
Thx all, for all replies.
Thx, I really did not understand what the problem is and cause of that i asked this simple question ! And unfortunately none of you notice that.
After the code :
Consume consume = new Consume();
consume.execute():
Compiler goes to execute next code too,Cause consume.execute() start another thread but the main thread continues.
Cause of that i received the value i wanted with a delay and therefore i though the problem is how to get the value,
But actually the problem was that i could not handle the thread asynchronization.
So i moved all them in onPre and onPost methods of AsyncTask class,And then it worked !
Related
I am seeking help so that I may get an ArrayList<String> in an alternate class. As you can see in the following code I have inner and outer classes. Both work as expected and I am both able to insert values and fetch details from my online database using php scripts (I have commented out these details for code clarity as it was taking up a lot of space).
public class ServerRequests {
ProgressDialog progressDialog;
public static final int CONNECTION_TIMEOUT = 15000;
public static final String SERVER_ADDRESS = "// my url domain";
public ArrayList<String> list1 = new ArrayList<>();
public ServerRequests(Context context)
{
progressDialog = new ProgressDialog(context);
progressDialog.setCancelable(false);
progressDialog.setTitle("Processing");
progressDialog.setMessage("Please wait..");
}
public void storeDataInBackground(MultiChallenge multiChallenge)
{
progressDialog.show();
new StoreDataAsyncTask(multiChallenge).execute();
}
public class StoreDataAsyncTask extends AsyncTask<Void , Void , Void>
{
MultiChallenge multiChallenge;
public StoreDataAsyncTask(MultiChallenge multiChallenge)
{
this.multiChallenge = multiChallenge;
}
#Override
protected Void doInBackground(Void... voids) {
// where I insert values...
#Override
protected void onPostExecute(Void aVoid) {
progressDialog.dismiss();
super.onPostExecute(aVoid);
Log.d("ServerRequests", "Post execute");
}
}
public ArrayList<String> fetchDataInBackground() {
progressDialog.show();
new FetchDataAsyncTask().execute();
return list1;
}
public class FetchDataAsyncTask extends AsyncTask<Void, Void, ArrayList<String>>
{
public FetchDataAsyncTask()
{
}
String text = "";
#Override
protected ArrayList<String> doInBackground(Void... params) {
InputStream is1;
HttpParams httpRequestParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpRequestParams, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpRequestParams, CONNECTION_TIMEOUT);
HttpClient client = new DefaultHttpClient(httpRequestParams);
HttpPost post = new HttpPost(// my url domain+ "// php script");
try {
HttpResponse httpResponse = client.execute(post);
is1 = httpResponse.getEntity().getContent();
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(is1, "iso-8859-1"), 8);
String line = null;
while ((line = reader.readLine()) != null) {
text += line + "\n";
}
is1.close();
JSONArray data = new JSONArray(text);
for (int i = 0; i < data.length(); i++) {
Log.d("GetNames", data.getString(i));
JSONObject jsonData = data.getJSONObject(i);
list1.add( // I successfully add details to list1 here, I have commented it out for code clarity);
}
for (int iterate = 0; iterate < list1.size(); iterate++) {
Log.d("list1", list1.get(iterate));
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
// catch (JSONException e) {e.printStackTrace();}
return list1;
}
#Override
protected void onPostExecute(ArrayList<String> myList) {
progressDialog.dismiss();
super.onPostExecute(myList);
}
}
}
Now that I successfully add to the list1 (I can tell values are added to it because of the for loop with the int iterate), I now need to send it to another class whereby I will put items in a listview. This is my code in the class in which I want to display the details of the ArrayList I get from ServerRequests:
ServerRequests serverRequests = new ServerRequests(DisplayInfo.this);
ArrayList<String> myList = new ArrayList<>();
myList = serverRequests.fetchDataInBackground();
for (int iterate = 0; iterate < myList.size(); iterate++) {
Log.d("Display", myList.get(iterate));
However the above for loop is never called, indicating that myList is never given the details that list1 manages to get in the doInBackground method of class FetchDataAsync.
Please note I did spend a number of hours attempting a variety of my own ideas and answers derived from SO before asking this question. Thank you all in advance of your help.
In the onPostExecute method call a function in the calling class
#Override
protected void onPostExecute(ArrayList<String> myList) {
progressDialog.dismiss();
super.onPostExecute(myList);
MainActivity.sendStrings(myList);
}
In the calling function implement a method:
public static void sendStrings(ArrayList<String> strings)
{
//Add for loop here
}
Alternatively you can also use interfaces. Call the interface in onPostExecute and implement the interface in the calling class
I have PostData class to transmit data lat, long,mac,.. to the server which is being sent to it from the service class. In PostData class, the data is being processed with the aid of AsyncTask and HttpURLConnection.
Now I have a new activity where the user can send query to the server. To reach that I have to get ArrayList<Integer> from the server and create a something like checkbox list, where the user can select the desirable items then the data will be sent to the server to retrieve a result.
Can I implement a new Asyntask and HttpURLConnection to achieve that or I have to use my AsynTask and HttpURLCOnnection in the POstData class?
I appreciate any help.
My PostData class:
public class PostData {
String jSONString;
private AsyncTaskCallback callback;
public PostData(AsyncTaskCallback callback) {
this.callback = callback;
}
public String getjSONString() {
return jSONString;
}
public void setjSONString(String jSONString) {
this.jSONString = jSONString;
}
public void post_data(String jSONString, Context context) {
this.jSONString = jSONString;
new MyAsyncTask(context).execute(jSONString);
}
class MyAsyncTask extends AsyncTask<String, Integer, ArrayList<Integer>> {
final Context mContext;
ArrayList<Integer> routes = new ArrayList<Integer>();
double distance;
public MyAsyncTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Integer> doInBackground(String... params) {
BufferedReader reader = null;
try {
URL myUrl = new URL(
"https://bustracker.rhcloud.com/webapi/test");
HttpURLConnection conn = (HttpURLConnection) myUrl
.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("Content-Type", "application/json");
conn.connect();
DataOutputStream wr = new DataOutputStream(
conn.getOutputStream());
wr.writeBytes(params[0]);
wr.close();
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
Gson gson = new Gson();
StopsJSON data = gson.fromJson(sb.toString(), StopsJSON.class);
routes = data.getRoutes();
distance = data.getDistance();
System.out.println("The output of the StringBulder: "
+ sb.toString());
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (reader != null) {
try {
reader.close();
return null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(ArrayList<Integer> result) {
if (routes != null && !routes.isEmpty()) {
callback.onAsyncTaskFinished(routes, distance);
}else{
Log.e("123", "Avoiding null pointer, the routes are null!!!");
}
}
}
}
This may set you on a path of some code refactoring, but for general good practice regarding REST requests you should look into Volley, or Retrofit, (also another SO question regarding retrofit that might help).
these libraries are very efficient performance-wise, and in the long run will save you a lot of grief, they take care of the background threading, and you won't necessarily need to explicitly use HttpUrlConnection.
Hope this helps.
Edit :
To further answer your question - if you do wish to specifically use AsyncTask - you should use the PostData class as a general purpose class, in your case for the network operations (might also possibly want to make it a Singleton, and give it a more general name).
and yes your implementation looks like you should be able to use it, and any corrections\changes\additions should be made in the AsyncTask itself under PostData, no need for another general class, if need be - you can just add more inner AsyncTask subclasses.
my (very very general) direction would be:
public class NetworkData {
String jSONString;
private AsyncTaskCallback callback;
public NetworkData(AsyncTaskCallback callback) {
this.callback = callback;
}
public String getjSONString() {
return jSONString;
}
public void setjSONString(String jSONString) {
this.jSONString = jSONString;
}
//let's say this is for post requests...
public void postData(String jSONString, Context context) {
this.jSONString = jSONString;
new MyPostTask(context).execute(jSONString);
}
//let's say this is for get requests...
public void getData(String jSONString, Context context) {
this.jSONString = jSONString;
new MyGetTask(context).execute(jSONString);
}
class MyPostTask extends AsyncTask<String, Integer, ArrayList<Integer>> {
final Context mContext;
ArrayList<Integer> routes = new ArrayList<Integer>();
double distance;
public MyPostTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Integer> doInBackground(String... params)
{
try
{
//do you stuff for post requests...
} catch (IOException e)
{
//...
}
finally
{
//...
}
}
}
class MyGetTask extends AsyncTask<String, Void, ArrayList<Object>> {
final Context mContext;
ArrayList<Object> routes = new ArrayList<Object>();
public MyPostTask(Context context) {
mContext = context;
}
#Override
protected ArrayList<Object> doInBackground(String... params)
{
try
{
//do you stuff for get requests...
}
catch (IOException e)
{
//...
}
finally
{
//...
}
}
}
}
If you do choose to use Volley or Retrofit, then keep using the general class structure and just modify it's utilities and replace the requset format (i.e. instead of the AsyncTask parts).
I am new to android development. I have a AsyncTask function in my application. Calling http request from all activities. Now in each activity I am using the following class to connect to server, in some activities I even called twice !!.
Basically I am a web developer and in such cases we use a single class which can be accessed from entire application(web) and use the common function to do the same activity. The only difference is input and out put will be changed.
My doubt is in this case can I use ( convert) this to such a function or class ?
My assume is
Create an android class ( which can be accessed from all the activities )
Just make the JSON string we need with specific server ( for process in server )
Just pass the created json to the created class and then made the http connect )
Process the returned data from server
Pass that to the corresponding activity
So that I can use the same function for all the activities and I can avoid duplicate query
Can I convert this code to such a manner ?
My Code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
LogIN loginUser = new LogIN();
LoginUser.execute("");
}
private class LogIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
if(flags.equals(1)){
Itent homepage = new Intent(MainActivity.this, RegisterDevice.class);
startActivity(homepage);
finish();
}
else {
Intent homepage = new Intent(MainActivity.this, LoginActivity.class);
startActivity(homepage);
finish();
}
super.onPostExecute(result);
}
}
}
Please any one help/advise
Thanks in advance
Extract your class to a different file and make it public
public class LogIN extends AsyncTask<Object, Integer, String> {
private ILoginListener listener;
#Override
protected String doInBackground(Object... arg0) {
try {
this.listener = (ILoginListener) arg0[0];
//You can also send the url in the obj array
String theUrl = (String) arg0[1];
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
listener.logInSessionCheckListener(flag.equals(1));
super.onPostExecute(result);
}
}
Regarding your other question, I normally have an interface for that, something like this:
public interface ILoginListener {
public void logInSessionCheckListener(SomeNeeded Value);
}
I implement the interface in the class where i need the postExecute result and in the overriden method you can to what you want with the result of your task.
Your class where you user it will look something like this:
public class SomeClass implements ILoginListener {
//Call it like this from any class:
LogIN loginTask = new LogIn();
Object[] someParams = new Object[2];
//add the listener
someParams[0] = SomeClass.this
//add the url
someParams[1] = someUrlString;
loginTask.execute(someParams);
#Override
public void logInSessionCheckListener(SomeNeeded Value){
//do Stuff with your results
}
}
You can do it like make separate class for everything inside doInBackground() method and called it in all activity with passing parameter to
LogIN loginUser = new LogIN(yourparameter);
LoginUser.execute("");
and check parameter in AsyncTask Class constructor like
public LogIN(Myparameter){
// Your data
}
On the other hand you can use this great framework for android : android-query and the async API.
It allows you to perform asynchroneous network tasks from activities and easily work with the results of your requests.
You should use interfaces to implement a callback to your ui activity.
Have a look at this thread, it might be useful:
android asynctask sending callbacks to ui
And your asyntask class should be in a seperate java file with public acces.
And to pass the parametres you simply have to call a new LogIN async Task like this:
new LogIN().execute(urls);
Hope it helped :)
Remember that you can never know when AsyncTask is going to finish. So if you're using this to authenticate users and then perform task X, task Y, or task Z,
then maybe it's better to create a Login helper class
public class LoginHelper {
public boolean login(params){
// Authenticate user and return true if successfull
}
}
and then have in your Activity classes
private class X extends AsyncTask {
#Override
protected String doInBackground(String... sUrl) {
...
boolean authenticated = LoginHelper.login(params...);
if(authenticated == true) {
// Perform task X here...
} else {
// Inform the user that the login failed...
}
}
First of all
You have to pass the context in which you are calling your async task
Sample Code
Login loginTask = new Long(getContext());
loginTask.execute();
You class Login should have a constructor that accepts the Context
Sample Code
public class Login extends AsyncTask<String, Integer, String> {
private Context mContext ;
private ProgressDialog pd;
private Handler handler = new Handler { };
public Login (Context context){
mContext = context ;
}
.....
Then make sure to create the method showDialog inside Login class to show the progress dialog
Note
You can add what ever Constructors you need to customize the behaviour of your Login task
for example : pass boolean parameter to tell that the Login Task is cancelable....
Hope that help you :)
I am calling Async Task class in my main activity:here is code
public class MainActivity extends Activity implements AsyncResponse {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Connection connection=new Connection();
connection.execute();
}
Here is my Connection class:
class Connection extends AsyncTask<String,String, Void>
{
public AsyncResponse delegate=null;
String result = "";
InputStream is=null;
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
/*ArrayList<NameValuePair> nameValuePairs = null;
int i=0;
String username=params[i].toString();
String password=params[i+1].toString();
String validation=params[i+2].toString();
nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("username",username));
nameValuePairs.add(new BasicNameValuePair("password",password));
// nameValuePairs.add(new BasicNameValuePair("username",));*/
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.0.2.2/connection.php");
// httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
return null;
// TODO Auto-generated method stub
}
protected void onPostExecute(Void v) {
try{
JSONArray jArray = new JSONArray(result);
delegate.processFinish(jArray);
// labels2.add(password);
//Returndata(labels2);
}
catch(JSONException e){
Log.e("log_tag", "Error parsing data "+e.toString());
}
}
}
On post execute I am sending Jarray to an interface:and using that interface in my main Activity:
Here is my interface:
public interface AsyncResponse {
void processFinish(JSONArray jArray);
}
And using it main activity like this:
#Override
public void processFinish(JSONArray jarray) {
// TODO Auto-generated method stub
try {
for(int i=0;i<=jarray.length();i++)
{
JSONObject json_data;
json_data = jarray.getJSONObject(i);
String username=json_data.getString("username");
String password=json_data.getString("password");
Toast.makeText(getBaseContext(),username+password,Toast.LENGTH_LONG).show();
}
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Just a suggestion When your doInBackground method returns String the params in onPostExecute will have that return value of doInBackground. You don't have to declare a seperate String. Have a look below,
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected String doInBackground(URL... urls) {
String someresult = "got from some operations";
return someresult;
}
protected void onPostExecute(String result) {
System.out.println("The resulting string from doInBackground is " + result);
}
}
Secondly with Connection class you have,
public AsyncResponse delegate=null;
You haven't initialized the delegate variable, it null!! So you have a Null pointer exception. You can never instantiate an interface in java. You can, however, refer to an object that implements an interface by the type of the interface. Hope this helps.
Edit:
If you have a interface implemented by class B then you can haveAsyncResponse test = new B(); like below
public interface AsyncResponse
{
}
public class B implements AsyncResponse
{
}
public static void main(String[] args)
{
AsyncResponse test = new B();
}
Now in Android you cannot instantiate an Activity. Instead have a reference to that activity instance. I bet you have a methods there.
I think the code do not declare the interface that is in use.
In the MainActivity class should declare something below.
The connection thread that you have created did not declare any interface.
And hence it will be declared to null value.
public class MainActivity extends Activity implements AsyncResponse {
Connection connection=new Connection(); // You shud declare on top
#Override
protected void onCreate(Bundle savedInstanceState) {
connection.delegate=this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connection.execute();
}
I am trying to pass a string array to my adapter. My problem is i initialized globally and try to create string array in my asynchronous task below. But i am getting as null. Below is my code. Actually in this example they taking it from resource folders bu i want it from my json response. Any help is appreciated.
String[] mString;
public ActionsAdapter(Context context) {
mInflater = LayoutInflater.from(context);
session = new SessionManager(context);
final Resources res = context.getResources();
new ConnectAppMenu(context).execute();
// mTitles = res.getStringArray(R.array.actions_names);
// mUrls = res.getStringArray(R.array.actions_links);
// mIcons = res.obtainTypedArray(R.array.actions_icons);
System.out.println("Menus"+ mString);
}
public class ConnectAppMenu extends AsyncTask<String, Void, String> {
private ProgressDialog dialog;
private final Context context;
public ConnectAppMenu(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// UI work allowed here
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setMessage("Connecting....");
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... params) {
String returnConnect = doConnectAppMenu();
return returnConnect;
}
public String doConnectAppMenu() {
HashMap<String, String> user = session.getUserDetails();
String client_url = user.get(SessionManager.KEY_CLIENT);
// if(connection) {
HttpParams connectionParameters = new BasicHttpParams();
int timeoutConnection = 8000;
HttpConnectionParams.setConnectionTimeout(connectionParameters, timeoutConnection);
int timeoutSocket = 10000;
HttpConnectionParams.setSoTimeout(connectionParameters, timeoutSocket);
HttpClient httpClient = new DefaultHttpClient(connectionParameters);
HttpPost httpPost = new HttpPost(client_url+"/api/common/app_menu");
JSONObject json = new JSONObject();
try{
json.put("data", 1);
json.put("versionid", 1);
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(se);
//Execute HTTP post request
appmenu_res = httpClient.execute(httpPost);
appmenu_obj = new org.json.JSONObject(org.apache.http.util.EntityUtils.toString(appmenu_res.getEntity()));
appmenu_result = appmenu_obj.toString();
}
catch(JSONException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// }
return appmenu_result;
}
#Override
public void onPostExecute(String result) {
int status_code = appmenu_res.getStatusLine().getStatusCode();
if (status_code == 200) {
dialog.dismiss();
try {
menuObject = new JSONObject(result);
JSONArray names= menuObject.names();
JSONArray values = menuObject.toJSONArray(names);
for (int i = 0; i< values.length(); i++) {
JSONObject json2 = (JSONObject) values.get(i);
int menu_id = json2.getInt("menu_id");
if (menu_id > 0) {
if (json2.has("menu_name")) {
menu_list = json2.get("menu_name").toString();
mString = new String[] { menu_list };
//mUrls = menu_list.length();
}
}
}
System.out.println("Json Menu" + Arrays.toString(mString));
/*Iterator<String> iter = menuObject.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
Object value = menuObject.get(key);
//System.out.println("Hai" +value);
System.out.println("Post Execute" + value);
} catch (JSONException e) {
// Something went wrong!
}
}*/
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//dialog.dismiss();
}
}
}
well first of all if you're looking for the JSON object as a String don't do what you did here:
appmenu_obj = new org.json.JSONObject(org.apache.http.util.EntityUtils.toString(appmenu_res.getEntity()));
I'd suggest doing the following:
String Json = EntityUtils.toString(appmenu_res.getEntity());
return Json;
Now if you want to do the processing of your JSON on the UI thread (as you seem to want to based on the return type being a string) this should work. However this method is not recommended since the Json will need to be processed into objects which will take time and clog the UI thread.
A better solution would be to serialize your Json on the background thread and then pass the serialized object back to the main thread to update the UI.
If you have many types I would suggest using generics. I've already built a Loader which can do what you want if you want here. You will need touse the GSON library and build appropriate seralizers. Also working with the loader class is different to working with the AsyncTaskClass so please read the documentation here
Edit
Ok so what you want to do if you want get the Activity to have a callback from the AsyncTask is to do something along the lines of:
public class MyActivity extends Activity implements AsyncTaskCallback
where AsyncTaskCallback looks something like :
public interface AsyncTaskCallback
{
public processData(Object responseObject);
}
now in your onPostExecute code you'll need to do somehting like:
#Override
protected void onPostExecute(Object r){
if (r != null) {
l.processData(data);
}
}
and add the following function to your async task
public void addAsyncTaskListener (final AsyncTaskListener l){
mCallback = l;
}
and then finally add the listner and process the data as required in the Activity in the function processData function that the interface forces your activity to implement.
Instead of using String[] you can use ArrayList for Setting list in adaptor.