在Android Activity的onCreate方法中调用QCoreApplication方法

5

我正在为Android开发一个基于Qt的应用程序。如果该应用程序是由打开文件引起的,则需要将该文件传递给Qt应用程序实例。我创建了一个自定义的Java活动以实现此行为:

public class MyActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);       

        Intent i = getIntent();
        String act = i.getAction();

        if (act != null) && act.compareTo(Intent.ACTION_VIEW) == 0) 
        {             
                int fd = -1;
                try
                {
                    fd = getContentResolver().openFileDescriptor(i.getData(), "r").detachFd();
                }
                catch (IOException e)
                {
                    Log.e("MyActivity::onCreate", "Exception caught: " + e.getMessage());
                }

                boolean ok = openFd(fd);            
        }
    }   // onCreate

    private static native boolean openFd(int fd);
} // MyActivity

在C++方面,我有以下代码:
#include <QDebug>

#include <jni.h>

jboolean processInputFile(JNIEnv *env, jobject obj, jint fileDescriptor)
{
    int fd = (int)fileDescriptor;

    qDebug() << "processInputFile called: " << fd;

    QFile f;
    if (f.open(fd, QIODevice::ReadOnly, QFileDevice::AutoCloseHandle))
    {
        QFileInfo fi(f);
        qDebug() << "Successfully opened the file " << f.fileName() << fi.absoluteFilePath() << fi.canonicalFilePath() << fi.fileName();
        return true;
    }
    else
    {
        qDebug() << "Failed to open the file: " << f.errorString();
        return false;
    }
}   // processInputFile

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
{
    qDebug() << "JNI_OnLoad got called";

    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    jclass javaClass = env->FindClass("com/mycompany/mypackage/MyActivity");
    if(!javaClass)
    {
        return JNI_ERR;
    }

    // Register methods with env->RegisterNatives

    static JNINativeMethod methodsArray[] =
    {
        {"openFd", "(I)Z", (void*)processInputFile}        
    };

    if(env->RegisterNatives(javaClass, methodsArray, sizeof(methodsArray) / sizeof(methodsArray[0])) < 0)
    {
        return JNI_ERR;
    }

    return JNI_VERSION_1_6;
}

int main(int argc, char *argv[])
{
    qDebug() << "Calling main()";

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    qDebug() << "main arguments:";
    for (int i = 0; i < argc; ++i)
        qDebug() << argv[i];

    // ...
}

在调用main()函数之前,C++方法(processInputFile)被调用,因此应用程序对象尚未创建。我无法处理传递的数据,因为在那个时候处理类还不存在。因此,我的问题是如何从android.app.Activity::onCreate方法调用Qt应用程序实例的方法?

另外一个问题:是否可以获取打开的文件名?有时意图的URI看起来像“content://downloads/my_downloads/47”,但我找到的转换方法都不起作用。QFile和QFileInfo也不返回fd的名称。了解名称将很有用,例如,描述正在处理的项目,而47并没有真正意义。

1个回答

1
我认为我找到了解决这个问题的方法。它是一种变通方法,但应该可以正常工作。
在 onCreate 函数中存储 filePath,并从 Qt 主循环中调用它:
public class MyActivity extends org.qtproject.qt5.android.bindings.QtActivity

{ String filePath;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);       

    Intent i = getIntent();
    String act = i.getAction();
    filePath = "";

    if (act != null) && act.compareTo(Intent.ACTION_VIEW) == 0) 
    {             
            filePath = i.getData();
    }
}   // onCreate

    public String getFile()
    {
        return filePath;
    }

} // MyActivity

然后在C++的main()函数中调用。
QAndroidJniObject javaFilePath =  QtAndroid::androidActivity().callObjectMethod("getFile", "()Ljava/lang/String;");
QString filePath = javaFilePath.toString();
if (filePath != "") {
    // do something
}

我刚试过了,似乎可以工作。也许需要更多的工作来处理所有情况,但作为一个基本想法,它似乎能够完成任务。
另一个可能性是使用挂起意图,如此处所述。它还包含将文件URI转换为实际路径的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接