I'm trying to modify koush's code from download sample with progressbar, to make it write to a FileOutputStream instead of File, but eclipse give me the following error:
The method progressHandler(new ProgressCallback(){}) is undefined for
the type ResponseFuture
Here is the code:
File file = new File(DownloadPath, uri.getLastPathSegment());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
}
Future<FileOutputStream> downloading = Ion.with(getApplicationContext())
.load(uri)
.write(fos)
.progressHandler(new ProgressCallback() {
#Override
public void onProgress(int downloaded, int total) {
// inform the progress bar of updates in progress
}
})
.setCallback(new FutureCallback<FileOutputStream>() {
#Override
public void onCompleted(Exception e, FileOutputStream file) {
// download done...
// do stuff with the File or error
}
});
You seem to have messed up with the order. Please try this:
Future<FileOutputStream> downloading = Ion.with(getApplicationContext())
.load("http://example.com/test.txt")
.progressHandler(new ProgressCallback() {
#Override
public void onProgress(int downloaded, int total) {
// inform the progress bar of updates in progress
}
})
.write(fos)
.setCallback(new FutureCallback<FileOutputStream>() {
#Override
public void onCompleted(Exception e, FileOutputStream file) {
// download done...
// do stuff with the File or error
}
});
Related
I'm having a little trouble, im executing a method in my doinBackground task, so I'm getting a crash because im accesing to another class without finishing this method first, so i want to add a return or something to let the method know when it needs to launch the other activity. I have searched and I can't return a boolean, true or false into Firebase asynctask method. This is the method I use to download a file and replace it into internal memory, but when im doing this , the other activity I need to launch after this launches and i get a crash, so i need to first execute this download task and then if something is true launch my other activity
This is where I want to put a boolean or something that tells me that the download finished.
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.e("TamañoArchivo",""+taskSnapshot.getTotalByteCount());
Log.e("NombreArchivo",""+xFile);
try {
FileOutputStream fos = context.openFileOutput("pictos.txt", Context.MODE_PRIVATE);
fos.write(getStringFromFile(xFile.getAbsolutePath()).getBytes());
Log.e("xFILEDESCARGARPAIS",""+getStringFromFile(xFile.getAbsolutePath()));
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
The method is not an asyncTask, is an async but from Firebase, this is the method:
public boolean DescargarArchivosPais(String locale){
File rootPath = new File(context.getCacheDir(),"MY_FILES");
if(!rootPath.exists()) {
rootPath.mkdirs();//si no existe el directorio lo creamos
}
StorageReference mStorageRef2 = FirebaseStorage.getInstance().getReference().child("Files/y/" + "y_" + locale + "." + "txt");
StorageReference mStorageRef1 = FirebaseStorage.getInstance().getReference().child("Files/x/" + "x_" + locale + "." + "txt");
Log.e("REFERENCIAx",""+ mStorageRef1);
Log.e("REFERENCIAy",""+ mStorageRef2);
final File xFile = new File(rootPath, "x.txt");
final File yFile = new File(rootPath, "y.txt");
mStorageRef1.getFile(xFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.e("TamañoArchivo",""+taskSnapshot.getTotalByteCount());
Log.e("NombreArchivo",""+xFile);
try {
FileOutputStream fos = context.openFileOutput("x.txt", Context.MODE_PRIVATE);
fos.write(getStringFromFile(xFile.getAbsolutePath()).getBytes());
Log.e("LOG",""+getStringFromFile(xFile.getAbsolutePath()));
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
mStorageRef2.getFile(yFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.e("TamañoArchivo",""+taskSnapshot.getTotalByteCount());
Log.e("NombreArchivo",""+yFile);
try {
FileOutputStream fos = context.openFileOutput("y.txt", Context.MODE_PRIVATE);
fos.write(getStringFromFile(gruposFile.getAbsolutePath()).getBytes());
Log.e("LOG2",""+getStringFromFile(gruposFile.getAbsolutePath()));
fos.close();
fSuccess = true;
} catch (Exception e) {
e.printStackTrace();
Log.e("printStackTrace",""+e.toString());
fSuccess = false;
}
fSuccess = true;
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
fSuccess=false;
Log.e("printStackTrace",""+e.toString());
}
});
return fSuccess;
}
Updated with following comment (replace Activity reference and introduce interface instead):
You can definitively do things like that with AsyncTask. Please have a look at the following minimalist code:
public class MyTask extends AsyncTask<Void, Void, Boolean> {
private IMyCallbackContext context;
public MyTask(IMyCallbackContext context) {
this.context = context;
}
#Override
protected void onPreExecute() {
// Here you are still on the MainThread
// Do Stuff
}
#Override
protected Boolean doInBackground(Void... params) {
// Here you are not on the MainThread
// Do Stuff
return isSuccess;
}
#Override
protected void onPostExecute(Boolean isSuccess) {
// Here you are again on the MainThread
if (isSuccess) {
context.onTaskSuccessDoStuff();
} else {
context.onTaskFailureDoStuff();
}
}
}
public interface IMyCallbackContext {
void onTaskSuccessDoStuff();
void onTaskFailureDoStuff();
}
public class MyActivity extends Activity implements IMyCallbackContext {
private void launchTask() {
MyTask myTask = new MyTask(this);
myTask.execute();
}
public void onTaskSuccessDoStuff() {
// Do stuff after the task has completed
}
public void onTaskFailureDoStuff() {
// Do stuff after the task has failed
}
}
Edit: sorry I thought you had an AsyncTask
onSuccess() method has an asynchronous behaviour. This means that in order to use the data that you are getting from Firebase Storage, you need to wait for it. So to do that, there is no need to use an AsyncTask, you can simply create your own custom callback.
To make this happen, please see the last part for my answer from this post. As Mohammed Atif mentioned in his comment, never use the Activity reference directly because it will cause memory leaks. So the way I mentioned above, is the simplest and safest way in which you can achieve this.
I'm trying to download multiple pictures using picasso. here's my code:
for(int i=1; i <=20; i++){
String url = img_url + i + "/profile.jpg";
String img_dir = img_dir + i;
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
}
Url of the site looks like this:
site.com/img/equipment/1/profile.jpg,
site.com/img/equipment/2/profile.jpg,
site.com/img/equipment/3/profile.jpg
and so on ...
i tried
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
without the for loop and it is working. images are not download when i place it inside the loop.
here's my Target
private Target picassoImageTarget(Context context, final String imageDir, final String imageName) {
Log.d("picassoImageTarget", " picassoImageTarget");
ContextWrapper cw = new ContextWrapper(context);
final File directory = cw.getDir(imageDir, Context.MODE_PRIVATE); // path to /data/data/yourapp/app_imageDir
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
final File myImageFile = new File(directory, imageName); // Create image file
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myImageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i("image", "image saved to >>>" + myImageFile.getAbsolutePath());
}
}).start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
if (placeHolderDrawable != null) {}
}
};
}
please help. thanks.
Targets are held in WeakReferences.
You need to hold a reference to the Targets you want to keep to prevent them from being garbage collected.
Maybe your code would look something like:
final class MyLoader {
final ArrayList<Target> targets = new ArrayList<>(20);
void load(...) {
for(...) {
Target target = picassoImageTarget(...);
targets.add(target);
picasso.load(...).into(target); // TODO: Maybe remove from list when complete.
}
}
}
I have a list of urls for images. I want to use Picasso to download these images to local storage on Android. I am using following method (using custom target). However I don't see all the images getting downloaded.
public void downloadAllMapImages(List<ProjectMapModel> models) {
List<Target> targetList=Lists.newArrayList();
for(ProjectMapModel model:models){
for (Map.Entry<Integer, String> entry : model.getMaps().entrySet()) {
String url=entry.getValue();
Target target=mapImageTarget(model.getProjectId(),entry.getKey());
targetList.add(target);
Picasso.with(this)
.load(url)
.into(target);
}
}
if(!isImageDownloadSuccessful)
showDownloadMapImageDataError();
//whatever images were downloaded, we need to write them to database
listDetailPresenter.onImageDownloadingSuccessful(projectMapOutputModels);
}
private Target mapImageTarget(final int projectId, final int mapType) {
//create the file name
final File file = new File(this.getExternalFilesDir(null) + File.separator + projectId+"_"+ mapType + ".jpg");
final String filePath=file.getAbsolutePath();
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
// loading of the bitmap was a success
// write the image to file
new Thread(new Runnable() {
#Override
public void run() {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
} catch (IOException e) {
Log.e(DashboardActivity.class.getName(), e.toString());
isImageDownloadSuccessful=false;
} finally {
try {
outputStream.close();
Log.i(DashboardActivity.class.getName(), "image saved");
} catch (IOException e) {
Log.e(DashboardActivity.class.getName(), e.toString());
isImageDownloadSuccessful=false;
}
}
projectMapOutputModels.add(new ProjectMapOutputData(projectId,filePath,mapType));
Log.i("image", "image saved to >>>" + filePath);
}
}).start();
//notify presenter that this image has been download and the path can be sent to presenter
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
// loading of the bitmap failed
// TODO show error message toast. dont write file path to database. continue with next image
isImageDownloadSuccessful=false;
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
}
Am I missing anything? Any help on this is really appreciated!
I'm trying to show my news in a custom ListView. Each news is included of some images and I want to
1.download images from server
2.save in local storage
3.save path of images into SQLite
4.show images in ListView using my custom adapter.
I just have problem with steps 1 & 2. I can get news from server and show them in my ListView
and show images from cache by add below code in my adapter:
Picasso.with(context).load(image[position]).into(iv);
By using Picasso.with(context).load(image[position]).into(target) , just I can save one
image in storage.
Please suggest me your idea ...
UPDATE: When I use below code, just one image (last index of my image array) being saved!
How can I save all images in array with this code?!
#Override
protected void onPostExecute(Void result) {
SaveImages();
pDialog.dismiss();
super.onPostExecute(result);
}
String fileName = null;
public void SaveImages() {
for(int i = 0; i < image.length; i++) {
Picasso.with(this).load(image[i]).into(target);
fileName = "image-" + i + ".jpg";
}
}
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom arg1) {
File file = new File(Environment.getExternalStorageDirectory().getPath() +"/" + fileName);
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 75, ostream);
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
};
Try to put Target target definition before call to Picasso.with(this).load(image[i]).into(target);
P.S. Using the following code and I saved images very well. Thanks, anyway.
My Code:
final String fileName = mDataset.get(i).getAid() + ".jpg";
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
return;
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom arg1) {
try {
File file = null;
// judge "imgs/.nomedia"'s existance to judge whether path available
if(LightCache.testFileExist(GlobalConfig.getFirstStoragePath()
+ "imgs" + File.separator +".nomedia") == true)
file = new File(GlobalConfig.getFirstStoragePath()
+ "imgs" + File.separator + fileName);
else file = new File(GlobalConfig.getSecondStoragePath()
+ "imgs" + File.separator + fileName);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, ostream);
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable arg0) {
return;
}
};
Picasso.with(GlobalConfig.getContext())
.load(Wenku8API.getCoverURL(mDataset.get(i).getAid()))
.into(target);
Custom target for storing photo in phone gallery.
public class TargetPhoneGallery implements Target
{
private final WeakReference<ContentResolver> resolver;
private final String name;
private final String desc;
public TargetPhoneGallery(ContentResolver r, String name, String desc)
{
this.resolver = new WeakReference<ContentResolver>(r);
this.name = name;
this.desc = desc;
}
#Override
public void onPrepareLoad (Drawable arg0)
{
}
#Override
public void onBitmapLoaded (Bitmap bitmap, LoadedFrom arg1)
{
ContentResolver r = resolver.get();
if (r != null)
{
MediaStore.Images.Media.insertImage(r, bitmap, name, desc);
}
}
#Override
public void onBitmapFailed (Drawable arg0)
{
}
}
Picasso.with(context).load(image[position]).into(new TargetPhoneGallery(view.getContentResolver(), "image name", "image desc"));
although this post is old, it seems the question hasn't been answered yet.
Reading your code, it appears the call you make to picasso could be asynchronous.
You should definitely check that, as if it is the case, you are starting image.length tasks, changing the filename at each new task, leading all tasks to complete and save to the last filename that was set.
To solve this, you should override Target constructor and add a filename parameter so it's ready when the task ends, in your onBitmapLoaded listener.
I have this code but the progress bar does not update the uploaded bytes/lenght of the file.
The progress dialog is displayed correctly but the progress stays in 0, then it simply disappears, the file was uploaded correctly but no progress is updated.
private class UploadFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
FTPClient client = null;
String filePath = params[0];
try {
// Get the FTP Connection from the Utility class
client = FTPUtility.connect(ipAddress, userName, password);
//if directory is not there, create it.
try {
client.changeDirectory(params[1]);
} catch(Exception e) {
client.createDirectory(params[1]);
client.changeDirectory(params[1]);
}
if (client != null) {
try {
// Define the File with complete path to be uploaded
File fileUpload = new File(filePath);
fileSize= fileUpload.length();
Log.d("FTPSync", "File Size: "+fileSize);
Log.d("FTPSync", "Uploading the " + filePath
+ " to Remote Machine");
// Upload the file
client.upload(fileUpload, new FTPDataTransferListener() {
#Override
public void started() {
// Transfer started
Log.d("FTP","TRANSFER-STATUS: File transfer started...");
}
#Override
public void transferred(int length) {
int progress = (length*100)/((int)fileSize);
publishProgress(progress);
Log.d("FTP","Progress: "+progress);
}
#Override
public void completed() {
Log.d("FTP","TRANSFER-STATUS: File transfer completed...");
}
#Override
public void aborted() {
// Transfer aborted
Log.d("FTP","TRANSFER-STATUS: File transfer aborted...");
}
#Override
public void failed() {
// Transfer failed
Log.d("FTP","TRANSFER-STATUS: File transfer failed...");
}
});
Log.d("FTPSync", "Successfully Uploaded the "
+ filePath + " File to Remote Machine");
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (client != null) {
try {
client.disconnect(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Boolean result) {
pDialog.dismiss();
Toast.makeText(context, "Operation Completed", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(context);
pDialog.setMessage(message);
pDialog.setIndeterminate(true);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
pDialog.setProgress(values[0]);
}
}
private static class FTPUtility {
public static FTPClient connect(String ipAddress, String userName,
String password) {
FTPClient client = new FTPClient();
Log.d("FTP","Connecting to " + ipAddress);
try {
client.setType(FTPClient.TYPE_BINARY);
client.connect(ipAddress);
client.login(userName, password);
return client;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
The debug shows only one entry about Progress:100
How can I make the progress bar update.
NOTE: I've tried with small and large files, so it seems to be the same issue in both file sizes.
All you need is to sum length and put it in ProgressBar. Something like this:
public class MyTransferListener implements FTPDataTransferListener {
JProgressBar jp;
int transfBytes=0;
public MyTransferListener(JProgressBar jp){
this.jp=jp;
}
public void started() {
// Transfer started
jp.setValue(0);
}
public void transferred(int length) {
// Yet other length bytes has been transferred since the last time this
// method was called
transfBytes+=length;
jp.setValue(transfBytes);
}
public void completed() {
// Transfer completed
jp.setValue(jp.getMaximum());
}
public void aborted() {
// Transfer aborted
}
public void failed() {
// Transfer failed
}
}
client.upload(fileUpload, new FTPDataTransferListener() {
int progress = 0;
#Override
public void started() {
// Transfer started
Log.d("FTP","TRANSFER-STATUS: File transfer
started...");
}
#Override
public void transferred(int length) {
progress = progress + length;
publishProgress((int) (((float)progress *
(float)100) / (float)fileSize));
Log.d("FTP","Progress: "+progress);
}
#Override
public void completed() {
Log.d("FTP","TRANSFER-STATUS: File transfer
completed...");
}
#Override
public void aborted() {
// Transfer aborted
Log.d("FTP","TRANSFER-STATUS: File transfer
aborted...");
}
#Override
public void failed() {
// Transfer failed
Log.d("FTP","TRANSFER-STATUS: File transfer
failed...");
}
});
It worked for me:
#Override
public void transferred(int totalTranfered) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
percent = percent + totalTranfered;
int percentage = (int) ((percent * 100)/ fileSize);
Log.e("Percentage Transfered", " " + percentage);
mBuilder.setProgress(100, percentage, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(id, mBuilder.build());
// publishProgress(percent);
}