Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImportError: dlopen failed: cannot locate symbol "SDL_ANDROID_GetJNIEnv" #25

Closed
rishabhjoshi opened this issue Mar 14, 2019 · 12 comments · Fixed by kivy/python-for-android#2375

Comments

@rishabhjoshi
Copy link

Hi
I tried the record_mac.py example provided. I also tried this code. The build process is fine and I have added audiostream to my requirements in buildozer.spec.
The problem I am facing is that the app crashes on the android device and logcat output is giving me the error.

01-17 13:37:04.206 12166 12439 I python  : Traceback (most recent call last):
01-17 13:37:04.206 12166 12439 I python  :   File "/home/test/Downloads/kivy/.buildozer/android/app/main.py", line 15, in <module>
01-17 13:37:04.207 12166 12439 I python  :   File "audiostream/core.pyx", line 236, in audiostream.core.get_input
01-17 13:37:04.208 12166 12439 I python  : ImportError: dlopen failed: cannot locate symbol "SDL_ANDROID_GetJNIEnv" referenced by "/data/data/org.test.myapp/files/app/_python_bundle/site-packages/audiostream/platform/plat_android.so"...
01-17 13:37:04.208 12166 12439 I python  : Python for android ended.

Any help is appreciated.

@ghost
Copy link

ghost commented Apr 17, 2019

I have the same issue, here is some additional info if it helps:

1- Python version: 3.7
2- Device OS tested: Android 8.1 and 5.1

Thanks!

@riku2015
Copy link

riku2015 commented Jan 20, 2020

I have same thing here. when using microphone on android. playback is fine.

@riku2015
Copy link

Changing the directory name from android/org/audiostream -> src/org/audiostream wont affect into error. actually it is same "cannot locate symbol "SDL_ANDROID_GetJNIEnv"", and this concludes the android_ext.h could not read AudioIn.java file.
So im very novice on this things, but could someone who understand more coding take a look on filepaths and see if they are right?

@pp721211
Copy link

I run into the same problem. Whenever I start recording with mic, the app crashed.
Seems this issue has been there for quite some time, and nobody bother to fix it?

@jbsidis
Copy link

jbsidis commented Jul 14, 2020

I tried changing from the source code, to try to see if the name of the Symbol was matching, it was not matching, so I changed the source code files from that Symbol error to a different one, in a way SDL2 can find it, but it did not work, the solution is to rewrite the source of the compilation of audiostream because at some point, the symbol is just getting lost and the get_input or get_output functions cannot link either

@xloem
Copy link
Contributor

xloem commented Sep 24, 2020

Is anyone able to describe how to reproduce this error to see it and fix it, for visiting developers new to the systems involved?
EDIT: There is a failing example at https://github.com/xloem/kivy-record-debug . Typing make will reproduce the issue. There is a log of building and running the app at https://github.com/xloem/kivy-record-debug/blob/master/buildrun.log . The error is down at the bottom.

@jbsidis
Copy link

jbsidis commented Sep 25, 2020

Hi,
Yes, in order to reproduce this error, what I do is the following:

  1. I use Python (3.x) stable version in Official Ubuntu Latest and stable version, I have installed the Kivy and KivyMD stable versions, I create a python script, inside of the script what I use is from the audiostream documentation, the "Record a sound example", this one:

from audiostream import get_input

declare a callback where we'll receive the data

def callback_mic(data):
print 'i got', len(data)

get the microphone (or from another source if available)

mic = get_input(callback=callback_mic)
mic.start()
sleep(5)
mic.stop()

And I read the Important note: "To be able to record microphone on Android, you need to have the RECORD_AUDIO permission"

So, I granted that permission.
How?
I use buildozer to convert the python script to a APK Android application, and then I install the apk in my phone.

Before I create the APK, I include the "audiostream" in the requirements of the "spec" file so that I make sure audiostream module is installed into the Apk, so after I built the apk and install in my Android phone, the error is the following:

Error dlopen: ... core.so
Cannot find the symbol SDL_AndroidGetJNIEnv

So, in conclusion, something in the source code of audiostream is not updated and that is why the compilation does not include that symbol,

Instead, if I use Pyjnius to load the Android Autoclass to Record sound, It is working fine and it records in High Quality, so, that is the issue, if you need the apk let me know

@xloem
Copy link
Contributor

xloem commented Sep 25, 2020

EDIT: commentary deleted to clarify issue thread. Could others organise and simplify information too?

It's likely possible to identify this issue, like most issues, by incrementally mutating a working case into a nonworking case, and seeing which change triggers the error. That might mean going inside python4android or audiostream to see how to relate with e.g. pyjnius.

@jbsidis
Copy link

jbsidis commented Sep 25, 2020

Thank you for your answer, in this case I have the following information:

I think (me, personally) the error maybe in this source code https://github.com/kivy/audiostream/blob/master/audiostream/platform/plat_android.pyx

Why?
Because in my android apk app, when I use the Record from Mic example:

