1

我使用 Amplify Storage 在我的 android 应用程序项目上工作了很长时间,但我遇到了一个我没有找到解决方案的问题。

我想从图库中检索图像/视频并将其上传到 S3,但我总是收到“光标”错误,它总是返回 null。

有没有更好的方法将 Uri 数据转换为文件,以便我可以将其上传到 S3?

这是我的代码:

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)
4

1 回答 1

1

Uri从 Android 10 开始,如果文件存储在您的应用程序目录中,您只能获取给定文件的路径。画廊中的照片不符合此标准。有关这方面的更多详细信息,请参阅Android 中的存储更新。

InputStream一种解决方案是直接从您的中创建一个Uri,如下所示:

InputStream inStream = getContentResolver().openInputStream(uri);

然后,您可以将其保存到 a File,就像您在 in 中所做的那样saveVideoToInternalStorage,然后将其传递FileAmplify.Storage.uploadFile

一个更好/更简单的解决方案是使用Amplify.Storage.uploadInputStreamAPI(而不是Amplify.Storage.uploadFile),如下所示:

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);
    }
);

在幕后,Amplify 库实际上做了与您正在做的事情相同的事情 - 它以 . 的形式将 写入InputStream临时目录File,上传File,然后在完成时将其从临时目录中删除。

于 2021-01-22T15:46:49.420 回答