m_imagePath = "";
//constuct Intent for IMAGE_CAPTURE
QAndroidJniObject action;
if(isImage)
action = QAndroidJniObject::fromString(
"android.media.action.IMAGE_CAPTURE");
else
action = QAndroidJniObject::fromString(
"android.media.action.VIDEO_CAPTURE");
QAndroidJniObject intent("android/content/Intent",
"(Ljava/lang/String;)V",
action.object<jstring>());
在 Java 里,目录、文件都通过 java.io.File 类来表示。 File 类有一个构造函数 File(String fileName) ,可以创建一个 File 对象,代表在所指定的目录下的文件(fileName是指文件的全路径名)。 File 对象的 toString() 方法会返回它所代表的文件的路径。
代码里的 savedImageFile对象,使用 “(Ljava/lang/String;)V”作为 File 类构造函数的签名,然后用 file.object() 获得全路径名来传递给构造函数。
在我们通过 Intent 调用 IMAGE_CAPTURE 时,要指定的存储位置,是通过 android.net.Uri 类表示的,因此我又调用 Uri 的静态方法 fromFile() 创建了一个 Uri 对象,fromFile()只有一个类型为 File 的入参,返回值则是 Uri ,因此方法签名为“(Ljava/io/File;)Landroid/net/Uri;”。
//setup saved image location
QString date = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
QString filepath = saveDir + "/asop_img/";
QDir tmpDir;
if(!tmpDir.mkpath(filepath))//创建所有不存在的目录
{
qDebug() << "mkpath failed";
return ;
}
QAndroidJniObject file;
if(isImage)
file = QAndroidJniObject::fromString(filepath + date + ".jpg");
else
file = QAndroidJniObject::fromString(filepath + date + ".mp4");
QAndroidJniObject savedImageFile(
"java/io/File",
"(Ljava/lang/String;)V",
file.object<jstring>());
qDebug() << "savedImageFile - " << savedImageFile.toString();
QAndroidJniObject savedImageUri =
QAndroidJniObject::callStaticObjectMethod(
"android/net/Uri",
"fromFile",
"(Ljava/io/File;)Landroid/net/Uri;",
savedImageFile.object<jobject>());
背景:
Android Intent 类提供了一系列的 putExtra 方法,让我们能够把类型为 int 、 float 、 String 、int[] 、double 、char 、 byte 等等的数据存储在 Intent 实例中,带给被调用方。被调用方可以用 getExtra 方法获取到发起调用一方传递的数据。这就是使用 Intent 传递数据的一般用法。
要在两个组件之间传递数据,就要有个约定,因为传递的数据可能不知一个,就需要给每个数据起个名字,这就是 key ,putExtra() 方法的第一个参数类型为字符串,用于指定数据的 key ,接收 Intent 的一方可以根据这个 key 把数据取出来。
IMAGE_CAPTURE
对于 IMAGE_CAPTURE ,它接受的数据是 Uri ,对应的 key 则为 android.provider.MediaStore.EXTRA_OUTPUT ,是 MediaStore 类的静态成员变量。因为我在代码里就先调用 QAndroidJniObject::getStaticObjectField() 方法获取到 EXTRA_OUTPUT 。
上述操作,通知照片的保存路径
//tell IMAGE_CAPTURE the output location
QAndroidJniObject mediaStoreExtraOutput
= QAndroidJniObject::getStaticObjectField(
"android/provider/MediaStore",
"EXTRA_OUTPUT",
"Ljava/lang/String;");
QAndroidJniObject mediaStoreTimeLimit
= QAndroidJniObject::getStaticObjectField(
"android/provider/MediaStore",
"EXTRA_DURATION_LIMIT",
"Ljava/lang/String;");
qDebug() << "MediaStore.EXTRA_OUTPUT - " << mediaStoreExtraOutput.toString();
qDebug() << "EXTRA_DURATION_LIMIT - " << mediaStoreTimeLimit.toString();
//通知IMAGE_CAPTURE组件照片的存储路径
intent.callObjectMethod(
"putExtra",
"(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;",
mediaStoreExtraOutput.object<jstring>(),
savedImageUri.object<jobject>());
//通知IMAGE_CAPTURE摄影时长限制
if(!isImage)
intent.callObjectMethod(
"putExtra",
"(Ljava/lang/String;I)Landroid/content/Intent;",
mediaStoreTimeLimit.object<jstring>(),
180); //20220711 sh 录像时长限制从30秒改为3分钟
创建了一个 QAndroidActivityResultReceiver 对象,传递给 startActivity ,同时也指定 requestCode 为 1。
m_imagePath = savedImageFile.toString();
QtAndroid::startActivity(intent, 1, receiver);
手机执行拍照功能后,返回结果的接受函数
void ResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
{
qDebug() << "handleActivityResult, requestCode - " << receiverRequestCode
<< " resultCode - " << resultCode
<< " data - " << data.toString();
//RESULT_OK == -1
if(resultCode == -1 && receiverRequestCode == 1) //拍照
{
emit sig_result(1);
}
if (resultCode == -1 && receiverRequestCode == 2) //获取照片
{
QAndroidJniObject url = data.callObjectMethod("getDataString", "()Ljava/lang/String;");
qDebug() << url.isClassAvailable("java/lang/String");
qDebug() << "string: "<< url.toString();
//提取本地文件路径
QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;");
QAndroidJniObject dadosAndroid = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$MediaColumns", "DATA", "Ljava/lang/String;");
QAndroidJniEnvironment env;
jobjectArray projecao = (jobjectArray)env->NewObjectArray(1, env->FindClass("java/lang/String"), NULL);
jobject projacaoDadosAndroid = env->NewStringUTF(dadosAndroid.toString().toStdString().c_str());
env->SetObjectArrayElement(projecao, 0, projacaoDadosAndroid);
QAndroidJniObject contentResolver = QtAndroid::androidActivity().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", uri.object<jobject>(), projecao, NULL, NULL, NULL);
jint columnIndex = cursor.callMethod<jint>("getColumnIndex", "(Ljava/lang/String;)I", dadosAndroid.object<jstring>());
cursor.callMethod<jboolean>("moveToFirst", "()Z");
QAndroidJniObject resultado = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", columnIndex);
m_strData = resultado.toString();
emit sig_result(2);
}
}