I have an AsyncTask that downloads a bunch of images, as seen below:
class DownloadHelper extends AsyncTask<Void, Void, Void> {
public Context mContext;
private DBHelper mDatabase;
DownloadHelper(Context context) {
this.mContext = context;
mDatabase = new DBHelper(mContext);
}
#Override
protected Void doInBackground(Void... voids) {
List<Exercise> mExercises = mDatabase.getExercises();
for (int i = 0; i < mExercises.size(); i++) {
Exercise e = mExercises.get(i);
Log.d("path", e.getImage_start());
saveFile(e.getLink_start(), e.getImage_start());
saveFile(e.getLink_end(), e.getImage_end());
}
return null;
}
private void saveFile(String url, String path){
//region Save Bitmap To File
URL mURL = null;
try { mURL = new URL( url ); }
catch (MalformedURLException e) { Log.d("Error", "ce url de cacat smr yo niki nu merge"); e.printStackTrace();}
HttpURLConnection mConn = null;
try { mConn = (HttpURLConnection) mURL.openConnection(); mConn.setDoInput(true); mConn.connect(); }
catch (IOException e) {e.printStackTrace();}
Bitmap mBitmap = null;
try {
InputStream mInput = mConn.getInputStream();
mBitmap = BitmapFactory.decodeStream(mInput);
} catch (Exception e) { e.printStackTrace(); }
//endregion
//region Save Bitmap
if (mBitmap != null){
try {
FileOutputStream mOutput = new FileOutputStream(path);
mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mOutput);
mOutput.close();
} catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); }
}
}
}
and it is called in a function like this:
public void initialize(){
PermissionManager mManager = new PermissionManager() {};
mManager.checkAndRequestPermissions((Activity) mContext);
downloadExercises();
//region Create Exercises Folder To Store Images
File mFolder = mContext.getDir("exercises", Context.MODE_PRIVATE);
if (!mFolder.exists()) mFolder.mkdir();
Log.d("path", mFolder.getAbsolutePath());
//endregion
DownloadHelper mDownload = new DownloadHelper(mContext);
mDownload.execute();
}
However, when i debug the app, i have a breakpoint on mDownload.execute() and then some other ones in the doInBackground(), but the app never gets to the async task.
What am i doing wrong?
I had a similar issue, I believe you need to pass in null parameters when executing your async task:
mDownload.execute((Void) null);
If this doesn't help, perhaps your if statement is not passing, therefore your method is never run?
Just try this,
class DownloadHelper extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... strings) {
String response=null;
//** Do Your code here and must the result declare to response **//
return response;
}
}
In your main class after declare Asyntask then get the return value
DownloadHelper mDownload = new DownloadHelper();
mDownload.execute(mContext);
then add this line
String get_return=mDownload.get();
I figured out what was the problem. The Async was running but it seems that the downloadExercises() function added the exercises to the database AFTER the async would call getExercises() in order to download the images and therefore it didnt do anything. The solution i found was to prompt the user with a dialog to download the images AFTER the download and insertion of exercises was completed.
Related
Every tutorial I find seems to use AsyncTask (depreciated) instead of ExecutorService. I took a java course on Udemy and they used AsyncTask for everything as well. Here is one class I'm working with:
public class FetchURL extends AsyncTask<String, Void, String> {
Context mContext;
String directionMode = "driving";
public FetchURL(Context mContext) {
this.mContext = mContext;
}
#Override
protected String doInBackground(String... strings) {
// For storing data from web service
String data = "";
directionMode = strings[1];
try {
// Fetching the data from web service
data = downloadUrl(strings[0]);
Log.d("mylog", "Background task data " + data.toString());
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
PointsParser parserTask = new PointsParser(mContext, directionMode);
// Invokes the thread for parsing the JSON data
parserTask.execute(s);
}
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
Log.d("mylog", "Downloaded URL: " + data.toString());
br.close();
} catch (Exception e) {
Log.d("mylog", "Exception downloading URL: " + e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
}
and I'd really like to use ExecutorService like here instead of AsyncTask. I'm beating my head against the wall and I can't seem to get the proper arguments in and this thing working.
Replace your AsyncTask with a Runnable:
public class FetchUrl implements Runnable {
public interface Callback {
void onSuccess(String data);
void onFailure(Exception e);
}
private String url;
private WeakReference<Callback> callbackWeakReference;
public FetchUrl(String url, Callback callback) {
this.url = url;
this.callbackWeakReference = new WeakReference<>(callback);
}
#Override
public void run() {
try {
String data = downloadUrl(url);
Callback callback = callbackWeakReference.get();
if (callback != null) {
callback.onSuccess(data);
}
} catch (Exception e) {
Callback callback = callbackWeakReference.get();
if (callback != null) {
callback.onFailure(e);
}
}
}
... // include your downloadUrl function
}
Then create and submit it to the ExecutorService:
FetchUrl.Callback callback = new FetchUrl.Callback() {
#Override
public void onSuccess(String data) {
// handle your data
}
#Override
public void onFailure(Exception e) {
// handle the exception
}
};
Runnable job = new FetchUrl(url, callback);
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(job);
Notice I used a WeakReference<Callback>, because code in your callback is holding a reference to Context and would cause Context leaks.
The submit() function returns a Future to control your submitted job. It's handy if you want to cancel the job or want to wait for its completion (blocking the current thread). The latter usecase would perhaps favor using Callable<Result> instead of Runnable, because the calling thread can handle the exception and there would be no use for a callback making your code more concise.
Also don't forget to call shutdown() on your ExecutorService when you no longer need it.
I am attempting to pass a string I got in an Asynchronous task class back in to my main activity, but when I pass the string result (which I know isn't null because logging the string right before passing it to the interface outputs what it should), I get a nullPointerException that says I can't pass a null object to the interface method.
Here is the AsyncTask class,
public class APICalls extends AsyncTask<String,Void, String> {
public AsyncResponse delegate;
protected String doInBackground(String... zipcodes){
String zipcode = zipcodes[0];
String apikey = "6562c36e87ba41f6bc887104d1e82eb8";
String baseURL = "https://congress.api.sunlightfoundation.com";
String zipCodeAddition = "/legislators/locate?apikey="+apikey + "&zip=" + zipcode;
String url = baseURL + zipCodeAddition;
String results = "";
URL apiurl = null;
try {
apiurl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpsURLConnection urlConnection = null;
try {
urlConnection = (HttpsURLConnection) apiurl.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
int data = in.read();
while(data != -1){
results += String.valueOf((char) data);
data = in.read();
}
in.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
urlConnection.disconnect();
}
return results;
}
protected void onPostExecute(String result){
String results = result;
try {
delegate.processFinish(results);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The error occurs in the line delegate.processFinish(results);. When I log the results string it is not null. The interface is:
public interface AsyncResponse {
void processFinish(String output) throws IOException;
}
Then in the main activity I implement the interface and have the method:
public void processFinish(String output) throws IOException {
Log.v("++++++++", output);
}
You get NPE not because output is null, but because delegate is. You never initialize it.
This question already has answers here:
Android AsyncTask don't return correct Result
(3 answers)
Closed 8 years ago.
in this below code i want to return value from AsyncTask with using an Interface. but i get wrong value and i can not return correct value from onPostExecute.
i'm developed this link tutorials with my code. i can not use correctly with that.
Interface:
public interface AsyncResponse {
void processFinish(String output);
}
Ksoap Main class:
public class WSDLHelper implements AsyncResponse{
public SoapObject request;
private String Mainresult;
public String call(SoapObject rq){
ProcessTask p =new ProcessTask(rq);
String tmp = String.valueOf(p.execute());
p.delegate = this;
return Mainresult;
}
#Override
public void processFinish(String output) {
this.Mainresult = output;
}
}
class ProcessTask extends AsyncTask<Void, Void, Void > {
public AsyncResponse delegate=null;
SoapObject req1;
private String result;
public ProcessTask(SoapObject rq) {
req1 = rq;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
this.result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", this.result);
return null;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(this.result);
}
}
please help me to resolve this problem
That can't work. You are creating and executing the AsyncTask (asynchronously!) and then call return Mainresult (synchronously!) when it hasn't received the result yet. The solution is to remove the redundant class WSDLHelper and access ProcessTask directly
Beside that, you're using AsyncTask incorrectly (saving the result in a class variable instead of passing it as a parameter). Here's the full version:
public class ProcessTask extends AsyncTask<Void, Void, String> {
public AsyncResponse delegate=null;
SoapObject req1;
public ProcessTask(SoapObject rq, AsyncResponse delegate) {
req1 = rq;
this.delegate = delegate;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
String result = null;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result != null && result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", result);
return result;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(result);
}
}
Now you would execute ProcessTask from outside like this, which will make sure you receive the result asynchronously:
new ProcessTask(rq, new AsyncResponse() {
#Override
public void processFinish(String output) {
// do whatever you want with the result
}
}).execute();
Your result will always be null, because you return null in the doInBackground() method. The value you return in doInBackground() will be passed to onPostExecute(). Change your AsyncTask<Void, Void, Void> to AsyncTask<Void, Void, String>, and return the result. This will call onPostExecute(String result) with the correct result.
Perhaps this link might help you a bit: http://bon-app-etit.blogspot.be/2012/12/using-asynctask.html
Dear android developers,
I'm trying to implement the sntpclient class in my application but it didn't work.
Class: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/net/SntpClient.java
in my code I have the following lines:
public void onClickBtn(View v)
{
SntpClient client = new SntpClient();
if (client.requestTime("pool.ntp.org", 10)) {
long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
Toast.makeText(this, "Offset: " + now, Toast.LENGTH_LONG).show();
}
}
I really don't know what the meaning of network timeout is in this case.
It would be great, when someone has any idea or tip for me.
Thanks in advance!
You should put it in AsyncTask like this :
class GetNTPAsynctask extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
private SntpClient sntpClient = new SntpClient();
return sntpClient.requestTime("pool.ntp.org", 30000);
}
}
Timeout: network timeout in milliseconds. So i use 30000 mean 30 seconds.
You can use this Full sample:
class getCurrentNetworkTime extends AsyncTask<String, Void, Boolean> {
private Exception exception;
protected Boolean doInBackground(String... urls) {
NTPUDPClient timeClient = new NTPUDPClient();
timeClient.setDefaultTimeout(3000);
InetAddress inetAddress = null;
boolean is_locale_date = false;
try {
inetAddress = InetAddress.getByName(G.TIME_SERVER);
TimeInfo timeInfo = null;
timeInfo = timeClient.getTime(inetAddress);
long localTime = timeInfo.getReturnTime();
long serverTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();
if (new Date(localTime) != new Date(serverTime))
is_locale_date = true;
} catch (UnknownHostException e) {
e.printStackTrace();
Log.e("UnknownHostException: ", e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.e("IOException: ", e.getMessage());
}
return is_locale_date;
}
protected void onPostExecute(boolean local_date) {
if(!local_date) {
Log.e("Check ", "dates not equal" + local_date);
}
}
}
How to use:
new getCurrentNetworkTime().execute();
Check that your manifest has this one:
<uses-permission android:name="android.permission.INTERNET" />
I am trying to get data from RSS feed to display it in fragments (11 fragment), but each time i pass to a new fragment the UI block for a several seconds because it's fetching data so i try to use asyncTask to do this in background but it seems that it does not work.
public class AndroidSaxFeedParser extends AsyncTask<String, Long, ArrayList<Article>>{
String dt;
String bb;
String nameCat;
RootElement root;
Element item;
static final String RSS = "rss";
static final String FEED = "feed";
static final String ENTRY = "entry";
static final String CHANNEL = "channel";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
static final String CATEGORY = "category";
static final String DURATION = "itunes:duration";
ArrayList<Article> rssItems = new ArrayList<Article>();
public URL feedUrl;
Context mContext;
public AndroidSaxFeedParser(Context context)
{
mContext = context;
}
// ProgressDialog pd = new ProgressDialog(mContext);
#Override
protected void onPostExecute(ArrayList<Article> result) {
// pd.dismiss();
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
// ProgressDialog.show(mContext, "", "Chargement...");
super.onPreExecute();
}
#Override
protected ArrayList<Article> doInBackground(String... params) {
try {
feedUrl = new URL(params[0]);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
final Article currentRssItem = new Article();
root = new RootElement(RSS);
Element channel = root.getChild(CHANNEL);
item = channel.getChild(ITEM);
item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentRssItem.setTitle(body);
Log.i("Title Article", " "+currentRssItem.getTitle());
}
});
item.getChild(CATEGORY).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentRssItem.setCategorie(body);
Log.i("Category Article", " "+currentRssItem.getCategorie());
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
String imgUrl, desc;
try {imgUrl = body.substring(body.indexOf("src=")+5,body.indexOf("\"", body.indexOf("src=")+6));}
catch (Exception e)
{imgUrl = "";}
try {desc=body;}
catch (Exception e)
{ desc = "";}
currentRssItem.setImageUrl(imgUrl);
currentRssItem.setDescription(desc);
Log.i("Image URL Article", " "+currentRssItem.getImageUrl());
Log.i("Description Article", " "+currentRssItem.getDescription());
}
});
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentRssItem.setPubDate(body);
Log.i("Date Article", " "+currentRssItem.getPubDate());
}
});
item.setEndElementListener(new EndElementListener(){
public void end() {
rssItems.add(currentRssItem.copy());
}
});
try {
Xml.parse(feedUrl.openConnection().getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return rssItems;
}
I am calling it this way in each fragment
ArrayList<Article> feeds ;
try {
feeds=AndroidSaxFeedParser.execute(url).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
You should always download the file and save it as a String before asking the XML class to parse it.
public String getXml(String url) {
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
// HTTP OK 200
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
// NOTE: Here need to set the default charset to be UTF-8
content = EntityUtils.toString(entity, "UTF-8");
return content;
}
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
content = null;
}
}
In this way it is less likely to get interrupted due to connection problem. In addtition, please tell us more about what "it seems that it does not work" means. Did it fail to parse the xml, fail to run the task, or fail what?
Also, you should not be calling
feeds=AndroidSaxFeedParser.execute(url).get();
in your fragment. You should modify this function of your AndroidSaxFeedParser:
#Override
protected void onPostExecute(ArrayList<Article> result) {
feeds = result;
// Do whatever you wanna do to set up things with the feeds
}
To make this work you must put your AndroidSaxFeedParser as an inner class of your fragment.