如何通过JNI在Android中调用C文件中的主要功能? [英] How to call the main function in C file by JNI in Android?
问题描述
我开发一个应用程序,我不得不使用 LIVE555
在Android 4.4.2。
LIVE555
是C源$ C $ C为流媒体
,我必须通过<叫它code> JNI 。
我有样订做以下图片为 LIVE555
中的.so:
我想通过JNI调用C源$ C $ C
问题1
我应该使用加载的库的System.loadLibrary
像 JAVA <以下code / code >?
静态{
的System.loadLibrary(什么函数库叫我应该载入?);
}
问题2
如何调用 主
在功能上的 的Java
使用的 公共本地字符串为主;
(主要功能是 JNI /媒体服务器/ live555MediaServer.cpp
)
的C源$ C $ C live555MediaServer.cpp
是这样的:
的#include&LT; BasicUsageEnvironment.hh&GT;
#包括DynamicRTSPServer.hh
#包括version.hhINT主(INT ARGC,字符** argv的){
//通过建立我们的使用环境开始:
*的TaskScheduler调度= BasicTaskScheduler :: createNew();
UsageEnvironment * ENV = BasicUsageEnvironment :: createNew(*调度程序); UserAuthenticationDatabase * authDB = NULL;
#IFDEF ACCESS_CONTROL
//实现客户的访问控制RTSP服务器,请执行以下操作:
authDB =新UserAuthenticationDatabase;
authDB-&GT; addUserRecord(用户名1,密码1); //替换这些与真正的字符串
//重复上述每个&lt;用户名&gt;中&LT;密码和GT;你希望允许
//对服务器的访问。
#万一 //创建RTSP服务器。首先尝试使用默认端口号(554),
//然后与备用端口号(8554):
RTSPServer * rtspServer;
portNumBits rtspServerPortNum = 554;
rtspServer = DynamicRTSPServer :: createNew(* ENV,rtspServerPortNum,authDB);
如果(rtspServer == NULL){
rtspServerPortNum = 8554;
rtspServer = DynamicRTSPServer :: createNew(* ENV,rtspServerPortNum,authDB);
}
如果(rtspServer == NULL){
* ENV&LT;&LT; 无法创建RTSP服务器:&LT;&LT; env-&GT; getResultMsg()&所述;&下; \\ n;
出口(1);
} * ENV&LT;&LT; LIVE555媒体服务器\\ n;
* ENV&LT;&LT; \\ tversion&LT;&LT; MEDIA_SERVER_VERSION_STRING
&LT;&LT; (LIVE555流媒体库的版本
&LT;&LT; LIVEMEDIA_LIBRARY_VERSION_STRING&LT;&LT; )\\ n; 字符* URL preFIX = rtspServer-&GT; RTSPURL preFIX();
* ENV&LT;&LT; 使用URL \\ n \\ t从该服务器播放流
&LT;&LT;网址preFIX&LT;&LT; &LT;&名GT; \\ nwhere&LT;文件名中的一个是在当前目录中的文件present \\ n;
* ENV&LT;&LT; 每个文件的类型,从它的名字后缀推断:\\ N的;
* ENV&LT;&LT; \\ t \\264 \\=&gt;将H.264视频基本流文件\\ n。
* ENV&LT;&LT; \\ t \\AAC \\=&gt;一种AAC音频(ADTS格式)文件\\ n。
* ENV&LT;&LT; \\ t \\AC3 \\=&gt;一种AC-3音频文件\\ n。
* ENV&LT;&LT; \\ t \\AMR \\=&gt;一种AMR音频文件\\ n;
* ENV&LT;&LT; \\ t \\DV \\=&gt;将DV的视频文件\\ n。
* ENV&LT;&LT; \\ t \\M4E \\=&gt;将MPEG-4视频基本流文件\\ n。
* ENV&LT;&LT; \\ t \\MKV \\=&gt;将Matroska的音频+视频+(可选)字幕文件\\ n;
* ENV&LT;&LT; \\ t \\MP3 \\=&gt;将MPEG-1或2音频文件\\ n。
* ENV&LT;&LT; \\ t \\MPG \\=&gt;将MPEG-1或2节目流(音频+视频)文件\\ n。
* ENV&LT;&LT; \\ t \\TS \\=&gt;将MPEG传送流文件\\ n。
* ENV&LT;&LT; \\ t \\ T(A \\TSX \\索引文件 - 如果present - 提供服务器特技播放支持)\\ n;
* ENV&LT;&LT; \\ t \\VOB \\=&gt;将VOB(MPEG-2视频与AC-3音频)文件\\ n。
* ENV&LT;&LT; \\ t \\WAV \\=&gt;将WAV音频文件\\ n。
* ENV&LT;&LT; \\ t \\WEBM \\=&gt;将WebM的音频(Vorbis格式)+视频(VP8)文件\\ n。
* ENV&LT;&LT; 对于其他文档见http://www.live555.com/mediaServer/ \\ n; //另外,尝试创建RTSP环比HTTP隧道HTTP服务器。
//首先尝试用默认的HTTP端口(80),然后用替代HTTP
//端口号(8000和8080)。 如果(rtspServer-&GT; setUpTunnelingOverHTTP(80)|| rtspServer-&GT; setUpTunnelingOverHTTP(8000)|| rtspServer-&GT; setUpTunnelingOverHTTP(8080)){
* ENV&LT;&LT; (我们使用端口&LT;&LT; rtspServer-&GT; httpServerPortNum()&LT;&LT;对RTSP环比HTTP隧道,或HTTP实时流(可选索引传输流文件只)。)\\ n;
}其他{
* ENV&LT;&LT; (RTSP环比HTTP隧道不可用。)\\ n;
} env-&GT;的TaskScheduler()doEventLoop()。 //不返回 返回0; //只有prevent编译器警告
}
-------------------------------编辑------------ ------------------------
JNI / live555.cpp:33:11:错误:'ARGC在此范围未声明
JNI / live555.cpp:33:17:错误:'argv的在此范围未声明
JNI / live555.cpp:33:21:错误:'主'不是在这个范围内声明
静态{
//当你有更多的。所以文件秩序的问题。
的System.loadLibrary(LIVE555);
}
现在调用带参数的主要功能。创建一个JNI方法,该方法字符串数组,并简单地调用该方法。在JNI字符串数组转换为C字符串数组,和你做。
JNIEXPORT return_type JNICALL Java_full_package_name_classname_functionname(JNIEnv的* ENV,jobject对象,Jobject字符串数组){
//你的ARGC
INT大小= env-&GT; GetArrayLength(字符串数组);
焦炭** argv的=新的char * [尺寸]
的for(int i = 0; I&LT;大小; ++ I)
{
的jstring字符串= env-&GT; GetObjectArrayElement(stringArrays,I);
为const char *的CString = env-&GT; GetStringUTFChars(字符串,0);
的argv [i] =的strdup(CString的);
env-&GT; ReleaseStringUTFChars(字符串,myarray的);
env-&GT; DeleteLocalRef(字符串);
}
//你将需要修改的主要所以它不正确清理
主(ARGC,ARGV);
// 清理
的for(int i = 0; I&LT;大小; ++ I)
免费(的argv [I]);
删除[] argv的;
}
您应该尝试一些的Hello World应用程序获取Java&LT; ---> C ++ code在Android和其余的应该是相当明显的工作。检查Android的样本。他们有良好的JNI样品。
I am developing an application where I have to use the Live555
on Android 4.4.2 .
Live555
is a C source code for Media Streaming
, and I have to call it by JNI
.
I have build the .so for Live555
like the following picture:
I want to call the C source code by JNI
The question 1
Which libraries should I load by using System.loadLibrary
like the following code in JAVA
?
static {
System.loadLibrary("What libraries name should I load ?");
}
The question 2
How to call the main
function in java
by using public native String main;
(main function is in jni/mediaServer/live555MediaServer.cpp
)
The C source code of live555MediaServer.cpp
is like the following:
#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
}
-------------------------------EDIT------------------------------------
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
static {
// order matters when you have more ".so" files.
System.loadLibrary("live555");
}
Now to call the main function with parameters. create a JNI method that takes an array of strings, and simply call that method. In the JNI convert the array of strings to array of C strings, and you are done.
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;
}
You should try some hello world apps to get Java<--->c++ code working on android and the rest should be fairly obvious. Check the android samples. They have good JNI samples.
这篇关于如何通过JNI在Android中调用C文件中的主要功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!