美文网首页
Android万能音频播放器08-添加播放器出错回调

Android万能音频播放器08-添加播放器出错回调

作者: 张俊峰0613 | 来源:发表于2019-01-10 11:09 被阅读0次

    如果出错,要把出错信息传给应用层,告诉开发者出错信息,然后做相应处理,出错回调:

    void onError(int code, String msg);
    

    在出错回调里面回收资源,并添加变量避免重复调用stop方法。

    回调Listener方法:

    public interface JfOnErrorListener {
        void onError(int code,String msg);
    }
    

    设置回调:

    private JfOnErrorListener jfOnErrorListener;
    
    public void setJfOnErrorListener(JfOnErrorListener jfOnErrorListener) {
        this.jfOnErrorListener = jfOnErrorListener;
    }
    
    //供C++调用
    public void onCallError(int code,String msg){
        if (jfOnErrorListener != null) {
            jfOnErrorListener.onError(code,msg);
        }
    }
    

    C++调用Java方法:

    jmid_error = env->GetMethodID(jclz,"onCallError","(ILjava/lang/String;)V");
    
    void JfCallJava::onCallError(int threadType, int code, char *msg) {
        if (threadType == MAIN_THREAD){
            jstring jmsg = jniEnv->NewStringUTF(msg);
            jniEnv->CallVoidMethod(jobj,jmid_error,code,jmsg);
            jniEnv->DeleteLocalRef(jmsg);
        } else if (threadType == CHILD_THREAD){
            JNIEnv *jniEnv;
            if (javaVM->AttachCurrentThread(&jniEnv,0) != JNI_OK){
                if (LOG_DEBUG) {
                    LOGE("GET CHILD THREAD JNIENV ERROR");
                    return;
                }
            }
            jstring jmsg = jniEnv->NewStringUTF(msg);
            jniEnv->CallVoidMethod(jobj,jmid_error,code,jmsg);
            jniEnv->DeleteLocalRef(jmsg);
            javaVM->DetachCurrentThread();
        }
    }
    

    在出错的地方调用,例如:

    void JfFFmpeg::decodeAudioThread() {
        pthread_mutex_lock(&init_mutex);
        av_register_all();
        avformat_network_init();
    
        pAFmtCtx = avformat_alloc_context();
    
        pAFmtCtx->interrupt_callback.callback = avformat_callback;
        pAFmtCtx->interrupt_callback.opaque = this;
    
        if (avformat_open_input(&pAFmtCtx,url,NULL,NULL) != 0){
            if (LOG_DEBUG){
                LOGE("open url file error url === %s",url);
                callJava->onCallError(CHILD_THREAD,401,"open url file error url");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        if (avformat_find_stream_info(pAFmtCtx,NULL) < 0){
            if (LOG_DEBUG){
                LOGE("find stream info error url === %s",url);
                callJava->onCallError(CHILD_THREAD,402,"find stream info error url");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        for (int i = 0; i < pAFmtCtx->nb_streams; i++) {
            if (pAFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                if (audio == NULL) {
                    audio = new JfAudio(playStatus,pAFmtCtx->streams[i]->codecpar->sample_rate,callJava);
                    audio->streamIndex = i;
                    audio->codecpar = pAFmtCtx->streams[i]->codecpar;
                    audio->duration = pAFmtCtx->duration / AV_TIME_BASE;//单位是秒
                    audio->time_base = pAFmtCtx->streams[i]->time_base;
                }
            }
        }
    
        AVCodec *dec = avcodec_find_decoder(audio->codecpar->codec_id);
        if (!dec){
            if (LOG_DEBUG){
                LOGE("FIND DECODER ERROR");
                callJava->onCallError(CHILD_THREAD,403,"FIND DECODER ERROR");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        audio->pACodecCtx = avcodec_alloc_context3(dec);
        if (!audio->pACodecCtx){
            if (LOG_DEBUG){
                LOGE("avcodec_alloc_context3 ERROR");
                callJava->onCallError(CHILD_THREAD,404,"avcodec_alloc_context3 ERROR");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        if (avcodec_parameters_to_context(audio->pACodecCtx,audio->codecpar)){//将解码器中信息复制到上下文当中
            if (LOG_DEBUG){
                LOGE("avcodec_parameters_to_context ERROR");
                callJava->onCallError(CHILD_THREAD,405,"avcodec_parameters_to_context ERROR");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        if (avcodec_open2(audio->pACodecCtx,dec,NULL) < 0){
            if (LOG_DEBUG){
                LOGE("avcodec_open2 ERROR");
                callJava->onCallError(CHILD_THREAD,406,"avcodec_open2 ERROR");
            }
            exit = true;
            pthread_mutex_unlock(&init_mutex);
            return;
        }
    
        if (callJava != NULL){
            if (playStatus != NULL && !playStatus->exit){
                callJava->onCallPrepared(CHILD_THREAD);
            } else {
                exit = true;
            }
        }
        pthread_mutex_unlock(&init_mutex);
    }
    

    在出错的时候要释放资源,调用stop方法,并添加变量避免重复调用stop方法。将变量nexit的初始值设为true,调用Java_com_example_myplayer_player_JfPlayer_n_1stop时,将nexit设为false,一直到资源释放完毕,再将nexit设为true,如果资源还没释放完毕,再次调用Java_com_example_myplayer_player_JfPlayer_n_1stop,此时nexit == false,则return,防止重复调用!

    bool nexit = true;
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_example_myplayer_player_JfPlayer_n_1stop(JNIEnv *env, jobject instance) {
    
        if (!nexit){
            return;
        }
        // TODO
        nexit = false;
        if (ffmpeg != NULL){
            ffmpeg->release();
            delete(ffmpeg);
            ffmpeg = NULL;
    
            if (callJava != NULL){
                delete(callJava);
                callJava = NULL;
            }
            if (playStatus != NULL){
                delete(playStatus);
                playStatus = NULL;
            }
        }
        nexit = true;
    }
    

    相关文章

      网友评论

          本文标题:Android万能音频播放器08-添加播放器出错回调

          本文链接:https://www.haomeiwen.com/subject/fxporqtx.html