No virtual method setOutputFile Ljava/io/File V in class Landroid/media/MediaRecorder

今天在使用MediaRecorder时进行音频录制时报错 java.lang.NoSuchMethodError: No virtual method setOutputFile(Ljava/io/File;)V in class Landroid/media/MediaRecorder; or its super classes (declaration of ‘android.media.MediaRecorder’ appears in /system/framework/framework.jar) 如下图:在这里插入图片描述

解决过程

如图错误的原因就是在使用MediaRecordersetOutputFile(file)传入一个File文件时报错,
但是仔细看了一下seOutputFIile有三个重载方法,如下图
在这里插入图片描述这就郁闷了,传入File文件对象就报错,系统api有问题吗,然后就是将参数改成图中所示,传入文件的绝对路径,String类型试试,发现没问,解决了,事后查了查原因,在SDK 26之前setOutputFile()方法中参数没有File重载方法,如下图
在这里插入图片描述即在API 版本小于26时,只有以上两个重载方法,那么如果想要使用此方法传入file文件则需加上校验:即可解决

    //设置输出文件
            if(Build.VERSION.SDK_INT < 26){
                //若api低于26,调用setOutputFile(String path)
                mediaRecorder.setOutputFile(file.getAbsolutePath());
            }else{
                //若API高于26 使用setOutputFile(File path)
                mediaRecorder.setOutputFile(file);
            }

特此记录一下。

好的,以下是一个简单的示例代码,用于C++调用安卓中mediacode方法将数据编码生成一个新的MP4文件: ```cpp #include <jni.h> #include <android/log.h> #include <android/native_window_jni.h> #include <android/native_window.h> #include <cstdlib> #include <cstdio> #include <cstring> #include <ctime> #include <unistd.h> #define LOG_TAG "H264Encoder" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) extern "C" JNIEXPORT jint JNICALL Java_com_example_h264encoder_MainActivity_encodeH264ToMP4( JNIEnv *env, jobject /* this */, jobject surface) { // 1. 初始化MediaCodec编码器 jclass mediaCodecClass = env->FindClass("android/media/MediaCodec"); jmethodID createEncoderMethodID = env->GetStaticMethodID(mediaCodecClass, "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;"); jobject mediaCodecObject = env->CallStaticObjectMethod(mediaCodecClass, createEncoderMethodID, env->NewStringUTF("video/avc")); // 2. 配置编码器 // 首先,需要创建一个编码器参数的Bundle对象,并设置一些参数 jclass bundleClass = env->FindClass("android/os/Bundle"); jmethodID createBundleMethodID = env->GetMethodID(bundleClass, "<init>", "()V"); jobject bundleObject = env->NewObject(bundleClass, createBundleMethodID); // 设置编码器参数 jmethodID putIntMethodID = env->GetMethodID(bundleClass, "putInt", "(Ljava/lang/String;I)V"); env->CallVoidMethod(bundleObject, putIntMethodID, env->NewStringUTF("color-format"), 19); env->CallVoidMethod(bundleObject, putIntMethodID, env->NewStringUTF("bitrate"), 2000000); env->CallVoidMethod(bundleObject, putIntMethodID, env->NewStringUTF("frame-rate"), 25); env->CallVoidMethod(bundleObject, putIntMethodID, env->NewStringUTF("i-frame-interval"), 5); // 然后,将参数传递给编码器 jmethodID configureMethodID = env->GetMethodID(mediaCodecClass, "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V"); jmethodID createVideoFormatMethodID = env->GetStaticMethodID(mediaFormatClass, "createVideoFormat", "(Ljava/lang/String;II)Landroid/media/MediaFormat;"); jobject mediaFormatObject = env->CallStaticObjectMethod(mediaFormatClass, createVideoFormatMethodID, env->NewStringUTF("video/avc"), 1280, 720); env->CallVoidMethod(mediaCodecObject, configureMethodID, mediaFormatObject, surface, NULL, 0); // 3. 启动编码器 jmethodID startMethodID = env->GetMethodID(mediaCodecClass, "start", "()V"); env->CallVoidMethod(mediaCodecObject, startMethodID); // 4. 编码数据 // 首先,需要从Surface中获取原始数据 ANativeWindow* window = ANativeWindow_fromSurface(env, surface); ANativeWindow_acquire(window); ANativeWindow_Buffer buffer; ANativeWindow_lock(window, &buffer, NULL); // 然后,将原始数据送到编码器中进行编码 jmethodID getInputBufferMethodID = env->GetMethodID(mediaCodecClass, "getInputBuffer", "(I)Ljava/nio/ByteBuffer;"); jmethodID queueInputBufferMethodID = env->GetMethodID(mediaCodecClass, "queueInputBuffer", "(IIIJI)V"); jobject inputBufferObject = env->CallObjectMethod(mediaCodecObject, getInputBufferMethodID, 0); jbyteArray inputByteArray = env->NewByteArray(buffer.width * buffer.height * 3 / 2); env->SetByteArrayRegion(inputByteArray, 0, buffer.width * buffer.height * 3 / 2, (jbyte*)buffer.bits); env->CallVoidMethod(inputBufferObject, putMethodID, 0, buffer.width * buffer.height * 3 / 2); env->CallVoidMethod(mediaCodecObject, queueInputBufferMethodID, 0, 0, buffer.width * buffer.height * 3 / 2, 0, 0); // 最后,需要从编码器中获取编码后的数据 jmethodID dequeueOutputBufferMethodID = env->GetMethodID(mediaCodecClass, "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I"); jmethodID getOutputBufferMethodID = env->GetMethodID(mediaCodecClass, "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;"); jmethodID releaseOutputBufferMethodID = env->GetMethodID(mediaCodecClass, "releaseOutputBuffer", "(IZ)V"); jobject outputBufferObject; jint outputBufferIndex; while ((outputBufferIndex = env->CallIntMethod(mediaCodecObject, dequeueOutputBufferMethodID, NULL, 0)) >= 0) { outputBufferObject = env->CallObjectMethod(mediaCodecObject, getOutputBufferMethodID, outputBufferIndex); env->CallVoidMethod(mediaCodecObject, releaseOutputBufferMethodID, outputBufferIndex, true); } // 5. 停止编码器 jmethodID stopMethodID = env->GetMethodID(mediaCodecClass, "stop", "()V"); env->CallVoidMethod(mediaCodecObject, stopMethodID); // 6. 释放资源 ANativeWindow_unlockAndPost(window); ANativeWindow_release(window); return 0; } ``` 请注意,此代码仅为示例,可能需要根据您的具体需求进行修改。此外,您还需要在Java代码中调用此函数,并将Surface对象作为参数传递给它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值