Get Android application lib directory - java

I need to specify the location of some native libraries in my Android application. I was accomplishing this with a hard-coded string:
public static final String DLL_DIR_STR = "/data/data/my.application.package/lib";
but wanted to get the path from Android instead. Following posts like this, I used getDir() to find the lib directory, changing
superCollider = new SCAudio(DLL_DIR_STR);
to
superCollider = new SCAudio(container.$context().getDir("lib", 0).getAbsolutePath());
Oddly, the initial libraries seem to load correctly
Trying to load lib /data/data/my.application.package/lib/libsndfile.so 0x42718d80
Added shared lib /data/data/my.application.package/lib/libsndfile.so 0x42718d80
No JNI_OnLoad found in /data/data/my.application.package/lib/libsndfile.so 0x42718d80, skipping init
Trying to load lib /data/data/my.application.package/lib/libscsynth.so 0x42718d80
Added shared lib /data/data/my.application.package/lib/libscsynth.so 0x42718d80
But when libscsynth tries to load some additional code, it's using the wrong path:
OK, listing opendir(/data/data/my.application.package/app_lib)
Any ideas where the "app_" comes from? I thought I must be using getDir() wrong, but the initial files load fine. Could it be something in the native code? Thanks for your help.

I found the answer, quite by accident, in this post. ApplicationInfo.dataDir holds the location of the data directory, and "lib" is easily navigated to from there:
superCollider = new SCAudio(container.$context().getApplicationInfo().dataDir + "/lib");
Alternatively, nativeLibraryDir takes you directly to the lib directory, but requires API level 9.
Thanks for your help!

getDir will always prepend app_ to the directory name so it is very odd that it is working the first time. I would either just expect the app_ to be there or try using getFilesDir, at least you always know what it will return. Does SuperCollider have a restriction on what the directory name is?
I found another SuperCollider Project that seems to be doing the same thing you did initially with the comment "// TODO: not very extensible,".. I found that funny :)

Related

How to avoid hard code full path in Paths#get method

I want to save a copy of Primefaces UploadedFile to my project directory. I have been searching the internet for the solution, what I have found is using Paths#get method. The example given in this answer is Paths.get("/path/to/uploads");, the problem is, where is the exact path of /path/to/uploads? I can't find it. I mean where should I create the path /path/to/uploads? Under my project directory? but which folder? I solve this issue temporary by hard coding the full path like Paths.get("C:/uploads/");
FacesContext.getCurrentInstance().getExternalContext().getRealPath("/") will return you the current installation directory of your project.
And as #Kukeltje suggested, never ever save an uploaded file to your project directory, ... save it outside the webapps or even outside your container.
Therefore create a directory outsite your container (where you want to place your uploaded copies) and append ../ to the above path for each back step.
Say, if your application is deployed at D:/Tools/Tomcat7/webapps/your-application-name (e.g. on Windows using Tomcat) and you want to save copies to D:/Tools/uploads then following will give you required file path:
String uploadsFilePath = FacesContext.getCurrentInstance().getExternalContext()
.getRealPath("../../../uploads");
Use it with the Paths.get(uploadsFilePath) and develop your download logic (I am not sure which library you are using for the Paths class).
How about getClassLoader().getResource(Path/to/file)
So like
MyClass.class.getResource(bla/bla)
Which are now nested in src/resources
Like this You are system independent
#profit
You have several options:
For very quick development, you can use a hardcoded path, but be sure that it exists in your SUT (system under test).
You can define it as a static final string in your module, but this means that each time you want to change that path, you will need to recompile...
You can read that value from a property/config file.
There are more options (like using the registry if you are on Windows, or using an environment variable).

Same code behaving differently on two different packaging

I have a set of codes which are common for two different products, but a part of the code is behaving differently for each product
URL wsdlURL = IntegrationLandscapeService.class.getClassLoader().getResource("IntegrationLandscapeService.wsdl");
For One set up it is giving absolute path and for the other its giving relative path and this is leading to problems, my requirement is to get absolute path for the issue.
Packaging:
Code flow:
The call is made from the Main Class File and from there CommonCode in common code it is looking for the WSDL located in LandScapeService.jar
Update:
The next line of the code is
IntegrationLandscapeService landscapeService = new IntegrationLandscapeService(wsdlURL);
but I get the below error
failed [Failed to access the WSDL at: jar:file:/
tracker.jar!/lib/t24-IF_IntegrationLandscapeService-IntegrationLandscapeService-jwc.jar!/IntegrationLandscapeService.wsdl
.It failed with:
\tracker.jar (The system cannot find the file specified).]
Screen Shot of Jar
The error shows two '!' in the path which indicates the resource is in an embedded/nested/inner jar-file. A product that uses the fat/bundled-jar approach (where one jar-file contains other jar-files) will need some trickery to load classes and resources from the embedded jar-files. You can read about it at http://www.jdotsoft.com/JarClassLoader.php (*)
In any case, there is not much you can do about it since loading resources from embedded jars is not supported natively by Java. The implementation providing the "trickery" I mentioned above will need to fix that (and some do it better than others, see the link above).
The other product with a Par-file indicates the use of OSGi which only requires proper configuration to keep resource-loading working. There is an answer here that explains your situation and solution options.
(*) Spring-boot also has some good documentation and a solution, but I have not tried using the solution with a non-Spring application. See https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html for more information.
You can use getAbsolutePath
File file = new File(url.getPath());
String path = file.getAbsolutePath();
Isn't that what you are looking for?
This is because the files inside the JAR are not treated as regular files, as they are not expanded and not available directly to file explorer.
In Jar, if the files are referred, you will get the path from the root of the JAR file.
Please make sure you have the classpath entry for the Jar location. This will help to find the resource. Otherwise, try the following code(not sure whether it will work in your case, give it a try).
String resource = "/com/example/IntegrationLandscapeService.wsdl"; //package structure of the file
URL res = IntegrationLandscapeService.class.getResource(resource);
Refer this answer to understand more Stack Overflow comment

Load files dynamically in multiple environments

so I am in the process of making a small application.
Right now, the project works fine. I am running it through an IDE. The problem comes about when trying to run the project as a jar - which is the end result. Right now, it fails to properly load the required files (classes and simple ASCII files).
The method I am using is one based off of:
final Enumeration<URL> paths = CLASS_LOADER.getResources("");
Where CLASS_LOADER is an instance of class.getClassLoader().
This works great when not inside a jar. Inside a jar though, it seems to fail horribly. For example, in the code above, paths would be empty.
I am assuming that the fault is that the files are all within a jar - the same jar to be precise.
The class path for the manifest file is blank at the moment.
If it helps, I have two tasks that require loading files.
I need to create a list of all files that are a subclass of
another class.
I need to load a list of language files (all of
which are in the same directory).
If you need anything else to help debug this problem or provide a solution - let me know. Thanks for reading this!
For ClassLoader.getResources() to work you need to feed a path relative to the jar root. If you want to search the jar then ClassLoader public API won't help you. You have to use custom code based on java.util.jar.JarFile, like the one here.

processing for android: AssetManager and list() not working

I've been developing for android using processing but have come to a halt when I wanted to retrieve a list of files within a given directory. Below is a screenshot of the code I have been trying.
I have tried different variations of this (such as getbaseContext().getAssets();) and nothing seems to work. Whenever the code tries to execute the list() part it has an error and there is nothing in 'fileNames'.
Am I missing anything? Is this a problem with processing?
Thanks
EDIT: The direction I am trying to access is "assets/Levels/" which I can see from my project view in eclipse.
I experienced a similar issue because I used folder names with a trailing / character.
So for others experiencing this issue, you need to make sure the folder name you use are just the folder name with no trailing / (so "movies" instead of "movies/")
You do not need any additional permissions in order to run the code that you have. I just compiled it on my device and it works fine. You mention you are attempting to list the files in a given directory. What you are doing is listing the files in the Levels folder, which should be a sub folder of assets. What you will get back is an array of all file names in that folder.
If you are actually looking to get a list of files from a given directory, it has nothing to do with the assets folder and I suggest you check out a tutorial on Android external and internal storage. The information directly on the android page was very helpful to me.
http://developer.android.com/guide/topics/data/data-storage.html
If that's not what you are looking for though, I suggest rewording your question.
So I got it to work!
Turns out it was a problem with where I was placing the 'String[] fileNames;' code before trying to put data into it. The below code works fine:
Thanks for the help!
*Note : Individual folder should not empty.. It will return zero for folder with no files. *
void getFolderDetais(String folder_name)
{
// pass folder_name empty to get detail of root that means assets folder details
String[] filelistInSubfolder = assetManager.list(folder_name);
Log.v("Floder Details ----- >", " Length --- "
+ filelistInSubfolder.length);
}

ClassLoader loading the wrong instance of a file

So I see there has already been a post very similar to this issue, however I am in a situation where I have no power to specify the location of this file within my jar and so am hoping someone is aware of a solution to get around this.
So I currently use the following snippet to obtain a file as an input stream, the file 'plugin.xml' is located at the root of the jar and I cannot change this location as another piece of software (dynatrace) creates this file and determines its location.
the standard snippet:
InputStream is = JmxPlugin.class.getResourceAsStream("/plugin.xml");
Now I am aware that the issue is that the ClassLoader is picking up the first file which matches the name 'Plugin.xml' along the classpath (one which isn't in my jar, yay).
Can anyone think of a way to ensure I pick up the correct file without having to move it? The relative path of my class in the jar is com/something/jmx/JmxPlugin.class.
(Id rather not have to unpack the jar in memory).
Many thanks for any contributions,
I'm not absolutely sure, but seems like Thread.currentThread().getContextClassLoader().getResourceAsStream("/plugin.xml") may solve your issue. If not, you'll have to create your own ClassLoader and resolve the issue there.
The simplies way is to move your jar in classpath to be the first containing Plugin.xml,
Another approach is to use getResource() to locate your jar file:
URL myJar=JmxPlugin.class.getResource("/"+JmxPlugin.class.getName().replace(".","/")+".class");
then use this URL to open jar file and extract Plugin.xml.

Categories

Resources