Android - Dynamically load system library without exact path? - java

A couple months ago I graduated from Android samples to work-related projects. As such, I am still painfully new to this build system and fully admit my inexperience with all things *.mk file and Android related.
I have a library that depends on OpenCL v1 or greater. Loading is delayed until the functionality is needed, and only if the minimum version of OpenCL is supported. Up until a couple days ago, I would receive a java.lang.UnsatisfiedLinkError whenever I tried to load it because libGLES_mali.so could not be located. Apparently the device my coworker tested on had this file while my device does not. I found other GLES libs that do exist on my test phone but my code to load them is... longer than I would think it should be.
Trying to use System.loadLibrary("GLES") didn't yield success, nor anything similar.
According to this site (http://www.2net.co.uk/tutorial/android-egl-cgf-is-dead) I need to try to load every GLES library I can think of by name, from both system/lib/ and system/lib/egl/. Consequently, currently my code for loading this library is as follows:
boolean bGles = false;
if(!bGles) {
try {
System.load("system/lib/egl/libGLES.so");
bGles = true;
} catch (java.lang.UnsatisfiedLinkError e) {
}
}
if(!bGles) {
try {
System.load("system/lib/libGLES.so");
bGles = true;
} catch (java.lang.UnsatisfiedLinkError e) {
}
}
if(!bGles) {
try {
System.load("system/lib/egl/libGLES_android.so");
bGles = true;
} catch (java.lang.UnsatisfiedLinkError e) {
}
}
if(!bGles) {
try {
System.load("system/lib/libGLESv1_CM.so");
bGles = true;
} catch (java.lang.UnsatisfiedLinkError e) {
}
}
if(!bGles) {
try {
System.load("system/lib/egl/libGLESv1_CM.so");
bGles = true;
} catch (java.lang.UnsatisfiedLinkError e) {
}
}
It's so terribly messy! Is there no way of asking Android to load whatever the default 'GLES' is on the system? Default version number? I can't knock the tutorial completely, as all my libraries now load and function correctly now, but what will I do for other devices? With other names for their GLES libs?
I feel that I must be misunderstanding the article. Certainly, there must be a better way to load a shared system library than this?

First off, there's a better way to do what you're doing
String libraries[] = {"name1","name2",...}
boolean success = false;
for(String library : libraries) {
try{
System.load(library);
success = true;
break;
}
catch(UnsatisfiedLinkError) {}
}
if(!success) {
//Handle the failed all case
}
Secondly- why do you think you need to do this to begin with? Why aren't you using the build in OpenGL functionality and Java classes? If you aren't, your app is likely to break badly between devices. Edit: Ok, I now noticed OpenCL and did some digging. Android does not support OpenCL. Some devices do, but there's no general libraries for it. I'd reconsider going this route, if you do follow it you will only ever work on a subset of devices, and you're going to have to add hacks for each new generation.

Related

How can i set rwxrwxrwx permission using Java code?

Hello at all the community ! I'm tring to change the frequency clock of the cpu but i'm a problem. To change the clock frequency i need to modify the file scaling_max_freq (/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq) but... this file has these permissions: rw-rw---- so with a file manager with root permissions i change rw-rw---- to rwxrwxrwx and all works fine (in this mode i can set the cpu frequency, with rw-rw---- permissions i can not do it). The code that i use for set the clock is this
public static boolean setClock(String filePath, String value) {
try {
fileWriter = new FileWriter(filePath);
fileWriter.write(value);
fileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
}
Now the question is: how can i set the permission for the file with code? how can i set rwxrwxrwx for the file scaling_max_freq? Thanks in advance.
You can't using Java 6.
You can using Java 7:
Files.setPosixAttributes(path, EnumSet.allOf(PosixFilePermission.class));
Now the question is why. You normally should not do it at all. Especially on a sysfs file.
You could try using Runtime but as fge stated you might not be able to set permission on your file system.

Printing values of attribute in android

This question may sound similar ,but non of the previous questions have been helpful to me.
In my app there are 2 activities,and 5 .java classes.
I need to know the value of an attribute which is there in the dependent classes (parking.java) (not in Main_Activity).
Till time i have tried putting
System.out.println ,Log.d/e/v/i ,but nothing seems to print my value.
what ever operations I tried,I did only in that particular class.(parking.java)
Also I have set debuggable =true in manifest file.
why the values are not getting printed ,am I putting them in wrong place ? ,or something else needs to be done
Please help
Here is the code
public void setLongitude(String Longitude){
try
{
ExifInterface exif = new ExifInterface(sd.toString());
_longitude=getExifTag(exif,ExifInterface.TAG_GPS_LONGITUDE);
Log.e("Tagname","_longitude");
}
catch(IOException e)
{
e.printStackTrace();
}
}
i have put Tagname as "Nihar"
still no success,
This is the change I have made ,
try
{
ExifInterface exif = new ExifInterface(sd.toString());
_longitude=getExifTag(exif,ExifInterface.TAG_GPS_LONGITUDE);
Log.v("Tagname",_longitude);
}
catch(IOException e)
{
e.printStackTrace();
}
Here is the image

android add java.lang.management API

Now I have a problem with Android non-supported libraries. In fact it does not support this API: "java.lang.management".
Eclipse shows me this error :
10-25 17:53:03.460: java.lang.NoClassDefFoundError: java.lang.management.ManagementFactory.
I wonder how I can add this API to be supported by my android application.
Any help please.
That API is not a part of Android, and is not compatible with Android.
The java.lang.management API is for managing and monitoring the Java VM. Android's Dalvik VM is not a Java VM.
It seems that with Android Version 23, situation has slightly improved. For example I found a replacement for:
GarbageCollectorMXBean gb = ....
long gctime = gb.getCollectionTime();
Thanks to #Jacob, I am now using this code. First the getRuntimeStat() method is not available in all android versions. So I am doing some reflection first:
static {
try {
Class<?> debugClass = Debug.class;
getRuntimeStat = debugClass.getDeclaredMethod(
"getRuntimeStat", String.class);
} catch (NoSuchMethodException x) {
getRuntimeStat = null;
}
}
Retrieving the GC time is then a matter of calling the method handle, with the correct property name. I am currently using this property name:
String gctimestr;
try {
gctimestr = (String) (getRuntimeStat != null ?
getRuntimeStat.invoke(null, "art.gc.gc-time") : null);
} catch (IllegalAccessException e) {
gctimestr = null;
} catch (InvocationTargetException e) {
gctimestr = null;
}
The gctimestr can then be converted to a long value, if its non-null. On the other hand if its null the statistics is not available, through this API.

Replace <Unknown Source> in Java Rhino (JSR223) with actual file name

In my code, all of the scripts are contained in .js files. Whenever one of the scripts contains an error, I get this:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "nonexistant" is not defined. (<Unknown source>#5) in <Unknown source> at line number 5
What bugs me is the <Unknown Source>. Multiple files are in one ScriptContext, and it can be hard to track down an error. It also looks horrible.
Is there a way to replace <Unknown Source> with the actual file name? None of the methods I see support passing a File object, so I'm really confused here.
Use the ScriptEngine.FILENAME constant:
scriptEngine.put(ScriptEngine.FILENAME, scriptFile.toString());
The question hasn't been specifically asked yet, but I thought I'd offer this to anyone who stumbles upon this topic in the future: this will change when Java 8 is released and we move from Rhino to Nashorn as the underlying JavaScript engine. Under Nashorn, the file name is applied to the ScriptContext, rather than to the ScriptEngine itself:
ScriptContext context = new SimpleScriptContext();
context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
try
{
engine.eval(script, context);
}
catch (ScriptException e)
{
/* e.getFileName() will return "test.js" */
}
If you attempt to apply the file name using ScriptEngine.put(), as you do under Rhino, nothing will happen and your exceptions will return "<eval>" as the file name.
I would imagine that a few people will run into this issue in the coming months, so thought I'd offer it. This does not appear to be documented anywhere. I had to dig into the Nashorn source code to figure it out.
The Java 8 (Nashorn) way of setting the filename for the script engine through the ScriptContext figured out by mattj65816, works for the Rhino engine as well. So, I'd recommend using only
context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
since this piece of code works for both common JavaScript engines. You don't event need to create you own context, but only set the attribute to the engine's default context:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
if (engine != null) {
ScriptContext ctx = engine.getContext();
ctx.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
...
}
perfect!
ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
// javax.script.filename
engine.put(ScriptEngine.FILENAME, "test1.js");
try {
engine.eval("function throwError1(){throw new Error('test, haha')}");
} catch (ScriptException e) {
}
engine.put(ScriptEngine.FILENAME, "test2.js");
try {
engine.eval("function throwError2(){throw new Error('test2, haha')}");
} catch (ScriptException e) {
}
try {
engine.eval("throwError1()");
} catch (ScriptException e) {
System.out.println(e.getMessage());
}
try {
engine.eval("throwError2()");
} catch (ScriptException e) {
System.out.println(e.getMessage());
}
output :
Error: test, haha in test1.js at line number 1
Error: test2, haha in test2.js at line number 1

FMJ Webcam capture example

I've been searching for while now and I can't find a simple example of how to capture a webcam stream with FMJ. Are there any tutorials or examples available which could help me?
I have been working with FMJ for a while and I haven't found many examples to start with either. What I would do is to explore the FmjStudio class that has the webcam functionality integrated and its pretty straight forward.
For bob:
What you want is FMJ. FMJ uses an DataSource implementation for civil to use it with JMF. I would recommend you to go to http://fmj-sf.net/ download the latest source and explore FmjStudio aswell since it uses civil to capture.
For theDude:
You are right, you can use JMF aswell but the same code you use for JMF will most likely work with FMJ (maybe with a coupla changes) and the performance will be much better, specially if you want a wide range of different webcams to work with your software.
I know this isn't what you want to hear, but I've used JMF for this task and it works very well. There are enough examples online to get a simple web cam capture app running pretty easily. I'll post more if you're interested.
The following code would get you started.
GlobalCaptureDevicePlugger.addCaptureDevices();
Vector<CaptureDeviceInfo> audioCapDevList = CaptureDeviceManager.getDeviceList(null);
if (audioCapDevList.size() != 0) {
for (int i = 0; i < audioCapDevList.size(); i++) {
audioCapDevInfo = audioCapDevList.elementAt(i);
Format[] videoFormats = audioCapDevInfo.getFormats();
System.out.println(audioCapDevInfo);
if (audioCapDevInfo.getName().startsWith("vfw:")) { // assume the name of the webcam starts with vfw:
for (int j = 0; j < videoFormats.length; j++) {
if (videoFormats[j] instanceof VideoFormat) {
currentFormat = (VideoFormat) videoFormats[i];
break;
}
}
System.out.println(currentFormat);
if (currentFormat == null) {
System.err.println("Search for VideoFormat failed");
System.exit(-1);
}
audioCapDevLoc = audioCapDevInfo.getLocator();
}
}
}
Please make sure the native libraries (civil.dll and jdshow.dll) are loaded into the JVM. Otherwise, you would get an java.lang.UnsatisfiedLinkError. The following code may do the job for you.
System.setProperty("java.library.path", "D:/fmj-sf/native/win32-x86/");
Field fieldSysPath;
try {
fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}

Categories