I'm trying to take a png in my drawable folder, retrieve it, and upload it to my server as a drawable using the Backendless api. However, it does not like this, telling me that it cannot update the object without any properties.
I/System.out: fault!
I/System.out: BackendlessFault{ code: '1001', message: 'Cannot update object without any properties: image' }
The Code:
try {
Event ne = new Event();
ne.title = "title of event";
ne.desc = "short desc";
ne.extDesc = "long desc";
ne.image = getDrawable(R.drawable.palestra);
System.out.println((ne.image != null ? "does" : "does not ") + "work");
Backendless.Persistence.save(ne, new AsyncCallback<Event>() {
#Override
public void handleResponse(Event event) {
System.out.println("successfull!");
}
#Override
public void handleFault(BackendlessFault backendlessFault) {
System.out.println("fault!");
System.out.println(backendlessFault.toString());
}
});
} catch (Exception e) {
System.out.println("caught exception! " + e.toString());
}
The purpose of this is to post an example event to the server so that when I pull the Event, with the properties title, desc, extDesc, and image, I can update my onscreen events accordingly. However, I can't seem to take an image I have locally and upload it as a Drawable.
Thanks for any help.
One solution would be to get the image Bitmap and save it to a file in backendless:
//The outer Backendless call saves the photo in the file and the inner Backendless
//call saves the object to the table and gives ne.image a String reference
//to the file path. the column type should be File Reference, saving the path
//as a String willw ork
Backendless.Files.Android.upload(mBitmap,
Bitmap.CompressFormat.JPEG, //compression type
100, //quality of image
"mImageName", //What you want to call your file, eg timestamp + "app_image"
"/my_images", //The path of the file in Backendless
new AsyncCallback<BackendlessFile>() {
#Override
public void handleResponse(BackendlessFile response) {
ne.title = "title of event";
ne.desc = "short desc";
ne.extDesc = "long desc";
ne.image = (response.getFileURL());
Backendless.Persistence.of(Ids.class).save(ne, new AsyncCallback<Ids>() {
#Override
public void handleResponse(Ids response) {
}//end handleResponse
#Override
public void handleFault(BackendlessFault fault) {
}//end handleFault
});
}//end handleResponse
#Override
public void handleFault(BackendlessFault fault) {
}//end handleFault
});
To retrieve the image fromt he url you have saved it to, you have to use an AsyncTask to get the image from the url.
You could create the following class:
public class MyAsyncTask extends AsyncTask<String, Integer, Bitmap> {
ImageView ivMyImage;
private Bitmap myImage;
public MyAsyncTask(ImageView ivMyImage) {
this.ivMyImage = ivMyImage;
}//end constructor
#Override
protected Bitmap doInBackground(String... urlString) {
try {
URL myImageUrl = new URL(urlString[0]);
myImage = BitmapFactory.decodeStream(myImageUrl.openConnection().getInputStream());
} //end try
catch (Exception e) {
e.printStackTrace();
}//end catch
return myImage;
}//end doInBackground
#Override
protected void onPostExecute(Bitmap bitmap) {
ivMyImage.setImageBitmap(myImage);
}//end onPostExecute
}//end class
And call the Async task wherever you want to use it with the following code:
MyAsyncTask myAsyncTask = new MyAsyncTask(ivMyImage);
myAsyncTask.execute(ne.getImage());//ne.getImage() should retrieve the image url you saved
Hope this helps
Related
I have array of url of images stored in firebase and I have used for loop for download in in mobile storage and after loop i set other method to showImages it in grid view. There is no problem in download but as it takes some time for download it so I want to execute showImage only after all images are successfully stored in mobile storage.
How can I do this task? Any help will be much helpful for me.
Class Images{
string imageUrl;
string name;
public Images(){
}
}
Here is a code for downloading images in the main activity.
for (Image image : imageList) {
String url = image.getImageUrl();
File file = new File(context.getExternalFilesDir, i + "_" + image.getName() + ".jpg");
if (!file.exists()) {
StorageReference downloadRef = FirebaseStorage.getInstance().getReferenceFromUrl(url);
downloadRef.getFile(file).addOnCompleteListener(new OnCompleteListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<FileDownloadTask.TaskSnapshot> task) {
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
i++;
}
}
showImages();
showImages() is used for showing images. But it is executed immediately after for loop and as images are bigger it takes some time for downloading.
So how can I make showImages() execute only after all image are downloaded successfully.
StorageReference's getFile(File destinationFile) method returns a FileDownloadTask object which is actually a Task.
To solve you can use Tasks's whenAllSuccess(Collection> tasks) method like this:
List<Task<?>> tasks = new ArrayList<>();
tasks.add(downloadRef.getFile(file1));
tasks.add(downloadRef.getFile(file2));
tasks.add(downloadRef.getFile(file3));
//And so on
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list
for (Object object : list) {
//Show images
}
}
});
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.
Actually It is changing but into Blank!
In my App, i going to get my Images-Path from Database and show them in main activity. this process achieves by selecting thumbnails of images in DialogFragment and sending their Record ID to main Activity withing an Interface for Communicating between Fragment-Activity.
at this point i am going to use an Asynctask inner class to get FilePath of selected Image and Show it to ImageView.
everythings works perfectly EXCEPT that the ImageView does not show it properly and it just show blank!
P.S.: the FilePath is Correct, i used it in onActivityResult on some place in app.
Thank you.
Main Activity code:
public class AnnotateDiagramActivity extends Activity implements Communicator {
#Override
public void respond(String data , int requestCode) {
//Passing Project ID from CPDialogFragment or PLDialogFragment
switch(requestCode) {
case OPEN_PROJECTID:
PROJECTID = Integer.valueOf(data);
loadProject(PROJECTID);
ToastShort(data);
break;
default:
break;
}
}
public class loadMainImage extends AsyncTask<Project,Integer,String>
{
#Override
protected String doInBackground(Project... params) {
return project.GetFilePath();
}
protected void onPostExecute( String result) {
//here is my main issue:
fragmentView.setImageBitmap(new ImageDecoder().decodeFile(new File(project.GetFilePath())));
fragmentView.postInvalidate();
}
}
public void loadProject(int ID)
{
project = new Project();
project= expertDbHelper.getProject(ID);
SharedPreferences openedProject = getSharedPreferences("openedProject", 0);
SharedPreferences.Editor projectEditor = openedProject.edit();
projectEditor.putInt("id",project.GetID());
projectEditor.putString("filePath",project.GetFilePath());
projectEditor.commit();
new loadMainImage().execute(project);
}
}
EDIT For Verifying on Returning Image From File Path:
protected void onPostExecute( String result) {
ImageDecoder imageDecoder = new ImageDecoder();
Bitmap bmp = null;
File file =new File(result);
if(file.isFile()) {
bmp=imageDecoder.decodeFile(file,500);
fragmentView.setImageBitmap(bmp);
fragmentView.postInvalidate();
}
else
{ Log.e("Async Task Is File: " ,String.valueOf(file.isFile()));}
}
I've found that my Image does not set properly due to some criteria that calculated from previous loaded image, so i check my code and find (layout boolean parameter) in my code that needs to be reset.
protected void onPostExecute( String result) {
ImageDecoder imageDecoder = new ImageDecoder();
Bitmap bmp = null;
File file =new File(result);
Log.e("Async Task Result: " ,result);
if(file.isFile()) {
bmp=imageDecoder.decodeFile(file,500);
fragmentView.reset();
fragmentView.recycle();
fragmentView.layout= false;
fragmentView.setImageBitmap(bmp);
}
else
{
Log.e("Async Task Is File: " ,String.valueOf(file.isFile()));
}
}
I'm currently downloading and save some pictures in my Android app.
Here is the class which do the work :
public class BitmapPersist extends AsyncTask<String, Void, Boolean> {
private ArrayList<String> photosNotDownloaded;
private File pointDir;
private KickstartrGeolocPoint point;
private OnBitmapPersistedListener onBitmapPersistedListener;
public BitmapPersist(ArrayList<String> photosNotDownloaded, File pointDir, KickstartrGeolocPoint point, OnBitmapPersistedListener onBitmapPersistedListener) {
this.photosNotDownloaded=photosNotDownloaded;
this.pointDir=pointDir;
this.point=point;
this.onBitmapPersistedListener=onBitmapPersistedListener;
}
#Override
protected Boolean doInBackground(String... params) {
Bitmap bmp;
FileOutputStream out = null;
for(String url : photosNotDownloaded) {
//download the picture synchronously
bmp = ImageLoader.getInstance().loadImageSync(url);
try {
out = new FileOutputStream(pointDir.getPath() + File.separator + FileUtils.getPointPhotoPrefix(point) + FileUtils.getFileNameFromUrl(url));
bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Throwable ignore) {
}
}
//send notification to the UI in order to scan again the directory and update the carousel
publishProgress();
}
return true;
}
#Override
protected void onPostExecute(Boolean success) {
if (success)
onBitmapPersistedListener.persistedSuccessfully(this.point, this.pointDir);
else
onBitmapPersistedListener.errorInPersistance();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
onBitmapPersistedListener.onProgress();
}
}
This class take an ArrayList of urls in parameter, and for each photo, it download it and save it.
Each time a photo is persisted, a notification is sent to the view to update a carousel (thanks to publishProgress(); )
The problem is that publishProgress() does not work, and every photos are displayed at the same time when every photos are downloaded.
Here is the call of my asynctask :
private void persistImageforPoint(ArrayList<String> photosNotDownloaded, KickstartrGeolocPoint point, File pointDir) {
// Create a subfolder for each point with its id
if (!pointDir.exists()) {
if (!pointDir.mkdirs()) {
LogWrapper.debug(FileUtils.class, "Failed to create directory");
return;
}
}
//save the file. Asynchronous task --> do not block the UI
new BitmapPersist(photosNotDownloaded, pointDir, point, new OnBitmapPersistedListener() {
#Override
public void persistedSuccessfully(KickstartrGeolocPoint point, File pointDir) {
if(currentPoint!=null) {
File pointDirectory = FileUtils.getPointPhotoDir(getActivity(), currentPoint);
loadCarousel(currentPoint, pointDirectory);
}
}
#Override
public void errorInPersistance() {
LogWrapper.error(getClass(),"Error persisting image");
}
#Override
public void onProgress() {
if(currentPoint!=null) {
final File pointDir = FileUtils.getPointPhotoDir(getActivity(), currentPoint);
loadCarousel(currentPoint, pointDir);
}
}
}).execute();
}
I don't have any errors in my logcat.
Thanks for your help ;)
I am fetching title, date and image from an online xml file and storing it in a arraylist. I have taken 3 different arraylists for storing title , date and image.
I am successful in getting image urls , my problem is how to download image from the url and show it in a imageview. The code for fetching the url is below.
if((xpp_name.equals("content")))
{
xpp.next();
strvalue=xpp.getText();
if(strvalue!=null){
String url = strvalue.substring(
strvalue.indexOf("src")+5,, strvalue.indexOf("jpg")+3);
arrayList_for_images.add(url);
}
xpp.next();
xpp.next();}
Start a new thread for downloading image from Url and set image in imageview in handler.
private Bitmap pop_up_image_bitmap ;
private Handler handler ;
private Runnable r;
new Thread(new Runnable() {
#Override
public void run() {
URL newurl;
try {
newurl = new URL(<Url>);
pop_up_image_bitmap = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream());
handler.post(r);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
Put handler :
handler = new Handler();
r = new Runnable()
{
public void run()
{
if(pop_up_image_bitmap!=null){
imageview.setImageBitmap(pop_up_image_bitmap);
handler.postDelayed(this, 1000);
popUpImageProgressBar.setVisibility(View.INVISIBLE);
}
}
};
handler.postDelayed(r, 1000);
Here you can find a lazy loading library to download images from a URL and show them in a ListView. Also i suggest you to avoid using 3 different Arraylists and use only one ArrayList, instead, with a custom class that is used to store the information of an image(title, date and image url).
EDIT: Here is an example class that holds the information needed for the image:
import java.util.Date;
public class ImageObject {
private String image_name;
private String image_url;
private Date image_date;
public ImageObject() {
}
public ImageObject(String image_name, String image_url, Date image_date) {
this.image_name = image_name;
this.image_url = image_url;
this.image_date = image_date;
}
public void setImageName(String image_name) {
this.image_name = image_name;
}
public void setImageURL(String image_url) {
this.image_url = image_url;
}
public void setImageDate(Date image_date) {
this.image_date = image_date;
}
public String getImageName() {
return this.image_name;
}
public String getImageURL() {
return this.image_url;
}
public Date getImageDate() {
return this.image_date;
}
}
Here is an example usage in witch i initiate a ArrayList with one ImageObject:
ArrayList<ImageObject> data = new ArrayList<ImageObject>();
ImageObject obj = new ImageObject("test.jpg", "www.imageurl.com", new Date());
data.add(obj);
And this is how you retrieve a value from a certain ImageObject object from the ArrayList:
data.get(0).getImageName();
try out this best image loading library ever.
https://github.com/nostra13/Android-Universal-Image-Loader