Android Question [SOLVED] Read file from jar inside a Class

Star-Dust

Expert
Licensed User
Longtime User
I'm trying to read a file inside my library compiled in jar.
I need to read this file from within the class that is contained in the library and not from the App

I tried this tutorial but it works only if I load the file inside the jar file from the application does not work if the load inside my own class
https://www.b4x.com/android/forum/threads/embedding-files-in-compiled-libraries.37689/#content

I explain better I'm creating a CustomView and that it needs to load an image that is inside the library itself and I would like to understand how to upload the image.

Thank's
 

JordiCP

Expert
Licensed User
Longtime User
Can't test it now, but most SO answers seem to go in this direction
B4X:
InputStream is = this.getClass().getResourceAsStream("/data/file.txt"); // or wherever the file is and how it is named
So an option would be to add an inline Java call based on this, and complete it to get the Bitmap from the InputStream.

If there isn't a simpler approach before, I'll be able to test it in a couple of hours.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
this error raises me
Cannot find file: sf1.png
sdswitch_v0 (java line: 124)
java.lang.RuntimeException: Object should first be initialized (InputStream).
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
at b4a.example.sdswitch._v0(sdswitch.java:124)
at b4a.example.sdswitch._v5(sdswitch.java:85)
at b4a.example.sdswitch._designercreateview(sdswitch.java:73)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:191)
at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:67)
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:162)
at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
at b4a.example.main._activity_create(main.java:341)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:191)
at b4a.example.main.afterFirstLayout(main.java:104)
at b4a.example.main.access$000(main.java:17)
at b4a.example.main$WaitForLayout.run(main.java:82)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

the code is this
B4X:
Public Sub LoadFileFileFromJar(FileName As String) As InputStream
    If fromAssets Then Return File.OpenInput(File.DirAssets, FileName)
    Dim r As Reflector
    r.Target = Me
    r.Target = r.RunMethod("getClass")
    Dim In As InputStream = r.RunMethod2("getResourceAsStream", "/data/" & FileName, "java.lang.String")
    If In.IsInitialized = False Then
        LogColor("Cannot find file: " & FileName, Colors.Red)
    End If
    Return In
End Sub

Public Sub LoadBitmapFromJar(FileName As String) As Bitmap
    Dim bmp As Bitmap
    Dim In As InputStream = LoadFileFileFromJar(FileName)
    bmp.Initialize2(In)
    In.Close
    Return bmp
End Sub
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I identified the melgium the error.
java.io.FileNotFoundException: sf1.png
But the file is present within the JAR
upload_2018-8-22_14-55-54.png


the error is generated in this row:
B4X:
Dim In As InputStream = LoadFileFileFromJar(FileName)
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can open the APK with 7zip and see where the file was copied to.

If you added a resource to an existing library then the IDE might still think that the library doesn't have resources as it caches this information. Try to restart the IDE.

Consider creating an AAR instead of a Jar. It will allow you to add assets files.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
You can open the APK with 7zip and see where the file was copied to.

If you added a resource to an existing library then the IDE might still think that the library doesn't have resources as it caches this information. Try to restart the IDE.

Consider creating an AAR instead of a Jar. It will allow you to add assets files.
Resources are added. I put the immegine in the previous post.
I restarted the IDe but it does not change anything.

Create an AAR with B4A?
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I have some other simpler way to include and use an image in my jar library created in b4A?
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I tried the exact minimum code 20 times and it gave me an error.
So I inserted some Try to handle errors.

Now put the orignal one back and it works :mad::mad::mad::mad:

Thank's Erel
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Probably because of the IDE cache. The IDE checks for resources only once when the library is first loaded.
Hidden trick ;)!! I also made several compilations but the file was never found!!
At the end I arrived to something similar but only could make it work if the file was placed in the same folder as the class, not the package root. I suppose that's because the paths are relative to it...
B4X:
Public Sub loadInternalBitmap As Bitmap
    Dim Jo As JavaObject = Me
    Dim b As Bitmap = Jo.RunMethod("loadMyBitmap",Null)
    Return b
End Sub

#if JAVA
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.InputStream;
public Bitmap loadMyBitmap() {
    InputStream is = this.getClass().getResourceAsStream("internalbitmap.jpg");
    Bitmap bmp = BitmapFactory.decodeStream(is);
    return(bmp);
}
#End If
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
but only could make it work if the file was placed in the same folder as the class, not the package root. I suppose that's because the paths are relative to it...
It is not complicated to put it in the same folder.

At this point only the string parameter for the file name is missing ;)
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I tried this variant where I entered the filename.
It works properly. Obviously the files must be placed in the same folder as the library.

Also to ensure that when I'm in the design mode of the library does not go to search in resources but in DirAssest... I made a small change that handles this thing.
B4X:
Public Sub loadInternalBitmap(Nomefile As String) As Bitmap
    If File.Exists(File.DirAssets,Nomefile) Then
        Return LoadBitmap(File.DirAssets,Nomefile)
    Else   
        Dim Jo As JavaObject = Me
        Dim b As Bitmap = Jo.RunMethod("loadMyBitmap",Array As Object(Nomefile))
        Return b
    End If
End Sub

#if JAVA
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.InputStream;
public Bitmap loadMyBitmap(String filename) {
    InputStream is = this.getClass().getResourceAsStream(filename);
    Bitmap bmp = BitmapFactory.decodeStream(is);
    return(bmp);
}
#End If
 
Upvote 0
Top