Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

java - Upload Media From Android Gallery to AWS S3

I have been working for a long time on my android app project with Amplify Storage, and I have faced a problem which I didn’t find a solution for.

I want to retrieve an image/video from the gallery and upload it to S3, but I always get an error with “Cursor” it always returns null.

Is there any better way to convert Uri data to a File so I can upload it to S3?

here is my code:

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

And I always have this error:

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)
question from:https://stackoverflow.com/questions/65842904/upload-media-from-android-gallery-to-aws-s3

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As of Android 10, you can only obtain the path for a given Uri if the File is stored within your application directory. Photos from the Gallery do not meet this criteria. See Storage updates in Android for more details on this.

One solution would be to create an InputStream directly from your Uri, like this:

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

Then, you can save that to a File, like you are doing in saveVideoToInternalStorage, and then pass the File to Amplify.Storage.uploadFile.

An even better/easier solution would be to use the Amplify.Storage.uploadInputStream API (instead of Amplify.Storage.uploadFile), like this:

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

Under the hood, the Amplify library actually does the same thing you are doing - it writes the InputStream to a temp directory as a File, uploads that File, and then deletes it from the temp directory on completion.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...