How to keep the screen on in Qt for android? - java

I found a couple of solutions how to do that in Java, but did not find how can I do it in QML or Qt. I know that first I should set the WAKE_LOCK permission in AndroidManifest.xml. What should I do to make it possible to turn on and off the screen locking from Qt in runtime?

Use window.callMethod<void> instead of window.callObjectMethod
Run on GUI thread with QtAndroid::runOnAndroidThread
Clear exceptions afterwards
To disable always on behaviour, use clearFlags
This is tested Qt 5.7 code:
void keep_screen_on(bool on) {
QtAndroid::runOnAndroidThread([on]{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window =
activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
if (on) {
window.callMethod<void>("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
} else {
window.callMethod<void>("clearFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}
QAndroidJniEnvironment env;
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
});
}

You can use the Qt Android Extras module and use JNI to call the relevant Java function from C++. Something like :
void keepScreenOn()
{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
window.callObjectMethod("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}

You can achieve this by editing the java file used by qt itself. In installation path under src in android path you will find QtActivity.java file. In the onCreate function add the below line
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WAKE_LOCK permission in AndroidManifest.xml also should be added.
Build the project, it will work fine.

Related

How do I set a Java library's custom event listener in Kotlin?

I have been working on an Android project in Kotlin and would like to use this UI library. However, it's written in Java (and so is the documentation), and I'm not sure how to implement the event listener for the buttons. This is how it's supposed to be done in Java:
final CircleMenuView menu = (CircleMenuView) findViewById(R.id.circle_menu);
menu.setEventListener(new CircleMenuView.EventListener() {
#Override
public void onMenuOpenAnimationStart(#NonNull CircleMenuView view) {
Log.d("D", "onMenuOpenAnimationStart");
}
}
Does anyone know how I could do the same in Kotlin? Thanks
You can just paste the code in Android Studio and it will suggest to you to convert it to Kotlin code
The same code in Kotlin will be like this
val menu = findViewById<CircleMenuView>(R.id.circle_menu)
menu.setEventListener(object : CircleMenuView.EventListener {
override fun onMenuOpenAnimationStart(view : CircleMenuView) {
Log.d("D", "onMenuOpenAnimationStart");
}
})
You could also try something like this
val menu = findViewById<CircleMenuView>(R.id.circle_menu)
menu.setEventListener{view->
//Listener code goes here
}

Frida Java windows

Is possible use Frida on Windows for tracing methods in Java apps?
I'm already use it for debugging APK on Android using Javascript, but I cannot do the same on Windows in a Java application.
More specific question: I need to hook some obfuscated functions and get parameters values and return value of those.
Yes.
You can hook method by address + base.
https://www.frida.re/docs/examples/windows/
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function(args) {
this.lib = Memory.readUtf8String(args[0]);
console.log("[*] dlopen called with: " + this.lib);
},
onLeave: function(retval) {
if (this.lib.endsWith(moduleName)) {
Interceptor.attach(Module.findBaseAddress(moduleName).add(nativeFuncAddr_AKA_offset), {
onEnter: function(args) {
console.log("[*] hook invoked");
}
});
}
}
});

How to get application arguments on Qt for android

I have a Qt application which has file associations defined in the AndroidManifest.xml so when I select a file in my browser I get a list of associated applications. My application is in the list, but when I select it the file path is not passed in the argv list in my main() method. How is the path passed to the application and how can I have it in Qt/C++?
After some research I came out with the following working solution:
void loadAndroidFile()
{
#ifdef Q_OS_ANDROID
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject intent = activity.callObjectMethod("getIntent", "()Landroid/content/Intent;");
if (intent.isValid()) {
QAndroidJniObject data = intent.callObjectMethod("getData", "()Landroid/net/Uri;");
if (data.isValid()) {
QAndroidJniObject path = data.callObjectMethod("getPath", "()Ljava/lang/String;");
if (path.isValid())
// Here path.toString() returns the path of the input file
QMetaObject::invokeMethod(rootComponent, "setSourcePath", Q_ARG(QVariant, QVariant("file://" + path.toString())));
}
}
}
#endif
}

Android JNI callback seems to call a random method

I'm experiencing a very strange bug, which I'm thinking might be an environment issue, but I'd like to know if anyone else here is experiencing something similar.
First of all, up until now, everything worked perfectly.
I have a project which works with a jni interface.
Here's the call from my java code:
myJniWrapper.load(CallbackActivity.this); // this code is inside a Runnable
Here's the load method:
public void load(Activity activityCalledFrom) {
if (mLoaded == false) {
loadNative(mNativeHandle, activityCalledFrom); // This is being called correctly.
}
}
private native void loadNative(long nativeHandle, Object activityCalledFrom);
Here's the c++:
JNIEXPORT void JNICALL Java_com_datalogics_dlreader_jni_RMBook_loadNative
(JNIEnv *env, jobject obj, jlong handle, jobject activityCalledFrom)
{
if (handle)
{
jmethodID meth = NULL;
// Convert the long back into a pointer
RMBookNative *theBook = (RMBookNative *) handle;
// Ensure the pointer is valid
if (theBook != NULL)
{
// Get the activity that we were called from
theBook->libraryActivityObj = env->NewGlobalRef(activityCalledFrom);
// Call loadDocument to set the URL for the dpdoc::Document
theBook->loadDocument();
}
}
}
Later on, once the loading is finished, the following code is called in the C++ code:
if (libraryActivityObj != NULL)
{
// Find the loadingFinished method on the library class
meth = jenv->GetMethodID(libraryActivityCls, "loadingFinished", "()V");
// Call the method on the activity
jenv->CallVoidMethod(libraryActivityObj, meth);
}
Then, back in the same activity, I have the following method:
public void loadingFinished()
{
Log.i(getClass().getSimpleName(), "loading finished");
doStuff();
}
The strange thing is, everything is working (at least according to the logs) - and when the c++ tries to call the loadingFinished() method, it instead invokes some random public method in the activity I'm sending - or to be precise, it will call the same random method every time, but if I add another method in the activity, a different method will be called by the tag[:C++] code. It seems to randomly choose a method to call based on the total amount of methods in the activity.
I have tried: cleaning & rebuilding, restarting eclipse, restarting my Mac, restarting the device - nothing helps.
I do not understand what is happening and was hoping if anyone had any insight.
Please let me know if you need me to post more code / general info.

How can I get the window handle (hWnd) for a Stage in JavaFX?

We're building a JavaFX application in Windows, and we want to be able to do some things to manipulate how our application appears in the Windows 7/8 taskbar. This requires modifying a Windows variable called the "Application User Model ID".
We've already managed to do exactly what we want in Swing by using JNA, and we'd like to repeat our solution in JavaFX. Unfortunately, to do this, we need to be able to retrieve the hWnd (window handle) for each window in our application. This can be done in Swing/AWT via the JNA Native.getWindowPointer() method, which works with java.awt.Window, but I can't figure out a good way to do this with a javafx.stage.Window.
Does anyone know of any way to do get hWnd for a Stage?
Here's a JavaFX2 version (uses Stage rather than Window):
private static Pointer getWindowPointer(Stage stage) {
try {
TKStage tkStage = stage.impl_getPeer();
Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow" );
getPlatformWindow.setAccessible(true);
Object platformWindow = getPlatformWindow.invoke(tkStage);
Method getNativeHandle = platformWindow.getClass().getMethod( "getNativeHandle" );
getNativeHandle.setAccessible(true);
Object nativeHandle = getNativeHandle.invoke(platformWindow);
return new Pointer((Long) nativeHandle);
} catch (Throwable e) {
System.err.println("Error getting Window Pointer");
return null;
}
}
Add a dependency on JNA:
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.3.1</version>
</dependency>
Then give your Stage a distinct title ("MyStage" in this example), and then get the Window ID like this:
WinDef.HWND hwnd = User32.INSTANCE.FindWindow(null, "MyStage");
long wid = Pointer.nativeValue(hwnd.getPointer());
This will work on Windows regardless of JavaFX version.
The following method shows how you can get a native window handle (hWnd) for a JavaFX Stage (or Window) and then store it in a JNA Pointer object:
private static Pointer getWindowPointer(javafx.stage.Window window) {
Pointer retval = null;
try {
Method getPeer = window.getClass().getMethod("impl_getPeer");
final Object tkStage = getPeer.invoke(window);
Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow");
getPlatformWindow.setAccessible(true);
final Object platformWindow = getPlatformWindow.invoke(tkStage);
Method getNativeHandle = platformWindow.getClass().getMethod("getNativeHandle");
retval = new Pointer((Long) getNativeHandle.invoke(platformWindow));
} catch (Throwable t) {
System.err.println("Error getting Window Pointer");
t.printStackTrace();
}
return retval;
}
This solution is fragile and generally undesirable, since it uses reflection to access a bunch of private methods. But it gets the job done. Hopefully Oracle will eventually give us direct access to native window handles so we don't have to do this.
Of course, this code only works when you're running on MS Windows. Also, I've only tried it out with early release builds of JavaFX 8 (but I suspect it will work fine on JavaFX 2 as well. EDIT: looks like it doesn't work in JavaFX 2.)
The following code works for me in JavaFX 11 on Windows (I only need it there). I haven't tested it in any other version.
It's quite brittle, but manageable in my case, as I bundle the Java Runtime with the application so I always know what's underneath.
If you use Java 9 modules, you also need to open up the packages to your calling module:
--add-opens javafx.graphics/javafx.stage=com.example and --add-opens javafx.graphics/com.sun.javafx.tk.quantum=com.example
package com.example;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.lang.reflect.Method;
public class FXWinUtil {
public static WinDef.HWND getNativeHandleForStage(Stage stage) {
try {
final Method getPeer = Window.class.getDeclaredMethod("getPeer", null);
getPeer.setAccessible(true);
final Object tkStage = getPeer.invoke(stage);
final Method getRawHandle = tkStage.getClass().getMethod("getRawHandle");
getRawHandle.setAccessible(true);
final Pointer pointer = new Pointer((Long) getRawHandle.invoke(tkStage));
return new WinDef.HWND(pointer);
} catch (Exception ex) {
System.err.println("Unable to determine native handle for window");
return null;
}
}
}
If you're using JNA (which is likely if you're doing hackish stuff like this), you can also profit from WinDef.HWND.
com.sun.glass.ui.Window.getWindows.get(0).getNativeWindow
//
com.sun.glass.ui.Window.getFocusedWindow.getNativeWindow
Solution for JavaFX 16, written on Kotlin (only Reflection)
fun getPointer(scene: Scene): Long {
val tkStage = SceneHelper.getPeer(scene)
val windowStage = tkStage.javaClass.getDeclaredMethod("getWindowStage")
.apply { isAccessible = true }
.invoke(tkStage)
val platformWindow = windowStage.javaClass.getDeclaredMethod("getPlatformWindow")
.apply { isAccessible = true }
.invoke(windowStage)
// Use fields 'ptr' and 'delegatePtr' instead of getNativeHandle() to avoid Platform.runLater
val ptr = Window::class.java.getDeclaredField("ptr")
.apply { isAccessible = true }[platformWindow] as Long
val delegatePtr = Window::class.java.getDeclaredField("delegatePtr")
.apply { isAccessible = true }[platformWindow] as Long
return if (delegatePtr != 0L) delegatePtr else ptr
}

Categories