from audiostream import get_input

def callback_mic(data):
print('i got', len(data))

mic = get_input(callback=callback_mic)
mic.start()
sleep(5)
mic.stop()

The apk is installed in the cellphone, I open the app and the error is:

dlopen failed: cannot locate symbol "SDL_ANDROID_GetJNIEnv" referenced by "/data/data/org.test.midletname/files/app/_python_bundle/site-packages/audiostream/platform/plat_android.so"...

So, it says something inside of plat_android.pxi does not locate the symbol SDL_ANDROID_GetJNIEnv, so what I did is something,

I uncompressed the apk file and I extracted the plat_android.so library, and then I went to Ubuntu Linux and I listed the available Symbols from that library, I did it using the command:

Using the answers from this https://stackoverflow.com/questions/34732/how-do-i-list-the-symbols-in-a-so-file#34796 page and I was able to list the Symbols inside

So, an small part of the problem is that instead of having the symbol SDL_ANDROID_GetJNIEnv, that plat_android.so file, has the symbol SDL_Android_GetJNIEnv

So, I went to edit all source pxi files that contains that error, and I recompiled the apk and the errors remains, but with new Symbol missing,

dlopen failed: cannot locate symbol "SDL_Android_GetJNIEnv" referenced by "/data/data/org.test.midletname/files/app/_python_bundle/site-packages/audiostream/platform/plat_android.so"...

And I said, okay
I must change this symbol in the source code of all the scripts in the SDL2 package (a lot of files ".h" and ".c" ),

I did it, and I recompiled the apk, but then I got an error from the MainActivity.java plus the same error for the SDL_Android_GetJNIEnv,

The solution for this, that I have found and it is working is that we must use pyjnius to load the Java Class that help us to record something,

The working example using pyjnius to record sound from the microphone and save it into a file is:

Remember to provide the RECORD_AUDIO permission to the android device, otherwise it wont work:
My own example, from Josue Carranza

This is if you are using kivy or kivymd and if you already imported the necesary libraries

from jnius import autoclass
from jnius import cast
import time
from kivy.uix.boxlayout import BoxLayout
import time
import shutil
from datetime import datetime
from datetime import date, timedelta

class clase_grabar_audio(BoxLayout):
def empezar_rec(self):
#java classes
MediaRecorder = autoclass('android.media.MediaRecorder')
AudioSource = autoclass('android.media.MediaRecorder$AudioSource')
OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat')
AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder')
# create out recorder
self.mRecorder = MediaRecorder()
self.mRecorder.setAudioSource(AudioSource.MIC)
self.mRecorder.setOutputFormat(OutputFormat.MPEG_4)
self.mRecorder.setAudioEncodingBitRate(16*44100)
self.mRecorder.setAudioSamplingRate(44100)
timestr = time.strftime("%d,%m,%Y_%H,%M,%S")
p="/home/c_exp/voice/Audio_{}.mp4".format(timestr)

    self.mRecorder.setOutputFile(p)
    self.mRecorder.setAudioEncoder(AudioEncoder.HE_AAC)
    self.mRecorder.prepare()
    self.mRecorder.start()
def detener_rec(self):
    self.mRecorder.stop()
    self.mRecorder.release()

This is a working example, I tested this from Android 6 to Android 10 and it is working, if you need more help or be part of developing software my name is Josue Carranza, from El Salvador.
ScreenshotCapture_2020_09_25_13_10_19 mp4

@xloem
Copy link
Contributor

xloem commented Dec 17, 2020

@jbsidis I'm reviewing this with goal to eventually fix it.

I have severe cognitive issues and need clear notes to help me move forward. Can you edit your failing example to format the code?

This will make it work when visitors copy-paste it.

There are two ways:

```
failing code example here (fenced by three backticks)
```

or

    failing code example here (every line indented by at least four spaces)

xloem added a commit to xloem/buildozer-recipe-debug that referenced this issue Dec 17, 2020
@xloem
Copy link
Contributor

xloem commented Dec 18, 2020

I've identified that this issue is because of a missing check for SDL2. In SDL2, this symbol was renamed.
A patch for this issue was committed to pythonforandroid for the android recipe in 2015 ( pythonforandroid/recipes/pyjnius/sdl2_jnienv_getter.patch in the python-for-android tree), and for the pyjnius recipe in 2016 ( d01413aa37fe4c5a1f05df166a5e3e944ea123f7 in the python-for-android repository). It should be relatively trivial to make a similar change inside the audiostream repository, as audiostream already checks for SDL2 in setup.py .

matham added a commit that referenced this issue Dec 19, 2020
Fix for one of the parts of #25: Missing symbol on android
@xloem
Copy link
Contributor

xloem commented Dec 22, 2020

#34 fixed this specific error and this bug should be closed. I have not tested an entire recording workflow on android at this time but am happy to make that work if somebody can write a test app.

@matham matham closed this as completed Dec 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants