This question already has answers here:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
(17 answers)
Closed 5 years ago.
How to catch moment when AsyncTask is finished?
I have ProfileUpdate class which extends AsyncTask, and from another activity I calling this method and after I need update my data. How to know that asynctask finished? My asynctask method in another class and not in activity class!!!
this is my onRefresh method in the activity:
#Override
public void onRefresh() {
if (!AlertView.isInternetAvailable(getContext())) {
swipeLayout.setRefreshing(false);
Toast.makeText(getContext(), Messages.CONNECTION_ERROR + ": " + Messages.NO_INTERNET, Toast.LENGTH_SHORT).show();
} else {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
new UpdateProfile(getActivity(), swipeLayout, sharedPreferences.getString(Constants.TOKEN, ""), user.getIin()).execute(Urls.GET_USER);
}
});
profileDefaults();
}
}
and here my AsyncTask method:
public class UpdateProfile extends AsyncTask <String, Void, String> {
private Activity activity;
private SwipeRefreshLayout swipeRefreshLayout;
private String token;
private String userIin;
private SharedPreferences sharedPreferences;
public UpdateProfile(Activity activity, SwipeRefreshLayout swipeRefreshLayout, String token, String userIin) {
this.activity = activity;
this.swipeRefreshLayout = swipeRefreshLayout;
this.token = token;
this.userIin = userIin;
sharedPreferences = this.activity.getSharedPreferences(Constants.PROJECT, Context.MODE_PRIVATE);
}
#Override
protected String doInBackground(String... params) {
URL url = null;
try {
url = new URL(params[0]);
try {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("iin", userIin)
.build();
Request request = new Request.Builder()
.url(url)
.addHeader(Constants.AUTH_TOKEN, token)
.post(body)
.build();
Response responses = null;
try {
responses = okHttpClient.newCall(request).execute();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
assert responses != null;
return responses.body().string();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
int code = Integer.valueOf(jsonObject.getString(Constants.CODE));
if (code == Codes.OK) {
Toast.makeText(activity, "Данные обновлены", Toast.LENGTH_SHORT).show();
String userHeader = jsonObject.getString("user");
JSONObject userInfo = new JSONObject(userHeader);
String mobilePhone = userInfo.getString(SingletonConstants.MOBILE_PHONE);
Boolean isActive = userInfo.getBoolean(SingletonConstants.IS_ACTIVE);
Boolean signedAgreement = userInfo.getBoolean(SingletonConstants.SIGNED_AGREEMENT);
Boolean esfEntered = userInfo.getBoolean(SingletonConstants.ESF_ENTERED);
String address = userInfo.getString(SingletonConstants.ADDRESS);
String iin = userInfo.getString(SingletonConstants.IIN);
String certExpDate = userInfo.getString(SingletonConstants.CERT_EXP_DATE);
String firstName = userInfo.getString(SingletonConstants.FIRST_NAME);
String middleName = userInfo.getString(SingletonConstants.MIDDLE_NAME);
String workPhone = userInfo.getString(SingletonConstants.WORK_PHONE);
String secondName = userInfo.getString(SingletonConstants.SECOND_NAME);
String avatarUrl = userInfo.getString(SingletonConstants.AVATAR_URL);;
String secondEmail = userInfo.getString(SingletonConstants.SECOND_EMAIL);
String email = userInfo.getString(SingletonConstants.EMAIL);
User newUser = new User(mobilePhone, isActive, signedAgreement, esfEntered, address, iin, certExpDate, firstName, middleName, workPhone, secondName, avatarUrl, secondEmail, email);
Gson gson = new Gson ();
String userGson = gson.toJson (newUser);
sharedPreferences.edit().putString(SingletonConstants.USER, userGson).apply();
swipeRefreshLayout.setRefreshing(false);
} else {
AlertView.showAlertView(activity, Messages.ERROR, jsonObject.getString(Constants.MESSAGE), Messages.OK);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
How I can call profileDefaults()? It's into my activity. And I need to call it after onPostExecute!
A cleaner way to do it is to use interfaces as listeners.
Create this interface:
public interface OnAsyncFinished{
void onAsyncFinished(Object o);
}
Add the interface as a parameter in your AsyncTaskClass constructor:
private OnAsyncFinished onAsyncFinished;
public UpdateProfile(..., OnAsyncFinished onAsyncFinished) {
...
this.onAsyncFinished = onAsyncFinished;
}
...
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
onAsyncFinished.onAsyncFinished(s); //This will notifiy the method on main activity, and you can now resume the work there
...
}
Implement the interface in your main activity:
public MainActivity extends Activity implements OnAsyncFinished {
#Override
public void onAsyncFinished(Object o) {
//This will get called after onPostExecute, do what u want with the object you got from onPostExecute, json or string in ur example
profileDefaults(); //call ur function
}
}
EDIT:
When creating the async task in your main activity pass this in the constructor likeso:
#Override
public void run() {
new UpdateProfile(..., this).execute(Urls.GET_USER);
}
Related
import com.github.nkzawa.emitter.Emitter;
private Emitter.Listener onNewMessage = new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONExpextion e) {
return;
}
}
});
}
};
When I put in this code in my project, it said "Cannot resolve method
get Activity "
then, how can I deal with this problem?
You are calling getActivity() from inner class Emitter. So you should replace getActivity() with the name of your activity followed by .this. For example the name of your activity is MainActivity, then replace getActivity() with MainActivity.this
And your code would be like this:
private Emitter.Listener onNewMessage = new Emitter.Listener() {
#Override
public void call(final Object... args) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONExpextion e) {
return;
}
}
});
}
};
I am currently trying to make an android app that basically downloads strings from a url. But I want to make it object oriented. My mainActivity gets string from webService which downloads string when button is clicked. But I am not good at interfaces and callbacks. What should I do to make this code run?
public class MainActivity extends Activity implements WebServiceInterface{
private TextView textView;
private Button readWebPage;
private WebService service;
private WebServiceInterface webServiceInterface;
private String response;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.TextView01);
readWebPage = (Button) findViewById(R.id.readWebpage);
service = new WebService();
readWebPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
service.execute(new String[]{"http://google.com/"});
onSuccess(response);
}
});
}
#Override
public void onSuccess(String response) {
textView.setText(Html.fromHtml(response));
}
#Override
public void onFail(Exception ex) {
textView.setText(ex.getLocalizedMessage());
}
}
public class WebService extends AsyncTask<String, Void, String> {
private WebServiceInterface webServiceInterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webServiceInterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webServiceInterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
public interface WebServiceInterface {
void onSuccess(String response);
void onFail(Exception ex);
}
you need to create one public method for set webServiceInterface in WebService class like
public setWebServiceInterface (WebServiceInterface listener)
{
this.webServiceInterface =listener;
}
in MainActivity activity call this method and pass argument this
service.setWebServiceInterface (this);
in WebService class in onPostExecute Method call
webServiceInterface.onSuccess(s);
Add WebService (WebServiceInterface webServiceInterface) in your AsyncTask as a constructor.
service = new WebService(new WebServiceInterface (){
void onSuccess(String response){
//do your stuff
}
void onFail(Exception ex){
//do your stuff
}
});
and in your asynctask
public class WebService extends AsyncTask<String, Void, String> {
public WebService (WebServiceInterface webServiceInterface){
this.webinterface= webServiceInterface;
}
private WebServiceInterface webinterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webinterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webinterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
I have found the problem, it is because of runOnUiThread is missing.
I am having trouble with my listblogs=parseJSONResponse(result), result is underlined red and if I hover over it it says that, I cannot apply a parseJsonResponse JSONARRAY to a JSONARRAY[]. Does anyone know why this is being caused does it have something to do with the params?
class YourTask extends AsyncTask<JSONArray, String, ArrayList<Blogs> > {
#Override
protected ArrayList<Blogs> doInBackground(JSONArray... result) {
listblogs.clear(); // here you clear the old data
listblogs=parseJSONResponse(result);
return listblogs;
}
#Override
protected void onPostExecute(ArrayList<Blogs> blogs) {
mAdapterDashBoard.setBloglist(listblogs);
}
}
private void JsonRequestMethod() {
final long start = SystemClock.elapsedRealtime();
mVolleySingleton = VolleySingleton.getInstance();
//intitalize Volley Singleton request key
mRequestQueue = mVolleySingleton.getRequestQueue();
//2 types of requests an Array request and an Object Request
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_API, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
System.out.print(response);
listblogs = new YourTask().doInBackground();
listblogs.clear();
listblogs=parseJSONResponse(response);
try {
listblogs = new YourTask().execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println(response);
Log.d("Testing", "Time elapsed: " + (SystemClock.elapsedRealtime() - start));
System.out.println("it worked!!!");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mRequestQueue.add(request);
}
private ArrayList<Blogs> parseJSONResponse(JSONArray response) {
if (!response.equals("")) {
try {
StringBuilder data = new StringBuilder();
for (int i = 0; i < response.length(); i++) {
JSONObject currentQuestions = response.getJSONObject(i);
String text = currentQuestions.getString("text");
String points = currentQuestions.getString("points");
String ID=currentQuestions.getString("id");
String studentId = currentQuestions.getString("studentId");
String DateCreated=currentQuestions.getString("created");
long time=Long.parseLong(DateCreated.trim());
data.append(text + "\n" + points + "\n");
System.out.println(data);
Blogs blogs = new Blogs();
blogs.setId(ID);
blogs.setMstudentId(studentId);
blogs.setMtext(text);
blogs.setPoints(points);
//The dateCreated was off by 1 hour so 3600000 ms where added=1hour, (UPDATE)
blogs.setDateCreated(getTimeAgo(time));
System.out.println(time + "time");
listblogs.add(blogs);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return listblogs;
}
AsyncTask
public class MyAsyncTask extends AsyncTask<Void, Void, ArrayList> {
JsonArray myJsonArray;
#Override
protected void onPreExecute() {
super.onPreExecute();
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
listblogs.clear();
}
#Override
protected ArrayList doInBackground(Void... params) {
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_API, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
myJsonArray = response;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mRequestQueue.add(request);
return null;
}
#Override
protected void onPostExecute(ArrayList arrayList) {
super.onPostExecute(arrayList);
ArrayList<Blogs> blogsArrayList = new ArrayList<>();
try {
StringBuilder data = new StringBuilder();
for (int i = 0; i < myJsonArray.length(); i++) {
JSONObject currentQuestions = myJsonArray.getJSONObject(i);
String text = currentQuestions.getString("text");
String points = currentQuestions.getString("points");
String ID=currentQuestions.getString("id");
String studentId = currentQuestions.getString("studentId");
String DateCreated=currentQuestions.getString("created");
long time=Long.parseLong(DateCreated.trim());
data.append(text + "\n" + points + "\n");
System.out.println(data);
Blogs blogs = new Blogs();
blogs.setId(ID);
blogs.setMstudentId(studentId);
blogs.setMtext(text);
blogs.setPoints(points);
//The dateCreated was off by 1 hour so 3600000 ms where added=1hour, (UPDATE)
blogs.setDateCreated(getTimeAgo(time));
System.out.println(time+"time");
blogsArrayList.add(blogs);
}
} catch (JSONException e) {
e.printStackTrace();
}
return blogsArrayList;
}
ArrayList
synchronous:
listblogs = new MyAsyncTask().execute().get();
asynchronous:
....
} catch (JSONException e) {
e.printStackTrace();
}
listblogs = blogsArrayList;
return blogsArrayList;
}
new MyAsyncTask().execute();
you can run any code inside an async task like this:
public class YourTask extends AsyncTask<String, Void, ArrayList<Blogs> > {
private static final String TAG = YourTask.class.getSimpleName();
private JSONArray mResponse;
private Activity mActivity;
public YourTask(final Activity activity, final JSONArray response) {
super();
this.mActivity = activity;
this.mResponse = response;
}
#Override
protected ArrayList<Blogs> doInBackground(String... params) {
if (!mResponse.equals("")) {
// Your Code
}
return listblogs;
}
#Override
protected void onPostExecute(final ArrayList<Blogs> blogs) {
if (mActivity instanceOf YourActivity) {
((YourActivity) activity).finishTask(blogs);
}
}
#Override
protected void onCancelled() {}
}
call this Task from your activity like:
AsyncTask<String, Void, JSONArray> task = new YourTask(this, response);
task.executeContent();
Basically just send the JSONArray you want to parse to the Async Task and handle all the UI in den finishTask method in your Activity. The advantage is that you can extract your task in an extra file and leave your activity to just handle controlling your views.
I have a problem and I can't find the solution on the internet. I saw a lot of examples but no one really answered to my problem.
I have a login page and then, after checked if the both fields (login/pass) are filled, try to connect by another thread.
public class LoginActivity extends AppCompatActivity {
private EditText login = null;
private EditText password = null;
private RadioButton radioButton = null;
private Button button = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
login = (EditText)findViewById(R.id.loginEditText);
password = (EditText)findViewById(R.id.passwordEditText);
radioButton = (RadioButton)findViewById(R.id.saveRadioButton);
button = (Button)findViewById(R.id.ConnectionButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (login.getText().toString().equals("")
|| password.getText().toString().equals("")) {
alert(getString(R.string.alertDialoguErrorTitle), getString(R.string.UnfilledFieldLogin));
} else {
boolean haveToSave = radioButton.isChecked();
User user = User.getUser(login.getText().toString(), password.getText().toString());
try {
Intranet.login.start();
Intranet.login.join();
Intranet.login.interrupt();
Intranet.login.join();
} catch (InterruptedException e) {
alert(getString(R.string.alertDialoguErrorTitle), e.toString());
login.setText("");
password.setText("");
} finally {
if (!user._token.equals("")) {
if (haveToSave) {
// SAVE DATA
}
finish();
} else {
login.setText("");
password.setText("");
alert(getString(R.string.alertDialoguErrorTitle), getString(R.string.badLoginPassword));
}
}
}
}
});
}
public void alert(String title, String message) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(LoginActivity.this);
alertDialog.setTitle(title);
alertDialog.setMessage(message);
alertDialog.setPositiveButton("Close",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// nothing
}
});
alertDialog.show();
}
}
// The class using on the other thread
public class Intranet {
public static int responseCode = 0;
public static String responseString = "";
public static Thread login = new Thread(new Runnable() {
private OkHttpClient client = new OkHttpClient();
private String url = "https://epitech-api.herokuapp.com/login";
private User user = User.getUser();
public void run() {
try {
// Build the request
RequestBody formBody = new FormEncodingBuilder()
.add("login", user._login)
.add("password", user._password)
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
Response responses = null;
// Reset the response code
responseCode = 0;
// Make the request
responses = client.newCall(request).execute();
if ((responseCode = responses.code()) == 200) {
// Get response
String jsonData = responses.body().string();
// Transform reponse to JSon Object
JSONObject json = new JSONObject(jsonData);
// Use the JSon Object
user._token = json.getString("token");
}
} catch (IOException e) {
responseString = e.toString();
} catch (JSONException e) {
responseString = e.toString();
}
;
}
});
}
I tried a lot of solutions with join() which wait the end of the thread. But finally, all time at the second time, when I try to connect myself, an exception comes up (The thread is already started). So how can this thread still running if it's interrupted before continuing?
When the new message is received, message should be passed to the internet for my further business logic.
To receive the new messages I used onReceive of broadcastreceiver and to process the internet business logics in background I used AsyncTask.
I am getting the null pointer exception in onPostExecute method of AyncTask, I read many stackoverflow and other website solutions and created the interface and initialized it in the AsyncTask extended class constructor. But getting only nullpointer.
My Full code:
MainActivity:
public class SmsActivity extends Activity implements ParseURL.OnAsyncRequestComplete {
private static SmsActivity inst;
public static final String SMS_BUNDLE = "pdus";
public static SmsActivity instance() {
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);
}
#Override
public void processResp(String output){
String outpu1 = output+" in main";
}
}
BroadCastReceiver:
public class SmsBroadcastReceiver extends BroadcastReceiver{
public static final String SMS_BUNDLE = "pdus";
public void onReceive(Context context, Intent intent) {
Bundle intentExtras = intent.getExtras();
if (intentExtras != null) {
Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
String smsMessageStr = "";
boolean rechargeResult = false;
for (int i = 0; i < sms.length; ++i) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
String smsBody = smsMessage.getMessageBody().toString();
String address = smsMessage.getOriginatingAddress();
smsMessageStr += "SMS From: " + address + "\n";
if (smsBody != null) {
String[] splitValues = smsBody.split(" ");
if (splitValues != null && splitValues.length > 0) {
String siteURL = "SITE_URL";
try {
ParseURL.OnAsyncRequestComplete procesInterf = null;
ParseURL urlParse = new ParseURL(procesInterf);
Toast.makeText(context, siteURL, Toast.LENGTH_LONG).show();
new ParseURL(procesInterf).execute(new String[]{siteURL});
} catch (Exception e) {
Toast.makeText(context, "123 "+e.getMessage(), Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(context, "split values is null", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context, "smsbody is null", Toast.LENGTH_LONG).show();
}
}
}
}
}
}
ParseURL:
public class ParseURL extends AsyncTask<String, Void, String> {
ProgressDialog progressDialog;
OnAsyncRequestComplete caller;
//Context context;
public ParseURL(OnAsyncRequestComplete a) {
caller = a;
// context = a;
}
public interface OnAsyncRequestComplete {
public void processResp(String response);
}
#Override
protected void onPreExecute()
{
progressDialog.setMessage("WAIT...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected String doInBackground(String... strings) {
String responseStatus = "";
try {
if(strings!=null) {
if (null != strings[0]) {
Document doc = Jsoup.connect(strings[0]).timeout(0).get();
if (doc != null) {
String result = doc.select("body").text();
if (null != result) {
if (result.toLowerCase().contains("FAILED".toLowerCase())) {
responseStatus = result;
} else if (result.toLowerCase().contains("SUCCESS".toLowerCase())) {
responseStatus = "SUCCESS";
} else {
responseStatus = "FAILED";
}
} else {
responseStatus = "google";
}
} else {
responseStatus = "facebook";
}
} else {
responseStatus = "youtube";
}
}else{
responseStatus = "ebay";
}
} catch (Throwable t) {
t.printStackTrace();
}
return responseStatus;
}
#Override
protected void onPostExecute(String s) {
caller.processResp(s);
}
}
I tried many solutions which is shared in the stackoverflow and other sites. But I could not solve it. Please do not mark this as duplicate.
Thanks in advance.
Ohh maaan...
ParseURL.OnAsyncRequestComplete procesInterf = null;
ParseURL urlParse = new ParseURL(procesInterf);
public ParseURL(OnAsyncRequestComplete a) {
caller = a;
}
#Override
protected void onPostExecute(String s) {
caller.processResp(s);
}
Are You see mistake?
You pass null to the ParseUrl constructor, so on PosteExecute() tries to call a method of a null callback.
I suspect that you would like to do that
ParseURL.OnAsyncRequestComplete procesInterf = SmsActivity.this;
But it will work, if your SmsBroadcastReceiver class is a inner class of SmsActivity.
You never initialize caller. Basically you set it to null, then you pass it to your AsyncTask, then you try to use it.
You already use the singleton pattern in your Activity, so you were probably after
ParseURL.OnAsyncRequestComplete procesInterf = SmsActivity.instance();