How java.net package works? - java

Android developer documentation describes the java.net package to be use for networking by apps. Now Android has a Linux kernel, so eventually any HTTP request made by the package has to translate into some system call.
What I want to ask is whether this library also ships with some JNI layer code, and does it rely on libc library to interact with the kernel ?

In Oracle JVM net.dll is loaded inside AbstractPlainSocketImpl which is present in jre/bin.
/**
* Load net library into runtime.
*/
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
}
Android's Dalvik also works the same way. Take a look at the following links:
https://github.com/android/platform_system_core/tree/master/libcutils
https://github.com/android/platform_system_core/blob/master/libcutils/socket_network_client.c

Related

Can we use ".so" library compiled for Linux into android?

I am writing a wrapper class for C++ ".so". I want to use the library in Java application and Android app using JNI. So I have to create header file and cpp file which will do JNI calls.
I could use that on Linux in Java application.
The steps I followed:
Created java class and called native functions in that class
public class TestWrapper {
static {
System.load("/home/native.so");
}
public static void main(String[] args) {
new TestWrapper().TestWrapper();
}
private native void sayHello();
}
Created header file and cpp file. CCP contains following code
JNIEXPORT void JNICALL Java_TestWrapper_sayHello(JNIEnv *, jobject){
uint16_t data = 0;
void (*func_print_name)(const uint16_t*);
void* handle = dlopen("libCppTobeUsed.so.0", RTLD_LAZY);
if (handle){
*(void**)(&func_print_name) = dlsym(handle, function_name);
func_print_name(&data);
dlclose(handle);
std::cout << "data received .." << data << std::endl;
}
}
}
Compiled this cpp class and generated "native.so"
This is working fine. The "native.so" could call the fuction form "ibCppTobeUsed.so.0" when called from TestWrapper.java.
I want to use same library for android as well. So, I have to write wrapper class all over again in Android NDK? Or I can compile my "native.so" for Android platform?
If I try to use it directly, I get error
"install_failed_no_matching_abis".
No, you cannot use the same shared library. Android is not GNU. You need to compile your libraries for Android.
So, I have to write wrapper class all over again in Android NDK?
No, you can write it in a way that works for both. You need to factor our your JNI wrapper class from your main class, since Android uses Activity instead of main.
I would also strongly recommend against ever relying on dlclose on any platform. The API is not sound, and will lead to surprising behavior with modern C++. A single global thread_local with a non-trivial destructor renders the library un-unloadable, so the next dlopen will not reset library state as you might expect. If you need to implement initialization/finalization logic for your library, make explicit Initialize and Finalize functions a part of the libary and call them directly.
Without knowing your architecture's full architecture I can't be sure, but from the sample you've given here I'd recommend dropping the dlopen/dlsym from your JNI entirely and just link against libCppTobeUsed directly.

How to execute JavaScript on Android?

