如何在 Android 上注册 ACTION_VIEW Intent?为啥我的 QApplication 没有收到 QEvent::FileOpen 事件?

Posted

技术标签:

【中文标题】如何在 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?如何在 Android 上注册 ACTION_VIEW Intent?为什么我的 QApplication 没有收到 QEvent::FileOpen 事件? 【发布时间】:2015-10-01 07:20:42 【问题描述】:

我正在尝试注册一个 QtQuick android 应用程序来打开某类文件并处理它们。

据我所知,当使用QApplication 打开文件时,会触发QEvent::FileOpen

对此我拥有的最有力(如果不确定)证据是在生产系统中发现的 this 提交,以及一些 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 和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 API 22 在我的 AVD 中的 ES 文件资源管理器中打开 .foo 文件时,我的应用程序确实被带到了前台,但是 没有 FileOpen 事件被记录。

如果我在我的过滤器方法中设置了一个断点,我似乎没有命中它。

这让我很困惑。

我通过扩展QApplication 并重载event(QEvent *) 尝试了另一种方法,结果几乎相同(没有命中)。

我做错了什么?


请找到此 MWE here 的完整存储库。

【问题讨论】:

【参考方案1】:

在阅读 Bogdan's tutorials 并从 Freenode 上的 #qt 获得一些宝贵的帮助后,我将回答我自己的问题。

看起来在 Android 中打开文件确实,实际上,会导致QEvent::FileOpen,这仅在具有窗口管理器的系统上有用。

相反,必须在 Java 中使用 subclass QtActivity and override onIntent,然后在 JNI 中使用 call an appropriate C++ method:

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。

【讨论】:

很好用。但是我怎样才能读取文件的内容呢? QFile::readAll() 抛出错误设备未打开。 @LiborB。我这辈子都不记得了。我会看看我是否可以在接下来的几天里挖掘这个代码并尝试回答你。

以上是关于如何在 Android 上注册 ACTION_VIEW Intent?为啥我的 QApplication 没有收到 QEvent::FileOpen 事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 上注册 ACTION_VIEW Intent?为啥我的 QApplication 没有收到 QEvent::FileOpen 事件?

android如何实现 登陆以及注册

如何获取 android 设备“上次看到的活动”和“注册日期”

如何使用 Smack 从 android 客户端获取 openfire 在线注册用户?

Android上如何实现自动登陆功能?

Android模拟器Genymotion安装使用教程详解