Windows Mobile Native Code - jstring to LPCTSTR - java

I have a Java app which needs to interact with the camera on a Windows Mobile device. I have written the Java Code and the Native code and it all works fine. The problem I am having now is that I want to start passing variables from Java to the Native code, e.g. the directory and file name to use for the photo.
The native code uses a SHCAMERACAPTURE object to interact with the camera and it expects the directory and filename to be specified using LPCTSTRs. The string passed in is a jstring, which I can get to a const char * by calling:
const char *strDir=(jEnv)->GetStringUTFChars(dirName, 0);
But I am not sure how I can pass this to the the SHCAMERACAPTURE object because it cannot convert const char * to LPCTSTR. I tried a cast (LPCTSTR)strDir and it compiled, but I get an error when it runs (that it can't create the file).
I am a Java developer and pretty new to C++ etc. so I am really not too sure what I need to do to get my string into the native call. Any ideas?

I think you should try GetStringChars() instead of GetStringUTFChars()
According to this page it returns the Unicode String.
WindowsCE and Windows mobile use UNICODE exclusively so LPCTSTR
is actually LPCWSTR (Long Pointer to Const WideChar String)
SHCAMERACAPTURE shcc;
ZeroMemory(&shcc, sizeof(shcc));
shcc.cbSize = sizeof(shcc);
shcc.pszInitialDir = (TCHAR*)(jEnv)->GetStringChars(dirName, 0 );
shcc.pszDefaultFileName = (TCHAR*)(jEnv)->GetStringChars(defFileName, 0 );
I assume you want to provide a path and a filename. This is adapted from this MS page

Related

Java File.renameTo() Implementation for UnixFileSystem

I was trying to figure how File.renameTo() works in Java and I reached the following method in UnixFileSystem.java (I'm on macOS).
private native boolean rename0(File f1, File f2);
I understand that (please correct if I'm wrong) native means JVM calls code/library written in another language. So, where/how can I or if it's possible see its implementation?
I'm curious to see its implementation as to confirm if I can use it for my following use case.
I need to run a Java application in two (or more) different servers which poll for files in the same directory (shared filesystem) and only one instance (server) should process a particular file. Whenever the application in any of the servers sees a file, it tries to move to some other directory and if the move is successful (determined by boolean returned by File.renameTo() method), that server start processing on those file contents (batch processing to be precise). I did a quick test with three different instances polling a single directory (generating new files at 1000 files per second) and the results were as expected. I just want to confirm if it scales.
Note that I'm not moving the actual file but a zero-byte file named something like <actual-filename>.DONE which is created after copying the file from source is complete.
AFAIK, Source of OpenJDK and Orale JDK are almost the same.
Therefore, you can find implementation of rename0 here:
#include <stdlib.h>
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
jobject from, jobject to)
{
jboolean rv = JNI_FALSE;
WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
if (rename(fromPath, toPath) == 0) {
rv = JNI_TRUE;
}
} END_PLATFORM_STRING(env, toPath);
} END_PLATFORM_STRING(env, fromPath);
return rv;
}
You can see that it's actually calling libc's rename.
Since most of the environment uses glibc, here's the document:
One useful feature of rename is that the meaning of newname changes “atomically” from any previously existing file by that name to its new meaning (i.e., the file that was called oldname). There is no instant at which newname is non-existent “in between” the old meaning and the new meaning. If there is a system crash during the operation, it is possible for both names to still exist; but newname will always be intact if it exists at all.
Maybe your code is safe as long as it does not crash, and filesystem is working fine. However It may depend on what filesystem you are using (e.g. nfs).
There's good another question in stackoverflow, so it may help.

Call .dll functions using Java

