0

realm newbie here and facing a problem in my project. So what I want to achieve is that, in my app when I click a photo I am saving a realm object inside my database as well as caching the image locally to be used later. Here is the code for both:

@Override
public void onPhotoSelected(PXImage photo) {

    PXComposition composition = null;
    PXPhoto photoParent = null;
    for (PXComposition pxComposition : mSession.getCompositions()) {
        if (pxComposition.getItems() == null || pxComposition.getItems().size() < 1)
            continue;

        for (PXPhoto item : pxComposition.getItems()) {
            if (item.getImage().getOriginalPath().equals(photo.getOriginalPath())) {
                composition = pxComposition;
                photoParent = item;
                break;
            }
        }
    }
    if (composition == null && photo.isSelected()) {
        mRealm.beginTransaction();
        String uuid = mSession.addPhoto(photo).getUuid();
        mRealm.commitTransaction(); // IMPORTANT to commit transaction. ContentDownloadTask requires PXImage to be written in Realm.
        ThreadUtils.getDefaultExecutorService().submit(new ContentDownloadTask(this, photo.getOriginalPath(), uuid));
    } else if (composition != null && !photo.isSelected()) {
        mRealm.beginTransaction();
        if (photoParent.getImage().isDownloaded()) // FIXME What if not copied yet ???
            FileUtils.deleteFile(photoParent.getImage().getApplicationPath());
        mSession.removePhoto(photoParent);
        mRealm.commitTransaction();
    }
    onCheckChanged(photo);
    App.log().v("SESSION", mSession.toString());
}

This is where click events on the photo are handled. After the selection click I am calling ThreadUtils.getDefaultExecutorService().submit(new ContentDownloadTask(this, photo.getOriginalPath(), uuid)); to cache the image locally. Here is the code for the ContentDownloadTask:

public class ContentDownloadTask implements Callable<Void> {

private String id;

private String path;

private Context context;

private Realm mRealm;

public static final String TAG = "ContentDownloadTask";

private static final String DIR_EXTERNAL_NAME = "Local";
private static final String FILE_EXTENSION = ".jpg";

public ContentDownloadTask(Context context, String path, String id) {
    this.path = path;
    this.id = id;
    this.context = context;
}

@Override
public Void call() throws Exception {

    try {
        Log.d(TAG, "Copying From " + path);
        //create output directory if it doesn't exist
        final File file = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (file == null) {
            throw new IllegalStateException("Failed to get external storage files directory");
        } else if (file.exists()) {
            if (!file.isDirectory()) {
                throw new IllegalStateException(file.getAbsolutePath() +
                        " already exists and is not a directory");
            }
        } else {
            if (!file.mkdirs()) {
                throw new IllegalStateException("Unable to create directory: " +
                        file.getAbsolutePath());
            }
        }

        File to = new File(file, DIR_EXTERNAL_NAME);
        if (to.exists()) {
            if (!to.isDirectory()) {
                throw new IllegalStateException(file.getAbsolutePath() +
                        " already exists and is not a directory");
            }
        } else if (!to.mkdirs()) {
            throw new IllegalStateException("Unable to create directory: " +
                    file.getAbsolutePath());
        }

        to = new File(to, fileName(this.id));
        if (!to.exists())
            to.createNewFile();

        InputStream in = null;
        if (PackageUtils.isContentUri(path)) {
            Uri uri = PackageUtils.toUri(path);
            in = context.getContentResolver().openInputStream(uri);
        } else {
            File from = new File(this.path);
            in = new FileInputStream(from);
        }

        OutputStream out = new FileOutputStream(to);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();

        mRealm = Realm.getDefaultInstance();
        PXImage image = mRealm.where(PXImage.class).equalTo("uuid", this.id).findFirst();

        if (image == null) {
            to.delete();
            throw new Exception("Photo Not Found ID: " + this.id);
        }

        mRealm.beginTransaction();
        image.setApplicationPath(to.getPath());
        mRealm.commitTransaction();
        mRealm.close();
        Log.d(TAG, "Complete Copied From " + path + " To " + to.getAbsolutePath());
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }

    return null;
}

Now the null is returned at this statement: PXImage image = mRealm.where(PXImage.class).equalTo("uuid", this.id).findFirst();. Basically here I need to save the application path of the image that I cached locally inside the realm object. But it's returning null. Also this not happening every time I click the photos. This only happens sometimes and the error is not reproducible. Any kind of help will be appreciated. I have already checked the following duplicate questions:

first

second

third

fourth

public PXPhoto addPhoto(PXImage image) {
    PXComposition composition = null;
    PXPhoto photo = null;
    boolean isLandscape = false;
    int photosPerItem = getProduct().getSelectedPhotosPerItem();
    switch (getProduct().getRootShortCode()) {
        case Product.CategoryType.SQUARES:
        case Product.CategoryType.CLASSIC:
        case Product.CategoryType.WALLOGRAPHS:
        case Product.CategoryType.SIGNATURES:
        case Product.CategoryType.MOSAIC:
            setLayoutType(image.isLandscape() ? C.LayoutType.LANDSCAPE.ordinal() : C.LayoutType.PORTRAIT.ordinal());
            composition = PXComposition.initializeNewComposition(this);
            photo = PXPhoto.initializePhoto(image);
            break;
        case Product.CategoryType.PANORAMA:
            composition = PXComposition.initializeNewComposition(this);
            photo = PXPhoto.initializePhoto(image);
            break;
        case Product.CategoryType.STRIPS:
        case Product.CategoryType.POSTERS:
            if (getCompositions() == null || getCompositions().size() == 0
                    || (getProduct().getRootShortCode().equals(Product.CategoryType.STRIPS) &&
                    getCompositions().last().getItems().size() % photosPerItem == 0))
                composition = PXComposition.initializeNewComposition(this);
            else
                composition = getCompositions().last();
            photo = PXPhoto.initializePhoto(image);
            break;
    }
    composition.addItem(photo);
    composition.updateComposition();
    if (!composition.isManaged()) {
        Realm realm = Realm.getDefaultInstance();
        composition = realm.copyToRealmOrUpdate(composition);
        realm.close();
        photo.setComposition(composition);
        addComposition(composition);
    } else
        photo.setComposition(composition);
    return photo;
}

EDIT:

uuid generation:

public PXPhoto() {
    this.uuid = UUID.randomUUID().toString();
    this.autoEnhance = false;
    this.zoom = 1;
}
  • I am not sure, but I not found where are you saving PXImage into Realm. In the first block of your code (String uuid = ...) you do nothing and commit nothing. – Pavel Shorokhov Aug 02 '17 at 07:59
  • hey @comm1x so sorry for that, here I edited the post – Akshit Jain Aug 02 '17 at 08:03
  • I am saving the PXimage here `String uuid = mSession.addPhoto(photo).getUuid();` – Akshit Jain Aug 02 '17 at 08:04
  • I still can not found where are you write uuid into database. Can you post getUuid() method and code, that generates uuid? – Pavel Shorokhov Aug 02 '17 at 08:11
  • getUuId() is simply a getter – Akshit Jain Aug 02 '17 at 08:18
  • I dont know, but I may advice to use realm.insertOrUpdate() method instead of copyToRealmOrUpdate(). I always use it, and I never have a problem with find-methods. Hope, it helps you. – Pavel Shorokhov Aug 02 '17 at 08:34
  • hey @comm1x but that didn't help..now the app is crashing – Akshit Jain Aug 02 '17 at 08:49
  • What's the size of your ThreadPool? you might have pending queries in `ContentDownloadTask` that holds an old version of Realm, causing it to not see the write transaction you perform in `onPhotoSelected` ... try calling `mRealm.refresh()` before you query for the photo inside the `ContentDownloadTask` – Nabil Hachicha Aug 03 '17 at 11:11

0 Answers0