is there someone who has experience with pyqtdeploy and adding external modules? I am currently using pyqtdeploy (version 1.2) together with PyQt 5.5.1 to write an application that can be deployed to an Android device. Without any external modules, the freezing with pyqtdeploy works pretty well. However, I am not really sure how I can add external modules (not pure Python ones) to my application.
In particular, I want to add the external module pycrypto. Therefore, I downloaded the pycrypto sourcecode, compiled it with the Android toolchain (from the Android NDK) and now I have a bunch of *.py and *.so files. How can I add them to my application?
My initial attempt was to add the *.py and the *.so files (so basically the whole pycrypto module) to the "Other Packages" tab in pyqtdeploy.
But now, when I import something pycrypto related in my application (from Crypto.Cipher import AES) i get the following error message:
File: ":/Crypto/Cipher/_AES.py", line 20 in __bootstrap__
TypeError: 'NoneType' object is not callable
The _AES.py file where the error is thrown, looks like this:
def __bootstrap__():
global __bootstrap__, __loader__, __file__
import sys, pkgutil, imp
__file__ = pkgutil.get_data(__name__,'_AES.cpython-34m.so')
__loader__ = None; del __bootstrap__, __loader__
imp.load_dynamic(__name__,__file__)
__bootstrap__()
At first I thought, that the *.so filename was just wrong and therefore, I got the NoneType Error, so I changed the filename in _AES.py to something other like 'test.so'. Surprisingly, now, I get a different error message than before:
File ":/pkgutil.py" line 629, in get_data
ImportError: qrcimporter: error opening file :/Crypto/Cipher/test.so
Ok, so the filename should be fine, right? But why do i get the 'NoneType` error message? What am I doing wrong? Is this the right way to accomplish this?
Any help is highly appreciated. I am pretty sure, that i'm only one small step away from getting this thing to work, but I can't figure out what i'm doing wrong.
Thanks!
Related
I am using QDirIterator to get a list of files in a directory and in subdirectories. It works fine on Windows but on Android it only works if there are no subdirectories (or if I don't tell it to look into subdirectories). I don't know what is going on but I suspect something odd with subdirectory permissions in Android. I can demonstrate the problem with a very short bit of code using the standard Qt Widgets QMainWindow application template in Qt Creator using Qt 6.4.1 and Android 9 (I am actually working on an Amazon Fire) using arm64_v8a ABI.
The code pops up a dialog to choose a directory and then outputs the contents of that directory to the console.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString folder = QFileDialog::getExistingDirectory(this, "Choose a folder");
QDirIterator dirIterator(folder, QDirIterator::Subdirectories);
while (dirIterator.hasNext())
{
qDebug() << dirIterator.next();
}
}
This will crash if the directory has subdirectories. Changing
QDirIterator dirIterator(folder, QDirIterator::Subdirectories)
to
QDirIterator dirIterator(folder)
stops it crashing but also stops me getting the contents of the subdirectories. I have played around using QDir::entryInfoList() but I get exactly the same problem (and checking the source code I think this just calls QDirIterator anyway).
The nature of the crash is rather strange. It gets stuck in an endless loop in the subdirectory. So if I point it at the downloads directory and I have a subdirectory called test the output is:
D libqdiriterator_test_arm64-v8a.so: "content://com.android.providers.downloads.documents/tree/downloads/test"
D libqdiriterator_test_arm64-v8a.so: "content://com.android.providers.downloads.documents/tree/downloads/test/test"
D libqdiriterator_test_arm64-v8a.so: "content://com.android.providers.downloads.documents/tree/downloads/test/test/test"
D libqdiriterator_test_arm64-v8a.so: "content://com.android.providers.downloads.documents/tree/downloads/test/test/test/test"
And this continues until the whole thing crashes. It is as if it never actually descends into the subdirectories and keeps listing the root directory. If there are files that would be listed before the subdirectory then these get listed again and again too as if they were in the subdirectory (which they aren't). I suppose I could work around it using opendir, readdir, closedir but this ought to be much easier and more portable in Qt, and if the problem really is permissions then using lower level Unix interfaces won't help.
So I use chaquopy to get simple python programs functioning in an old (jelly bean) tablet (I replace the example console app's main.py in the src directory). Not bad for a beginner's start and I'm very happy.
But now for a test I try to display a matplotlib graph like this:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def main():
image = mpimg.imread("/storage/emulated/0/Documents/test.png")
plt.imshow(image)
plt.show()
The matplotlib library was installed from within android studio (albeit with a few missing elements, manual pip3 install and usage of local files). Now the build and program finish without errors, but there is no graph. Installation of pillow and use of other graph types no avail.
Can this be handled in python, or is a dive into android studio / java required?
Thanks for any advice
You'll have to include an ImageView in your app's layout, and then load the image file into it, as in this answer.
For an image which is generated dynamically by matplotlib, either save it to a file and then load from that file, or save it to a bytes object like this:
import io
bio = io.BytesIO()
plt.savefig(bio, format="png")
b = bio.getvalue()
... and then load that bytes object into the ImageView like in this app.
I have an Android native library (C++ code base) called:
libserverapp.so
And I cannot get the Android build to find it:
"DllNotFoundException: serverapp"
I am using an internal build system, but when I parse the output of the build process, I can see many calls of the form:
android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++.exe -march=armv7-a
After building my Android app, I inspect the resulting APK (renaming to .zip and extracting), and can see my library file here:
lib/armeabi-v7a/libserverapp.so
I can confirm that "ARMv7" is the target architecture in the Android Player settings, and I access the library, in C#, via:
[DllImport("serverapp", CallingConvention = CallingConvention.Cdecl)]
private static extern void run_sim(StringBuilder matchInput, StringBuilder results, int randomSeed);
I have built a Windows DLL of the C++ code, to use in the Editor, and everything works great. However, when I move to Android, the .so cannot be found. The import settings for libserverapp.so are:
Platform: Android; CPU: ARMv7; Path: Assets/Plugins/Android/libserverapp.so; Type: Native
Given that the final APK includes the .so where I expect it to be (lib/armeabi-v7a/), I assume my Unity settings are correct? Also, I am not using IL2CPP for the Android build.
Finally, when I do an object dump of the library file (using arm-linux-androideabi-objdump.exe), the file format of the library file is "elf32-littlearm".
I feel that the issue here is simply finding the .so, not the functionality within it. Any ideas on what's going on here?
Thanks!
I ended up solving the problem. I mentioned that was using an internal build system. Well, there seems to be a bug in it. I ported things over to official Android NDK makefiles, and then it "just worked". So in this case, the library could be found, but its contents weren't valid.
this is related to my previous question. I'm trying to build Phone application from android 4.0.4 using maven (I'm adding framework_intermediates as dependency, so internal apis problems are solved), and I ran into this problem. Some parts of the logs are as follows:
Phone/src/com/android/phone/CallNotifier.java:[601,32] cannot find symbol
symbol : variable EventLogTags
(the corresponding line in CallNotifier.java is: EventLog.writeEvent(EventLogTags.PHONE_UI_MULTIPLE_QUERY); )
Phone/src/com/android/phone/InCallScreen.java:[723,28] cannot find symbol
symbol : variable EventLogTags
(the corresponding line in InCallScreen.java is: EventLog.writeEvent(EventLogTags.PHONE_UI_ENTER); )
So... it cannot find the class EventLogTags. There is actually a file Phone/src/com/android/phone/EventLogTags.logtags which has the following contents:
# See system/core/logcat/event.logtags for a description of the format of this file.
option java_package com.android.phone;
70301 phone_ui_enter
70302 phone_ui_exit
70303 phone_ui_button_click (text|3)
70304 phone_ui_ringer_query_elapsed
70305 phone_ui_multiple_query
Apparently, this file tells the system to use some particular tags to log important events in the system. I did a full grep, but could not find any file which defines the values PHONE_UI_ENTER, PHONE_UI_MULTIPLE_QUERY, etc. These are just logs, so I could just comment out these and get it working. But I don't want to do this because I need to build this inside the entire aosp later on. So my question is, how do I get this to compile using maven, without modifying any file?
The Android build system code-generates a Java class out of .logtags files if needed. See: https://github.com/android/platform_build/blob/master/core/base_rules.mk
You will need to decipher the make rules and run that code generation yourself, I imagine.
Getting "system.entrypointnotfoundexception: loadlibrary" While trying to use SevenZipLib.dll to uncompress the .7z file containing media contents/file in the Android evn.
Context:
-The whole program is written in c# as a MONO Android Project. No Build/Deployment Error/warnings.
While running the apk, its throwing "system.entrypointnotfoundexception: loadlibrary".
-Also tested the same code as windows project (not mono) - uncompressing in the windows evn.
Assumptions for the issue:
7zip internally might be using COM components & Mono frame work is not supporting.
Question:
Has anyone come across similar issue? Please suggest some alternative dll/framework which can be used by my apk for uncompressing the .7z file.
Assuming that SevenZipLib.dll is the SevenZipLib Library on CodePlex, the problem is SevenZipLib\SevelZipLib\SevenZipArchive.cs:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern SafeLibraryHandle LoadLibrary(
[MarshalAs(UnmanagedType.LPTStr)] string lpFileName);
The project contains numerous P/Invokes into kernel32.dll (LoadLibrary(), GetProcAddress(), FreeLibrary()), ole32.dll (PropVariantClear()), oleaut32.dll (SafeArrayCreateVector()), and more.
In short, this library is intimately tied to Windows, and isn't going to work on a non-Windows platform in any meaningful fashion, not without a lot of work.
If you need 7z support in a Mono for Android application, you'll need to look into a different library. It looks like the 7-zip SDK includes C# source for reading LZMA files that doesn't rely on P/Invoke, so perhaps that would work?