在一个Android项目中,我有一个非常混乱的继承情况,我无法完全理解。
这是我得到的错误:

proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:4458:51: error: cannot allocate an object of abstract type 'android::MediaRecorder'
         m_MediaRecorderClient = new MediaRecorder();
                                                   ^
In file included from proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.h:101:0,
                 from proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:199:
frameworks/av/include/media/mediarecorder.h:245:7: note:   because the following virtual functions are pure within 'android::MediaRecorder':
 class MediaRecorder : public BnMediaRecorderClient,
       ^
In file included from frameworks/av/include/media/mediarecorder.h:30:0,
                 from proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.h:101,
                 from proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:199:
frameworks/av/include/media/IMediaRecorderClient.h:32:18: note:     virtual void android::IMediaRecorderClient::readAudio()
     virtual void readAudio() = 0;


这是来自mediarecorder.h的MediaRecorder类

............
.......
#include <media/IMediaRecorderClient.h>
.......
...........

class MediaRecorder : public BnMediaRecorderClient,
                      public virtual IMediaDeathNotifier
{
public:
    MediaRecorder();
    ~MediaRecorder();

    void        died();
    status_t    initCheck();
    status_t    setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
    status_t    setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
    status_t    setVideoSource(int vs);
    status_t    setAudioSource(int as);
    status_t    setOutputFormat(int of);
    status_t    setVideoEncoder(int ve);
    status_t    setAudioEncoder(int ae);
    status_t    setOutputFile(const char* path);
    status_t    setOutputFile(int fd, int64_t offset, int64_t length);
    status_t    setVideoSize(int width, int height);
    status_t    setVideoFrameRate(int frames_per_second);
    status_t    setParameters(const String8& params);
    status_t    setListener(const sp<MediaRecorderListener>& listener);
    status_t    setClientName(const String16& clientName);
    status_t    prepare();
    status_t    getMaxAmplitude(int* max);
    status_t    start();
    status_t    stop();
    status_t    reset();
    status_t    init();
    status_t    close();
    status_t    release();
    void        notify(int msg, int ext1, int ext2);
    sp<IGraphicBufferProducer>     querySurfaceMediaSourceFromMediaServer();

#ifdef MTK_AOSP_ENHANCEMENT
    status_t    setParametersExtra(const String8& params);
#endif

private:
    void                    doCleanUp();
    status_t                doReset();

    sp<IMediaRecorder>          mMediaRecorder;
    sp<MediaRecorderListener>   mListener;

    // Reference to IGraphicBufferProducer
    // for encoding GL Frames. That is useful only when the
    // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
    sp<IGraphicBufferProducer>  mSurfaceMediaSource;

    media_recorder_states       mCurrentState;
    bool                        mIsAudioSourceSet;
    bool                        mIsVideoSourceSet;
    bool                        mIsAudioEncoderSet;
    bool                        mIsVideoEncoderSet;
    bool                        mIsOutputFileSet;
    Mutex                       mLock;
    Mutex                       mNotifyLock;
};


这是IMediaRecorderClient.h

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android {

class IMediaRecorderClient: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaRecorderClient);

    virtual void notify(int msg, int ext1, int ext2) = 0;
    virtual void readAudio() = 0;
};

// ----------------------------------------------------------------------------

class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

};


这是从IMediaRecorderClient.cpp中摘录的,对我来说似乎实现了抽象方法virtual void readAudio()

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

#include <media/IMediaRecorderClient.h>

namespace android {

enum {
    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
    READ_AUDIO,
};

class BpMediaRecorderClient: public BpInterface<IMediaRecorderClient>
{
public:
    BpMediaRecorderClient(const sp<IBinder>& impl)
        : BpInterface<IMediaRecorderClient>(impl)
    {
    }

    virtual void notify(int msg, int ext1, int ext2)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
        data.writeInt32(msg);
        data.writeInt32(ext1);
        data.writeInt32(ext2);
        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
    }

    virtual void readAudio()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
        remote()->transact(READ_AUDIO, data, &reply, IBinder::FLAG_ONEWAY);
    }
};


我哪里错了?

最佳答案

编译器在AudioCmdHandler.cpp的以下语句中告诉您:

    m_MediaRecorderClient = new MediaRecorder();


试图实例化作为抽象类的类MediaRecorder。抽象类意味着它具有至少一个根本没有定义的虚函数,在您的情况下为readAudio()

怎么来的 ?

您显示的MediaRecorder的类定义不提供readAudio()。但是该类继承自BnMediaRecorderClient。这个也不提供readAudio(),并且从模板BnInterface<IMediaRecorderClient>继承。

我不知道模板类BnInterface<...>是如何定义的,但是我想它是CRTP扩展了作为参数提供的接口,因此最终MediaRecorder将间接继承自IMediaRecorderClient

而这个定义了这个纯虚函数:

virtual void readAudio() = 0;


怎么解决呢?

您必须在MediaRecorder中提供提供并实现此功能,才能实例化此类的对象。

08-17 09:46