Skip to main content

Photo Operations

This section describes operations with PhotoItem (photo/video files).

Upload Single Photo to Cloud (Force Upload)#

The force upload function is used to force upload photos/videos to the cloud storage. It can be used for:

  • Uploading photos/videos to the cloud storage when automatic upload is stopped for some reason (auto upload is disabled, battery power is insufficient, wi-fi is not available, etc. (see Autoupload).
  • Skipping an automatic sequential photo/video upload.

Also, when creating an album and/or adding a photo/video to an album, if the items have not yet been uploaded to the cloud storage, force upload is automatically applied to them first.

Keep in mind that the main purpose of the force upload function is to allow the user to upload specific items from the local gallery to the cloud without having to upload everything.

The following reasons prevent a force upload from being performed (see Autoupload):

  • BACKEND_NOT_READ;
  • LOCAL_GALLERY_NOT_READ;
  • ANOTHER_APP_INSTALLED;
  • NO_CONNECTION;
  • CONNECTION_ROAMING;
  • LOW_CLOUD_STORAGE;
  • TOKEN_EXPIRED;
  • LOGGING_OUT.

The following reasons are not an obstacle to force upload:

  • AUTO_UPLOAD_DISABLED;
  • NO_CONNECTION_WIFI;
  • LOW_BATTERY.

If, for example, the backend has not been read yet, then force upload (like normal autoloading) will not be performed.

To upload single photo to the cloud, use the following code example.

var disposable: Disposable? = null
// This is a list of items for which you want to cancel the push download.var photoItems: List<PhotoItem>? = null
// ...
// You have to subscribe to the returned Completable in order to receive updates.disposable = PhotoManager.uploadManager.forceUploadItems(photoItems)        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onComplete = {                    // Handle it                },                onError = { // it: Throwable                    // Handle it                }        )
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()
important

If the list of photoItems contains the items that have already been uploaded to the cloud, then the returned single will not emit them (they do not participate in the upload).

To cancel force upload, use the following code example.

var disposable: Disposable? = null
// Photo list for cancel force upload.var photoItems: List<PhotoItem>? = null
// ...
// You have to subscribe to the returned Completable in order to receive updates.disposable = PhotoManager.uploadManager.cancelForceUploadItems(photoItems)        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onComplete = {                    // Handle it                },                onError = { // it: Throwable                    // Handle it                }        )
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()

Links - PhotoItem.

Copy To Family Cloud#

To copy media to family cloud, use the following code example.

important

It can be called only using the personal PhotoManager.timeline instance.

var disposable: Disposable? = null
var photoList: List<PhotoList> = listOf()
// ...
// Can be called only using the personal timeline instance.// Returns completable in OperationCopyPhotos, which completes when the operation ends.// You have to subscribe to the returned completable in order to receive updates.disposable = PhotoManager.timeline.operations        .copyPhotosToFamily(photoList)        .completable        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onComplete = {                    // Handle it                },                onError = { // it: Throwable                    // Handle it                }        )
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()

Link - PhotoItem, OperationCopyPhotos.

Copy To Personal Cloud#

To copy media to Personal, use the following code example.

important

It can be called only using the PhotoManager.familyTimeline instance.

var disposable: Disposable? = null
var photoList: List<PhotoList> = listOf()
// ...
// Can be called only using the family timeline instance// Returns completable in OperationCopyPhotos, which completes when the operation ends.// You have to subscribe to the returned completable in order to receive updates.disposable = PhotoManager.familyTimeline.operations        .copyPhotosToPersonal(photoList)        .completable        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onComplete = {                    // Handle it                },                onError = {                    // Handle it                }        )
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()

Link - PhotoItem, OperationCopyPhotos.

Download Photo#

The Photos SDK provides two functions for downloading media files from cloud storage to your mobile device.

fun downloadPhotos(    photoList: List<PhotoItem>,    destUri: Uri,    isPassToScanner: Boolean = true): OperationDownloadPhotos

This function allows you to set the directory to save media files as a Uri.

Another function allows you to specify the absolute path to the directory:

fun downloadPhotos(    photoList: List<PhotoItem>,    destDir: String,    isPassToScanner: Boolean = true): OperationDownloadPhotos

Parameters:

  • photoList - this is a list of media elements that you need to download to your local device.
  • destUri - specifies the directory on the device as a Uri where to put the downloaded files.
  • destDir - specifies the directory on the device as an absolute path (String) where to put the downloaded files.
  • isPassToScanner - If true, the downloaded file will be added to the device's media collection (i.e. it will be added to the device's gallery).