I have code which uses ScriptEngineManager, ScriptEngine class for executing JavaScript code using Java. But it works fine in Java SE, and doesn't work in Android - SDK show error of missing classes. Is it possible to execute JS code in Android? Thank you.
AndroidJSCore is a great one. And here is another little library I wrote for evaluating JavaScript:
https://github.com/evgenyneu/js-evaluator-for-android
jsEvaluator.evaluate("function hello(){ return 'Hello world!'; } hello();", new JsCallback() {
#Override
public void onResult(final String result) {
// get result here (optional)
}
});
It creates a WebView behind the scenes. Works on Android version 3 and newer.
You can use Webview which inherits View class. Make an XML tag and use findViewById() function to use in the activity. But to use the JavaScript, you can make a HTML file containing the JavaScript code. The example blelow might help.
Webview browser=(Webview) findViewById(R.main.browser); //if you gave the id as browser
browser.getSettings().setJavaScriptEnabled(true); //Yes you have to do it
browser.loadUrl("file:///android_asset/JsPage.html"); //If you put the HTML file in asset folder of android
Remember that the JS will run on WebView, not in native environment, thus you might experience a lag or slow FPS in emulator. However when using on an actual phone, the code may run fast, depending on how fast is your phone.
http://divineprogrammer.blogspot.com/2009/11/javascript-rhino-on-android.html will get you started. ScriptEngine is a java thing. Android doesn't have a JVM but a DalvikVM which is not identical but similar.
UPDATE 2018: AndroidJSCore has been superseded by LiquidCore, which is based on V8. Not only does it include the V8 engine, but all of Node.js is available as well.
Original answer:
AndroidJSCore is an Android Java JNI wrapper around Webkit's JavaScriptCore C library. It is inspired by the Objective-C JavaScriptCore Framework included natively in iOS 7. Being able to natively use JavaScript in an app without requiring the use of JavaScript injection on a bloated, slow, security-constrained WebView is very useful for many types of apps, such as games or platforms that support plugins. However, its use is artificially limited because the framework is only supported on iOS. Most developers want to use technologies that will scale across both major mobile operating systems. AndroidJSCore was designed to support that requirement.
For example, you can share Java objects and make async calls:
public interface IAsyncObj {
public void callMeMaybe(Integer ms, JSValue callback) throws JSException;
}
public class AsyncObj extends JSObject implements IAsyncObj {
public AsyncObj(JSContext ctx) throws JSException { super(ctx,IAsyncObj.class); }
#Override
public void callMeMaybe(Integer ms, JSValue callback) throws JSException {
new CallMeLater(ms).execute(callback.toObject());
}
private class CallMeLater extends AsyncTask<JSObject, Void, JSObject> {
public CallMeLater(Integer ms) {
this.ms = ms;
}
private final Integer ms;
#Override
protected JSObject doInBackground(JSObject... params) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
Thread.interrupted();
}
return params[0];
}
#Override
protected void onPostExecute(JSObject callback) {
JSValue args [] = { new JSValue(context,
"This is a delayed message from Java!") };
try {
callback.callAsFunction(null, args);
} catch (JSException e) {
System.out.println(e);
}
}
}
}
public void run() throws JSException {
AsyncObj async = new AsyncObj(context);
context.property("async",async);
context.evaluateScript(
"log('Please call me back in 5 seconds');\n" +
"async.callMeMaybe(5000, function(msg) {\n" +
" alert(msg);\n" +
" log('Whoomp. There it is.');\n" +
"});\n" +
"log('async.callMeMaybe() has returned, but wait for it ...');\n"
);
}
I was also looking for a way to run javascript on Android and came across j2v8 library. This is a java wrapper for Google's v8 engine.
To use it add a dependency:
compile 'com.eclipsesource.j2v8:j2v8_android:3.0.5#aar'
It has pretty simple api, but I haven't found any docs online apart from javadoc in maven repository. The articles on their blog are also useful.
Code sample from this article:
public static void main(String[] args) {
V8 runtime = V8.createV8Runtime();
int result = runtime.executeIntegerScript(""
+ "var hello = 'hello, ';\n"
+ "var world = 'world!';\n"
+ "hello.concat(world).length;\n");
System.out.println(result);
runtime.release();
}
The javax.script package is not part of the Android SDK. You can execute JavaScript in a WebView, as described here. You perhaps can use Rhino, as described here. You might also take a look at the Scripting Layer for Android project.
You can use Rhino library to execute JavaScript without WebView.
Download Rhino first, unzip it, put the js.jar file under libs folder. It is very small, so you don't need to worry your apk file will be ridiculously large because of this one external jar.
Here is some simple code to execute JavaScript code.
Object[] params = new Object[] { "javaScriptParam" };
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
Context rhino = Context.enter();
// Turn off optimization to make Rhino Android compatible
rhino.setOptimizationLevel(-1);
try {
Scriptable scope = rhino.initStandardObjects();
// Note the forth argument is 1, which means the JavaScript source has
// been compressed to only one line using something like YUI
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
// Get the functionName defined in JavaScriptCode
Object obj = scope.get(functionNameInJavaScriptCode, scope);
if (obj instanceof Function) {
Function jsFunction = (Function) obj;
// Call the function with params
Object jsResult = jsFunction.call(rhino, scope, scope, params);
// Parse the jsResult object to a String
String result = Context.toString(jsResult);
}
} finally {
Context.exit();
}
You can see more details at my post.
Given that ScriptEngineManager and ScriptEngine are part of the JDK and Android SDK is not the same thing as the JDK I would say that you can't use these classes to work with JavaScript under Android.
You can check the Android SDK's reference documentation/package index to see what classes are included (what can you work on Android out of the box) and which of them are missing.
I just found the App JavaScript for Android, which is the Rhino JavaScript engine for Java. It can use all Java-classes, so it has BIG potential. The problem is it might be slow, since it is not really optimized (heavy CPU load). There is another JavaScript engine named Nashorn, but that unfortunately doesn't works on Google's DalvikVM Java engine (does not support the optimizations of Oracle Java engine). I hope Google keeps up with that, I would just love it!
If you want to run some javascript code on chrome browser as per the question copy this code and paste it into address bar:
data:text/html, <html contenteditable> <title> Notepad </title> <script> alert('Abhasker Alert Test on Mobile'); </script> </html>

