如何在 Android 上注册 ACTION_VIEW Intent?为什么我的 QApplication 没有收到 QEvent::FileOpen 事件?
How to register for ACTION_VIEW Intent on Android? Why doesn't my QApplication receive QEvent::FileOpen events?
我正在尝试注册一个 QtQuick Android 应用程序来打开某个 class 文件并处理它们。
据我所知,当使用 QApplication
打开文件时,会触发 QEvent::FileOpen
。
我拥有的最有力(如果不确定)证据是 this commit found in a production system, plus a number of blog posts 和 Google 结果。
所以,我先创建一个new empty QtQuick project。
我then write an EventFilter,像这样:
#include <QtGui>
#include <QApplication>
#include <QFileOpenEvent>
class MyEventFilter : public QObject {
public:
MyEventFilter();
virtual ~MyEventFilter();
protected:
virtual bool eventFilter(QObject* object,QEvent* event);
};
#include "myeventfilter.h"
MyEventFilter::MyEventFilter() : QObject () {}
MyEventFilter::~MyEventFilter() {}
bool MyEventFilter::eventFilter(QObject* object,QEvent* e) {
qDebug() << "Received" << e->type();
if (e->type() == QEvent::FileOpen) {
QFile file(static_cast<QFileOpenEvent *>(e)->file());
qDebug() << "File to open:" << file.fileName();
// This is where I would do stuff
return true;
} else {
return QObject::eventFilter(object,e);
}
}
然后我 register it and edit my manifest accordingly,通过添加
<intent-filter android:label="Foo File" android:priority="1">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file" android:host="success"/>
<data android:host="*"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\.foo"/>
</intent-filter>
此时,我在 Android 模拟器中启动我的应用程序。
当我使用 Nexus 5 在我的 AVD 中从 ES 文件资源管理器打开 .foo
文件时,API 22,我的应用程序 确实 置于前台,但没有 FileOpen
事件 已记录。
如果我在我的过滤方法中设置了一个断点,我似乎没有命中它。
这让我很困惑。
我通过扩展 QApplication
和重载 event(QEvent *)
尝试了另一种方法,结果几乎相同(没有命中)。
我可能做错了什么?
请找到此 MWE here 的完整存储库。
我将在仔细阅读 Bogdan's tutorials 并从 #qt
在 Freenode 上获得一些宝贵帮助后回答我自己的问题。
它看起来像在 Android 中打开文件 而不是 ,实际上,结果是 QEvent::FileOpen
,这仅在具有window 经理。
相反,必须 subclass QtActivity
and override onIntent
in Java, then call an appropriate C++ method 使用 JNI:
package com.foo;
import android.content.Intent;
import org.qtproject.qt5.android.bindings.QtActivity;
class Bar
{
public static native void openUri(String uri);
// Notice the 'native' keyword
}
public class MyActivity extends QtActivity {
public void onNewIntent(Intent i) {
if (i.getAction() == Intent.ACTION_VIEW) {
Bar.openUri(i.getData().toString());
}
super.onNewIntent(i);
}
}
class URIHandler : public QObject {
public:
void openUri(QString uri) {
qDebug() << "Open URI" << uri;
}
}
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL
Java_com_foo_Bar_openUri(JNIEnv *env,
jobject obj,
jstring uri)
{
jboolean isCopy;
isCopy = false;
const char* utf = env->GetStringUTFChars(uri, &isCopy);
handler.openUri(QString(utf));
env->ReleaseStringUTFChars(uri, utf);
}
#ifdef __cplusplus
}
#endif
请注意,有 some tricky subtleties 带有 JNI 方法名称。
您可以找到此示例的更新后的工作版本 here。
我正在尝试注册一个 QtQuick Android 应用程序来打开某个 class 文件并处理它们。
据我所知,当使用 QApplication
打开文件时,会触发 QEvent::FileOpen
。
我拥有的最有力(如果不确定)证据是 this commit found in a production system, plus a number of blog posts 和 Google 结果。
所以,我先创建一个new empty QtQuick project。
我then write an EventFilter,像这样:
#include <QtGui>
#include <QApplication>
#include <QFileOpenEvent>
class MyEventFilter : public QObject {
public:
MyEventFilter();
virtual ~MyEventFilter();
protected:
virtual bool eventFilter(QObject* object,QEvent* event);
};
#include "myeventfilter.h"
MyEventFilter::MyEventFilter() : QObject () {}
MyEventFilter::~MyEventFilter() {}
bool MyEventFilter::eventFilter(QObject* object,QEvent* e) {
qDebug() << "Received" << e->type();
if (e->type() == QEvent::FileOpen) {
QFile file(static_cast<QFileOpenEvent *>(e)->file());
qDebug() << "File to open:" << file.fileName();
// This is where I would do stuff
return true;
} else {
return QObject::eventFilter(object,e);
}
}
然后我 register it and edit my manifest accordingly,通过添加
<intent-filter android:label="Foo File" android:priority="1">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="file" android:host="success"/>
<data android:host="*"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\.foo"/>
</intent-filter>
此时,我在 Android 模拟器中启动我的应用程序。
当我使用 Nexus 5 在我的 AVD 中从 ES 文件资源管理器打开 .foo
文件时,API 22,我的应用程序 确实 置于前台,但没有 FileOpen
事件 已记录。
如果我在我的过滤方法中设置了一个断点,我似乎没有命中它。
这让我很困惑。
我通过扩展 QApplication
和重载 event(QEvent *)
尝试了另一种方法,结果几乎相同(没有命中)。
我可能做错了什么?
请找到此 MWE here 的完整存储库。
我将在仔细阅读 Bogdan's tutorials 并从 #qt
在 Freenode 上获得一些宝贵帮助后回答我自己的问题。
它看起来像在 Android 中打开文件 而不是 ,实际上,结果是 QEvent::FileOpen
,这仅在具有window 经理。
相反,必须 subclass QtActivity
and override onIntent
in Java, then call an appropriate C++ method 使用 JNI:
package com.foo;
import android.content.Intent;
import org.qtproject.qt5.android.bindings.QtActivity;
class Bar
{
public static native void openUri(String uri);
// Notice the 'native' keyword
}
public class MyActivity extends QtActivity {
public void onNewIntent(Intent i) {
if (i.getAction() == Intent.ACTION_VIEW) {
Bar.openUri(i.getData().toString());
}
super.onNewIntent(i);
}
}
class URIHandler : public QObject {
public:
void openUri(QString uri) {
qDebug() << "Open URI" << uri;
}
}
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL
Java_com_foo_Bar_openUri(JNIEnv *env,
jobject obj,
jstring uri)
{
jboolean isCopy;
isCopy = false;
const char* utf = env->GetStringUTFChars(uri, &isCopy);
handler.openUri(QString(utf));
env->ReleaseStringUTFChars(uri, utf);
}
#ifdef __cplusplus
}
#endif
请注意,有 some tricky subtleties 带有 JNI 方法名称。
您可以找到此示例的更新后的工作版本 here。