2014-03-31 55 views
1

我正在開發一個應用程序,我必須在Android 4.4.2上使用Live555如何在Android中通過JNI調用C文件中的主函數?

Live555Media Streaming的C源代碼,我必須通過JNI來調用它。

我已經建立了。所以爲Live555像下面的圖片:

enter image description here

我想通過JNI調用C源代碼

The question 1

哪個庫我應該使用System.loadLibrary加載,如下面的代碼JAVA

static { 
     System.loadLibrary("What libraries name should I load ?"); 
    } 

The question 2

如何通過使用調用javamain功能public native String main;主要功能是在jni/mediaServer/live555MediaServer.cpp

live555MediaServer.cpp的C源代碼是這樣的:

#include <BasicUsageEnvironment.hh> 
#include "DynamicRTSPServer.hh" 
#include "version.hh" 

int main(int argc, char** argv) { 
    // Begin by setting up our usage environment: 
    TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 
    UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); 

    UserAuthenticationDatabase* authDB = NULL; 
#ifdef ACCESS_CONTROL 
    // To implement client access control to the RTSP server, do the following: 
    authDB = new UserAuthenticationDatabase; 
    authDB->addUserRecord("username1", "password1"); // replace these with real strings 
    // Repeat the above with each <username>, <password> that you wish to allow 
    // access to the server. 
#endif 

    // Create the RTSP server. Try first with the default port number (554), 
    // and then with the alternative port number (8554): 
    RTSPServer* rtspServer; 
    portNumBits rtspServerPortNum = 554; 
    rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB); 
    if (rtspServer == NULL) { 
    rtspServerPortNum = 8554; 
    rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB); 
    } 
    if (rtspServer == NULL) { 
    *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; 
    exit(1); 
    } 

    *env << "LIVE555 Media Server\n"; 
    *env << "\tversion " << MEDIA_SERVER_VERSION_STRING 
     << " (LIVE555 Streaming Media library version " 
     << LIVEMEDIA_LIBRARY_VERSION_STRING << ").\n"; 

    char* urlPrefix = rtspServer->rtspURLPrefix(); 
    *env << "Play streams from this server using the URL\n\t" 
     << urlPrefix << "<filename>\nwhere <filename> is a file present in the current directory.\n"; 
    *env << "Each file's type is inferred from its name suffix:\n"; 
    *env << "\t\".264\" => a H.264 Video Elementary Stream file\n"; 
    *env << "\t\".aac\" => an AAC Audio (ADTS format) file\n"; 
    *env << "\t\".ac3\" => an AC-3 Audio file\n"; 
    *env << "\t\".amr\" => an AMR Audio file\n"; 
    *env << "\t\".dv\" => a DV Video file\n"; 
    *env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n"; 
    *env << "\t\".mkv\" => a Matroska audio+video+(optional)subtitles file\n"; 
    *env << "\t\".mp3\" => a MPEG-1 or 2 Audio file\n"; 
    *env << "\t\".mpg\" => a MPEG-1 or 2 Program Stream (audio+video) file\n"; 
    *env << "\t\".ts\" => a MPEG Transport Stream file\n"; 
    *env << "\t\t(a \".tsx\" index file - if present - provides server 'trick play' support)\n"; 
    *env << "\t\".vob\" => a VOB (MPEG-2 video with AC-3 audio) file\n"; 
    *env << "\t\".wav\" => a WAV Audio file\n"; 
    *env << "\t\".webm\" => a WebM audio(Vorbis)+video(VP8) file\n"; 
    *env << "See http://www.live555.com/mediaServer/ for additional documentation.\n"; 

    // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling. 
    // Try first with the default HTTP port (80), and then with the alternative HTTP 
    // port numbers (8000 and 8080). 

    if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) { 
    *env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)\n"; 
    } else { 
    *env << "(RTSP-over-HTTP tunneling is not available.)\n"; 
    } 

    env->taskScheduler().doEventLoop(); // does not return 

    return 0; // only to prevent compiler warning 
} 

--------------------------- ----編輯------------------------------------

jni/live555.cpp:33:11: error: 'argc' was not declared in this scope 
jni/live555.cpp:33:17: error: 'argv' was not declared in this scope 
jni/live555.cpp:33:21: error: 'main' was not declared in this scope 

回答

2

問題1-您計劃直接從Java進行調用的任何庫。任何由C調用的東西都將由C鏈接器處理。

問題2你不應該直接調用main。您只能使用正確的命名約定來調用函數。您需要創建一個定義爲本地函數的Java對象。然後在C代碼中,您需要匹配的JNIEXPORT return_type JNICALL Java_full_package_name_classname_functionname(JNIEnv *,jobject,params);

然後只需調用java本地函數。

+0

**對於問題1:**但我不知道圖書館可以在哪裏打電話? **對於問題2:** Thansk,我知道我必須使用'native'。但是,如果C源代碼與我編輯的內容相似,我該怎麼做? – Martin

2
static { 
     // order matters when you have more ".so" files. 
     System.loadLibrary("live555"); 
    } 

現在用參數調用主函數。創建一個採用一串字符串的JNI方法,並簡單地調用該方法。在JNI中,將字符串數組轉換爲C字符串數組,然後完成。

JNIEXPORT return_type JNICALL Java_full_package_name_classname_functionname(JNIEnv *env, jobject object, Jobject stringArray){ 
    // your argc 
    int size = env->GetArrayLength(stringArray); 
    char **argv = new char*[size]; 
    for (int i=0; i < size; ++i) 
    { 
     jstring string = env->GetObjectArrayElement(stringArrays, i); 
     const char* cString = env->GetStringUTFChars(string, 0); 
     argv[i] = strdup(cString); 
     env->ReleaseStringUTFChars(string, myarray); 
     env->DeleteLocalRef(string); 
    } 
    // you will need to modify main so it does properly cleanup 
    main(argc, argv); 
    // clean up 
    for(int i = 0; i < size; ++i) 
     free(argv[i]); 
    delete [] argv; 
} 

你應該嘗試一些的Hello World應用程序獲取Java < ---> C++代碼在Android上工作,其餘的應該是相當明顯的。檢查android樣本。他們有很好的JNI樣本。

+0

我參考了'Hello-JNI'的示例。它通過使用'System.loadLibrary(「hello-jni」);'來加載庫,但是我找不到名稱爲hello-jni的庫...... – Martin

+2

當您執行'ndk-build'來構建生成的C++代碼時一個「.so」文件,比如「libNAME.so」,無論你傳遞給System.loadLibrary(「NAME」)是什麼「NAME」; –

+0

謝謝你,但你的意思是'stdC++。a'錯誤?我參考了以下鏈接http://blog.csdn.net/sunwutian0325/article/details/8582524。它似乎也有stdC++。a。它有什麼不對嗎? – Martin

相關問題