5

parse.com provide a way to save object in offline mode with object.saveEventually(); call.. this stores object in local dataStore unless the syncing done with server.

the problem is,I can not store file with below given lines

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 80, stream);
byte[] byteArray = stream.toByteArray();
file = new ParseFile("pic.png",byteArray);  
object.put("file.png", file);   
object.saveEventually();

it gives following error

java.lang.IllegalStateException: Unable to encode an unsaved ParseFile

according to parse documentation to save file file.saveInBackground should be called... and I think saveInBackground only works when there is internet connection...

but the thing which I want to implement is get data (object or file) from local dataStore until sync is done with server...

so how can I save file in such a way in offline mode that I can access that file from local dataStore until the sync is done with the server...

Naveed Ali
  • 2,609
  • 1
  • 22
  • 37

4 Answers4

2

I also faced the same problem, I did like this to match my requirements. I hope it might be helpful.

How to pin a ParseObject with a ParseFile to the Parse Local Datastore in OFFLINE?

Community
  • 1
  • 1
ashokgujju
  • 320
  • 2
  • 4
  • 17
  • 1
    good approach, I already know that. But the problem was use the parse data which was firstly made and used by ios application.. so I had to save File not bytes... any way I solved my problem by keeping files in sqlite db and submitted to parse when connection made.. :) – Naveed Ali Nov 18 '14 at 07:17
2

save your object eventually and in the callback of saveeventually call saveinbackground of parsefile and again put that file in your object and save it eventually. This will save your file offline

vaibhav
  • 634
  • 1
  • 4
  • 23
1

You never call call save on the file (read the error carefully: "Unable to encode an UNSAVED ParseFile")

You must first save the file - when that completes you can then call save on the object that references the file.

I recommend you call file.saveInBackground() using callbacks. https://parse.com/docs/android/api/com/parse/ParseFile.html#saveInBackground(com.parse.SaveCallback, com.parse.ProgressCallback)

example:

private void saveImageOnParseWithCallbacks(){

parseFile = new ParseFile(gate_image.getName(), byte_image);
parseFile.saveInBackground(new SaveCallback() {
    @Override
public void done(ParseException e) {                          
                if (e == null) {
                    saveParseObject(); // this is where you call object.SaveEven....
                }else {
                   e.printStackTrace(System.err);
                }
              }   
             }, new ProgressCallback() {
               @Override
           public void done(Integer percentDone) {
              // Update your progress spinner here. percentDone will be between 0 and 100.
                }
              });
    }

Look at parse's new local data store. It works for ParseObjects but not ParseFiles (as far as i know) For an offline solution you will have to pin object files first and store the image locally on sdcard. When the savecallback on object completes you can save the image (i.e. you know you have internet restored). When the image savecallback completes you can update the object with a ref to the image.

https://parse.com/docs/android/api/com/parse/ParseObject.html#pinAllInBackground(java.lang.String, java.util.List, com.parse.SaveCallback)

navraj
  • 23
  • 6
1

I encountered the same situation recently. The answer by @vaibhav worked for me until the time that the device is offline with unsaved object and the app is closed down from task manager. If the app is terminated before the callback of saveEventually() runs, I noticed that the callback will not be run anymore. This resulted in the parseFile not being saved.

A workaround that I used is to store the byte array first as part of the parseObject. Like this

object.put("imgBytes", byteArray);

When you call saveEventually on object, the bytes will come along with it to the server. But when you retrieve the object from parse, it takes longer because it is also sending you the bytes. So I decided to use cloud code beforeSave trigger to turn it into a parseFile once it reaches the server. The code I used is this...

Parse.Cloud.beforeSave(Parse.Object.extend("<Name of Class>"), function(request, response){
        var object = request.object;
        var bytes = object.get("imgBytes");
        if(bytes != null){
            var parsefile=new Parse.File("img.png",bytes);
            parsefile.save().then(function(file){
            object.set("ImageParseFile",file);
            object.set("imgBytes",null);
            response.success();

            },function(error){
            console.error("Can't save imageBytes as ParseFile");
            response.error("Error in cloud code before save");     //set to response.error if parsefile is required, otherwise response.success()
            });
        }
        else{
             response.success();
         }

});

Using the code above, it will just be like a normal parsefile when you retrieve the object. Even when the app is terminated, the parsefile will still be saved and linked to the object. Remember to change to your class name.

SoulRider
  • 145
  • 2
  • 3
  • 11