Android Question Need better performance of my sub

schimanski

Well-Known Member
Licensed User
Longtime User
I'm using the following code to encrypt and decrypt each files of my apps under B4A, B4I and B4J. It works without problems with each file and the speed is also very fast. The crypted file has the same size as the decrypted. The only problem I have is, that it is not possible to encrypt big files, because of running in an out of memory, I think. Under windows, I have tested it with files up to 200 MB, no problem. On my Galaxy S6, I get problems with files up to 30 MB. Is there a way to make the subs more efficient?

Thanks for help...

B4X:
Sub encryptFile(DirSource As String, fileSource As String, DirTarget As String, FileTarget As String, PW As String) As Boolean
    Try
        Dim in As InputStream
        in = File.OpenInput(DirSource, fileSource)
        Dim out As OutputStream
        out.InitializeToBytesArray(0)
        File.Copy2(in, out)

        Dim data() As Byte
        data = out.ToBytesArray
        data=Cipher.Encrypt(data, PW)
       
        Dim Dokumentdatei As RandomAccessFile
        Dokumentdatei.Initialize(DirTarget, FileTarget, False)
        Dokumentdatei.WriteB4XObject(data, 0)
        Dokumentdatei.Close
       
        Return True
    Catch
        Log(LastException.Message)
        Return False
    End Try
End Sub

'Verschlüsselte Datei mit B4XObject laden, entschlüsseln und als Byte-Array in ursprünglicher Form speichern'
Sub decryptFile(DirSource As String, FileSource As String, DirTarget As String, FileTarget As String, PW As String) As Boolean
    Try
       
        Dim data() As Byte
        Dim Dokumentdatei As RandomAccessFile
        Dokumentdatei.Initialize(DirSource, FileSource, False)
        data=Dokumentdatei.ReadB4XObject(0)
        Dokumentdatei.Close
       
        data=Cipher.Decrypt(data, PW)

        Dim in As InputStream
        in.InitializeFromBytesArray(data, 0, data.Length)
        Dim out As OutputStream
        out=File.OpenOutput(DirTarget, FileTarget, False)
        File.Copy2(in, out)
        out.Close
       
        Return True
    Catch
        Log(LastException.Message)
        Return False
    End Try
End Sub
 

sorex

Expert
Licensed User
Longtime User
Cipher.Encrypt is that a library or a class file?

if it is a class you can add a doevents somewhere in the encrypt/decrypt loop or run it on another thread.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
that's a "locked" library, not a class. not much options then besides running it in another thread (if that works, never used threads)
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Ok, thanks for your efforts. I thought, that it is perhaps possible to encrypt the data without holding the whole data at once.
I suppose, that it is a memory problem, but when the original file is 30 MB and the encrypted file also, I can't understand, why the app crashes...
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
The problem does only exists, when I try to encrypt video-files, because of their big sizes. I don't know, if it is possible to encrypt only parts of a file????

That is the exception of my Galaxy S6 Edge:

B4X:
** Activity (main) Create, isFirst = true **
java.lang.OutOfMemoryError: Failed to allocate a 268419084 byte allocation with 16777216 free bytes and 99MB until OOM
    at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:201)
    at anywheresoftware.b4a.objects.streams.File.Copy2(File.java:357)
    at b4a.example.wandler._vv4(wandler.java:88)
    at b4a.example.main._activity_create(main.java:331)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    at b4a.example.main.afterFirstLayout(main.java:102)
    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:145)
    at android.app.ActivityThread.main(ActivityThread.java:6837)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

Is it perhaps possible, to catch the out of memory-exception?
 
Last edited:
Upvote 0

sorex

Expert
Licensed User
Longtime User
you could split them up and merge them again after decrypt with append.
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
You can also request largeHeap=true in your manifest. This won't completely solve the problem, but it will push it to a different file size scale.
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
@Erel:
I'm sending most sensitive data with my special unit.

@Roycefer
Thanks, i 'm still using
B4X:
SetApplicationAttribute(android:largeHeap, "true")

@sorex
That is a way, that I should try.

Is it possible, to encrypt the first 10 Mb? I'don't know, how save the file is, after that...
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…