Android Tutorial URI content://media ... to real file

Hello
I created an application that manages about audio files, video and other files. I have used several things, including ContentChooser. ContentChooser returns files like "content:// media/external/video/media/1".

I saw on the forum how access the file, basically copying it to another folder. But, I need original name of file, but not how to recover actual path of selected file and it's name.

I've seen on the internet, many sites that indicate how to obtain it with the following code.

B4X:
public String getRealPathFromURI(Uri contentUri)
 {       String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(contentUri, proj, null, null, null);
        int column_index  = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
}

Is there any possibility to run this code through reflection or otherwise from B4A?

Perhaps a good solution would be to integrate a method in ContentChooser that returns the original path, not olny URI path. Is posible en next releases?

Thanks in advance
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Perhaps a good solution would be to integrate a method in ContentChooser that returns the original path, not olny URI path. Is posible en next releases?
There is no general way to get the path to the actual resource. This solution will only work for the media store.

Update: Use the code here instead: http://www.b4x.com/android/forum/threads/using-photos-from-the-phone.37444/#post-221367
The code here will not work with Android 4.4.


Here is the solution (requires Reflection library and SQL):
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim cc As ContentChooser
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   cc.Initialize("cc")
   cc.Show("image/*", "")
End Sub
Sub CC_Result (Success As Boolean, Dir As String, FileName As String)
   Activity.SetBackgroundImage(LoadBitmap("", GetPathFromContentResult(FileName)))
End Sub

Sub GetPathFromContentResult(UriString As String) As String
   If UriString.StartsWith("/") Then Return UriString 'If the user used a file manager to choose the image
   Dim Proj() As String
   Proj = Array As String("_data")
   Dim Cursor As Cursor
   Dim r As Reflector
   Dim Uri As Object
   Uri = r.RunStaticMethod("android.net.Uri", "parse", _
      Array As Object(UriString), _
      Array As String("java.lang.String"))
   r.Target = r.GetContext
   r.Target = r.RunMethod("getContentResolver")
   Cursor = r.RunMethod4("query", _
   Array As Object(Uri, Proj, Null, Null, Null), _
   Array As String("android.net.Uri", _
      "[Ljava.lang.String;", "java.lang.String", _
      "[Ljava.lang.String;", "java.lang.String"))
 
   Cursor.Position = 0
   Dim res As String
   res = Cursor.GetString("_data")
   Cursor.Close
   Return res
End Sub
 
Last edited:

MrRey

Member
Licensed User
Longtime User
I tried this code as posted. However, in v1.80, I received this error when running the app:

An error has occurred in sub: main_v6 (java line: 289)
java.lang.RuntimeException:
Object should first be initialized (Cursor).
Continue?

Of course, no matter how I answer, the app does not finish.

Can someone help?
 

MrRey

Member
Licensed User
Longtime User
I discovered what's happening: It works fine the first time with UriString of
B4X:
content://media/external/images/media/939

with a successful return of the path (/mnt/sdcard/ etc...)

However, if I call GetPathFromContentResult again, I get the errors I listed above.

So basically, it only works the first time that sub is called, but throws errors if it's run again during the life of the activity.
 

MrRey

Member
Licensed User
Longtime User
What I've done now as a test that seems to work:

I added the Cursor to my Process_Globals, and then I added
B4X:
Sub Activity_Pause (UserClosed As Boolean)
   If UserClosed Then
      Cursor.Close
   End If
End Sub

It seems to work now. I'm concerned that if the user presses Home, the Cursor will not be closed and the resources will not be freed. If you have a better way of handling the code posted above, please share.

Thanks in advance! :)
 

Danie Steyn

Member
Licensed User
Longtime User
Hello. I hope this question is not to stupid. I tested the GetPathFromContentResult(UriString AsString) to get the path of the selected file. It works great, but I am looking for a way to split the result into dir and filename for example I get the result /mnt/sdcard/DCIM/Camera/20130715_093101.jpg, this is great if I wanted to load the file to an image view or something but I want to copy it and the file.copy required a directory and filename. So is it possible to somehow split the result to dir = /mnt/sdcard/DCIM/Camera/ and file = 20130715_093101.jpg?
Thanks in advance
 

Danie Steyn

Member
Licensed User
Longtime User
I found a solution for this. In case someone else finds the tread and has the same question as me I solved it by using foundslash = returntext.lastindexof("/").
returntext is my string "/mnt/sdcard/DCIM/Camera/20130715_093101.jpg" and foundslash is a integer that i declared. By doing this I get the posistion of the last "/" in the string and from there I can build the folder and filenames with filename = returntext.substring(foundslash + 1) and
folder = returntext.substring2(0, foundslash)
A little logic goes a long way.
I hope this helps someone out there.
 

omidaghakhani1368

Well-Known Member
Licensed User
Longtime User
There is no general way to get the path to the actual resource. This solution will only work for the media store.

Update: Use the code here instead: http://www.b4x.com/android/forum/threads/using-photos-from-the-phone.37444/#post-221367
The code here will not work with Android 4.4.

Here is the solution (requires Reflection library and SQL):
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim cc As ContentChooser
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
   cc.Initialize("cc")
   cc.Show("image/*", "")
End Sub
Sub CC_Result (Success As Boolean, Dir As String, FileName As String)
   Activity.SetBackgroundImage(LoadBitmap("", GetPathFromContentResult(FileName)))
End Sub

Sub GetPathFromContentResult(UriString As String) As String
   If UriString.StartsWith("/") Then Return UriString 'If the user used a file manager to choose the image
   Dim Proj() As String
   Proj = Array As String("_data")
   Dim Cursor As Cursor
   Dim r As Reflector
   Dim Uri As Object
   Uri = r.RunStaticMethod("android.net.Uri", "parse", _
      Array As Object(UriString), _
      Array As String("java.lang.String"))
   r.Target = r.GetContext
   r.Target = r.RunMethod("getContentResolver")
   Cursor = r.RunMethod4("query", _
   Array As Object(Uri, Proj, Null, Null, Null), _
   Array As String("android.net.Uri", _
      "[Ljava.lang.String;", "java.lang.String", _
      "[Ljava.lang.String;", "java.lang.String"))

   Cursor.Position = 0
   Dim res As String
   res = Cursor.GetString("_data")
   Cursor.Close
   Return res
End Sub
Hi Erel.
how i can select audio and get real path on all version android even android 4.4
 
Top