The application usually calls the uri option if it uses SAF (Storage Access Framework) to select target directory.

If the application has full access to the local storage and uses its own UI to select a directory, it can be easier to pass the direct path to the directory via the destDir parameter.

To download media from storage, use the following code example.

// List of items to download to your local device.// Приложение обычно дает пользователю возможность выбрать один или несколько элементов в Timelinevar photoList: List<PhotoList> = listOf()
// The Uri of the directory on the device where to place the downloaded files.// App usually receives uri when it starts Intent.ACTION_OPEN_DOCUMENT_TREEvar destUri: Uri = ...
// Returns OperationDownloadPhotosval operation = PhotoManager.timeline.operations        .downloadPhotos(photoList, destUri)
// App have to subscribe to the statusObservable in order to receive updates.val disposable = operation.statusObservable        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onNext = { // it: DownloadStatus                    // Handle it                },                onComplete = {                    // Handle it                },                onError = { // it: Throwable                    // Handle it                }        )
// ...
// App must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()

Return - PhotoItem, OperationDownloadPhotos.

The DownloadStatus class contains the following fields:

  • totalPhotoCount - The total number of media files to download.
  • currentPhotoProgress - The progress of the current file.
  • downloadedTargets - The container for the list of downloaded files. Contains either an instance of DownloadedPaths or DownloadedUris.

The downloadedTargets field contains the DownloadedUris object if the application passes the directory as a Uri. If the application passes the absolute directory path, the downloadedTargets field contains the DownloadedPathsobject. The actual type of the field depends on whether the application specifies the destination directory as an absolute file path (String) or as a Uri.

important

If the app passes the absolute path to the target directory and this directory is located outside of the app-specific directory, then the app must have write access to the shared local storage. Otherwise OperationDownloadPhotos.statusObservable will fail with one of the following errors:

  • PermissionsNotGrantedException - if the app has opted out of scoped storage restrictions, but does not have the WRITE_EXTERNAL_STORAGE permission.
  • IllegalStateException - if Scoped Storage restrictions applied to the app.

Link - PhotoItem, OperationDownloadPhotos.

Delete Photo#

To delete media from storage, use the following code example.

var disposable: Disposable? = null
// A list of items to remove from the cloud storage.var photoList: List<PhotoList> = listOf()
// ...
// Returns completable, which completes when the operation ends.// You have to subscribe to the returned completable in order to receive updates.disposable = PhotoManager.timeline.operations        .deletePhotos(photoItems)        .observeOn(AndroidSchedulers.mainThread())        .subscribeBy(                onComplete = {                    // Handle it                },                onError = { // it: Throwable                    // Handle it                }        )
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()

When you delete items from the Timeline, they are moved to the trash bin, see Timeline Trash Bin and removed from all albums, see Albums.

Cancel Operation#

To cancel operation, use the following code example.

// Start operationval operation = PhotoManager.timeline.operations        .copyPhotosToFamily(photoList)
// Subscribe on operation's completable to get notified when operation is doneval disposable = operation.completable        .observeOn(AndroidSchedulers.mainThread())        .subscribe( {            // ...        } )
// ...
// Cancel operationPhotoManager.timeline.operations        .cancelOperation(operation.id)
// Don't forget to dispose observable when cancelling the operationdisposable.dispose()