目前,已经搞清楚了ndk文件的编写及调用。如果JNI是cpp文件,则与c文件有所不同,需要用extern c处理一下。其他则无不同。
现在可以调到库中的函数,线程创建也正常,但是设备启动时出现了异常。有以下怀疑:原dms程序是在命令行下运行,输入的字符及log的输出有个根据地(shell),但是如果用ui启动,则失去了这个根据地。
需要在Build.scons中做以下配置:
LibraryModule(name = 'dms',
build_source_files = {'Apps/dms':'dmsJNI.cpp'},
linked_modules = ['Platinum', 'PltMediaServer', 'PltMediaRenderer', 'PltMediaConnect'],
included_modules = ['Platinum', 'PltMediaServer', 'PltMediaRenderer', 'PltMediaConnect'],
source_root = 'Source',
shared = True,
install = True)
其中,dms是动态库的名字,生成的动态库为libdms.so。
需要生成库的文件:dmsJNI.cpp:
#include <jni.h>
#include "Neptune.h"
#include "Platinum.h"
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
NPT_SET_LOCAL_LOGGER("platinum.media.server")
PLT_UPnP upnp;
PLT_DeviceHostReference device;
pthread_t thread;
static void* start_dms(void* thread_param)
{
// setup Neptune logging
NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42");
NPT_LOG_INFO("baojinyu--------dms_lib---->start_dms.\n");
device = new PLT_FileMediaServer("/data/local",
"UPnP Media Server");
NPT_List<NPT_IpAddress> list;
PLT_UPnPMessageHelper::GetIPAddresses(list);
//NPT_String ip = list.GetFirstItem()->ToString();
device->m_ModelDescription = "Platinum Media Server";
device->m_ModelURL = "http://www.plutinosoft.com/";
device->m_ModelNumber = "1.0";
device->m_ModelName = "Platinum Media Server";
device->m_Manufacturer = "Plutinosoft";
device->m_ManufacturerURL = "http://www.plutinosoft.com/";
upnp.AddDevice(device);
upnp.Start();
//NPT_CHECK_SEVERE(upnp.Start());
while(1)
{
}
return NULL;
}
static int stop_dms()
{
NPT_LOG_INFO("baojinyu--------dms_lib---->stop_dms.\n");
//printf("baojinyu--------dms_lib---->stop_dms.\n");
upnp.Stop();
return 0;
}
//------------
extern "C" {
JNIEXPORT int JNICALL Java_com_android_dlna_dms_dmsThreadBegin(JNIEnv *env, jobject obj);
JNIEXPORT int JNICALL Java_com_android_dlna_dms_dmsThreadEnd(JNIEnv *env, jobject obj);
};
JNIEXPORT int JNICALL
Java_com_android_dlna_dms_dmsThreadBegin(JNIEnv *env, jobject obj)
{
int retval;
retval = pthread_create(&thread, NULL, start_dms, NULL);
if(retval != 0)
{
NPT_LOG_INFO("create thread fail!\n");
//printf("create thread fail!\n");
return -1; //exit会导致整个进程的所有线程都终止。
}
else
{
NPT_LOG_INFO("pthread_create success.\n");
}
return 0;
}
JNIEXPORT int JNICALL
Java_com_android_dlna_dms_dmsThreadEnd(JNIEnv *env, jobject obj)
{
stop_dms();
pthread_exit(NULL);//终止线程自己
//pthread_cancel(thread);//终止同一进程中的其他线程,未定义?
NPT_LOG_INFO("thread exit!\n");
return 0;
}
此外,dms.java定义了java类dms,供ui使用。
/**
* file: dms.java
* {@hide}
*/
package com.android.dlna;
public class dms
{
static {
System.loadLibrary("dms");
}
public static native int dmsThreadBegin();
public static native int dmsThreadEnd();
}
在ui中,同样需要包的声明:
package com.android.dlna;
函数的调用很简单:
dms.dmsThreadBegin();
dms.dmsThreadEnd();
小结一下,原来内容就这么一点。
原来混乱不清的很多问题都搞清楚了。
下一步的工作是搞清楚设备启动前后的所有奥秘。