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):
- LOCAL_STORAGE_PERMISSIONS_NOT_GRANTED;
- BACKEND_STORAGE_NOT_READ;
- BACKEND_STORAGE_LOW_VOLUME;
- APP_ANOTHER_INSTALLED;
- NETWORK_NO_CONNECTION;
- NETWORK_ROAMING;
- NETWORK_TOKEN_EXPIRED;
- NETWORK_CERTIFICATE_PINNING_FAILED;
- LOGGING_OUT;
The following reasons are not an obstacle to force upload:
- UPLOADER_DISABLED;
- NETWORK_NO_WIFI_CONNECTION;
- BATTERY_LOW_CHARGE_LEVEL.
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. This is suspended function, so it should be called from a coroutine.
//..val photoUris = listOf( // List of photo URIs to upload to the cloud)// As an alternative, you can use photoIds instead of photoUrisval photoIds = listOf( // List of photo IDs to upload to the cloud)
photosScope.launch { photoManager.uploader.uploadMediaByUris(photoUris, UploaderType.FORCED)}//..
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).
Links - PhotoItem.
#
Copy To Family CloudTo copy media to family cloud, use the following code example.
important
It can be called only on the personal timeline instance.
var disposable: Disposable? = null
var photoList: List<PhotoItem> = listOf()
// ...
// It can be called only on personal timeline instance.disposable = photoManager.timline.copyToAnotherCloud(photoList).single.subscribeBy( onSuccess = { // Handle it }, onError = { // Handle it })
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it is no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()
Link - PhotoItem, OperationCopyToAnotherCloud.
#
Copy To Personal CloudTo copy media to personal, use the following code example.
important
It can be called only on the family timeline instance.
var disposable: Disposable? = null
var photoList: List<PhotoList> = listOf()
// ...
// It can be called only on family timeline instancedisposable = photoManager.familyTimeline.copyToAnotherCloud(photoList).single.subscribeBy( onSuccess = { // Handle it }, onError = { // Handle it })
// ...
// You must call dispose() on disposable that returned by subscribe() method,// when it is no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()
Link - PhotoItem, OperationCopyToAnotherCloud.
#
Download PhotoThe Photos SDK provides two functions for downloading media files from cloud storage to your mobile device.
fun downloadPhotos( photoList: List<PhotoItem>, destinationUri: 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>, destinationDirectory: String, isPassToScanner: Boolean = true): OperationDownloadPhotos
Parameters:
photoList
- this is a list of media elements that you need to download to your local device.destinationUri
- specifies the directory on the device as aUri
where to put the downloaded files.destinationDirectory
- specifies the directory on the device as an absolute path (String
) where to put the downloaded files.isPassToScanner
- Iftrue
, 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 destinationUri
parameter.
To download media from storage, use the following code example.
// List of items to download to your local device.// The application usually gives the user the ability to select one or more items in the Timeline.var 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 destinationUri: Uri = ...
// Returns OperationDownloadPhotosval operation = PhotoManager.timeline.downloadPhotos(photoList, destinationUri)
// 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 is 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 ofDownloadedPaths
orDownloadedUris
.
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 DownloadedPaths
object.
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 theWRITE_EXTERNAL_STORAGE
permission.IllegalStateException
- if Scoped Storage restrictions applied to the app.
Link - PhotoItem, OperationDownloadPhotos.
#
Add To FavoriteTo add photo to favorites, use the following code example.
// ...var disposable: Disposable? = null
// A list of items to add to favorites.var photoList: List<PhotoList> = listOf()
disposable = photoManager.timeline.addToFavorites(photoList).completable.subscribeBy( onComplete = { // Handle it }, onError = { // Handle it })// App must call dispose() on disposable that returned by subscribe() method, // when it is no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()// ...
Link - PhotoItem, OperationAddToFavorites.
#
Remove From FavoriteTo remove photo from favorites, use the following code example.
// ...var disposable: Disposable? = null
// A list of items to remove from favorites.var photoList: List<PhotoList> = listOf()
disposable = photoManager.timeline.removeFromFavorites(photoList).completable.subscribeBy( onComplete = { // Handle it }, onError = { // Handle it })
// App must call dispose() on disposable that returned by subscribe() method,// when it is no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()// ...
Link - PhotoItem, OperationRemoveFromFavorites.
#
Export PhotosFrom the Timeline, you can export photos to another application. Selected photos will be downloaded to the cache directory and returned as a list of Uri(or paths) in the onComplete callback.
// ...var disposable: Disposable? = null
// A list of items to export.var photoList: List<PhotoList> = listOf()
disposable = photoManager.timeline.exportPhotos(photoList).statusObservable.subscribeBy( onNext = { // it: DownloadStatus // Handle it }, onComplete = { // Handle it }, onError = { // Handle it })
// App must call dispose() on disposable that returned by subscribe() method,// when it is no longer needed, for example in your fragment’s onStop() or onPause().disposable?.dispose()// ...
Link - PhotoItem, OperationDownloadPhotos.
#
Delete PhotoTo 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.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 is 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 OperationTo cancel operation, use the following code example.
// Start operationval operation = PhotoManager.timeline.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()