Android Code Snippet Upload files with WebView

Code requires Android 5+

1. Set a custom WebViewChromeClient. It is implemented with inline Java code.

2. The ShowFile_Chooser event is raised when the user clicks on a "browse" button.

3. You need to get the file URI with FileProvider and call SendResult.
Example based on ContentChooser.
B4X:
Sub ShowFile_Chooser (FilePathCallback As Object, FileChooserParams As Object)
   cc.Initialize("CC")
   cc.Show("*/*", "Choose File")
   Wait For CC_Result (Success As Boolean, Dir As String, FileName As String)
   Dim jo As JavaObject = Me
   If Success Then
       Log(FileName)
       File.Copy(Dir, FileName, Starter.Provider.SharedFolder, "TempFile")
       jo.RunMethod("SendResult", Array(Starter.Provider.GetFileUri("TempFile"), FilePathCallback))
   Else
       jo.RunMethod("SendResult", Array(Null, FilePathCallback))
   End If
End Sub

Project is attached. Don't miss the manifest editor entries that are required for FileProvider.

Example of requesting the Geolocation permission: https://www.b4x.com/android/forum/threads/webviewextra-2-2-enable-geolocation.114147/post-712994

Notes:
- If the code is added to a different activity then you should change ".main$ with ".youractivity$" and it should be lower cased.
 

Attachments

  • WebViewFileUpload.zip
    10.3 KB · Views: 1,991
Last edited:

Brandsum

Well-Known Member
Licensed User
you will get a "File type is not allowed!" error.
This error is coming from the JavaScript instead of php. What happening is after choosing the file a JavaScript function is extracting the extension from the file name and checking if its end with jpeg, jpg or png. If its not then the error message is coming. Check line 32 of fileupload.php and add this following line after that line to check what file name your webpage is receiving,
HTML:
alert(this.files[0].name);
 
Last edited:

JohnC

Expert
Licensed User
The alert displays "TempFile", which obviously is not a valid filename.

This error happens with both <24 API and >24 API.

I see where Erel is using "TempFile" in his example, and I will see why its not "FileName"...
 

JohnC

Expert
Licensed User
OK, the problem seems to be this...

Erel's code assume the website will not check the extension of the filename (because his code always uploads the file with the name "TempFile"

So, I could manually extract the extension from the file name by looking to the right of the ".", but then all files will be uploaded as "tempfile.xxx" where the xxx is the extension of the file selected by the user.

What would be better is if I can upload the file using it's actual filename, but I am not sure what the universal way to do this, so I posted a question here:

https://www.b4x.com/android/forum/threads/get-name-of-file-from-contentchooser-result.108120/
 

JohnC

Expert
Licensed User
OK, I modified a sub in Erel's example so it will upload the selected file using it's actual name:

B4X:
Sub ShowFile_Chooser (FilePathCallback As Object, FileChooserParams As Object)
    cc.Initialize("CC")
    cc.Show("*/*", "Choose File")
    Wait For CC_Result (Success As Boolean, Dir As String, FileName As String)
    Dim jo As JavaObject = Me
    If Success Then
        Dim FN As String = GetFileNameFromContentResult(FileName)
        Log(FileName)
        Log(FN)
        File.Copy(Dir, FileName, Starter.Provider.SharedFolder, FN)
        jo.RunMethod("SendResult", Array(Starter.Provider.GetFileUri(FN), FilePathCallback))
    Else
        jo.RunMethod("SendResult", Array(Null, FilePathCallback))
    End If
End Sub

And I added this routine:

B4X:
Sub GetFileNameFromContentResult(UriString As String) As String
    If UriString.StartsWith("/") Then 'If the user used a file manager to choose file
        Return UriString.SubString2(UriString.LastIndexOf("/")+3,UriString.Length)
    Else if UriString.IndexOf("%3A") > -1 Then
        Return UriString.SubString2(UriString.LastIndexOf("%3A")+3,UriString.Length)
    Else
        Return UriString
    End If
End Sub
 

youjunjer

Member
Licensed User
Use these codes, I only got a serial number, not the real file name.

OK, I modified a sub in Erel's example so it will upload the selected file using it's actual name:

B4X:
Sub ShowFile_Chooser (FilePathCallback As Object, FileChooserParams As Object)
    cc.Initialize("CC")
    cc.Show("*/*", "Choose File")
    Wait For CC_Result (Success As Boolean, Dir As String, FileName As String)
    Dim jo As JavaObject = Me
    If Success Then
        Dim FN As String = GetFileNameFromContentResult(FileName)
        Log(FileName)
        Log(FN)
        File.Copy(Dir, FileName, Starter.Provider.SharedFolder, FN)
        jo.RunMethod("SendResult", Array(Starter.Provider.GetFileUri(FN), FilePathCallback))
    Else
        jo.RunMethod("SendResult", Array(Null, FilePathCallback))
    End If
End Sub

And I added this routine:

B4X:
Sub GetFileNameFromContentResult(UriString As String) As String
    If UriString.StartsWith("/") Then 'If the user used a file manager to choose file
        Return UriString.SubString2(UriString.LastIndexOf("/")+3,UriString.Length)
    Else if UriString.IndexOf("%3A") > -1 Then
        Return UriString.SubString2(UriString.LastIndexOf("%3A")+3,UriString.Length)
    Else
        Return UriString
    End If
End Sub
 

nikitaganco

Member
Licensed User
hello, is it possible to add option to take picture from camera and upload it? on iphone it is possible and very handy.
 

JohnC

Expert
Licensed User
You can easily combine this code with the camera code to do that:

 

nicieri

Active Member
Licensed User
Code requires Android 5+

1. Set a custom WebViewChromeClient. It is implemented with inline Java code.

2. The ShowFile_Chooser event is raised when the user clicks on a "browse" button.

3. You need to get the file URI with FileProvider and call SendResult.
Example based on ContentChooser.
B4X:
Sub ShowFile_Chooser (FilePathCallback As Object, FileChooserParams As Object)
   cc.Initialize("CC")
   cc.Show("*/*", "Choose File")
   Wait For CC_Result (Success As Boolean, Dir As String, FileName As String)
   Dim jo As JavaObject = Me
   If Success Then
       Log(FileName)
       File.Copy(Dir, FileName, Starter.Provider.SharedFolder, "TempFile")
       jo.RunMethod("SendResult", Array(Starter.Provider.GetFileUri("TempFile"), FilePathCallback))
   Else
       jo.RunMethod("SendResult", Array(Null, FilePathCallback))
   End If
End Sub

Project is attached. Don't miss the manifest editor entries that are required for FileProvider.

Example of requesting the Geolocation permission: https://www.b4x.com/android/forum/threads/webviewextra-2-2-enable-geolocation.114147/post-712994

Notes:
- If the code is added to a different activity then you should change ".main$ with ".youractivity$" and it should be lower cased.

How can I set the main in B4X??... because I'm get an error

\b4xmainpage.java:825: error: cannot find symbol
processBA.raiseEventFromUI(this, "showfile_chooser", filePathCallback, fileChooserParams);
^
symbol: variable processBA
location: class MyChromeClient
 
Top