我正在为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并没有真正意义。