{"id":19760701,"url":"https://github.com/storj/uplink-android","last_synced_at":"2025-04-30T13:32:55.212Z","repository":{"id":65509311,"uuid":"210459617","full_name":"storj/uplink-android","owner":"storj","description":"Storj network Android library","archived":false,"fork":false,"pushed_at":"2023-02-24T15:07:03.000Z","size":738,"stargazers_count":19,"open_issues_count":2,"forks_count":7,"subscribers_count":25,"default_branch":"main","last_synced_at":"2025-04-06T02:12:17.851Z","etag":null,"topics":["android","android-bindings","java","storj","storj-network"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/storj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-23T21:55:42.000Z","updated_at":"2024-05-20T17:22:05.000Z","dependencies_parsed_at":"2023-01-30T13:30:24.111Z","dependency_job_id":null,"html_url":"https://github.com/storj/uplink-android","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/storj%2Fuplink-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/storj%2Fuplink-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/storj%2Fuplink-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/storj%2Fuplink-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/storj","download_url":"https://codeload.github.com/storj/uplink-android/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251713016,"owners_count":21631473,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-bindings","java","storj","storj-network"],"created_at":"2024-11-12T03:38:22.268Z","updated_at":"2025-04-30T13:32:54.925Z","avatar_url":"https://github.com/storj.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# android-libuplink\n\n[![Javadocs](https://img.shields.io/badge/javadoc-1.0.0--rc.1-blue.svg)](https://storj.github.io/uplink-android/javadoc/1.0.0-rc.1/)\n\nAndroid bindings to Storj V3 libuplink.\n\n## Requirements\n\n* Android 5.0 Lollipop or newer\n\n## Setup\n\nAdd the Gradle dependency to the `build.gradle` file of the app module:\n\n```Gradle\ndependencies {\n    implementation 'io.storj:uplink-android:1.0.0-rc.1'\n}\n```\n\n## Usage\n\n+ [Access Grant](#access-grant)\n  - [Creating new access grant from passphrase](#creating-new-access-grant-from-passphrase)\n  - [Sharing access grant](#sharing-access-grant)\n  - [Serializing access grant to string](#serializing-access-grant-to-string)\n  - [Parsing serialized access grant from string](#parsing-serialized-access-grant-from-string)\n+ [Buckets](#buckets)\n  - [Creating new bucket](#creating-new-bucket)\n  - [Getting info about a bucket](#getting-info-about-a-bucket)\n  - [Listing buckets](#listing-buckets)\n  - [Deleting a bucket](#deleting-a-bucket)\n+ [Objects](#objects)\n  - [Downloading an object](#downloading-an-object)\n  - [Downloading a range of an object](#downloading-a-range-of-an-object)\n  - [Downloading an object with progress monitoring and cancellation](#downloading-an-object-with-progress-monitoring-and-cancellation)\n  - [Uploading new object](#uploading-new-object)\n  - [Uploading new object with progress monitoring and cancellation](#uploading-new-object-with-progress-monitoring-and-cancellation)\n  - [Listing objects](#listing-objects)\n  - [Deleting an object](#deleting-an-object)\n+ [Sharing content](#sharing-content)\n\n### Access Grant\n\nThe `Access Grant` contains all information required to access resources on the Storj network:\n- Satellite Address where metadata is stored\n- API Key for accessing a project on the satellite\n- Encryption Access for decrypting the content\n\n#### Creating new access grant from passphrase\n\nNew `Access Grant` can be requested from satellite with Satellite Address, API Key and passphrase.\n\n```java\nString satelliteAddress = \"12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S@us1.storj.io:7777\";\nString serializedApiKey = \"13Yqft7v...\";\nString passphrase = \"super secret passphrase\";\n\nUplink uplink = new Uplink();\nAccess access = uplink.requestAccessWithPassphrase(satelliteAddress, serializedApiKey, passphrase);\n```\n\n#### Sharing access grant\n\n`Access Grant` can be shared in terms of allowed operations and access to specific buckets and objects.\n\n```java\nPermission permission = new Permission.Builder().allowDownload().allowList().build();\naccess.share(permission, new SharePrefix(\"my-bucket\", \"pictures/birthday/\"));\n```\n\n#### Serializing access grant to string\n\n`Access Grant` can be serialized to string for easy sharing.\n\n```java\nAccess access = ...;\nString serializedAccess = access.serialize(); \n```\n\n#### Parsing serialized access grant from string\n\nIf received a serialized `Access Grant` as a string, it can be parsed to `Access` object.\n\n```java\nString serializedAccess = \"13GRuHAW...\";\nAccess access = Access.parse(serializedAccess);\n```\n\n### Buckets\n\n#### Creating new bucket\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access)) {\n    project.createBucket(\"my-bucket\");\n}\n```\n\n#### Getting info about a bucket\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access)) {\n    BucketInfo info = project.statBucket(\"my-bucket\"));\n}\n```\n\n#### Listing buckets\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access);\n        BucketIterator iterator = project.listBuckets()) {\n    for (BucketInfo info : iterator) {\n        // Do something for each bucket.\n    }\n}\n```\n\n#### Deleting a bucket\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access)) {\n    BucketInfo info = project.deleteBucket(\"my-bucket\"));\n}\n```\n\n### Objects\n\n#### Downloading an object\n\nBelow is the easiest way for downloading a complete object to a local file.\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access);\n        InputStream in = project.downloadObject(\"my-bucket\", \"key/to/my/object\");\n        OutputStream out = new FileOutputStream(\"path/to/local/file\")) {\n    byte[] buffer = new byte[8 * 1024];\n    int bytesRead;\n    while ((bytesRead = in.read(buffer)) != -1) {\n        out.write(buffer, 0, bytesRead);\n    }\n}\n```\n\n#### Downloading a range of an object\n\nIf only a portion of the object should be downloaded, this can be specified with download options. The example below will download only 4 KiB from the object, starting at 1 KiB offset.\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\nObjectDownloadOption[] options = new ObjectDownloadOption[]{\n        ObjectDownloadOption.offset(1024),\n        ObjectDownloadOption.length(4096)\n};\ntry (Project project = uplink.openProject(access);\n        InputStream in = project.downloadObject(\"my-bucket\", \"key/to/my/object\",\n                options);\n        OutputStream out = new FileOutputStream(\"path/to/local/file\")) {\n    byte[] buffer = new byte[8 * 1024];\n    int bytesRead;\n    while ((bytesRead = in.read(buffer)) != -1) {\n        out.write(buffer, 0, bytesRead);\n    }\n}\n```\n\n#### Downloading an object with progress monitoring and cancellation\n\nIf progress monitoring and/or cancellation is important, the client can take advantage of the `ObjectInputStream` class.\n\nAs all operations in the Storj Java API are blocking, the client should use some means for asynchronous processing - like the `AsyncTask` from the Android platform.\n\nThe example below shows how to download with progress monitoring and cancellation using the `AsyncTask`:\n\n```java\npublic class DownloadTask extends AsyncTask\u003cVoid, Long, Throwable\u003e {\n\n    private Access mAccess;\n    private String mBucket;\n    private ObjectInfo mInfo;\n    private File mLocalFile;\n\n    private int mNotificationId;\n    private long mDownloadedBytes;\n    private long mLastNotifiedTime;\n\n    DownloadTask(Access access, String bucket, ObjectInfo info, File localFile) {\n        mAccess = access;\n        mBucket = bucket;\n        mInfo = info;\n        mLocalFile = localFile;\n    }\n\n    @Override\n    protected Exception doInBackground(Void... params) {\n        try (Project project = new Uplink().openProject(mAccess);\n             ObjectInputStream in = project.downloadObject(mBucket, mInfo.getKey());\n             OutputStream out = new FileOutputStream(mLocalFile)) {\n            byte[] buffer = new byte[128 * 1024];\n            int len;\n            while ((len = in.read(buffer)) != -1) {\n                if (isCancelled()) {\n                    // exiting the try-with-resource block aborts the download process\n                    return null;\n                }\n                out.write(buffer, 0, len);\n                if (isCancelled()) {\n                    // exiting the try-with-resource block aborts the download process\n                    return null;\n                }\n                publishProgress((long) len);\n            }\n        } catch (StorjException | IOException e) {\n            return e;\n        }\n    }\n\n    @Override\n    protected void onProgressUpdate(Long... params) {\n        long increment = params[0];\n        mDownloadedBytes += increment;\n\n        long now = System.currentTimeMillis();\n\n        // Calculate the progress in percents.\n        long size = mFile.getSystemMetadata().getContentLength();\n        int progress = (size == 0) ? 100 : (int) ((mDownloadedBytes * 100) / size);\n\n        // Check if 1 second elapsed since last notification or progress is at 100%.\n        if (progress == 100 || mLastNotifiedTime == 0 || now \u003e mLastNotifiedTime + 1150) {\n            // Place your code here to update the GUI with the new progress.\n            mLastNotifiedTime = now;\n        }\n    }\n\n    @Override\n    protected void onPostExecute(Throwable t) {\n        if (t != null) {\n            String errorMessage = t.getMessage();\n            // The download failed.\n            // Place your code here to update the GUI with the error message.\n            return;\n        }\n\n        // The download is successful.\n        // Place your code here to update the GUI.\n    }\n\n    protected void onCancelled(Throwable t) {\n        // The download was cancelled.\n        // Place your code here to update the GUI.\n    }\n\n    /**\n     * Call this method to cancel the download.\n     */\n    void cancel() {\n        this.cancel(false);\n    }\n}\n```\n\n#### Uploading new object\n\nBelow is the easiest way for uploading new object.\n\nNote the importance of specifying the location of the temp directory using the `UplinkOption.tempDir()` option. This is where the file being uploaded will be first encrypted before actually uploaded into pieces to the Storj network. For Android, it is recommended to set the temp directory to the application's cache directory.\n\n```java\nAccess access = ...;\nString tempDir = ...;\nUplink uplink = new Uplink(UplinkOption.tempDir(tempDir));\ntry (Project project = uplink.openProject(access);\n        OutputStream out = project.uploadObject(\"my-bucket\", \"key/to/my/object\");\n        InputStream in = new FileInputStream(\"path/to/local/file\")) {\n    byte[] buffer = new byte[8 * 1024];\n    int bytesRead;\n    while ((bytesRead = in.read(buffer)) != -1) {\n        out.write(buffer, 0, bytesRead);\n    }\n}\n```\n\n#### Uploading new object with progress monitoring and cancellation\n\nIf progress monitoring and/or cancellation is important, the client can take advantage of the `ObjectOutputStream` class.\n\nAs all operations in the Storj Java API are blocking, the client should use some means for asynchronous processing - like the `AsyncTask` from the Android platform.\n\nThe example below shows how to upload with progress monitoring and cancellation using the `AsyncTask`.\n\nNote the importance of specifying the location of the temp directory using the `UplinkOption.tempDir()` option. This is where the file being uploaded will be first encrypted before actually uploaded into pieces to the Storj network. For Android, it is recommended to set the temp directory to the application's cache directory.\n\n```java\npublic class UploadTask extends AsyncTask\u003cVoid, Long, Throwable\u003e {\n\n    private Access mAccess;\n    private String mBucket;\n    private String mObjectKey;\n    private File mFile;\n    private String mTempDir;\n\n    private long mFileSize;\n    private long mUploadedBytes;\n    private long mLastNotifiedTime;\n\n    UploadTask(Access access, String bucket, String objectKey, File file, String tempDir) {\n        mAccess = scope;\n        mBucket = bucket;\n        mObjectKey = objectKey;\n        mFile = file;\n        mTempDir = tempDir;\n        mFileSize = mFile.length();\n    }\n\n    @Override\n    protected Exception doInBackground(Void... params) {\n        Uplink uplink = new Uplink(UplinkOption.tempDir(mTempDir));\n        try (Project project = uplink.openProject(mAccess);\n             InputStream in = new FileInputStream(mFilePath);\n             ObjectOutputStream out = project.uploadObject(mBucket, mObjectKey)) {\n            byte[] buffer = new byte[128 * 1024];\n            int len;\n            while ((len = in.read(buffer)) != -1) {\n                if (isCancelled()) {\n                    // exiting the try-with-resource block without commit aborts the upload process\n                    return null;\n                }\n                out.write(buffer, 0, len);\n                if (isCancelled()) {\n                    // exiting the try-with-resource block without commit aborts the upload process\n                    return null;\n                }\n                publishProgress((long) len);\n            }\n            out.commit();\n        } catch (StorjException | IOException e) {\n            // exiting the try-with-resource block without commit aborts the upload process\n            return e;\n        }\n\n        return null;\n    }\n\n    @Override\n    protected void onProgressUpdate(Long... params) {\n        long increment = params[0];\n        mUploadedBytes += increment;\n\n        long now = System.currentTimeMillis();\n\n        // Calculate the progress in percents.\n        int progress = (mFileSize == 0) ? 100 : (int) ((mUploadedBytes * 100) / mFileSize);\n\n        // check if 1 second elapsed since last notification or progress is at 100%\n        if (progress == 100 || mLastNotifiedTime == 0 || now \u003e mLastNotifiedTime + 1150) {\n            // Place your code here to update the GUI with the new progress.\n            mLastNotifiedTime = now;\n        }\n    }\n\n    @Override\n    protected void onPostExecute(Throwable t) {\n        if (t != null) {\n            String errorMessage = t.getMessage();\n            // The upload failed.\n            // Place your code here to update the GUI with the error message.\n            return;\n        }\n\n        // The upload is successful.\n        // Place your code here to update the GUI.\n    }\n\n    protected void onCancelled(Throwable t) {\n        // The upload was cancelled.\n        // Place your code here to update the GUI.\n    }\n\n    /**\n     * Call this method to cancel the upload.\n     */\n    void cancel() {\n        this.cancel(false);\n    }\n}\n```\n\n#### Listing objects\n\nListing the content of a bucket, non-recursive:\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access)) {\n    Iterable\u003cObjectInfo\u003e objects = bucket.listObjects();\n    for (ObjectInfo object : objects) {\n        // Do something for each object.\n    }\n}\n```\n\nListing all content under specific prefix, recursive:\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access);\n        ObjectIterator objects = project.listObjects(\"my-bucket\",\n                ObjectListOption.prefix(\"some/key/prefix\"), ObjectListOption.recursive())) {\n    for (ObjectInfo object : objects) {\n        // Do something for each object.\n    }\n}\n```\n\n#### Deleting an object\n\n```java\nAccess access = ...;\nUplink uplink = new Uplink();\ntry (Project project = uplink.openProject(access)) {\n    project.deleteObject(\"my-bucket\", \"key/to/my/object\"));\n}\n```\n\n### Sharing content\n\nSharing content on the Storj network is achieved by sharing the following pieces of information to the receiving party:\n\n1. A serialized shared `Access` Grant to access the shared content.\n1. The bucket name containing the shared content.\n1. The object key or prefix to the share content.\n\nBelow is an example for uploading a file and preparing the restricted `Access` Grant:\n\n```java\nAccess access = ...;\nString tempDir = ...;\nUplink uplink = new Uplink(UplinkOption.tempDir(tempDir));\ntry (Project project = uplink.openProject(access);\n        OutputStream out = project.uploadObject(\"my-bucket\", \"key/to/my/object\");\n        InputStream in = new FileInputStream(\"path/to/local/file\")) {\n    byte[] buffer = new byte[8 * 1024];\n    int bytesRead;\n    while ((bytesRead = in.read(buffer)) != -1) {\n        out.write(buffer, 0, bytesRead);\n    }\n}\n\n// Share a read-only access grant to \"my-bucket/key/to/my\" prefix.\n// It is possible to share the access grant only to \"my-bucket/key/to/my/file\" object too.\nScope sharedAccess = access.share(\n        new Permission.Builder().allowDownload().allowList().build(),\n        new SharePrefix(\"my-bucket\", \"key/to/my\"));\n\n// Serialize the access grant to, so it can be easily sent to the receiving party.\nString serializedShare = sharedAccess.serialize();\n```\n\nThe receiving party can download the shared file using the following example:\n\n```java\n// Info received by the other party\nString serializedAccess = \"13GRuHAW...\";\nString bucketName = \"my-bucket\";\nString objectKey = \"key/to/my/object\";\n\nAccess access = Access.parse(serializedAccess);\ntry (Project project = uplink.openProject(access);\n        InputStream in = project.downloadObject(bucketName, objectKey);\n        OutputStream out = new FileOutputStream(\"path/to/local/file\")) {\n    byte[] buffer = new byte[8 * 1024];\n    int bytesRead;\n    while ((bytesRead = in.read(buffer)) != -1) {\n        out.write(buffer, 0, bytesRead);\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstorj%2Fuplink-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstorj%2Fuplink-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstorj%2Fuplink-android/lists"}