Code Monkey home page Code Monkey logo

uplink-android's Introduction

android-libuplink

Javadocs

Android bindings to Storj V3 libuplink.

Requirements

  • Android 5.0 Lollipop or newer

Setup

Add the Gradle dependency to the build.gradle file of the app module:

dependencies {
    implementation 'io.storj:uplink-android:1.0.0-rc.1'
}

Usage

Access Grant

The Access Grant contains all information required to access resources on the Storj network:

  • Satellite Address where metadata is stored
  • API Key for accessing a project on the satellite
  • Encryption Access for decrypting the content

Creating new access grant from passphrase

New Access Grant can be requested from satellite with Satellite Address, API Key and passphrase.

String satelliteAddress = "[email protected]:7777";
String serializedApiKey = "13Yqft7v...";
String passphrase = "super secret passphrase";

Uplink uplink = new Uplink();
Access access = uplink.requestAccessWithPassphrase(satelliteAddress, serializedApiKey, passphrase);

Sharing access grant

Access Grant can be shared in terms of allowed operations and access to specific buckets and objects.

Permission permission = new Permission.Builder().allowDownload().allowList().build();
access.share(permission, new SharePrefix("my-bucket", "pictures/birthday/"));

Serializing access grant to string

Access Grant can be serialized to string for easy sharing.

Access access = ...;
String serializedAccess = access.serialize(); 

Parsing serialized access grant from string

If received a serialized Access Grant as a string, it can be parsed to Access object.

String serializedAccess = "13GRuHAW...";
Access access = Access.parse(serializedAccess);

Buckets

Creating new bucket

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access)) {
    project.createBucket("my-bucket");
}

Getting info about a bucket

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access)) {
    BucketInfo info = project.statBucket("my-bucket"));
}

Listing buckets

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access);
        BucketIterator iterator = project.listBuckets()) {
    for (BucketInfo info : iterator) {
        // Do something for each bucket.
    }
}

Deleting a bucket

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access)) {
    BucketInfo info = project.deleteBucket("my-bucket"));
}

Objects

Downloading an object

Below is the easiest way for downloading a complete object to a local file.

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access);
        InputStream in = project.downloadObject("my-bucket", "key/to/my/object");
        OutputStream out = new FileOutputStream("path/to/local/file")) {
    byte[] buffer = new byte[8 * 1024];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
    }
}

Downloading a range of an object

If 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.

Access access = ...;
Uplink uplink = new Uplink();
ObjectDownloadOption[] options = new ObjectDownloadOption[]{
        ObjectDownloadOption.offset(1024),
        ObjectDownloadOption.length(4096)
};
try (Project project = uplink.openProject(access);
        InputStream in = project.downloadObject("my-bucket", "key/to/my/object",
                options);
        OutputStream out = new FileOutputStream("path/to/local/file")) {
    byte[] buffer = new byte[8 * 1024];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
    }
}

Downloading an object with progress monitoring and cancellation

If progress monitoring and/or cancellation is important, the client can take advantage of the ObjectInputStream class.

As 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.

The example below shows how to download with progress monitoring and cancellation using the AsyncTask:

public class DownloadTask extends AsyncTask<Void, Long, Throwable> {

    private Access mAccess;
    private String mBucket;
    private ObjectInfo mInfo;
    private File mLocalFile;

    private int mNotificationId;
    private long mDownloadedBytes;
    private long mLastNotifiedTime;

    DownloadTask(Access access, String bucket, ObjectInfo info, File localFile) {
        mAccess = access;
        mBucket = bucket;
        mInfo = info;
        mLocalFile = localFile;
    }

    @Override
    protected Exception doInBackground(Void... params) {
        try (Project project = new Uplink().openProject(mAccess);
             ObjectInputStream in = project.downloadObject(mBucket, mInfo.getKey());
             OutputStream out = new FileOutputStream(mLocalFile)) {
            byte[] buffer = new byte[128 * 1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                if (isCancelled()) {
                    // exiting the try-with-resource block aborts the download process
                    return null;
                }
                out.write(buffer, 0, len);
                if (isCancelled()) {
                    // exiting the try-with-resource block aborts the download process
                    return null;
                }
                publishProgress((long) len);
            }
        } catch (StorjException | IOException e) {
            return e;
        }
    }

    @Override
    protected void onProgressUpdate(Long... params) {
        long increment = params[0];
        mDownloadedBytes += increment;

        long now = System.currentTimeMillis();

        // Calculate the progress in percents.
        long size = mFile.getSystemMetadata().getContentLength();
        int progress = (size == 0) ? 100 : (int) ((mDownloadedBytes * 100) / size);

        // Check if 1 second elapsed since last notification or progress is at 100%.
        if (progress == 100 || mLastNotifiedTime == 0 || now > mLastNotifiedTime + 1150) {
            // Place your code here to update the GUI with the new progress.
            mLastNotifiedTime = now;
        }
    }

