Android Question Out of Memory (java.lang.AbstractStringBuilder.enlargeBuffer)

energypf

Member
Licensed User
Longtime User
Hi, I have a problem with the memory. When you use a webservice and the response is a PDF file 7 Mb, I try to store the response in a string, and the app goes into error. Is there a way to save it in a variable, the XML response from the webserver?

Public Sub GetString2(Encoding As String) As String
Dim tr As TextReader
tr.Initialize2(File.OpenInput(HttpUtils2Service.TempFolder, taskId), Encoding)
Dim res As String
res = tr.ReadAll <--- CRASH POINT (Out of Memory)
tr.Close
Return res
End Sub

WEBSERVER RESPONSE

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetReportResponse xmlns="http://*********/">
<GetReportResult>base64Binary</GetReportResult> <--- 7 MB
<Errore>string</Errore>
<Paziente>string</Paziente>
<CodReferto>string</CodReferto>
<Feedback>boolean</Feedback>
</GetReportResponse>
</soap:Body>
</soap:Envelope>
 

energypf

Member
Licensed User
Longtime User
I had already tried with the XML parser, but makes the same mistake. I would need a way to read the contents of the TAG "<GetReportResult>" and save it to a file, but first must be decoded from Base64. The content is a PDF file that contains the patient report. Thank you very much in advance.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
This code works:
B4X:
Sub ParseFile
   Dim In As InputStream = File.OpenInput(File.DirAssets, "filename.xml")
   Dim tr As TextReader
   tr.Initialize2(In, "ASCII")
   Dim buffer(1) As Char
   Dim sb As StringBuilder
   sb.Initialize
   Do Until sb.ToString.EndsWith("<GetReportResult>")
     tr.Read(buffer, 0, 1)
     sb.Append(buffer(0))
   Loop
   Dim base64File As OutputStream = File.OpenOutput(File.DirRootExternal, "1.base64", False)
   Dim tbase64File As TextWriter
   tbase64File.Initialize2(base64File, "ASCII")
   Dim count As Int
   Do While True
     tr.Read(buffer, 0, 1)
     If buffer(0) = "<" Then Exit
     tbase64File.Write(buffer(0))
     count = count + 1
     If count Mod 1000 = 0 Then Log(count)
   Loop
   tbase64File.Close
   Dim In As InputStream = File.OpenInput(File.DirRootExternal, "1.base64")
   Dim bis As JavaObject
   bis.InitializeNewInstance("android.util.Base64InputStream", Array(In, 0))
   Dim bb(8192) As Byte
   Dim out As OutputStream = File.OpenOutput(File.DirRootExternal, "1.pdf", False)
   Dim count As Int = bis.RunMethod("read", Array(bb, 0, bb.Length))
   Do While count > 0
     out.WriteBytes(bb, 0, count)
     Dim count As Int = bis.RunMethod("read", Array(bb, 0, bb.Length))
   Loop
   out.Close
End Sub

Parsing a string of 7mb is a slow operation. Test it in Release mode. You should probably use the Threading library to make it run in a background thread.

Short explanation:
- The code finds the beginning of the b64 string.
- It writes this string to a file named 1.base64.
- It uses Base64InputStream to read the saved file and write the decoded bytes to a new file.
 
Upvote 0

energypf

Member
Licensed User
Longtime User
Perfect work, but is a bit slow. However, I solved by adding the entry in the manifest file: SetApplicationAttribute (android: largeHeap, "true"). Although this only works for devices with SDK> = 3, but it is not a problem. Thank you so much.
 
Upvote 0
Top