Android Question SOLVED: Saving ContentChooser_Result as a regular file

Didier9

Well-Known Member
Licensed User
Longtime User
I am having difficulties with using the file name returned from the ContentChooser
I illustrated these in the small attached project.
In short, I look for a picture file using the ContentChooser. When selected, I display it in an ImageView.
I also save the Dir and FileName variables returned by the ContentChooser in order to be able to reopen the activity with that image preloaded.

This works fine the first time, when I choose the image and display it. If I leave the activity and return to it, I get an error (below) when I try to load the file in the ImageView:

B4X:
Error occurred on line: 120 (Main)
java.lang.SecurityException: Permission Denial: opening provider com.android.externalstorage.ExternalStorageProvider from ProcessRecord{5a536e3 26867:b4a.example/u0a120} (pid=26867, uid=10120) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
    at android.os.Parcel.readException(Parcel.java:1620)
    at android.os.Parcel.readException(Parcel.java:1573)
    at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:3577)
    at android.app.ActivityThread.acquireProvider(ActivityThread.java:4778)
    at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2018)
    at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1471)
    at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1090)
    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:944)
    at android.content.ContentResolver.openInputStream(ContentResolver.java:664)
    at anywheresoftware.b4a.objects.streams.File.OpenInput(File.java:206)
    at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:516)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:755)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:345)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:249)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:139)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:259)
    at b4a.example.main._loadmap(main.java:437)
    at b4a.example.main._activity_resume(main.java:429)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:710)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:342)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:249)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:139)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:166)
    at b4a.example.main.afterFirstLayout(main.java:108)
    at b4a.example.main.access$000(main.java:17)
    at b4a.example.main$WaitForLayout.run(main.java:80)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Cannot find MapFile: ContentDircontent://com.android.externalstorage.documents/document/primary%3ADownload%2Fmap_sample.png
** Activity (main) Pause, UserClosed = false **
(the line starting with "Cannot find MapFile:" is logged by the app)

The line causing the error is:
B4X:
bm.Initialize( Starter.MapDir, Starter.MapFile )

I have added the following permissions to the manifest:

B4X:
AddPermission(android.permission.READ_EXTERNAL_STORAGE)
AddPermission(android.permission.MANAGE_DOCUMENTS)

Note that this works fine every time if I use the "normal" path (File.DirRootExternal & "/Downloads") and filename for the file, so it seems as if the file format used by the ContentChooser requires different permissions?
 

Attachments

  • Test.zip
    139.1 KB · Views: 373

Didier9

Well-Known Member
Licensed User
Longtime User
The image url is not permanent. You can use File.Copy2 to copy it to a temporary file and then load your file.

So is the copy I make with File.Copy2 permanent? Looking at the definition for Copy2 it copies from a Java input stream to a Java output stream, so the destination is also in the form content://...
Is there a way to copy (or save) from a Java stream to a regular file?
I suppose I could save the image from my app once it is loaded in the ImageView?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Copy2 it copies from a Java input stream to a Java output stream, so the destination is also in the form content://...
yes? Why?
Is there a way to copy (or save) from a Java stream to a regular file?
- Create an outputstream for the file you want to save
- and a inputstream for the file you got with content chosser.
- Copy the inputstream to the outputstream
- and close the outputstream.
 
Last edited:
Upvote 0

Didier9

Well-Known Member
Licensed User
Longtime User
I finally got it nailed:

B4X:
Sub ContentChooser_Result( Success As Boolean, Dir As String, FileName As String )
    Dim tempbitmap As Bitmap
    Dim out As OutputStream
 
    If Success = True Then
        ImageView1.SetBackgroundImage( Null )
        LoadMap( Dir, FileName ) ' this scales the picture and places it in ImageView1 on the screen
        tempbitmap = ImageView1.Bitmap
        out = File.OpenOutput( Starter.AppFolder, "Test.png", False ) ' create the output stream
        tempbitmap.WriteToStream(out, 100, "PNG") ' save the bitmap as a png file
        out.Close
        ' here save file location (Starter.AppFolder, "Test.png") for next time the app is started
    Else
        ToastMessageShow( "Getting filename failed", False )
    End If
End Sub ' cc_Result()

Thank you!

I changed the title to better reflect what I was trying to do.
 
Last edited:
Upvote 0
Top