Java: load shared libraries with dependencies

I am wrapping a shared library (written in C) with Java using JNA. The shared library is written internally, but that library uses functions from another external library, which again depends another external library. So the situation is something like this:
ext1 <- ext2 <- internal
I.e. the internal uses external library ext2 which again uses external library ext1. What I have tried is:
System.loadLibrary("ext1");
System.loadLibrary("ext2");
NativeLIbrary.loadLibrary("internal",xxx.class);
This approach fails with "UnresolvedException" when loading the library "ext2"; the linker complains about symbols which are indeed present in the library "ext1". So it semmes that the System.loadLibrary() function does not make the symbols from "ext1" globally available? When using the stdlib function dlopen() as:
handle = dlopen( lib_name , RTLD_GLOBAL );
All the symbols found in #lib_name will be available for symbol resolution in subsequent loads; I guess what I would like was something similar for the java variety System.loadLibrary()?
Regards - Joakim Hove
It's an old question, but I've found an acceptable solution, which should also be portable, and I thought I should post an answer. The solution is to use JNA's NativeLibrary#getInstance(), because on Linux this will pass RTLD_GLOBAL to dlopen() (and on Windows this is not needed).
Now, if you are using this library to implement a Java native method, you will also need to call System.load() (or Sysem.loadLibrary()) on the same library, after calling NativeLibrary#getInstance().
First, a link to a JNA bug: JNA-61
A comment in there says that basically one should load dependencies before the actual library to use from within JNA, not the standard Java way. I'll just copy-paste my code, it's a typical scenario:
String libPath =
"/path/to/my/lib:" + // My library file
"/usr/local/lib:" + // Libraries lept and tesseract
System.getProperty("java.library.path");
System.setProperty("jna.library.path", libPath);
NativeLibrary.getInstance("lept");
NativeLibrary.getInstance("tesseract");
OcrTesseractInterf ocrInstance = (OcrTesseractInterf)
Native.loadLibrary(OcrTesseractInterf.JNA_LIBRARY_NAME, OcrTesseractInterf.class);
I've written a small library to provide OCR capability to my Java app using Tesseract. Tesseract dependes on Leptonica, so to use my library, I need to load libraries lept and tesseract first. Loading the libraries with the standard means (System.load() and System.loadLibrary()) doesn't do the trick, neither does setting properties jna.library.path or java.library.path. Obviously, JNA likes to load libraries its own way.
This works for me in Linux, I guess if one sets the proper library path, this should work in other OSs as well.
There is yet another solution for that. You can dlopen directly inside JNI code, like this:
void loadLibrary() {
if(handle == NULL) {
handle = dlopen("libname.so", RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
}
}
...
...
loadLibrary();
This way, you will open library with RTLD_GLOBAL.
You can find detailed description here: http://www.owsiak.org/?p=3640
OK;
I have found an acceptable solution in the end, but not without significant amount of hoops. What I do is
Use the normal JNA mechanism to map the dlopen() function from the dynamic linking library (libdl.so).
Use the dlopen() function mapped in with JNA to load external libraries "ext1" and "ext2" with the option RTLD_GLOBAL set.
It actually seems to work :-)
As described at http://www.owsiak.org/?p=3640, an easy but crude solution on Linux is to use LD_PRELOAD.
If that's not acceptable, then I'd recommend the answer by Oo.oO: dlopen the library with RTLD_GLOBAL within JNI code.
Try this, add this function to your code. Call it before you load your dlls. For the parameter, use the location of your dlls.
public boolean addDllLocationToPath(String dllLocation)
{
try
{
System.setProperty("java.library.path", System.getProperty("java.library.path") + ";" + dllLocation);
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
}
catch (Exception e)
{
System.err.println("Could not modify path");
return false;
}
return true;
}
}
In order to fix your issue you can use this package: https://github.com/victor-paltz/global-load-library. It loads the libraries directly with the RTLD_GLOBAL flag.
Here is an example:
import com.globalload.LibraryLoaderJNI;
public class HelloWorldJNI {
static {
// Loaded with RTLD_GLOBAL flag
try {
LibraryLoaderJNI.loadLibrary("/path/to/my_native_lib_A");
} catch (UnsatisfiedLinkError e) {
System.Println("Couldn't load my_native_lib_A");
System.Println(e.getMessage());
e.printStackTrace();
}
// Not loaded with RTLD_GLOBAL flag
try {
System.load("/path/to/my_native_lib_B");
} catch (UnsatisfiedLinkError e) {
System.Println("Couldn't load my_native_lib_B");
System.Println(e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
new HelloWorldJNI().sayHello();
}
private native void sayHello();
}
It is using the same dlopen() trick as the previous answers, but it is packaged in a standalone code.

Possible to only load specific lines of code according to Android OS version?

Is there a simple line of code that would allow only loading the code if the OS version meets the requirements?
Lets say I have my target OS as 2.2 but the min sdk is 3 for android 1.5 so even if i have some code in my project that isn't compatable with 1.5 it will still compile since the target OS is 2.2. Anyway, I want to ad a feature that requires code that's not in the 1.5 SDK and will cause a crash if it's loaded on a 1.5 phone. Is there a simple thing like this that I can do? So i dont have to make the entire app not available to 1.5 users?
if (Android OS == >2.1){
//Insert code here that requires 2.1 and up}
else{
//insert code that would appear is OS is <2.1}
Yes, you can do that. In fact there is more than one way. (Note: the only Android specific part of this answer is the way that you find out the platform version.)
Suppose that class X has method void y() in version 2.0 onwards, but not before.
One way to invoke this method with out introducing any compile time dependencies whatsoever is to use reflection to locate the Method and call invoke on it. For example:
X x = ...
if (BUILD.VERSION.RELEASE.compareTo("2.0") >= 0) {
// (exception handling omitted ...)
Method m = c.getClass().getDeclaredMethod("y");
m.invoke(x);
}
Another way is to create a version compatibility adapter API for your application like this:
/** Version compatibility adapter API */
interface Compat {
void doY();
}
/** Adapter class for version 1 */
class CompatV1 {
public void y(X x) {
// do nothing
}
}
/** Adapter class for version 2 */
class CompatV2 {
public void y(X x) {
x.y();
}
}
//
// Code to instantiate the relevant adapter for the current platform.
//
Class<?> compatClass;
// (Exception handling omitted)
if (BUILD.VERSION.RELEASE.compareTo("2.0") < 0) {
compatClass = Class.forName("...CompatV1");
} else {
compatClass = Class.forName("...CompatV2");
}
// (Exception handling omitted)
Compat compat = (Compat) compatClass.newInstance();
// The adapter object can be passed around as a parameter, wrapped
// as a singleton or injected using dependency injection.
// Invoke X.y() as follows:
X x = ...
compat.y(x);
The second version looks a bit heavyweight, but it has the advantages that the dynamic (slow, non-type-safe) code is executed just once, and that the version specific code is isolated from the rest of the code. In real life, you would probably put a number of methods into the adapter interface.
This approach requires a bit more thought, to work out how to design the compatibility API so that it cleanly isolates the version dependencies from the rest of the code. You might also to have to revise the adapter API, and create new adapter classes for each new (incompatible) major release.
Finally, if the platform API changes that you need to adapt to entail using classes or methods in the older version that are removed in the newer version, then you will need to compile your various adapter classes (e.g. the CompatV* classes) using different Android SDKs. This will make your build processes rather more complicated.
For other "takes" on this problem, read the following articles on the Android Blog:
Backward compatibility for Android applications
How to have your (Cup-)cake and eat it too.
Here is another example w/o reflection
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html
See Backward compatibility for Android (using Reflection).
You can check with Build.VERSION.RELEASE, it gives you the current version of your android system (1.5,1.6,2.1,2.2)
There is more on Build.VERSION

Pinning a Java application to the Windows 7 taskbar

I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.

Categories