'Creating file from Uri

I'm trying to upload a image to php, for that I need to send a File to the server. So I am trying to create a file from the data parameter.

But I got this error Cannot resolve constructor File

Here's my code:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
            // Get the url from data
            Uri selectedImageUri = data.getData();
            if (null != selectedImageUri) {
                // File
                File imageFilePath = new File(selectedImageUri);


Solution 1:[1]

The appropriate way is to getContentResolver().openInputStream(uri_of_your_file); and using a FileOutputStream to your desired path and then use that file.

As from Commonsware answer

You can use ContentResolver and openInputStream() to get an InputStream on the content represented by the Uri. You can create a FileOutputStream on some file that you control. And, you can use Java I/O to copy from the InputStream to the OutputStream, making your own copy of the content in a file that you control.

Sample code for doing that,

InputStream in =  getContentResolver().openInputStream("your_uri_here");
OutputStream out = new FileOutputStream(new File("your_file_here"));
        byte[] buf = new byte[1024];
        int len;
        while((len=in.read(buf))>0){
            out.write(buf,0,len);
        }
        out.close();
        in.close();

Solution 2:[2]

@GeekDroid's answer is correct, but I thought I would provide more info to help clarify.

I've also created a library that will return the file path from an Uri when selecting a File from MediaStore.


I've created a class that will copy/create a new file inside your application's directory. This is done on the background thread, as it should be done.

I have also created a callback interface to get the "status" and display a ProgressBar

Here is the interface(You can change the name and callbacks to whatever):

interface CallBackTask {
    void onCopyPreExecute();
    void onCopyProgressUpdate(int progress);
    void onCopyPostExecute(String path, boolean wasSuccessful, String reason);
}

Here is the class to copy the file:

public class CopyFileAsyncTask extends AsyncTask<Uri, Integer, String> {
    private Uri mUri;
    private CallBackTask callback;
    private WeakReference<Context> mContext;
    private String pathPlusName;
    private File folder;
    private Cursor returnCursor;
    private InputStream is = null;
    private String errorReason = "";

    DownloadAsyncTask(Uri uri, Context context, CallBackTask callback) {
        this.mUri = uri;
        mContext = new WeakReference<>(context);
        this.callback = callback;
    }

    @Override
    protected void onPreExecute() {
        callback.onCopyPreExecute();
        Context context = mContext.get();
        if (context != null) {
            folder = context.getExternalFilesDir("Temp");
            returnCursor = context.getContentResolver().query(mUri, null, null, null, null);
            try {
                is = context.getContentResolver().openInputStream(mUri);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        int post = values[0];
        callback.onCopyProgressUpdate(post);
    }

    @Override
    protected String doInBackground(Uri... params) {
        File file = null;
        int size = -1;

        try {
            try {
                if (returnCursor != null && returnCursor.moveToFirst()){
                    if (mUri.getScheme() != null)
                    if (mUri.getScheme().equals("content")) {
                        int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
                        size = (int) returnCursor.getLong(sizeIndex);
                    }else if (mUri.getScheme().equals("file")) {
                        File ff = new File(mUri.getPath());
                        size = (int) ff.length();
                    }
                }
            }
            finally {
                if (returnCursor != null)
                returnCursor.close();
            }

            pathPlusName = folder + "/" + getFileName(mUri, mContext.get());
            file = new File(folder + "/" + getFileName(mUri, mContext.get()));

            BufferedInputStream bis = new BufferedInputStream(is);
            FileOutputStream fos = new FileOutputStream(file);


            byte[] data = new byte[1024];
            long total = 0;
            int count;
            while ((count = bis.read(data)) != -1) {
                if (!isCancelled()) {
                    total += count;
                    if (size != -1) {
                        publishProgress((int) ((total * 100) / size));
                    }
                    fos.write(data, 0, count);
                }
            }
            fos.flush();
            fos.close();

        } catch (IOException e) {
            errorReason = e.getMessage();
        }

        return file.getAbsolutePath();

    }

    private String getFileName(Uri uri, Context context) {
        String result = null;
        if (uri.getScheme() != null) {
            if (uri.getScheme().equals("content")) {
                Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            assert result != null;
            int cut = result.lastIndexOf('/');
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    protected void onPostExecute(String result) {
        if(result == null){
            callback.onCopyPostExecute(pathPlusName, false, errorReason);
        }else {
            callback.onCopyPostExecute(pathPlusName, true, "");
        }
    }
}

In your Activity you should do the following:

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class ExampleActivity extends AppCompatActivity implements CallBackTask{
    Button someBtn;
    Uri someUri = .... //This is just an example, you should provide your own Uri

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        someBtn = findViewById(R.id.someBtn);

        someBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CopyFileAsyncTask asyntask = new CopyFileAsyncTask(someUri, ExampleActivity.this, ExampleActivity.this);
                asyntask.execute();
            }
        });

    }
    
    ProgressBar mProgressBar;
    TextView percentText;
    private AlertDialog mdialog;

    @Override
    public void onCopyPreExecute() {
        final AlertDialog.Builder mPro = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.myDialog));
        @SuppressLint("InflateParams") final View mPView = LayoutInflater.from(this).inflate(R.layout.dailog_layout, null);
        percentText = mPView.findViewById(R.id.percentText);

        mProgressBar = mPView.findViewById(R.id.mProgressBar);
        mProgressBar.setMax(100);
        mPro.setView(mPView);
        mdialog = mPro.create();
        mdialog.show();
    }

    @Override
    public void onCopyProgressUpdate(int progress) {
        String progressPlusPercent = progress + "%";
        percentText.setText(progressPlusPercent);
        mProgressBar.setProgress(progress);
    }

    @Override
    public void onCopyPostExecute(String path, boolean wasSuccessful, String reason) {
        if (mdialog != null && mdialog.isShowing()) {
            mdialog.cancel();
        }

        if (wasSuccessful){
            Toast.makeText(this, "File was created at - "+path, Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "Error - "+reason, Toast.LENGTH_SHORT).show();
        }
        
    }
}

