接上篇博文:基于Platinum库的DMR实现(android)

文章讲述了如何使用Platinum库实现DMR

今天同样使用该库,来讲解一下DMS的实现

关于该库如何编译,请参考这篇博文:NDK下 将Platinum SDK 编译成so库 (android - upnp)

下面给出运行效果图:

界面很简单,就是一些开关和设备名以及设备运行状态的展现

下面看看代码片段:

JNI接口文件:

public class DMSJniInterface {

    static {
System.loadLibrary("git-platinum");
} public static native int startServer(byte[] rootDir,byte[] name ,byte[] uid);
public static native int stopServer(); public static native boolean enableLogPrint(boolean flag); //////////////////////////////////////////////////////////////////////////////////////////
public static int startServer(String rootDir, String name ,String uid){
if (rootDir == null){
rootDir = "";
}
if (name == null){
name = "";
}
if (uid == null){
uid = "";
}
int ret = -1;
try {
ret = startServer(rootDir.getBytes("utf-8"), name.getBytes("utf-8"), uid.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return ret;
} }

后台服务:

public class DMSService extends Service implements IBaseEngine{

	private static final CommonLog log = LogFactory.createLog();

	public static final String START_SERVER_ENGINE = "com.geniusgithub.start.dmsengine";
public static final String RESTART_SERVER_ENGINE = "com.geniusgithub.restart.dmsengine"; private DMSWorkThread mWorkThread; private Handler mHandler;
private static final int START_ENGINE_MSG_ID = 0x0001;
private static final int RESTART_ENGINE_MSG_ID = 0x0002; private static final int DELAY_TIME = 1000; private MediaStoreCenter mMediaStoreCenter; @Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public void onCreate() {
super.onCreate();
initService();
log.e("MediaServerService onCreate");
} @Override
public void onDestroy() {
unInitService();
log.e("MediaServerService onDestroy");
super.onDestroy(); } @Override
public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null){
String actionString = intent.getAction();
if (actionString != null){
if (actionString.equalsIgnoreCase(START_SERVER_ENGINE)){
delayToSendStartMsg();
}else if (actionString.equalsIgnoreCase(RESTART_SERVER_ENGINE)){
delayToSendRestartMsg();
}
}
} return super.onStartCommand(intent, flags, startId); } private void initService(){ mWorkThread = new DMSWorkThread(this); mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case START_ENGINE_MSG_ID:
startEngine();
break;
case RESTART_ENGINE_MSG_ID:
restartEngine();
break;
}
} }; mMediaStoreCenter = MediaStoreCenter.getInstance();
mMediaStoreCenter.clearWebFolder();
mMediaStoreCenter.createWebFolder();
mMediaStoreCenter.doScanMedia();
} private void unInitService(){
stopEngine();
removeStartMsg();
removeRestartMsg();
mMediaStoreCenter.clearAllData();
} private void delayToSendStartMsg(){
removeStartMsg();
mHandler.sendEmptyMessageDelayed(START_ENGINE_MSG_ID, DELAY_TIME);
} private void delayToSendRestartMsg(){
removeStartMsg();
removeRestartMsg();
mHandler.sendEmptyMessageDelayed(RESTART_ENGINE_MSG_ID, DELAY_TIME);
} private void removeStartMsg(){
mHandler.removeMessages(START_ENGINE_MSG_ID);
} private void removeRestartMsg(){
mHandler.removeMessages(RESTART_ENGINE_MSG_ID);
} @Override
public boolean startEngine() {
awakeWorkThread();
return true;
} @Override
public boolean stopEngine() {
mWorkThread.setParam("", "", "");
exitWorkThread();
return true;
} @Override
public boolean restartEngine() {
String friendName = DlnaUtils.getDevName(this);
String uuid = DlnaUtils.creat12BitUUID(this);
mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid);
if (mWorkThread.isAlive()){
mWorkThread.restartEngine();
}else{
mWorkThread.start();
}
return true;
} private void awakeWorkThread(){
String friendName = DlnaUtils.getDevName(this);
String uuid = DlnaUtils.creat12BitUUID(this);
mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid); if (mWorkThread.isAlive()){
mWorkThread.awakeThread();
}else{
mWorkThread.start();
}
} private void exitWorkThread(){
if (mWorkThread != null && mWorkThread.isAlive()){
mWorkThread.exit();
long time1 = System.currentTimeMillis();
while(mWorkThread.isAlive()){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long time2 = System.currentTimeMillis();
log.e("exitWorkThread cost time:" + (time2 - time1));
mWorkThread = null;
}
} }

