Android Code Snippet Get the path to media files returned from ContentChooser

Discussion in 'Code Snippets' started by Erel, Mar 27, 2014.

  1. Erel

    Erel Administrator Staff Member Licensed User

    SubName: GetPathFromContentResult

    Description: Content providers such as the media gallery return a URL that starts with content://...

    If you are just interested in showing the selected image then you can use File.OpenInput to open an input stream. You can also use it together with File.Copy2 to copy the media to a new location.

    With the following code you can find the actual file path (if it is available):
    This code depends on ContentResolver and SQL libraries.
    Code:
    Sub GetPathFromContentResult(UriString As StringAs String
      
    If UriString.StartsWith("/"Then Return UriString 'If the user used a file manager to choose the image
      Dim Cursor1 As Cursor
      
    Dim Uri1 As Uri
      
    Dim Proj() As String = Array As String("_data")
      
    Dim cr As ContentResolver
      cr.Initialize(
    "")
      
    If UriString.StartsWith("content://com.android.providers.media.documents"Then
      
    Dim i As Int = UriString.IndexOf("%3A")
      
    Dim id As String = UriString.SubString(i + 3)
      Uri1.Parse(
    "content://media/external/images/media")
      Cursor1 = cr.Query(Uri1, Proj, 
    "_id = ?"Array As String(id), "")
      
    Else
      Uri1.Parse(UriString)
      Cursor1 = cr.Query(Uri1, Proj, 
    ""Null"")
      
    End If
      Cursor1.Position = 
    0
      
    Dim res As String
      res = Cursor1.GetString(
    "_data")
      Cursor1.Close
      
    Return res
    End Sub
    In most cases it is a mistake to use this sub. Especially in newer versions of Android. You shouldn't assume that the resource returned from ContentChooser comes from the file system and if it is, you most probably won't have permissions to directly access it.
     
    Last edited: Jun 13, 2018
  2. Douglas Farias

    Douglas Farias Expert Licensed User

    This code works on debug here, on the release have error on my MOTO G
     

    Attached Files:

  3. Erel

    Erel Administrator Staff Member Licensed User

    Add this line to the manifest editor:
    Code:
    AddPermission(android.permission.READ_EXTERNAL_STORAGE)
     
  4. Douglas Farias

    Douglas Farias Expert Licensed User

  5. Douglas Farias

    Douglas Farias Expert Licensed User

    Erel how can i fix this error?
    I have this error sometimes, sometimes works fine can i select a image from chooser, sometimes give me this error
    Moto G
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    Add Try / Catch to catch this error. Not all images come from actual files. There may be cases where there is no file at all or that the file is not accessible.

    This is why it is safer to access the input stream.
     
    Douglas Farias likes this.
  7. Douglas Farias

    Douglas Farias Expert Licensed User

    Realy i go use File.copy thx
     
  8. alexb

    alexb Member Licensed User

    Is it possible to adapt the above SUB to find the actual file path for a GMAIL attachment ?

    Example:
    'Bundle[{android.intent.extra.STREAM=content://gmail-ls/mymail@gmail.com/messages/681/attachments/0.1/BEST/false}]

    I am able to pass the UriString 'content://gmail-ls/mymail@gmail.com/messages/681/attachments/0.1/BEST/false' but for obvious reasons the SUB cannot handle it. I have no clue about the data structure, therefore I would not know how to modify the sub. Can anybody help? Thx!
    (btw: this was for an image)

    Note: I modified above sub and added following line because on my phone file browser intent (data) was preceded by 'file:/' :
    If UriString.StartsWith("file:/") Then Return UriString.Replace("file:/","") 'If the user used a file manager to choose the image
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    It is possible that there is no file at all, or that the file is not accessible.

    However you can still open a stream to this resource and then copy it.
     
  10. alexb

    alexb Member Licensed User

    Erel. thank you for your reply

    The file is shared correctly when I choose a different app such as another Email program where the photo is then displayed correctly(and with the original file name), so I must assume the data is valid.

    I have tried to use File.OpenInput but was not successful with that either, I did not obtain a valid stream. The code looks like that:

    Dim UriString As String
    UriString ="content://gmail-ls/mymail@gmail.com/messages/681/attachments/0.1/BEST/false"
    File.OpenInput("",UriString)

    Do you consider this correct or is there a mistake with the arguments?

    Btw: I had the same STREAM problem with File.OpenInput and type media "content://media/external/images/media", however for the media contents the above routine works fine, so I did not care. Maybe a full example would help that I do not make any stupid error . THANK YOU!
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    Try this:
    Code:
    Dim jo As JavaObject
    jo = jo.InitializeStatic(
    "anywheresoftware.b4a.objects.streams.File").GetField("ContentDir")
    Dim UriString As String = "content://gmail...")
    Dim in As InputStream = File.OpenInput(jo, UriString)
     
  12. alexb

    alexb Member Licensed User

    Erel, THANKS SO MUCH FOR YOUR OUTSTANDING SUPPORT!

    It worked for me with following modification:
    Dim jo As JavaObject
    jo = jo.InitializeStatic("anywheresoftware.b4a.objects.streams.File").GetField("ContentDir")
    Dim jo2 As Object
    jo2 = jo
    Dim In As InputStream = File.OpenInput(jo2, UriString)

    I noticed the IDE complaint about string instead of object. Maybe because I am still using an older B4A version?
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    It is better to write it this way:
    Code:
    Dim jo As JavaObject
    Dim cd As String = jo.InitializeStatic("anywheresoftware.b4a.objects.streams.File").GetField("ContentDir")
    Dim UriString As String = "content://gmail..."
    Dim In As InputStream = File.OpenInput(cd , UriString)
     
  14. alexb

    alexb Member Licensed User

    Confirm - works too. Again, thanks a lot for all your help!
     
  15. delozoya

    delozoya Member Licensed User

    Helo. I have a problem. When I use GetPathFromContentResult It return null. This is code
    Code:
    Sub CC_Result (Success As Boolean, Dir As String, FileName As String)
        
    If Success Then
        
    Log("filename: "&FileName)

            
    Dim normalizedFile As String = GetPathFromContentResult(FileName)
            
    Log("normalize : "&normalizedFile)
        
    '        CallSubDelayed3(FileTranser, "SendFile",Dir,normalizedFile)
               
        
    Else
            
    If LastException.IsInitialized Then ToastMessageShow(LastException.Message, True)
        
    End If
    End Sub



    Sub GetPathFromContentResult(UriString As StringAs 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, NullNullNull), _
       
    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
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    What is the source of the "file"? Why do you need to find the path?

    There are cases where the resource doesn't come from a real file.
     
  17. delozoya

    delozoya Member Licensed User

    Log's: - filename: content://com.android.externalstorage.documents/document/primary%3A1.wav
    - normalize : null

    Any Solution
     
    Last edited: Feb 25, 2015
  18. delozoya

    delozoya Member Licensed User

    Thaks, I,ll Test then
     
  19. Mark Zraik

    Mark Zraik Member Licensed User

  20. Erel

    Erel Administrator Staff Member Licensed User

    Why do you need to file path?

    The correct way to load such resources is with File.OpenInput.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice