I am new in working with UpNp and DLNA. I am using cling library and DLNA code from here. In this code, everything working perfectly but my need is something else. It is giving me all media folders(Videos, Audio and Images) from selected device in network. But what I want is non media files from selected device on the network i.e., .docx, .srt, .txt etc.
Here is some code portion:
upnpService.getControlPoint().execute(
new ContentBrowseActionCallback(ContentActivity.this,
service, createRootContainer(service), mContentList,
mHandler));
Root Container:
protected Container createRootContainer(Service service) {
Container rootContainer = new Container();
rootContainer.setId("0");
rootContainer.setTitle("Content Directory on "
+ service.getDevice().getDisplayString());
Log.e("createRootContainer", "service.getDevice().getDisplayString() : " + service.getDevice().getDisplayString());
return rootContainer;
}
ContentBrowseActionCallback:
public class ContentBrowseActionCallback extends Browse {
private static Logger log = Logger
.getLogger(ContentBrowseActionCallback.class.getName());
private Service service;
private Container container;
private ArrayList<ContentItem> list;
private Activity activity;
private Handler handler;
public ContentBrowseActionCallback(Activity activity, Service service,
Container container, ArrayList<ContentItem> list, Handler handler) {
super(service, container.getId(), BrowseFlag.DIRECT_CHILDREN, "*", 0,
null, new SortCriterion(true, "dc:title"));
this.activity = activity;
this.service = service;
this.container = container;
this.list = list;
this.handler = handler;
}
public void received(final ActionInvocation actionInvocation,
final DIDLContent didl) {
log.fine("Received browse action DIDL descriptor, creating tree nodes");
activity.runOnUiThread(new Runnable() {
public void run() {
try {
list.clear();
// Containers first
for (Container childContainer : didl.getContainers()) {
Log.e("Item", "childContainer : " + childContainer.getTitle());
log.fine("add child container "
+ childContainer.getTitle());
list.add(new ContentItem(childContainer, service));
}
// Now items
for (Item childItem : didl.getItems()) {
Log.e("Item", "childItem : " + childItem.getTitle());
log.fine("add child item" + childItem.getTitle());
list.add(new ContentItem(childItem, service));
}
} catch (Exception ex) {
log.fine("Creating DIDL tree nodes failed: " + ex);
actionInvocation.setFailure(new ActionException(
ErrorCode.ACTION_FAILED,
"Can't create list childs: " + ex, ex));
failure(actionInvocation, null);
handler.sendEmptyMessage(ContentActivity.CONTENT_GET_FAIL);
}
ConfigData.listPhotos.clear();
Iterator iterator = didl.getItems().iterator();
while (iterator.hasNext()) {
Item item = (Item) iterator.next();
Log.e("received", "item.getTitle() : " + item.getTitle());
ContentItem contentItem = new ContentItem(item,
ContentBrowseActionCallback.this.service);
if ((contentItem.getItem().getTitle().toString() != null)
&& (contentItem.getItem().getResources() != null)) {
List list = contentItem.getItem().getResources();
if ((list.size() != 0)
&& (((Res) list.get(0)).getProtocolInfo() != null)
&& (((Res) list.get(0)).getProtocolInfo()
.getContentFormat() != null)) {
Log.e("received", "list.get(0).getProtocolInfo() : " + ((Res) list.get(0)).getProtocolInfo());
Log.e("received", "list.get(0).getProtocolInfo().getContentFormat() : " + ((Res) list.get(0)).getProtocolInfo().getContentFormat());
Log.e("received", "list.get(0).getProtocolInfo().getContentFormat().substring() : " + ((Res) list.get(0)).getProtocolInfo().getContentFormat().substring(0,
((Res) list.get(0))
.getProtocolInfo()
.getContentFormat()
.indexOf("/")));
if (((Res) list.get(0))
.getProtocolInfo()
.getContentFormat()
.substring(
0,
((Res) list.get(0))
.getProtocolInfo()
.getContentFormat()
.indexOf("/"))
.equals("image")) {
ConfigData.listPhotos
.add(new ContentItem(
item,
ContentBrowseActionCallback.this.service));
} else if (((Res) list.get(0))
.getProtocolInfo()
.getContentFormat()
.substring(
0,
((Res) list.get(0))
.getProtocolInfo()
.getContentFormat()
.indexOf("/"))
.equals("audio")) {
ConfigData.listAudios
.add(new ContentItem(
item,
ContentBrowseActionCallback.this.service));
} else {
Log.e("received", "item : " + item.getTitle());
ConfigData.listVideos
.add(new ContentItem(
item,
ContentBrowseActionCallback.this.service));
}
}
}
}
handler.sendEmptyMessage(ContentActivity.CONTENT_GET_SUC);
}
});
}
public void updateStatus(final Status status) {
}
@Override
public void failure(ActionInvocation invocation, UpnpResponse operation,
final String defaultMsg) {
}
}
I googled a lot about this point but nothing in hand. I got few ideas about container id and how it works.
Please let me know how to achieve this scenario. I also don't have much idea about how DLNA and UPNP works. Please also help me to understand DLNA and UPNP better.
Thank You!
Ok, After diving into code from more than a week, I got basic idea how DLNA and UPNP works. How callbacks are made and how it fetches media files from device. So, now I am able to answer my own question.
HOW TO GET NON MEDIA FILES:
Whenever discovery service found your own device, it will prepare media server which will fetch all media from your device. First it creates a Node for specific type of media.e.g., Videos, Photos, Audios etc. Here is the code:
ContentNode rootNode = ContentTree.getRootNode();
// Video Container
Container videoContainer = new Container();
videoContainer.setClazz(new DIDLObject.Class("object.container"));
videoContainer.setId(ContentTree.MY_FOLDER_ID);
videoContainer.setParentID(ContentTree.ROOT_ID);
videoContainer.setTitle("My Folder Name");
videoContainer.setRestricted(true);
videoContainer.setWriteStatus(WriteStatus.NOT_WRITABLE);
videoContainer.setChildCount(0);
rootNode.getContainer().addContainer(videoContainer);
rootNode.getContainer().setChildCount(
rootNode.getContainer().getChildCount() + 1);
ContentTree.addNode(ContentTree.MY_FOLDER_ID, new ContentNode(
ContentTree.MY_FOLDER_ID, videoContainer));
This way you can add your own folder.
To fetch files you need to use Cursor to get files from your device. Something like this:
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
Uri externalUri = MediaStore.Files.getContentUri("external");
String[] filePathColumn = {MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA};
Cursor cursor = contentResolver.query(externalUri, filePathColumn,
selection, null, null);
cursor.moveToFirst();
do {
String id =
cursor.getString(cursor.getColumnIndex(filePathColumn[0]));
String path =
cursor.getString(cursor.getColumnIndex(filePathColumn[1]));
String serverPath = "http://" + mediaServer.getAddress() + "/"
+path;
} while (cursor.moveToNext());
cursor.close();
Thus, serverPath
will become your file path and you can access your file from another device. You can filter your files using file extension.
I must say this is huge project which I am using, so there are many changes I did to achieve my requirement. But, this answer justify my question.
Thank You!