问题
I am trying to connect ContentResolver and Firebase Storage downloads.
Goal: download the files from Firebase storage either into the image gallery or to audio folder.
What I did:
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "FileName1");
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures" + customDir);
AsyncQueryHandler asyncQueryHandler1 = new AsyncQueryHandler(myContentResolver){
@Override
protected void onInsertComplete(int token, Object cookie, Uri uri) {
super.onInsertComplete(token, cookie, uri);
File localFile = new File(uri.getPath());
StorageReference ref = FirebaseStorage.getInstance().getReference(myFireStorageFilePath());
ref.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
........
}
};
asyncQueryHandler1.startInsert(-1, null, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
However, I get the error (even though I requested the permissions):
E/StorageException: Permission denied
java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:317)
at java.io.File.createNewFile(File.java:1008)
at com.google.firebase.storage.FileDownloadTask.processResponse(com.google.firebase:firebase-storage@@17.0.0:138)
at com.google.firebase.storage.FileDownloadTask.run(com.google.firebase:firebase-storage@@17.0.0:229)
at com.google.firebase.storage.StorageTask.lambda$getRunnable$7(com.google.firebase:firebase-storage@@17.0.0:1106)
at com.google.firebase.storage.StorageTask$$Lambda$10.run(Unknown Source:2)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
I can't understand what I am doing wrong. Can I create Uri and then create a file?
Thanks
回答1:
Eventually I couldn't stick together Uri & File in API >= 29, but here is what worked for me:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, af.getFileName());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures" + customDir);
values.put(MediaStore.MediaColumns.IS_PENDING, 1);
AsyncQueryHandler asyncQueryHandler1 = new AsyncQueryHandler(cr){
@Override
protected void onInsertComplete(int token, Object cookie, Uri uri) {
super.onInsertComplete(token, cookie, uri);
onUriCreated(uri, af, token, fr);
}
};
asyncQueryHandler1.startInsert(i, null, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
The function:
void onUriCreated(Uri uri, Attachedfile af, int finalI, FileRepo fr) {
if(uri != null){
StorageReference ref = FirebaseStorage.getInstance().getReference(myFireStorageFilePath);
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri downloadUri) {
RetrieveAndInsert(downloadUri.toString(), uri, finalI, af, fr);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
// Handle any errors
}
});
}
}
and here's where the file gets saved:
public void RetrieveAndInsert (String downloadUri, Uri localUri) {
new RetrieveTask(localUri).execute(downloadUri);
}
class RetrieveTask extends AsyncTask<String, Void, Void> {
String downloadUri;
Uri localUri;
RetrieveTask(Uri localUri) {
this.localUri = localUri;
}
@Override
protected Void doInBackground(final String... downloadUri) {
this.downloadUri = downloadUri[0];
InputStream inp = null;
OutputStream output = null;
try{
URL url = new URL(this.downloadUri);
URLConnection urlCon = url.openConnection();
HttpURLConnection httpCon = (HttpURLConnection) urlCon;
httpCon.connect();
output = cr.openOutputStream(localUri);
int lengthOfFile = httpCon.getContentLength();
inp = new BufferedInputStream(url.openStream(), 8192);// httpCon.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead;
long total = 0;
while ((bytesRead = inp.read(buffer)) != -1) {
total += bytesRead;
output.write(buffer, 0, bytesRead);
}
downloadedFiles[0]++;
} catch (MalformedURLException e) {
e.printStackTrace();
cr.delete(localUri, null, null);
} catch (IOException e) {
e.printStackTrace();
cr.delete(localUri, null, null);
} finally{
try {
inp.close();
output.flush();
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.IS_PENDING, 0);
cr.update(localUri, values, null, null);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
//
}
}
来源:https://stackoverflow.com/questions/59494844/download-from-firebase-storage-contentresolver-api-29