Java 将媒体从Android Gallery上传到AWS S3
我用Amplify Storage开发android应用程序项目已经有很长时间了,我遇到了一个我没有找到解决方案的问题 我想从gallery中检索图像/视频并将其上载到S3,但我总是收到一个“Cursor”错误,它总是返回null 有没有更好的方法将Uri数据转换为文件,以便我可以将其上载到S3 这是我的密码:Java 将媒体从Android Gallery上传到AWS S3,java,android,amazon-s3,aws-amplify,amplify,Java,Android,Amazon S3,Aws Amplify,Amplify,我用Amplify Storage开发android应用程序项目已经有很长时间了,我遇到了一个我没有找到解决方案的问题 我想从gallery中检索图像/视频并将其上载到S3,但我总是收到一个“Cursor”错误,它总是返回null 有没有更好的方法将Uri数据转换为文件,以便我可以将其上载到S3 这是我的密码: public void openPhotoGallery(View v) { Intent intent = new Intent(); intent.setType(
public void openPhotoGallery(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select file to upload "), 8);
}
@Override
protected void onActivityResult(int requestCode, final int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == 8) {
Uri selectedMediaUri = data.getData();
String filePath = getPath(selectedMediaUri);
File file = saveVideoToInternalStorage(filePath);
Amplify.Storage.uploadFile("test/image", file, result -> {
Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getKey());
file.delete();
}, error -> {
Log.e("MyAmplifyApp", "Upload failed", error);
});
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); // Line of error
cursor.moveToFirst();
return cursor.getString(column_index);
}
private File saveVideoToInternalStorage (String filePath) {
File newfile = null;
try {
File currentFile = new File(filePath);
ContextWrapper cw = new ContextWrapper(getApplicationContext());
newfile = new File(this.getFilesDir().getPath().toString() + "/video1.mp4");
if(currentFile.exists()){
InputStream in = new FileInputStream(currentFile);
OutputStream out = new FileOutputStream(newfile);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.v("", "Video file saved successfully.");
} else {
Log.v("", "Video saving failed. Source file missing.");
}
} catch (Exception e) {
e.printStackTrace();
}
return newfile;
}
我总是有这样的错误:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.abdulelah.taajerpartners, PID: 24163
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=8, result=-1, data=Intent { dat=content://media/external/images/media/419319 flg=0x1 (has extras) }} to activity {com.abdulelah.taajerpartners/com.ajjerly.partners.TestActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getColumnIndexOrThrow(java.lang.String)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:5078)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5120)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
at android.os.Handler.dispatchMessage(Handler.java:112)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getColumnIndexOrThrow(java.lang.String)' on a null object reference
at com.ajjerly.partners.TestActivity.getPath(TestActivity.java:114)
at com.ajjerly.partners.TestActivity.onActivityResult(TestActivity.java:72)
at android.app.Activity.dispatchActivityResult(Activity.java:7797)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5071)
从Android 10开始,如果文件存储在应用程序目录中,则只能获取给定
Uri
的路径。库中的照片不符合此标准。有关此操作的更多详细信息,请参阅
一种解决方案是直接从Uri
创建InputStream
,如下所示:
InputStream inStream = getContentResolver().openInputStream(uri);
InputStream inStream = getContentResolver().openInputStream(uri);
Amplify.Storage.uploadInputStream("test/image", inputStream,
result -> {
Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getKey());
}, error -> {
Log.e("MyAmplifyApp", "Upload failed", error);
}
);
然后,您可以将其保存到文件
,就像您在saveVideoToInternalStorage
中所做的那样,然后将文件
传递到放大.Storage.uploadFile
更好/更简单的解决方案是使用Amplify.Storage.uploadInputStream
API(而不是Amplify.Storage.uploadFile
),如下所示:
InputStream inStream = getContentResolver().openInputStream(uri);
InputStream inStream = getContentResolver().openInputStream(uri);
Amplify.Storage.uploadInputStream("test/image", inputStream,
result -> {
Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getKey());
}, error -> {
Log.e("MyAmplifyApp", "Upload failed", error);
}
);
在引擎盖下,放大库实际上做的事情与您正在做的事情相同——它将
输入流作为文件写入临时目录,上载该文件,然后在完成时将其从临时目录中删除。尝试将一个好的uri转换为文件实例是一个非常糟糕的想法。最好看看Alpine是否可以从流中上传。此外,我不理解如果你可以将uri转换为文件实例,那么你就必须先复制该文件。请解释一下。