I'm developing an android application that uses OpenCV C++ dll(.so file) in Unity.
The C++ dll accesses a cascade file to use OpenCV functions.
*C++ DLL side code
cv::String face_cascade_name = "haarcascade_frontalface_alt.xml";
if (!face_cascade.load(face_cascade_name)) {
printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n");
return -1;
};
However If I build an android application in Unity and install the app on Android device, it fails to load the xml file.
How can I access the cascade xml in C++ DLL in Android apk?
*If I put the xml to assets/StreamingAssets in Unity, the xml file exists in myapp.apk/assets folder.
Android is a special case since the StreamingAssets folder is compressed and unusable by the OpenCV file reader. You have to 1) copy the file from your StreamingAssets folder to the persistent data path (there's documentation on how to copy and write files in the unity manual), 2) fetch the name of that file using Application.persistantDataPath, like:
string cascadeFileName = (Application.persistentDataPath + "/" + fileName);
Related
I never make a android project and i don't know java. I am trying to port my c++ sdl opengl project to android. I am using android studio. I opened sdl sample android project and now i can manage project from main.cpp . How do i know this because I changed the color of the window and it worked. But when i try to load shader.text file with ifstream program crashed. I understand that this will not happen. After this i searched but I couldn't find a complete code or an example.
When i put files in assets folder and build apk. apk size grows as files. Therefore I need to kepth files in assets folder ?
I think i need to use asset manager but of course i don't know.
What files should I write what code? I mean what i need to add main.cpp and I need to add code java side also ?
main.cpp :
int main()
{
//lets say i have filePath like these
char file_vert[100];
snprintf(file_vert,100,"shaders/vertexShader.text");
char file_Texture[100];
snprintf(file_Texture,100,"textures/image.jpg");
//i am using them in cpp project
//shader text file like this
std::ifstream vShaderFile;
vShaderFile.open(file_vert);
//and i am loading texture file with "stbi" library
unsigned char *data = stbi_load(file_Texture, &width, &height, &nrComponents, 0);
}
I wrote a script that allows you to read and write to a json file. As long as I tried the script in unity editor, I didn't have any problems. But when I switched to installing the application on an Android device, I can't find my json file.
The json file is called "playerData.json" and has been placed in a folder called "playerData.json".
This is the code for the path of the json file (working on unity but not working on android)
path = Application.streamingAssetsPath + "/playerData.json";
I tried using this string of code to get the code to work on android as well, but there is no way to get it to work.
path = System.IO.Path.Combine(Application.streamingAssetsPath, "/playerData.json");
I only wrote the line concerning the path as my android device cannot find the JSON file. Thanks everyone for the help!
Application.streamingAssetsPath does not work on Android and WebGL
It is not possible to access the StreamingAssets folder on WebGL and Android platforms. No file access is available on WebGL. Android uses a compressed .apk file. These platforms return a URL. Use the UnityWebRequest class to access the Assets.
There is a workaround though as mentioned using UnityWebRequest, can find an example in this Unity Answer
I am creating an app in android studio that uses library opencv and yolo. I want to store the yolo config file and weights inside the android package. Right now I have those file in the external storage of my phone and I access them like this:
String yoloCfg = Environment.getExternalStorageDirectory() + "/dnns/traffic-yolov3-tiny.cfg" ;
String yoloWeights = Environment.getExternalStorageDirectory() + "/dnns/traffic-yolov3-tiny_15000.weights";
yolo = Dnn.readNetFromDarknet(yoloCfg, yoloWeights);
My question is: where do I put yolo config file and weights for them to be inside the app when the user downloads the apk and how do I get the path to them, since readNetFromDarknet needs as args the path of those files.
I have tried put them in the asset and attempt to get the path to asset but it doesnt work. This is the code I tried:
String yoloCfg = "file:///android_asset/traffic-yolov3-tiny.cfg";
String yoloWeights = "file:///android_asset/traffic-yolov3-tiny_15000.weights";
yolo = Dnn.readNetFromDarknet(yoloCfg, yoloWeights);
This is where I have the files:
Location of files
And this is the error I get:
E/cv::error(): OpenCV(4.0.1) Error: Parsing error (Failed to parse NetParameter file: file:///android_asset/traffic-yolov3-tiny.cfg) in readNetFromDarknet, file /build/master_pack-android/opencv/modules/dnn/src/darknet/darknet_importer.cpp, line 207
E/org.opencv.dnn: dnn::readNetFromDarknet_10() caught cv::Exception: OpenCV(4.0.1) /build/master_pack-android/opencv/modules/dnn/src/darknet/darknet_importer.cpp:207: error: (-212:Parsing error) Failed to parse NetParameter file: file:///android_asset/traffic-yolov3-tiny.cfg in function 'readNetFromDarknet'
E/SurfaceView: Exception configuring surface
I had the exact same issue. What I did to fix this was to add the files in the asset folder; then I created two files and copied the content of the asset folder files there.
Make sure to use the following path and create your files there:
applicationContext.filesDir.absolutePath
In my iOS project i kept a binary file and used NSBundle class to access that file.
How do i do that same thing in Android since recently i have started working on Android platform, i wanted to know how do i package and read a binary file in Android app.
I started doing it via native call, created a java wrapper and called a function in cpp file and in that function i am trying to read the binary file.
File *f = fopen("absolute file path on my laptop", "r")
Here f is always null whereas in iOS using NSBunle i am able to access the file in my iOS app
I passed and assetmanager object from java to NDK end.
then called on AAssetManager_fromJava and fetched AAssetManager object on jni layer and used that final object to read the asset.
Put the file at design time in assets directory.
At run time open an InputStream for the file in assets and read() its bytes.
You can all do in Java. Easy.
Need to use a shared lib for android from 3rd party, the lib's soname and file name are same, in format libxx.so.1.2.3, which is common on linux. I rename the lib file to libxx.so, and link libxx.so in libmyjni.so using ndk-build. In my java code, before calling the functions in libmyjni.so, I load them like this:
System.load("/data/local/tmp/libxx.so.1.2.3");
System.loadLibrary("myjni");
I have to manually copy libxx.so.1.2.3 to /data/local/tmp/. It works well in this way, after above loading, I can call functions in libmyjni.so.
In code "System.loadLibrary("myjni");", system always trying to get libxx.so.1.2.3 from somewhere. I want to know, in the real world, how could I copy libxx.so.1.2.3 to a specific location on android device during installation? so that I can System.load() it.
Or android has official way to install self made lib to /system/lib/?
If libxx.so.1.2.3 is in format libxx.so then I can use System.loadLibrary("xx") to load it.
Here is finally what I did, keep the libxx.so.1.2.3 untouched and do all stuff in Java:
Put libxx.so.1.2.3 in android assets.
In MainApp.OnCreate(), copy the file to private file folder and load it from there:
AssetManager am = applicationContext.getAssets();
in = am.open(OPENSSL_SO_LIB_NAME); // source instream
File privateStorageDir = applicationContext.getFilesDir();
String libPath = privateStorageDir.getAbsolutePath(); // copy the lib to here ...
System.load(libPath + "/" + SO_LIB_NAME);