Android Question Using Photos from the Phone

Shadow&Max

Active Member
Licensed User
OK, so I want to retrieve a photo from the phone... I use the ContentChooser to get the photo.

Now, I want to save the location of that picture in a file, and reload it at a later time.

I can GET the picture the first time... That's working. Then I save the Dir and FileName to variables that are saved in the file.

When I reload the file, I want to set an image control to that photo.

I'm getting a Security message when I try to access that file again:
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{429c19b0 13253:com.twodogapps.gaa/u0a136} (pid=13253, uid=10136) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS

The file dir and file name that are being saved are:
Dir: ContentDir
FileName: content://com.android.providers.media.documents/document/image%3A131

The ContentChooser is initialized, I'm pretty sure. I set the image like this:

iv.SetBackgroundImage(LoadBitmap(gs.listhere(Index).PhotoDir, gs.listhere(Index).PhotoFile))

In the above line, the index is correct and is getting the values above. As soon as it hits this line, I get the SecurityException shown above.

What am I doing wrong here?

Also, on my phone's permissions for the app it says:

  1. Modify or delete the contents of your USB storage
  2. full network access
  3. access Bluetooth settings - Pair with Bluetooth devices
  4. read the contents of your USB storage.
As far as I can tell those are all I need in terms of permissions.

I don't want to save the file in my apps database because they're just too big and no need to waste duplicate space.
 
Last edited:

hibrid0

Active Member
Licensed User
I try your code, And I dont use SQL in my App, I add SQL Library and say "java.lang.RuntimeException: Object should first be initialized (Cursor)."



You can use this code to get the full path (if such is available):
B4X:
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 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
It depends on the following libraries: ContentResolver, SQL and Phone.
 
Upvote 0

Marco Nissen

Member
Licensed User
This means that the file path is not available. Note that in most cases you do not need this path to work with the selected image.

Well, it seems as if the file path is a security issue for the latest update of Android. Instead, you should use the input stream via content resolver / openinputstream .. small snippet:

B4X:
Sub GetStreamFromContentResult(UriString As String) As InputStream
    Dim r As Reflector
    Dim Uri As Object
    Dim iStream As InputStream
    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")
    iStream = r.RunMethod4( "openInputStream", Array As Object(Uri), Array As String("android.net.Uri"))
    Return iStream
End Sub

With this, you can easily receive e.g. a PDF

B4X:
Try
                         Dim theTitle As String =getTitleFromContent(ShareString)  ' the approach above using _display_name
                        Dim thePath As String = ah.getTemporaryDirectory ' my way to obtain a writeable path
                        Dim jo As JavaObject
                        Dim Inp As InputStream  = GetStreamFromContentResult(ShareString)
                        Dim Out As OutputStream = File.OpenOutput(thePath, theTitle, False)
                        File.copy2(Inp, Out)
                        Inp.Close
                        Out.Close
                                                receivedPDF = thePath & "/" & theTitle
                    Catch
                        Log(":: issue " & LastException)
                    End Try
 
Upvote 0
Top