基于Platinum库的DMS实现(android)
接上篇博文:基于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)的更多相关文章
- 关于Platinum库的MediaRender具体C++代码实现探讨
接上篇博文 NDK下 将Platinum SDK 编译成so库 (android - upnp) 讲述了如何利用该代码库编译给android程序调用的so库,其中也提到了,在使用sample-upnp ...
- 【ATX学习大纲】【ATX基于uiautomator2+Python学习】之Android自动化
github学习地址:https://github.com/openatx/uiautomator2 <_io.TextIOWrapper name='<stderr>' mode= ...
- WebGIS中基于控制点库进行SHP数据坐标转换的一种查询优化策略
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.前言 目前项目中基于控制点库进行SHP数据的坐标转换,流程大致为:遍 ...
- 基于 libpcap库的sniffer程序
基于 libpcap库的sniffer程序 Libpcap库是WireSharek和Tcpdump抓包程序的基础,利用libcap我们自己也可以实现自己的抓包程序,在网络上实时抓包分析,或者利用处理的 ...
- 基于jsmpeg库下使用ffmpeg创建视频流连接websocket中继器传输视频并播放
这个功能的基本工作是这样的: 1.使用node运行jsmpeg库下的websocket-relay.js文件,这个文件的作用是创建一个websocket视频传输中继器 2.运行ffmpeg,将输出发送 ...
- STM32F1固件库文件讲解与基于固件库新建MDK工程模板
操作系统:win10 1.文件目录 (在cmd下用"cd 文件夹" 进入到要显示的文件夹,如cd d:\en.stsw-stm32054,然后输入tree 回车就会出现上图的目录结 ...
- 【GMT43智能液晶模块】基于HAL库的SDRAM和LCD驱动例程(MDK工程&CubeMX工程)
说明: 1.该工程基于HAL库实现动态存储器SDRAM驱动以及液晶控制器LCD驱动. 2.工程通过STM32CubeMX(Version 4.22.0)配置生成,可直接打开进行配置. 3.KEIL M ...
- VC++基于CXImage库实现缩略图
一般的图像处理软件都对读入程序的图像文件建一个缩略图的列表,像ACDSee那样.笔者最近在做一个图像处理的项目,处理的原始数据就是图像文件.从项目一开始就想做一个缩略图,但一直苦于技术水平有限,且时间 ...
- 跨平台网络通信与服务器框架 acl 3.2.0 发布,acl_cpp 是基于 acl 库的 C++ 库
acl 3.2.0 版本发布了,acl 是 one advanced C/C++ library 的简称,主要包括网络通信库以及服务器框架库等功能,支持 Linux/Windows/Solaris/F ...
随机推荐
- VB.NET生成Excel,已存在提示框点否时报错
如题 Exception from HRESULT: 0x800A03EC 最终没有好的解决方案,只好屏蔽掉 Try obook.SaveAs(excelSaveName) Catch ex As S ...
- TensorFlow 深度学习笔记 TensorFlow实现与优化深度神经网络
转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地址 视频/字幕下载 全 ...
- 解析XML【C#】
1.XML元素XML元素包含一个开标记.元素中的数据.闭标记例如:<book>book name</book>其中book是元素名称 book name是元素数据元素名称区 ...
- 【Leetcode】寻找数串中连续最大整数和且最大长度的子串
寻找数串中连续最大整数和且最大长度的子串 输入示例: 1000 -100 200 -200 100 -100 10 90 输出结果: 1100 分析: 分治法解决问题非常方便,依然分为三种情况:a[1 ...
- Snippet Compiler——代码段编译工具
原文地址:http://www.cnblogs.com/conexpress/archive/2011/07/24/2115308.html 不知道大家在工作中是否遇到过下面的情况:在项目中实现了一段 ...
- Android常用代码
1.图片旋转 Bitmap bitmapOrg = BitmapFactory.decodeResource(this.getContext().getResources(), R.drawable. ...
- hdu 1150 Machine Schedule hdu 1151 Air Raid 匈牙利模版
//两道大水……哦不 两道结论题 结论:二部图的最小覆盖数=二部图的最大匹配数 有向图的最小覆盖数=节点数-二部图的最大匹配数 //hdu 1150 #include<cstdio> #i ...
- linux 用户空间获得纳秒级时间ns
一.引言 我们在测试程序的性能的时候往往需要获得ns级的精确时间去衡量一个程序的性能,下面介绍下linux中用户空间获得ns级时间的方法 二.用户空间获得ns级时间 使用clock_gettime函数 ...
- ACM计算几何题目推荐
//第一期 计算几何题的特点与做题要领: 1.大部分不会很难,少部分题目思路很巧妙 2.做计算几何题目,模板很重要,模板必须高度可靠. 3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面 ...
- leetcode_question_130 Surrounded Regions
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...