工作线程:

public class DMSWorkThread extends Thread implements IBaseEngine{

	private static final CommonLog log = LogFactory.createLog();

	private static final int CHECK_INTERVAL = 30 * 1000; 

	private Context mContext = null;
private boolean mStartSuccess = false;
private boolean mExitFlag = false; private String mRootdir = "";
private String mFriendName = "";
private String mUUID = "";
private ServerApplication mApplication; public DMSWorkThread(Context context){
mContext = context;
mApplication = ServerApplication.getInstance();
} public void setFlag(boolean flag){
mStartSuccess = flag;
} public void setParam(String rootDir, String friendName, String uuid){
mRootdir = rootDir;
mFriendName = friendName;
mUUID = uuid;
mApplication.updateDevInfo(mRootdir, mFriendName, mUUID);
} public void awakeThread(){
synchronized (this) {
notifyAll();
}
} public void exit(){
mExitFlag = true;
awakeThread();
} @Override
public void run() { log.e("DMSWorkThread run..."); while(true)
{
if (mExitFlag){
stopEngine();
break;
}
refreshNotify();
synchronized(this)
{
try
{
wait(CHECK_INTERVAL);
}
catch(Exception e)
{
e.printStackTrace();
}
}
if (mExitFlag){
stopEngine();
break;
}
} log.e("DMSWorkThread over..."); } public void refreshNotify(){
if (!CommonUtil.checkNetworkState(mContext)){
return ;
} if (!mStartSuccess){
stopEngine();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean ret = startEngine();
if (ret){
mStartSuccess = true;
}
} } @Override
public boolean startEngine() {
if (mFriendName.length() == 0){
return false;
} int ret = DMSJniInterface.startServer(mRootdir, mFriendName, mUUID); boolean result = (ret == 0 ? true : false);
mApplication.setDevStatus(result);
return result;
} @Override
public boolean stopEngine() {
DMSJniInterface.stopServer();
mApplication.setDevStatus(false);
return true;
} @Override
public boolean restartEngine() {
setFlag(false);
awakeThread();
return true;
} }

多媒体遍历:

public class MediaScannerCenter {

	private static final CommonLog log = LogFactory.createLog();

