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);
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();
@GeekDroid's answer is correct, but I thought I would provide more info to help clarify.
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:
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.
You can try this;
try {
Uri uri = data.getData();
String selectedFilePath = FilePath.getPath(getActivity(), uri);
final File file = new File(selectedFilePath);
new UploadFileToServer().execute(file);
}
catch (Exception e)
{
e.printStackTrace();
}
and define FilePath
class like this;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
public class FilePath {
/**
* Method for return file path of Gallery image/ Document / Video / Audio
*
* @param context
* @param uri
* @return path of the selected image file from gallery
*/
public static String getPath(final Context context, final Uri uri) {
// check here to KITKAT or new version
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context
* The context.
* @param uri
* The Uri to query.
* @param selection
* (Optional) Filter used in the query.
* @param selectionArgs
* (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri
.getAuthority());
}
}
One line solution for your problem
File imageFile = new File(selectedImageUri.getPath());
You missed
.getPath()
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)
}
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.