I need to write an application for a client that calls a method from a ".dll" file. The ".dll" file was previously executed manually from an ".exe" GUI but now they want to automate the process.
I never worked with .dll files so everything that I found until now is the result of a complete day of research, I also received a small documentation with this tool:
The interface is an ActiveX DLL which provides two functions (GetUnitInfo and SaveResult).
In the moment I just want to run the "GetUnitInfo" method from the Winwdows command line using RUNDLL32.exe.
This is the documentation for the "GetUnitInfo" method:
The interface for GetUnitInfo is as follows:
Public Function GetUnitInfo( _
ByVal strRequest As String, _
ByRef strUnitInfo As String,
Optional ByVal strStationName As String = "") As Long
Sample calling code can be:
Dim lRet As Long
Dim strXML as String
lRet = GetUnitInfo( _“<?xml version=""1.0"" ?><GetUnitInfo
xmlns=""urn:GetUnitInfo-schema"" SerialNumber=""BD3ZZTC8MA"" />", strXML)
So I tried to run this method with some dummy parameters because the method returns an error if the parameters are not OK. The command:
RUNDLL32.EXE FFTester.dll, GetUnitInfo test1, test2
But I receive this error:
I used "Dependency Walker" to list the functions from the dll file:
But this are all the functions, normally I would expected that also "GetUnitInfo" is listed.
Can somebody help? It is not mandatory to use RUNDLL32.
Later edit:
I want to call this DLL from a tool that is written in JAVA, I tried to use JNA but I failed so I was thinking to call the dll functions from the command line because if this works I can use a process builder to execute the command.
I fixed my problem and I will provide a solution, maybe it will help someone else.
I used com4j library to generate the interfaces for my dll. After this you need to register your DLL otherwise most problely your code will throw an "ComException", you can read more in my second question.
To register a DLL:
C:\Windows\SysWOW64>regsvr32.exe "path to your DLL" for 32 bit DLL
Or
C:\Windows\System32>regsvr32.exe "path to your DLL" for 64 bit DLL
Also depending on your DLL type, 32 or 64 bit, you need to use proper Eclipse/JDK.

How to retrieve string data from parcel in native space?

I have a Native Command which interacts with a System Service in Android Framework through binder using parcel to fetch some data and display it to the user. The data consists of integer and string variables. The data sent from SS is sent using
parcel.writeInt()
and
parcel.writeString()
respectively for integer and string data.
Now, the problem is how do I retrieve this data in native space ( not JNI though ) where my native command handling code is present in the form of a .cpp file? There is no equivalent parcel.readInt() or parcel.readString() methods in native space available to unmarshall or process the received parcel data. If I use the available methods there like parcel.readInt32() and parcel.readString16() methods, the data is incorrect ( probably ) and is not displayed on the screen.
Any insight and possible solution to this problem would be much appreciated.
Thanks & Regards,
You need can create an function in Java that gets a string from the parcel:
private String getDataFromParcel(Parcel parcel) {
return parcel.readString();
}
And call it from JNI (you said you have the parcel in the JNI context):
std::string getString(jobject object, jobject parcel) const {
bool result = false;
JNIEnv *env = JniGetEnv();
jmethod jGetDataFromParcelMethod = getJMethod(object);
jstring javaValue = (jstring) env->CallObjectMethod(object, jGetDataFromParcelMethod, parcel);
...
}

How to create a string array using JNI in Qt

I have to write some Android platform specific code in Qt and need to use JNI. I have a problem with how to create an array of some object. In this case I want to construct an array of strings from C++.
In the two code snippets below the first one creates a java string and it works as expected. In the second code snippet I want to create a java string array, but I get the debug message: "Java string array not valid" so I assume the signature and/or parameters passed to the "QAndroidJniObject javaStringArray()" function is not correct.
I have been looking at the documentation, but was not able to find or properly understand how to do this.
I assume I have to send in the size of the java string array object I want to construct as well.
Any help is appreciated!
QAndroidJniObject javaString("java/lang/String");
if (!javaString.isValid()) {
qDebug() << "Java string not valid";
return false;
}
QAndroidJniObject javaStringArray("[Ljava/lang/String;");
if (!javaStringArray.isValid()) {
qDebug() << "Java string array not valid";
return false;
}
The QAndroidJniObject constructor you are using takes a class name, so I'm afraid passing a string array signature won't work. You'll probably have to get your hands dirty and call JNI NewObjectArray(). Try something like:
QAndroidJniEnvironment env;
jobjectArray stringArray = env->NewObjectArray(5, env->FindClass("java/lang/String"), NULL);
QAndroidJniObject jniArray = QAndroidJniObject::fromLocalRef(stringArray);
// ...
This would create an array of 5 null strings, and transfer the ownership to QAndroidJniObject if you prefer, or else you'll have to take care of calling DeleteLocalRef().

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