	public static final int AUDIO_TYPE = 0;
public static final int VIDEO_TYPE = 1;
public static final int IMAGE_TYPE = 2; String AUDIO_PATH = MediaStore.Audio.AudioColumns.DATA;
String AUDIO_DISPLAYHNAME = MediaStore.Audio.AudioColumns.DISPLAY_NAME;
String AUDIO_COLUMN_STRS[] = {AUDIO_PATH, AUDIO_DISPLAYHNAME}; String VIDEO_PATH = MediaStore.Video.VideoColumns.DATA;
String VIDEO_DISPLAYHNAME = MediaStore.Video.VideoColumns.DISPLAY_NAME;
String VIDEO_COLUMN_STRS[] = {VIDEO_PATH, VIDEO_DISPLAYHNAME}; String IMAGE_PATH = MediaStore.Images.ImageColumns.DATA;
String IMAGE_DISPLAYHNAME = MediaStore.Images.ImageColumns.DISPLAY_NAME;
String IMAGE_COLUMN_STRS[] = {IMAGE_PATH, IMAGE_DISPLAYHNAME}; private static MediaScannerCenter mInstance;
private Context mContext; private ScanMediaThread mediaThread; private MediaScannerCenter(Context context) {
mContext = context; initData();
} public static synchronized MediaScannerCenter getInstance() {
if (mInstance == null){
mInstance = new MediaScannerCenter(ServerApplication.getInstance());
}
return mInstance;
} private void initData(){ } public synchronized boolean startScanThread(IMediaScanListener listener){
if (mediaThread == null || !mediaThread.isAlive()){
mediaThread = new ScanMediaThread(listener);
mediaThread.start();
} return true;
} public synchronized void stopScanThread(){
if (mediaThread != null){
if (mediaThread.isAlive()){
mediaThread.exit();
}
mediaThread = null;
}
} public synchronized boolean isThreadOver(){
if (mediaThread != null && mediaThread.isAlive()){
return false;
} return true;
} private boolean scanMusic(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { Cursor cursor = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
AUDIO_COLUMN_STRS,
null,
null,
AUDIO_DISPLAYHNAME); if (cursor != null)
{
int count = cursor.getCount();
if (count != 0)
{
int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
if (cursor.moveToFirst()) {
do {
if (cancelObser.ifCancel()){
return false;
}
String srcpath = cursor.getString(_dir_index);
String name = cursor.getString(_name_index);
listener.mediaScan(AUDIO_TYPE, srcpath, name); } while (cursor.moveToNext());
}
}
cursor.close();
return true;
} return false;
} private boolean scanVideo(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { Cursor cursor = mContext.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
VIDEO_COLUMN_STRS,
null,
null,
VIDEO_DISPLAYHNAME); if (cursor != null)
{
int count = cursor.getCount();
if (count != 0)
{
int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
if (cursor.moveToFirst()) {
do {
if (cancelObser.ifCancel()){
return false;
}
String srcpath = cursor.getString(_dir_index);
String name = cursor.getString(_name_index);
listener.mediaScan(VIDEO_TYPE, srcpath, name);
} while (cursor.moveToNext());
}
}
cursor.close();
return true;
} return false;
} private boolean scanImage(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { Cursor cursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_COLUMN_STRS,
null,
null,
IMAGE_DISPLAYHNAME); if (cursor != null)
{
int count = cursor.getCount();
if (count != 0)
{
int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
do {
if (cancelObser.ifCancel()){
return false;
}
String srcpath = cursor.getString(_dir_index);
String name = cursor.getString(_name_index);
listener.mediaScan(IMAGE_TYPE, srcpath, name); } while (cursor.moveToNext());
}
}
cursor.close();
return true;
} return false;
} public class ScanMediaThread extends Thread implements ICancelScanMedia{ IMediaScanListener mListener;
boolean exitFlag = false; public ScanMediaThread(IMediaScanListener listener){
mListener = listener;
} public void exit(){
exitFlag = true;
} @Override
public void run() { try {
scanMusic(mListener, this);
scanVideo(mListener, this);
scanImage(mListener, this);
} catch (Exception e) {
e.printStackTrace();
} super.run();
} @Override
public boolean ifCancel() {
return exitFlag;
}
} public interface ICancelScanMedia{
public boolean ifCancel();
} }

startServer和stopServer分别对应设备的开启关闭

在startServer需要传入的三个参数分别是根目录,设备名和设备ID

在本地构建好web目录后将根目录路径设置进去

然后开启一个线程来浏览本地多媒体文件并通过创建软链接来映射本地路径和web路径

详看这个类:

public class MediaStoreCenter implements IMediaScanListener{

	private static final CommonLog log = LogFactory.createLog();

