i am trying to pass an error message between my doInBackground into my onPostExecute. Would there be any way to do this using data structures? In my situation i'm am trying to avoid making a class and returning an object
#Override
protected User doInBackground(List<Pair<String, String>>... params) {
randomAPI api = randomAPI
.getInstance(context);
try {
**thing that will generate error**
}
} catch (RandomException e) {
Log.e(TAG, "Error", e);
}
return somethingThatIsUsableInOnPostExecute;
}
#Override
protected void onPostExecute(User result) {
}
private String exception = "";
#Override
protected User doInBackground(List<Pair<String, String>>... params) {
randomAPI api = randomAPI
.getInstance(context);
try {
**thing that will generate error**
}
} catch (RandomException e) {
Log.e(TAG, "Error", e);
exception = e.getMessage();
}
return somethingThatIsUsableInOnPostExecute;
}
#Override
protected void onPostExecute(User result) {
if(!exception.isEmpty()){
//exception path
}
}
you should try to change return type of doInBackground from
User object to Object and cast it in onPostExecute.
Related
the following function is supposed to wait for the integrityresponse. I'd actually like not to have the final return statement ("I shouldn't be down here") at all. However, Android Studio yells at me if I do not include it... why? Also, why doesn't the function wait for the onResult/onError events?
public class IntegrityResponse {
final IntegrityTokenResponse token;
final Exception exception;
public IntegrityResponse (IntegrityTokenResponse token, Exception exception) {
this.token = token;
this.exception = exception;
}
}
public IntegrityResponse doIntegrityCheck() {
Log.d("AuthModule", "Module called");
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
MainApplication application = (MainApplication) currentActivity.getApplication();
IntegrityHandler integrityManager = application.getIntegrityManager();
Log.d("AuthModule", "Success!");
integrityManager.checkIntegrity(new Callback() {
#Override
public IntegrityResponse onResult(IntegrityTokenResponse result) {
Log.d ("AuthModule", "Integrity Result obtained");
return new IntegrityResponse(result, null);
}
#Override
public IntegrityResponse onError(Exception exception) {
Log.d ("AuthModule", exception.toString());
return new IntegrityResponse(null, exception);
}
});
}
else {
Log.d("AuthErr", "Couldn't get the main application");
}
Log.d("AuhErr", "I shouldn't be down here");
return new IntegrityResponse(null, new Exception("Returned all the way at the bottom"));
}
From my Login Activity (First Activity Opened) I always do a check if the token is still active on my server which is done through Async Task that does API call to server.
here's the code from LoginActivity :
private void checkIfAuthenticated(){
SharedPreferences reader_auth = getSharedPreferences(getString(R.string.auth_preferences), MODE_PRIVATE);
String auth_key = reader_auth.getString(getString(R.string.auth_access_key),null);
String mobile_token = reader_auth.getString(getString(R.string.auth_mobile_token),null);
if (auth_key != null) {
//THIS PART RUNS THE TOKEN CHECK TO SERVER
authGlobal = new AuthenticationGlobal(this);
// I WANT THIS FUNCTION TO FINISH FIRST BEFORE IT GOES TO THE NEXT PART OF THE CODE
authGlobal.runAuthenticationCheck(auth_key,mobile_token);
String Auth_Key = reader_auth.getString(getString(R.string.auth_access_key),null);
Log.d("Auth Key Check 0",Auth_Key);
if (Auth_Key != null) {
Log.d("Auth Key Check 1",Auth_Key);
MoveToDashboardActivity();
}
}
}
The runAuthenticationCheck(String,String) Code is located on another class (Because it was meant to be a global function which can be called from any function on any activity)
runAuthenticationCheck is located in AuthenticationGlobal Class, here's the code :
public void runAuthenticationCheck (String mobile_token, String Access_token) {
checkAuthTask = new checkAuthenticationTask(mobile_token, Access_token);
checkAuthTask.execute((Void) null);
}
public class checkAuthenticationTask extends AsyncTask<Void, Void, Boolean> {
private GetDataService service;
private String mobile_token;
private String access_token;
checkAuthenticationTask( String Access_token,String Mobile_token) {
/*Create handle for the RetrofitInstance interface*/
mobile_token = Mobile_token;
access_token = Access_token;
service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
}
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
try {
Call<CheckAuthenticationResponse> call = service.checkAuthentication(access_token,mobile_token);
Response<CheckAuthenticationResponse> CheckAuthenticationResponse = call.execute();
if (CheckAuthenticationResponse.code() == 200){
} else{
//clear shared preferences
clearAuthentication();
Log.e("AuthKey Global","Expired0");
}
} catch (IOException ea) {
clearAuthentication();
Log.e("AuthKey Global","Expired1");
Log.e("AuthenticationResponseError Global","Network Went Wrong");
ea.printStackTrace();
}
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
//mAuthTask = null;
//showProgress(false);
if (success) {
Log.e("AuthKey Global","Done");
} else {
// mPasswordView.setError(getString(R.string.error_incorrect_password));
clearAuthentication();
Log.e("AuthKey Global","Expired2");
}
}
#Override
protected void onCancelled() {
//mAuthTask = null;
//showProgress(false);
}
There are 2 Class / Activity : "LoginActivity" and "AuthenticationGlobal".
There are 3 Function :
checkIfAuthenticated => located in LoginActivity, Which in turn actually call another function from another class (Function number 2 : "runAuthenticationCheck")
runAuthenticationCheck => located in AuthenticationGlobal. which in calls a AsyncTask via .execute(...) command.
checkAuthenticationTask => located in AuthenticationGlobal. Which actually does the API Call to server.
From "LoginActivity" I run a function "checkIfAuthenticated" => which calls function "runAuthenticationCheck" located at "AuthenticationGlobal" => which runs a Task "checkAuthenticationTask" which does API Call to server and does stuff.
The problem is, when I called the first Function, the code doesn't wait until the function "checkIfAuthenticated" / "checkAuthenticationTask" is done. Is there a way for me to make the app wait until the task / function finish first??
Thank you
UPDATE :
I ONLY NEED TO ADD .get() at the end of .execute() and wrap it inside try catch.
public void runAuthenticationCheck (String mobile_token, String Access_token) {
checkAuthTask = new checkAuthenticationTask(mobile_token, Access_token);
try {
checkAuthTask.execute((Void) null).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Well. I just need to add a .get() on the execute() and wrap it inside a try catch.
A dumb mistake.
here's the updated code :
public void runAuthenticationCheck (String mobile_token, String Access_token) {
checkAuthTask = new checkAuthenticationTask(mobile_token, Access_token);
try {
checkAuthTask.execute((Void) null).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I want to get the data using twitter's fabric api but whenever i tend to verify credentials and use a callback it shows an error , specifically ,"The arguments differ in length"
void getUserData() {
Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false, new Callback<User>() {
#Override
public void failure(TwitterException e) {
}
#Override
public void success(Result<User> userResult) {
User user = userResult.data;
String twitterImage = user.profileImageUrl;
try {
Log.d("imageurl", user.profileImageUrl);
Log.d("name", user.name);
Log.d("email",user.email);
Log.d("des", user.description);
Log.d("followers ", String.valueOf(user.followersCount));
Log.d("createdAt", user.createdAt);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
If you check the fabric documentation, it shows two version of the method, however when I tried to open the source code in Android Studio but it had only the version without the callback.
You can solve the isssue as follows:
//Getting the account service of the user logged in
Call<User> call = Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false);
call.enqueue(new Callback<User>() {
#Override
public void failure(TwitterException e) {
//If any error occurs handle it here
}
#Override
public void success(Result<User> userResult) {
//If it succeeds creating a User object from userResult.data
User user = userResult.data;
String twitterImage = user.profileImageUrl;
try {
Log.d("imageurl", user.profileImageUrl);
Log.d("name", user.name);
Log.d("email",user.email);
Log.d("des", user.description);
Log.d("followers ", String.valueOf(user.followersCount));
Log.d("createdAt", user.createdAt);
} catch (Exception e) {
e.printStackTrace();
}
}
});
Source
Documentation
Just change the twitter dependency in your Build.Gradle
from
compile('com.twitter.sdk.android:twitter:2.0.0#aar') {
transitive = true;
}
to
compile('com.twitter.sdk.android:twitter:1.11.0#aar') {
transitive = true;
}
The new version of the .verifyCredentials() method doesn't accept a callback hence your error.
I want to know why the method myServer() return null, and not the value "result" that is assigned to finalResult inside " public void onSuccessInMainThread(...)" I'm new to java and there are some things I don't understand
protected LemmaValidationJob finalResult;
public LemmaValidationJob myServer(){
TaskConfiguration config = new TaskConfiguration(TaskType.RELATION);
config.setLanguage(Language.EN);
try{
AnnotationManager.getInstance().getData(config,
new MainThreadCallback<LemmaValidationJob>(){
#Override
public void onSuccessInMainThread(LemmaValidationJob result){
finalResult = result;
}
#Override
public void onFailureInMainThread(Throwable cause){
// TODO Auto-generated method stub
}
});
} catch (AuthenticationRequiredException e) {
System.err.println("NO LOGIN");
e.printStackTrace();
}
return finalResult;
}
The problem is that your myServer() method probably returns before the execution of the onSuccessInMainThread() method.
If a method performs an ansychronous thread then in most cases the calling method must also have an asynchronous signature. So in this case myServer must be void, and must receive a callback as a parameter. So it will be something like
public void myServer(Consumer<LemmaValidationJob> onSuccess){
TaskConfiguration config = new TaskConfiguration(TaskType.RELATION);
config.setLanguage(Language.EN);
try{
AnnotationManager.getInstance().getData(config,
new MainThreadCallback<LemmaValidationJob>(){
#Override
public void onSuccessInMainThread(LemmaValidationJob result){
onSuccess.apply(result);
}
#Override
public void onFailureInMainThread(Throwable cause){
// TODO Auto-generated method stub
}
});
} catch (AuthenticationRequiredException e) {
System.err.println("NO LOGIN");
e.printStackTrace();
}
}
I am using AsyncTask in conjunction with StreamScraper to get shoucast metadata for an app I am developing. Right now, I am getting only the song title, but I would also like to get the stream title (which is achieved with stream.getTitle();.) Below is my AsyncTask.
public class HarvesterAsync extends AsyncTask <String, Void, String> {
#Override
protected String doInBackground(String... params) {
String songTitle = null;
Scraper scraper = new ShoutCastScraper();
List<Stream> streams = null;
try {
streams = scraper.scrape(new URI(params[0]));
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ScrapeException e) {
e.printStackTrace();
}
for (Stream stream: streams) {
songTitle = stream.getCurrentSong();
}
return songTitle;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
MainActivity.songTitle.setText(s);
}
}
What do I need to change so that I can get more than one string?
The simplest way to return more than one value from a background task in this case is to return an array.
#Override
protected String[] doInBackground(String... params) {
String songTitle = null;
String streamTitle = null; // new
Scraper scraper = new ShoutCastScraper();
List<Stream> streams = null;
try {
streams = scraper.scrape(new URI(params[0]));
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ScrapeException e) {
e.printStackTrace();
}
for (Stream stream: streams) {
songTitle = stream.getCurrentSong();
streamTitle = stream.getTitle(); // new. I don't know what method you call to get the stream title - this is an example.
}
return new String[] {songTitle, streamTitle}; // new
}
#Override
protected void onPostExecute(String[] s) {
super.onPostExecute(s); // this like is unnecessary, BTW
MainActivity.songTitle.setText(s[0]);
MainActivity.streamTitle.setText(s[1]); // new. Or whatever you want to do with the stream title.
}