jni開發-GetMethodID與CallObjectMethod的坑

在java層中聲明一個方法用於創建一個audiotrack,在C層中調用這個方法並獲取audiotrack對象。

先看下面的代碼:SuPlayer.java

public AudioTrack createAudioTrack(int sampleRateInHz, int nb_channels) {
    //固定格式的音頻碼流
    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    //聲道佈局
    int channelConfig;
    if (nb_channels == 1) {
        channelConfig = android.media.AudioFormat.CHANNEL_OUT_MONO;
    } else if (nb_channels == 2) {
        channelConfig = android.media.AudioFormat.CHANNEL_OUT_STEREO;
    } else {
        channelConfig = android.media.AudioFormat.CHANNEL_OUT_STEREO;
    }

    int bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);

    AudioTrack audioTrack = new AudioTrack(
            AudioManager.STREAM_MUSIC,
            sampleRateInHz, channelConfig,
            audioFormat,
            bufferSizeInBytes, AudioTrack.MODE_STREAM);
    //播放
    //audioTrack.play();
    //寫入PCM
    //audioTrack.write(audioData, offsetInBytes, sizeInBytes);
    return audioTrack;
}

//只播放視頻
public static native int playVideo(String url, Surface surface);

//音視頻同步播放
public native void playSyncVideo(String url, Surface surface);

C層實現:

JNIEXPORT void
JNICALL Java_com_eebbk_suplayer_SuPlayer_playSyncVideo(JNIEnv *env, jobject thiz, jstring inputPath_, jobject surface) {
    int i = 1;
    //JNI begin------------------
    jclass player_class = env->GetObjectClass(jthiz);//獲取當前類的class
    //獲取methodID,調java層的createAudioTrack函數,返回值是(II)Landroid/media/AudioTrack;
    //詳細參考:http://hubeihuyanwei.blog.163.com/blog/static/28205284201282911925396/
    jmethodID create_audio_track_mid = env->GetMethodID(player_class, "createAudioTrack",
                                                        "(II)Landroid/media/AudioTrack;");
    if (create_audio_track_mid == NULL) {
        LOGE("%s", "createAudioTrack 方法沒找到!\n");
    }
    //獲取audio_track對象,傳入methodid、java層中對應方法的形參
    jobject audio_track = env->CallObjectMethod(jthiz, create_audio_track_mid, i, i);
    //調用AudioTrack.play方法
    jclass audio_track_class = env->GetObjectClass(audio_track);
    jmethodID audio_track_play_mid = env->GetMethodID(audio_track_class, "play", "()V");
    env->CallVoidMethod(audio_track, audio_track_play_mid);
    //AudioTrack.write
    jmethodID audio_track_write_mid = env->GetMethodID(audio_track_class, "write",  "([BII)I");
    LOGE("%s", "44444");
    //JNI end------------------
}

就這麼簡單的調用順序,爲什麼要寫這篇筆記呢???因爲在寫這個的時候,把SuPlayer.java中public AudioTrack createAudioTrack(int sampleRateInHz, int nb_channels)這個方法寫成了靜態方法public static AudioTrack createAudioTrack(int sampleRateInHz, int nb_channels)。導致排查的時候一直以爲env->GetMethodID()這個函數寫的有問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章