bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.44k stars 1.57k forks source link

Dynamic Loading generate .so Files #1404

Open Hosseinyzr opened 4 years ago

Hosseinyzr commented 4 years ago

Hi, when I use these: implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}", classifier: 'android-arm'

implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}", classifier: 'android-arm64'

implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}", classifier: 'android-x86'

the final apk size will be large! Unfortunately I release my app in local store that doesn't support app bundle based on cpu architectures . Is there any way to dynamic loading the lib? or the generated .so file? for example downloading the dependency or .so files and loading them dynamically

Hosseinyzr commented 4 years ago

Currently I can load .so files from a path in phone dir , but I faced this issue :

java.lang.NoClassDefFoundError: org.bytedeco.javacpp.avutil
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:453)
        at org.bytedeco.javacpp.Loader.load(Loader.java:950)
        at org.bytedeco.javacpp.Loader.load(Loader.java:891)
        at org.bytedeco.javacpp.avformat$Read_packet_Pointer_BytePointer_int.<clinit>(avformat.java:632)
        at org.bytedeco.javacv.FFmpegFrameGrabber.<clinit>(FFmpegFrameGrabber.java:298)
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.ProccessingGif.lambda$initialThreads$3(ProccessingGif.java:327)
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.-$$Lambda$ProccessingGif$ZCSfOH9JH3DORFhMIvx72fg-WOg.run(Unknown Source:2)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk"],nativeLibraryDirectories=[/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/lib/arm64, /data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk!/lib/arm64-v8a, /system/lib64]]] couldn't find "libjniavutil.so"
        at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
        at java.lang.System.loadLibrary(System.java:1669)
        at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1258)
        at org.bytedeco.javacpp.Loader.load(Loader.java:999)
        at org.bytedeco.javacpp.Loader.load(Loader.java:891)
        at org.bytedeco.javacpp.avutil.<clinit>(avutil.java:10)
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:453)
        at org.bytedeco.javacpp.Loader.load(Loader.java:950)
        at org.bytedeco.javacpp.Loader.load(Loader.java:907)
        at org.bytedeco.javacv.FFmpegFrameGrabber.tryLoad(FFmpegFrameGrabber.java:98)
        at org.bytedeco.javacv.FFmpegFrameGrabber.<clinit>(FFmpegFrameGrabber.java:124)
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.ProccessingGif.lambda$initialThreads$3(ProccessingGif.java:327) 
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.-$$Lambda$ProccessingGif$ZCSfOH9JH3DORFhMIvx72fg-WOg.run(Unknown Source:2) 
        at java.lang.Thread.run(Thread.java:764) 
     Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk"],nativeLibraryDirectories=[/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/lib/arm64, /data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk!/lib/arm64-v8a, /system/lib64]]] couldn't find "libavutil.so"
        at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
        at java.lang.System.loadLibrary(System.java:1669)
        at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1258)
        at org.bytedeco.javacpp.Loader.load(Loader.java:977)
        at org.bytedeco.javacpp.Loader.load(Loader.java:891) 
        at org.bytedeco.javacpp.avutil.<clinit>(avutil.java:10) 
        at java.lang.Class.classForName(Native Method) 
        at java.lang.Class.forName(Class.java:453) 
        at org.bytedeco.javacpp.Loader.load(Loader.java:950) 
        at org.bytedeco.javacpp.Loader.load(Loader.java:907) 
        at org.bytedeco.javacv.FFmpegFrameGrabber.tryLoad(FFmpegFrameGrabber.java:98) 
        at org.bytedeco.javacv.FFmpegFrameGrabber.<clinit>(FFmpegFrameGrabber.java:124) 
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.ProccessingGif.lambda$initialThreads$3(ProccessingGif.java:327) 
        at app.mytoon.MyTest.MVP.Gif.GifProductMaker.-$$Lambda$ProccessingGif$ZCSfOH9JH3DORFhMIvx72fg-WOg.run(Unknown Source:2) 
        at java.lang.Thread.run(Thread.java:764) 

I think The so file should be placed in one of these places :

dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk"],nativeLibraryDirectories=[/data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/lib/arm64, /data/app/app.mytoon-YHd785OyrBrtjdWb9draAA==/base.apk!/lib/arm64-v8a, /system/lib64]]]

but when I tried to coppy file in thsese dirs , It said permission denied.

saudet commented 4 years ago

To reduce the size of the final APK, follow the instructions here: https://github.com/bytedeco/javacpp-presets/wiki/Reducing-the-Number-of-Dependencies#including-binaries-only-for-mobile-platforms

You can also offer 1 APK per architecture to reduce the size of each APK. Google Play can also do that for us, but I'm not familiar with the details.

I suppose it's possible to download the files separately, yes, but I wouldn't recommend it for security reasons, and it's probably something that is restricted on those devices anyway.

saudet commented 4 years ago

BTW, there is now a plugin for Gradle to exclude by platform names: https://github.com/bytedeco/gradle-javacpp#the-platform-plugin If you try it out and find anything missing, please let me know!