**Problem:**I'm updating an app to Android 11 (API 30) and I cannot get the getContentResolver()
to work in the following instance though it works elsewhere.
With help from this forum and reading the Scoped Storage docs, elsewhere in the app, the following code works within the Actiities
they reside; which includes inputting and outputting from the shared download folder using the getContentResolver()
. The file types are a variety.
What I'm trying to do: This app also allows a user (with approved permissions) to attach a variety of files (e.g., docs, audio, video, etc.) to notes in a database. In this case, a PDF. However, the file information gets passed to a Singleton
class created to avoid redundancy in the same code within other activities
, so I just pass the Context
if needed.
As I mentioned, this code works fine when contained within the Activity
and the only difference I see is the context is passed to a singleton class. I was hoping someone would see something I'm not.
I do realize the URI is not passed (see the resultLauncher
code, but I don't believe that really matters, I can take the file path and change it to an URI, which I have successfully multiple times. Aside from passing to a singleton class, this is the only difference (I can see) compared to my other code.
I could be way off here, the first app and all. A user needs to have the option to attach multiple file types.
**INTENT**
btnAddFile.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
resultLauncher.launch(intent);
});
RESULT LAUNCHER
resultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null){
Uri uri = result.getData().getData();
String util = UriUtils.getPathFromUri(this, uri);
tableLayoutFiles.addView(BuildTableLayout.setupFilesTableRow(EditNote.this,tableLayoutFiles, util,false));
}
});
CODE WITHIN SINGLETON CLASS METHOD (a TableLayout
of files and file paths TextViews
are passed. So the following code resides in a loop iterating the TextView
(i.e., tv) file paths.
File f = new File(tv.getText().toString());
String n = f.getName();
try {
InputStream fis = context.getContentResolver().openInputStream(Uri.fromFile(new File(f.getPath())));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for (int read; (read = fis.read(buf)) != -1; ) {
bos.write(buf, 0, read);
}
fis.close();
noteFiles.add(new Files(0, n, bos.toByteArray()));
} catch (Exception e) {
Log.e("getContentResolver", e.toString());
e.printStackTrace();
}
Well I solved my own problem and as I suspected, I had to pass the Uri
directly to the getContentResolver().openInputStream()
and could not convert a path using Uri.fromFile()
. Another learners experience.
Adding a new variable HashMap<String, Uri>()
called fileURIs
to my method, I passed the file Uri
to my method. I used a file path as the key and the file's Uri
as the key value. I updated the getContentResolver().openInputStream()
within the for
loop to retrieve the correct file Uri
.
Update:
InputStream fis = context.getContentResolver().openInputStream(fileURIs.get(f.getPath()));
File f = new File(tv.getText().toString());
String n = f.getName();
try {
InputStream fis = context.getContentResolver().openInputStream(fileURIs.get(f.getPath()));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for (int read; (read = fis.read(buf)) != -1; ) {
bos.write(buf, 0, read);
}
fis.close();
noteFiles.add(new Files(0, n, bos.toByteArray()));
} catch (Exception e) {
Log.e("getContentResolver", e.toString());
e.printStackTrace();
}
And I should clarify, the use of Uri.fromFile()
does work on file/directories that are not "access denied", so passing a cache
file path can be passed to the ContextResolver()
without issue in this fashion. In my case, when files are imported from an xml, they get moved to the cache directory which eliminates the issue and why Uri.fromFile()
works. That was part of my confusion and not being fully eductated on scoped storage.