	private static  MediaStoreCenter mInstance;
private Context mContext; private String mShareRootPath = "";
private String mImageFolderPath = "";
private String mVideoFolderPath = "";
private String mAudioFolderPath = ""; private MediaScannerCenter mMediaScannerCenter;
private Map<String, String> mMediaStoreMap = new HashMap<String, String>(); private MediaStoreCenter(Context context) {
mContext = context; initData();
} public static synchronized MediaStoreCenter getInstance() {
if (mInstance == null){
mInstance = new MediaStoreCenter(ServerApplication.getInstance());
}
return mInstance;
} private void initData(){
mShareRootPath = mContext.getFilesDir().getAbsolutePath()+"/" + "rootFolder";
mImageFolderPath = mShareRootPath + "/" + "Image";
mVideoFolderPath = mShareRootPath + "/" + "Video";
mAudioFolderPath = mShareRootPath + "/" + "Audio";
mMediaScannerCenter = MediaScannerCenter.getInstance();
} public String getRootDir(){
return mShareRootPath;
}
public void clearAllData(){
stopScanMedia();
clearMediaCache();
clearWebFolder();
} public boolean createWebFolder(){
boolean ret = FileHelper.createDirectory(mShareRootPath);
if (!ret){
return false;
} FileHelper.createDirectory(mImageFolderPath);
FileHelper.createDirectory(mVideoFolderPath);
FileHelper.createDirectory(mAudioFolderPath); return true;
} public boolean clearWebFolder(){ long time = System.currentTimeMillis();
boolean ret = FileHelper.deleteDirectory(mShareRootPath);
long time1 = System.currentTimeMillis();
log.e("clearWebFolder cost : " + (time1 - time));
return ret;
} public void clearMediaCache(){
mMediaStoreMap.clear();
} public void doScanMedia(){
mMediaScannerCenter.startScanThread(this);
} public void stopScanMedia(){
mMediaScannerCenter.stopScanThread();
while(!mMediaScannerCenter.isThreadOver()){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} @Override
public void mediaScan(int mediaType, String mediaPath, String mediaName) { switch (mediaType) {
case MediaScannerCenter.AUDIO_TYPE:
mapAudio(mediaPath, mediaName);
break;
case MediaScannerCenter.VIDEO_TYPE:
mapVideo(mediaPath, mediaName);
break;
case MediaScannerCenter.IMAGE_TYPE:
mapImage(mediaPath, mediaName);
break;
default:
break;
} } private void mapAudio( String mediaPath, String mediaName){
String webPath = mAudioFolderPath + "/" + mediaName;
mMediaStoreMap.put(mediaPath, webPath);
softLinkMode(mediaPath, webPath);
} private void mapVideo( String mediaPath, String mediaName){
String webPath = mVideoFolderPath + "/" + mediaName;
mMediaStoreMap.put(mediaPath, webPath);
softLinkMode(mediaPath, webPath);
} private void mapImage( String mediaPath, String mediaName){
String webPath = mImageFolderPath + "/" + mediaName;
mMediaStoreMap.put(mediaPath, webPath);
softLinkMode(mediaPath, webPath);
} private boolean softLinkMode(String localPath, String webPath){
Process p;
int status;
try {
long time = System.currentTimeMillis();
String cmd = "ln -s " + localPath + " "+ webPath;
p = Runtime.getRuntime().exec(cmd);
releaseProcessStream(p); status = p.waitFor();
if (status == 0) {
return true;//success
} else {
log.e("status = " + status + ", run ln -s failed !localPath = " + localPath);
return false;
}
}catch (Exception e) {
log.e("Catch Exceptino run ln -s failed !localPath = " + localPath);
return false;
}
} private void releaseProcessStream(Process p) throws IOException{
InputStream stderr = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null)
System.out.println(line);
}
}

这样控制点访问的时候就可以浏览到多媒体文件了

关键代码大都已经贴出来了,详情大家down code去了解吧

Github下载页:https://github.com/geniusgithub/MediaServer

当然关于android上的DMS实现网上已有一个不错的开源项目wireme

下载地址 http://code.google.com/p/wireme/

用的是cling库,下载链接https://github.com/4thline/cling

不过Platinum库在稳定性方面还是要胜过其它java库的,而且效率也高,所以推荐大家使用

DLNA开发文档链接:http://download.csdn.net/detail/geniuseoe2012/4969961

more brilliant,Please pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012

