Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

new BlobStoreManager read write on Android 11

I previously used external storage to store specific data that I would like to share between my applications (without having any contentprovider "host")

File folder = new File(Environment.getExternalStorageDirectory(), "FOLDER_NAME");
File file = new File(folder, "FILE_NAME.dat");
FileOutputStream outputStream = new FileOutputStream(file);

That is why I am trying to use BlobStoreManager, as suggested in google's recommendation for targeting 30 (https://developer.android.com/training/data-storage/shared/datasets)

The read & write are based on a BlobHandle with 4 parameters, one being MessageDigest based on a "content". BlobHandle must use the same 4 parameters, or read will fail (SecurityException).

I managed to write data, and to read it, but it makes no sense: It seems that in order to write, I need to use the data I want to write to generate the BlobHandle.

Then, to read, as BlobHandle must use the same 4 parameters, I also need the data I wrote to be able to read. Totally illogic, as I wanted to read this data, I don't have it!

I must miss something or just do not understand how it work. If someone can help :)

Here are my sample:

If I set the following:

  • createBlobHandle: content = "mydata"
  • write: data = "mydata"
  • Then write will success, and read will success too. But it I can not know the value before reading it in a normal usecase :(

If I set the following (which would be logic, at least to me):

  • createBlobHandle: content = "somekey"
  • write: data = "mydata"
  • Then write will fail :(
@RequiresApi(api = Build.VERSION_CODES.R)
private BlobHandle createBlobHandle() {
    //Transfer object
    String content = "SomeContentToWrite";
    String label = "label123";
    String tag = "test";

    //Sha256 summary of the transmission object
    try {
        byte[] contentByte = content.getBytes("utf-8");

        MessageDigest md = MessageDigest.getInstance("sha256");
        byte[] contentHash = md.digest(contentByte);

        return BlobHandle.createWithSha256(contentHash, label,0, tag);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}

private void write() {
    String data = "SomeContentToWrite";
    @SuppressLint("WrongConstant") final BlobStoreManager blobStoreManager = ((BlobStoreManager) applicationContext.getSystemService(Context.BLOB_STORE_SERVICE));

    //Generate the session of this operation
    try {
        BlobHandle blobHandle = createBlobHandle();
        if (blobHandle == null)
            return;
        long sessionId = blobStoreManager.createSession(blobHandle);
        try (BlobStoreManager.Session session = blobStoreManager.openSession(sessionId)) {
            try (OutputStream pfd = new ParcelFileDescriptor.AutoCloseOutputStream(session.openWrite(0, data.getBytes().length))) {
                //The abstract of the written object must be consistent with the above, otherwise it will report SecurityException
                Log.d(TAG, "writeFile: >>>>>>>>>>text = " + data);
                pfd.write(data.getBytes());
                pfd.flush();

                //Allow public access
                session.allowPublicAccess();
                session.commit(applicationContext.getMainExecutor(), new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) {
                        //0 success 1 failure
                        Log.d(TAG, "accept: >>>>>>>>" + integer);
                    }
                });
            }
        }
    } catch (IOException e) {
            e.printStackTrace();
    }
}

private String read() {
    String data = "";
    @SuppressLint("WrongConstant") final BlobStoreManager blobStoreManager = ((BlobStoreManager) applicationContext.getSystemService(Context.BLOB_STORE_SERVICE));

    BlobHandle blobHandle = createBlobHandle();
    if (blobHandle != null) {
        try (InputStream pfd = new ParcelFileDescriptor.AutoCloseInputStream(blobStoreManager.openBlob(createBlobHandle()))) {
            //Read data
            byte[] buffer = new byte[pfd.available()];
            pfd.read(buffer);
            String text = new String(buffer, Charset.forName("UTF-8"));
            Log.d(TAG, "readFile: >>>>>>>>>>>>>>>>>>>>" + text);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
    return data;
}
like image 374
Thomas Thomas Avatar asked Aug 31 '25 03:08

Thomas Thomas


1 Answers

According to the official training documentation linked in the question, the missing piece of information, at the time of the question having been asked, is that the four pieces of data contained in the BlobHandler need to be uploaded to a server owned by the client application then subsequently downloaded by which ever other application wants to access the blob via the BlobStorageManager.

So it would seem that on-device blob discovery is not supported. There could also be a solution possible using a Content Provider which could offer up the four required pieces of data, thus circumventing the need for the server infrastructure.

enter image description here

like image 138
Hrafn Avatar answered Sep 02 '25 15:09

Hrafn