You can cancel the copying of the file at any time, by calling:

if (asyntask!=null){
    asyntask.cancel(true);
}

If you want to implement it exactly as I did and display a ProgressBar while the file is being copied, then here is the layout and style of my dialog:

R.style.myDialog:

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="myDialog" parent="Theme.AppCompat.Dialog.Alert">
        <item name="android:windowNoTitle">true</item>
        <item name="android:background">#fff</item>
        <item name="android:windowBackground">@null</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:backgroundDimEnabled">true</item>
    </style>

</resources>

R.layout.dailog_layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/loadContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:padding="20dp">

        <RelativeLayout
            android:id="@+id/dotRel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/percentText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="15dp"
                android:text="0 %"
                android:textColor="@android:color/black"
                android:textSize="25sp" />

            <ProgressBar
                android:id="@+id/mProgressBar"
                style="@android:style/Widget.ProgressBar.Horizontal"
                android:layout_width="match_parent"
                android:layout_height="5dp"
                android:layout_below="@+id/percentText"
                android:progressDrawable="@drawable/progressbar" />

        </RelativeLayout>

    </RelativeLayout>

</RelativeLayout>

Here is the dialog while the file is being copied:

example


Conclusion:

With the above, your file will be copied to /storage/emulated/0/Android/data/yourPackageName/files/Temp/YourFile.jpg. While the files are being copied a progress dialog will be displayed indicating the progress as a percentage (this is useful for when copying large files). If there was an error while copying the file, the reason will be provided in onCopyPostExecute

This will work with file and content Uri's.

Solution 3:[3]

One line solution for your problem

File imageFile = new File(selectedImageUri.getPath());

You missed

.getPath()

Solution 4:[4]

How to create file using android Uri

It may seem difficult to create a java.io.File from an android.net.Uri, since there is no direct way to convert an android.net.Uri into java.net.URI. But if you have the ApplicationContext you can do it very easily.

Here's how to do it from inside a fragment class.

fun createFile(uri: Uri) {
    try {
requireContext().applicationContext.contentResolver.openFileDescriptor(uri, "w")?.use { fd ->
        FileOutputStream(fd).use { fos ->

            // do your job on the FileOutputStream
            // also use background thread

            fos.close()
        }
    }
  } catch (e: Exception) {

  }
}

Note: File operations throws multiple exceptions, so handle them carefully. And also do file operations in worker threads.

Solution 5:[5]

you can use this funtion for get file from uri in new android and older:

fun getFileFromUri(context: Context, uri: Uri?): File? {
    uri ?: return null
    uri.path ?: return null

    var newUriString = uri.toString()
    newUriString = newUriString.replace(
        "content://com.android.providers.downloads.documents/",
        "content://com.android.providers.media.documents/"
    )
    newUriString = newUriString.replace(
        "/msf%3A", "/image%3A"
    )
    val newUri = Uri.parse(newUriString)

    var realPath = String()
    val databaseUri: Uri
    val selection: String?
    val selectionArgs: Array<String>?
    if (newUri.path?.contains("/document/image:") == true) {
        databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        selection = "_id=?"
        selectionArgs = arrayOf(DocumentsContract.getDocumentId(newUri).split(":")[1])
    } else {
        databaseUri = newUri
        selection = null
        selectionArgs = null
    }
    try {
        val column = "_data"
        val projection = arrayOf(column)
        val cursor = context.contentResolver.query(
            databaseUri,
            projection,
            selection,
            selectionArgs,
            null
        )
        cursor?.let {
            if (it.moveToFirst()) {
                val columnIndex = cursor.getColumnIndexOrThrow(column)
                realPath = cursor.getString(columnIndex)
            }
            cursor.close()
        }
    } catch (e: Exception) {
        Log.i("GetFileUri Exception:", e.message ?: "")
    }
    val path = realPath.ifEmpty {
        when {
            newUri.path?.contains("/document/raw:") == true -> newUri.path?.replace(
                "/document/raw:",
                ""
            )
            newUri.path?.contains("/document/primary:") == true -> newUri.path?.replace(
                "/document/primary:",
                "/storage/emulated/0/"
            )
            else -> return null
        }
    }
    return if (path.isNullOrEmpty()) null else File(path)
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 GeekDroid
Solution 2
Solution 3 Vignes
Solution 4
Solution 5