基于Platinum库的DMS实现(android)的更多相关文章

  1. 关于Platinum库的MediaRender具体C++代码实现探讨

    接上篇博文 NDK下 将Platinum SDK 编译成so库 (android - upnp) 讲述了如何利用该代码库编译给android程序调用的so库,其中也提到了,在使用sample-upnp ...

  2. 【ATX学习大纲】【ATX基于uiautomator2+Python学习】之Android自动化

    github学习地址:https://github.com/openatx/uiautomator2 <_io.TextIOWrapper name='<stderr>' mode= ...

  3. WebGIS中基于控制点库进行SHP数据坐标转换的一种查询优化策略

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.前言 目前项目中基于控制点库进行SHP数据的坐标转换,流程大致为:遍 ...

  4. 基于 libpcap库的sniffer程序

    基于 libpcap库的sniffer程序 Libpcap库是WireSharek和Tcpdump抓包程序的基础,利用libcap我们自己也可以实现自己的抓包程序,在网络上实时抓包分析,或者利用处理的 ...

  5. 基于jsmpeg库下使用ffmpeg创建视频流连接websocket中继器传输视频并播放

    这个功能的基本工作是这样的: 1.使用node运行jsmpeg库下的websocket-relay.js文件,这个文件的作用是创建一个websocket视频传输中继器 2.运行ffmpeg,将输出发送 ...

  6. STM32F1固件库文件讲解与基于固件库新建MDK工程模板

    操作系统:win10 1.文件目录 (在cmd下用"cd 文件夹" 进入到要显示的文件夹,如cd d:\en.stsw-stm32054,然后输入tree 回车就会出现上图的目录结 ...

  7. 【GMT43智能液晶模块】基于HAL库的SDRAM和LCD驱动例程(MDK工程&CubeMX工程)

    说明: 1.该工程基于HAL库实现动态存储器SDRAM驱动以及液晶控制器LCD驱动. 2.工程通过STM32CubeMX(Version 4.22.0)配置生成,可直接打开进行配置. 3.KEIL M ...

  8. VC++基于CXImage库实现缩略图

    一般的图像处理软件都对读入程序的图像文件建一个缩略图的列表,像ACDSee那样.笔者最近在做一个图像处理的项目,处理的原始数据就是图像文件.从项目一开始就想做一个缩略图,但一直苦于技术水平有限,且时间 ...

  9. 跨平台网络通信与服务器框架 acl 3.2.0 发布,acl_cpp 是基于 acl 库的 C++ 库

    acl 3.2.0 版本发布了,acl 是 one advanced C/C++ library 的简称,主要包括网络通信库以及服务器框架库等功能,支持 Linux/Windows/Solaris/F ...

随机推荐

  1. 构建混合云:配置Azure site to site VPN连接(1)

      用户在构建自己云计算解决方案的时候,往往会选择私有云或者公有云来做部署,但在一些场景下,用户更加希望通过混合云的方案来满足自己的业务需求.Azure为混合云的部署提供多种不同的连接方案,最常见的是 ...

  2. SQL Server数据库空间管理 (1)

    数据库经常遇到的问题: 1).数据库文件空间用尽  2).日志文件不停增长 3).数据库文件无法收缩  4).自动增长和自动收缩 本系列就以上面的4个问题入手分析并总结数据库空间的管理方法.   1. ...

  3. MS SQL 小总结

    1.获取当前数据库下所有的表名称: Use 你的数据库 select Name from sysobjects where xtype='U' 2.获取当前表下的列名: select name fro ...

  4. 一步一步学python(四) - 字典

    1.字典的使用 创建字典:phonebook = {'Alice': '1234' , 'Beth':'9120'} 2.dict函数 >>>items = [('name','Gu ...

  5. ui的设计原则

    部分网页设计原则 规划目录结构时应当遵循的几个原则: 1.不要将所有文件都存放在根目录下; 2.按栏目内容分别建立子目录; 3.在每个主目录下都建立独立的images目录; 4.目录的层次不要太深; ...

  6. C# 如何获取当前应用程序的父目录

    //获取当前运行路径的上级目录(父目录) System.IO.DirectoryInfo topDir = System.IO.Directory.GetParent(System.Environme ...

  7. hdu 2157 How many ways_ 矩阵快速幂

    题意:略 直接矩阵乘法就行了 #include <iostream> #include<cstdio> #include<cstring> using namesp ...

  8. A Game with Colored Balls

    题目链接 题意: 给一个长度为n的字符串,每次删除字母同样切连续的串,假设有多个,删除最左边的.最长的串.每次删除输出串的字母,每一个字母的下标(1-n) N (1 ≤ N ≤ 106),串仅仅包含r ...

  9. 通过Jetty搭建一个简单的Servlet运行环境

    最近在做一些简单的Servlet开发的时候,感觉每次调试的时候都要发布到tomcat上很麻烦,把程序共享给同事也很麻烦,需要帮他设置本地的tomcat环境. 在网上找了找其他的Servlet运行环境, ...

  10. [置顶] viewPager控制滑动速度和时间

    遇到如下问题:viewpager滑动时如果想跳过很多条直接到最后一条,中间会黑屏.黑屏是因为中间的view没有加载出来的缘故. stackOverflow上看到的解决方案,在这里记录一下, publi ...