0

I want to get the path of a file(pdf in this case). I tried myFile.getAbsolutePath() and uri.getPath() but instead of returning /storage/emulated/0/Download/dummy.pdf it returns /com.android.providers.downloads.documents/document/8 .

I couldn't find a working solution for this problem so instead I used FilePath.getPath(context, uri) .

It was working perfectly fine but after a few runs it stopped working and gave me exception : java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/msf:31 flg=0x1 }} to activity {com.example.pm/com.example.pm.UploadFileActivity}: java.lang.NumberFormatException: For input string: "msf:31" And that's why I don't like using FilePath.

Anybody have any Idea why in the first place I'm not getting the correct path (it worked before) and how can I fix this problem? If not is there any other way that I can get the file path being 100% sure that it always works?

I would appreciate your help in advance. thanks.

EDIT:

InputStreamRequestBody :

new RequestBodyUtil();
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("name",name)
            .addFormDataPart("category",category)
            .addFormDataPart("date",date)
            .addFormDataPart("time",time)
            .addFormDataPart("author", Objects.requireNonNull(LoginActivity.sharedPreferences.getString("id", "")))
            .addFormDataPart("file", fileName,
                    RequestBodyUtil.create(MediaType.parse(mime),is))
            .build();

File Manager :

private void doBrowseFile()  {
    Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
    chooseFileIntent.setType("application/pdf");
    // Only return URIs that can be opened with ContentResolver
    chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);

    chooseFileIntent = Intent.createChooser(chooseFileIntent, "Choose a file");
    startActivityForResult(chooseFileIntent, UNIQUE_REQUEST_CODE);
}

Activity result :

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == UNIQUE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
            if (data != null) {
                Uri uri = data.getData();

                Log.i(LOG_TAG, "Uri: " + uri);

                assert uri != null;
                String uriString = uri.toString();
                File myFile = new File(uriString);
                String path = myFile.getAbsolutePath();
                String displayName;

                if (uriString.startsWith("content://")) {
                    Cursor cursor = null;
                    try {
                        cursor = this.getContentResolver().query(uri, null, null, null, null);
                        if (cursor != null && cursor.moveToFirst()) {
                            displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                            Log.d("nameeeee>>>>  ", displayName);
                        }
                    } finally {
                        cursor.close();
                    }
                } else if (uriString.startsWith("file://")) {
                    displayName = myFile.getName();
                    Log.d("nameeeee>>>>  ", displayName);
                }

                fUri = uri;
                tvFilePath.setText(path);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

I need file path for uploading data to database using okhttp :

if(fUri == null){
        progressDialog.dismiss();
        return;
    }


    String mime = "application/pdf";

    //Log.e(TAG, imageFile.getName()+" "+mime+" "+uriToFilename(uri));
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("name",name)
            .addFormDataPart("category",category)
            .addFormDataPart("date",date)
            .addFormDataPart("time",time)
            .addFormDataPart("author", Objects.requireNonNull(LoginActivity.sharedPreferences.getString("id", "")))
            .addFormDataPart("file", fileName,
                    RequestBody.create(new File(path), MediaType.parse(mime))) 
            .build();

FilePath class :

/**
 * Created by Juned on 1/17/2017.
 */



public class FilePath
{
    /**
     * Method for return file path of Gallery image
     *
     * @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());
}
  • 1
    Have a look at uri.toString(). Start with telling how you obtained that uri. I dont know class FilePath. Post the code of FilePath.getPath(). – blackapps Mar 28 '21 at 16:41
  • @blackappa `Uri uri = data.getData(); String uriString = uri.toString(); File myFile = new File(uriString);` in onActivityResult after browsing the pdf file. –  Mar 28 '21 at 16:47
  • @blackapps Sorry I didn't understand what you meant. post edited. what do you mean by `...how you obtained that uri` –  Mar 28 '21 at 17:02
  • Which action caused that onActivityResult? You should have started with it! And you stil did not tell the value of uri.toString(). And it looks as if your getPath is like getRealPathForUri() which is already long time cursed. – blackapps Mar 28 '21 at 17:51
  • it's `contents://com.android.providers.downloads.documents/document/8` . `startActivityForResult(chooseFileIntent, UNIQUE_REQUEST_CODE);` caused the onActivityResult –  Mar 28 '21 at 18:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/230484/discussion-between-azin-and-blackapps). –  Mar 28 '21 at 18:33
  • `chooseFileIntent` Still we have to guess which action that would be. Put that code at start of your post. '`You should have started with it.` Not in a comment. Why do you let us guess? I will not chat. And.. you have a nice content scheme uri. Use it for your file. Dont even try to get a file path as that is not needed these times. – blackapps Mar 28 '21 at 19:38
  • @blackapps sorry and thank you for trying to help. I edited my post. if there is anything more you need from my code please let me know. –  Mar 28 '21 at 19:47
  • @blackapps Also I need path for uploading the pdf to my database by okhttp : `RequestBody.create(new File(path), MediaType.parse(mime))) .build(); ` –  Mar 28 '21 at 19:47
  • So you use ACTION_GET_CONTENT to obtain a nice content scheme uri. Now use that uri and do not even try to convert it to a classic file system path. This has been said before. `Also I need path for uploading the pdf to my database by okhttp : ` No. And you did not tell that in your post either... You should use `InputStreamRequestBody` to offer it an InputStream you opened for the uri. – blackapps Mar 28 '21 at 20:07
  • @blackapps result is the same. Apparently in Kitkat and higher ACTION_GET_CONTENT works like a document so the data's path is /com.android.providers.downloads.documents/document/8 . I want a solution as I need the path. –  Mar 28 '21 at 20:11
  • 1
    `path of a file in android studio is not in a correct format` You mean: `How to upload a file from uri obtained with ACTION_GET_CONTENT with okhttp?` – blackapps Mar 28 '21 at 20:12
  • 1
    No you did something wrong then. And do not use uri.getPath(). but the uri itself or uri.toString(). And open an InputStream for the uri. `InputStream is = getContentResolver().openInputStream(data.getData());` – blackapps Mar 28 '21 at 20:14
  • @blackapps Yes that can be another way to say it but because it okhttp needed the correct path for a file to upload it I said it this way. should i ask another question with that topic?? –  Mar 28 '21 at 20:17
  • @blackapps no actually I'm doing it with MultipartBody. How should I do it with InputStreamRequestBody ?? –  Mar 28 '21 at 20:26
  • @blackapps yes thank you I found this https://stackoverflow.com/questions/25367888/upload-binary-file-with-okhttp-from-resources . I have another question: can I use 2 .post in request (one for multipart and one for Input stream?? –  Mar 28 '21 at 20:33
  • @blackapps like this `Request request = new Request.Builder() .url(PDF_UPLOAD_HTTP_URL) .post(requestBody) .post(requestbody2) .build();` –  Mar 28 '21 at 20:34
  • Again you posted code in a comment... sigh... And you did not even use InputStreamRequestBody. Post full code in a new code block in your post. Further i never used it myself... So please try all... – blackapps Mar 28 '21 at 20:37
  • @blackapps I’m sorry I will post it as soon as I write it but I’m reading more about it in google and it seems like that there is no way to add a name to it so I can retrieve it by FILE in php –  Mar 28 '21 at 22:04
  • You can use DISPLAY_NAME. – blackapps Mar 28 '21 at 22:31
  • @blackapps Sorry I know I'm troubling you too much and too long but I edited my post. Can I use InputstreamRequestBody like that?? RequestBodyUtils is InputstreamRequestBody's class. –  Mar 28 '21 at 22:42
  • My god... You are not even using InputStreamRequestBody class... – blackapps Mar 29 '21 at 06:42
  • https://github.com/square/okhttp/issues/3585 – blackapps Mar 29 '21 at 06:47

0 Answers0