    @Override
    protected void onPostExecute(Throwable t) {
        if (t != null) {
            String errorMessage = t.getMessage();
            // The download failed.
            // Place your code here to update the GUI with the error message.
            return;
        }

        // The download is successful.
        // Place your code here to update the GUI.
    }

    protected void onCancelled(Throwable t) {
        // The download was cancelled.
        // Place your code here to update the GUI.
    }

    /**
     * Call this method to cancel the download.
     */
    void cancel() {
        this.cancel(false);
    }
}

Uploading new object

Below is the easiest way for uploading new object.

Note 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.

Access access = ...;
String tempDir = ...;
Uplink uplink = new Uplink(UplinkOption.tempDir(tempDir));
try (Project project = uplink.openProject(access);
        OutputStream out = project.uploadObject("my-bucket", "key/to/my/object");
        InputStream in = new FileInputStream("path/to/local/file")) {
    byte[] buffer = new byte[8 * 1024];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
    }
}

Uploading new object with progress monitoring and cancellation

If progress monitoring and/or cancellation is important, the client can take advantage of the ObjectOutputStream class.

As 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.

The example below shows how to upload with progress monitoring and cancellation using the AsyncTask.

Note 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.

public class UploadTask extends AsyncTask<Void, Long, Throwable> {

    private Access mAccess;
    private String mBucket;
    private String mObjectKey;
    private File mFile;
    private String mTempDir;

    private long mFileSize;
    private long mUploadedBytes;
    private long mLastNotifiedTime;

    UploadTask(Access access, String bucket, String objectKey, File file, String tempDir) {
        mAccess = scope;
        mBucket = bucket;
        mObjectKey = objectKey;
        mFile = file;
        mTempDir = tempDir;
        mFileSize = mFile.length();
    }

    @Override
    protected Exception doInBackground(Void... params) {
        Uplink uplink = new Uplink(UplinkOption.tempDir(mTempDir));
        try (Project project = uplink.openProject(mAccess);
             InputStream in = new FileInputStream(mFilePath);
             ObjectOutputStream out = project.uploadObject(mBucket, mObjectKey)) {
            byte[] buffer = new byte[128 * 1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                if (isCancelled()) {
                    // exiting the try-with-resource block without commit aborts the upload process
                    return null;
                }
                out.write(buffer, 0, len);
                if (isCancelled()) {
                    // exiting the try-with-resource block without commit aborts the upload process
                    return null;
                }
                publishProgress((long) len);
            }
            out.commit();
        } catch (StorjException | IOException e) {
            // exiting the try-with-resource block without commit aborts the upload process
            return e;
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Long... params) {
        long increment = params[0];
        mUploadedBytes += increment;

        long now = System.currentTimeMillis();

        // Calculate the progress in percents.
        int progress = (mFileSize == 0) ? 100 : (int) ((mUploadedBytes * 100) / mFileSize);

        // check if 1 second elapsed since last notification or progress is at 100%
        if (progress == 100 || mLastNotifiedTime == 0 || now > mLastNotifiedTime + 1150) {
            // Place your code here to update the GUI with the new progress.
            mLastNotifiedTime = now;
        }
    }

    @Override
    protected void onPostExecute(Throwable t) {
        if (t != null) {
            String errorMessage = t.getMessage();
            // The upload failed.
            // Place your code here to update the GUI with the error message.
            return;
        }

        // The upload is successful.
        // Place your code here to update the GUI.
    }

    protected void onCancelled(Throwable t) {
        // The upload was cancelled.
        // Place your code here to update the GUI.
    }

    /**
     * Call this method to cancel the upload.
     */
    void cancel() {
        this.cancel(false);
    }
}

Listing objects

Listing the content of a bucket, non-recursive:

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access)) {
    Iterable<ObjectInfo> objects = bucket.listObjects();
    for (ObjectInfo object : objects) {
        // Do something for each object.
    }
}

Listing all content under specific prefix, recursive:

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access);
        ObjectIterator objects = project.listObjects("my-bucket",
                ObjectListOption.prefix("some/key/prefix"), ObjectListOption.recursive())) {
    for (ObjectInfo object : objects) {
        // Do something for each object.
    }
}

Deleting an object

Access access = ...;
Uplink uplink = new Uplink();
try (Project project = uplink.openProject(access)) {
    project.deleteObject("my-bucket", "key/to/my/object"));
}

Sharing content

Sharing content on the Storj network is achieved by sharing the following pieces of information to the receiving party:

  1. A serialized shared Access Grant to access the shared content.
  2. The bucket name containing the shared content.
  3. The object key or prefix to the share content.

Below is an example for uploading a file and preparing the restricted Access Grant:

Access access = ...;
String tempDir = ...;
Uplink uplink = new Uplink(UplinkOption.tempDir(tempDir));
try (Project project = uplink.openProject(access);
        OutputStream out = project.uploadObject("my-bucket", "key/to/my/object");
        InputStream in = new FileInputStream("path/to/local/file")) {
    byte[] buffer = new byte[8 * 1024];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
    }
}

// Share a read-only access grant to "my-bucket/key/to/my" prefix.
// It is possible to share the access grant only to "my-bucket/key/to/my/file" object too.
Scope sharedAccess = access.share(
        new Permission.Builder().allowDownload().allowList().build(),
        new SharePrefix("my-bucket", "key/to/my"));

// Serialize the access grant to, so it can be easily sent to the receiving party.
String serializedShare = sharedAccess.serialize();

The receiving party can download the shared file using the following example:

// Info received by the other party
String serializedAccess = "13GRuHAW...";
String bucketName = "my-bucket";
String objectKey = "key/to/my/object";

Access access = Access.parse(serializedAccess);
try (Project project = uplink.openProject(access);
        InputStream in = project.downloadObject(bucketName, objectKey);
        OutputStream out = new FileOutputStream("path/to/local/file")) {
    byte[] buffer = new byte[8 * 1024];
    int bytesRead;
    while ((bytesRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, bytesRead);
    }
}

uplink-android's People

Contributors

erikvv avatar kaloyan-raev avatar mniewrzal avatar stefanbenten avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uplink-android's Issues

ObjectListOption.prefix() returns nothing

If I upload an object with the options path = /test/filename.jpeg and path /test/again/filename.jpg then they do not seem to be correctly returned. When i call bucket.listObjects(), I get back a ObjectInfo that has path = /. If I then call bucket.listObject(ObjestListOption.prefix("/")), I get back no results. Is there a bug in the code or am I doing something wrong?

I imagine it all to be like the following analogy. A bucket is a hard drive in a computer. You can have multiple hard drives. A path is a specified location in that hard drive, and the full path will always be unique among files.

Error when list objects

When I try to get objects that were loaded from desktop uplink I get the error:
go.Universe$Proxyerror: segment size must be larger than 0

I've tried both source code from the master and uplink-1.0 branches.

Upload successful, but no files

access = uplink2.requestAccessWithPassphrase(satelliteAddress, serializedApiKey, passphrase);
try (Project project = uplink2.openProject(access);
OutputStream out = project.uploadObject("my-bucket", "test.jpg");
InputStream in = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
// out.close();
}

uploadObject error

java.io.IOException: io.storj.StorjException: open /data/local/tmp/tee758781382: permission denied

uplink Android does not exist in Maven central repository

Hi,

I am developing an Android app and Storj turns out to be a perfect choice for image storage. But, the problem is, your Android library seems to be no longer available in Maven repository. To be specific, when I navigate to https://github.com/storj/uplink-android to learn how to implement your Android library in my Android project, I tried to add the library by calling:

implementation 'io.storj:uplink-android:1.0.0-rc.1'

But it imported nothing to my project. Then I looked up this library on https://search.maven.org/, it turns out that this library does not exist anymore (but the Java lib does).

Can you please confirm and provide a resolution? Am I missing something? Thank you very much indeed!

Opening a project fails

When opening a project as specified in instructions, the following error is returned

go.Universe$proxyerror: metainfo error: rpccompat: dial tcp: lookup us-central-1.tardigrade.io: No address associated with hostname

The satellite address I am using is us-central-1.tardigrade.io:7777

My code is

    fun login(
        satelliteAddress: String,
        apiKey: String,
        encryptionAccess: String
    ): Result<Scope, Exception> {
        val key = ApiKey.parse(apiKey)
        return try {
            val project = Uplink().openProject(satelliteAddress, key)
            val saltedKey = Key.getSaltedKeyFromPassphrase(project, encryptionAccess)
            val access = EncryptionAccess(saltedKey)
            Success(Scope(satelliteAddress, key, access))
        } catch (ex: StorjException) {
            return Error(ex)
        }
    }

Issue with Android upload

So I'm not sure what I'm doing wrong here. I'm able to list objects and download objects without a problem. But when I try to upload a .jpg or .png image to 'my-bucket,' the file doesn't seem to upload. I see the bytes being uploaded and I'm not catching any errors. But afterwards, I don't see any new files in 'my-bucket.'

I've tried a .jpg of 80kb and a .png of 800kb. I've tried different buffer sizes as well, between 8kb and 128kb

Here is the code:

try (Project project = uplink.openProject(access);
                 OutputStream out = project.uploadObject(bucket, objectKey);
                 InputStream in = new FileInputStream(photoDir)) {
             byte[] buffer = new byte[size * 1024];
             int bytesRead;
             while ((bytesRead = in.read(buffer)) != -1) {
                 out.write(buffer, 0, bytesRead);
             }
         } catch(Exception e) {
            Log.v(e.getMessage());
         }

Any help appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.