Android Open Source - DroidUPnP Media Server






From Project

Back to project page DroidUPnP.

License

The source code is released under:

GNU General Public License

If you think the Android project DroidUPnP listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright (C) 2013 Aurlien Chabot <aurelien@chabot.fr>
 */* w ww  . ja va  2 s  . c o m*/
 * This file is part of DroidUPNP.
 *
 * DroidUPNP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DroidUPNP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DroidUPNP.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.droidupnp.model.mediaserver;

import java.io.File;
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.droidupnp.R;
import org.droidupnp.view.SettingsActivity;
import org.fourthline.cling.binding.annotations.AnnotationLocalServiceBinder;
import org.fourthline.cling.model.DefaultServiceManager;
import org.fourthline.cling.model.ValidationError;
import org.fourthline.cling.model.ValidationException;
import org.fourthline.cling.model.meta.DeviceDetails;
import org.fourthline.cling.model.meta.DeviceIdentity;
import org.fourthline.cling.model.meta.LocalDevice;
import org.fourthline.cling.model.meta.LocalService;
import org.fourthline.cling.model.meta.ManufacturerDetails;
import org.fourthline.cling.model.meta.ModelDetails;
import org.fourthline.cling.model.types.DeviceType;
import org.fourthline.cling.model.types.UDADeviceType;
import org.fourthline.cling.model.types.UDN;

import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.util.Log;

public class MediaServer extends fi.iki.elonen.SimpleWebServer
{
  private final static String TAG = "MediaServer";

  private UDN udn = null;
  private LocalDevice localDevice = null;
  private LocalService localService = null;
  private Context ctx = null;

  private final static int port = 8192;
  private static InetAddress localAddress;

  public MediaServer(InetAddress localAddress, Context ctx) throws ValidationException
  {
    super(null, port, null, true);

    Log.e(TAG, "Creating media server !");

    localService = new AnnotationLocalServiceBinder()
        .read(ContentDirectoryService.class);

    localService.setManager(new DefaultServiceManager<ContentDirectoryService>(
        localService, ContentDirectoryService.class));

    udn = UDN.valueOf(new UUID(0,10).toString());
    this.localAddress = localAddress;
    this.ctx = ctx;
    createLocalDevice();

    ContentDirectoryService contentDirectoryService = (ContentDirectoryService)localService.getManager().getImplementation();
    contentDirectoryService.setContext(ctx);
    contentDirectoryService.setBaseURL(getAddress());
  }

  public void restart()
  {
    Log.d(TAG, "Restart mediaServer");
//    try {
//      stop();
//      createLocalDevice();
//      start();
//    } catch (Exception e) {
//      e.printStackTrace();
//    }
  }

  public void createLocalDevice() throws ValidationException
  {
    String version = "";
    try {
      version = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionName;
    } catch (PackageManager.NameNotFoundException e) {
      Log.e(TAG, "Application version name not found");
    }

    DeviceDetails details = new DeviceDetails(
      SettingsActivity.getSettingContentDirectoryName(ctx),
      new ManufacturerDetails(ctx.getString(R.string.app_name), ctx.getString(R.string.app_url)),
      new ModelDetails(ctx.getString(R.string.app_name), ctx.getString(R.string.app_url)),
      ctx.getString(R.string.app_name), version);

    List<ValidationError> l = details.validate();
    for( ValidationError v : l )
    {
      Log.e(TAG, "Validation pb for property "+ v.getPropertyName());
      Log.e(TAG, "Error is " + v.getMessage());
    }


    DeviceType type = new UDADeviceType("MediaServer", 1);

    localDevice = new LocalDevice(new DeviceIdentity(udn), type, details, localService);
  }


  public LocalDevice getDevice() {
    return localDevice;
  }

  public String getAddress() {
    return localAddress.getHostAddress() + ":" + port;
  }

  public class InvalidIdentificatorException extends java.lang.Exception
  {
    public InvalidIdentificatorException(){super();}
    public InvalidIdentificatorException(String message){super(message);}
  }

  class ServerObject
  {
    ServerObject(String path, String mime)
    {
      this.path = path;
      this.mime = mime;
    }
    public String path;
    public String mime;
  }

  private ServerObject getFileServerObject(String id) throws InvalidIdentificatorException
  {
    try
    {
      // Remove extension
      int dot = id.lastIndexOf('.');
      if (dot >= 0)
        id = id.substring(0,dot);

      // Try to get media id
      int mediaId = Integer.parseInt(id.substring(3));
      Log.v(TAG, "media of id is " + mediaId);

      MediaStore.MediaColumns mediaColumns = null;
      Uri uri = null;

      if(id.startsWith("/"+ContentDirectoryService.AUDIO_PREFIX))
      {
        Log.v(TAG, "Ask for audio");
        uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        mediaColumns = new MediaStore.Audio.Media();
      }
      else if(id.startsWith("/"+ContentDirectoryService.VIDEO_PREFIX))
      {
        Log.v(TAG, "Ask for video");
        uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        mediaColumns = new MediaStore.Video.Media();
      }
      else if(id.startsWith("/"+ContentDirectoryService.IMAGE_PREFIX))
      {
        Log.v(TAG, "Ask for image");
        uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        mediaColumns = new MediaStore.Images.Media();
      }

      if(uri!=null && mediaColumns!=null)
      {
        String[] columns = new String[]{mediaColumns.DATA, mediaColumns.MIME_TYPE};
        String where = mediaColumns._ID + "=?";
        String[] whereVal = {"" + mediaId};

        String path = null;
        String mime = null;
        Cursor cursor = ctx.getContentResolver().query(uri, columns, where, whereVal, null);

        if(cursor.moveToFirst())
        {
          path = cursor.getString(cursor.getColumnIndexOrThrow(mediaColumns.DATA));
          mime = cursor.getString(cursor.getColumnIndexOrThrow(mediaColumns.MIME_TYPE));
        }
        cursor.close();

        if(path!=null)
          return new ServerObject(path, mime);
      }
    }
    catch (Exception e)
    {
      Log.e(TAG, "Error while parsing " + id);
      Log.e(TAG, "exception", e);
    }

    throw new InvalidIdentificatorException(id + " was not found in media database");
  }

  @Override
  public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parms,
                        Map<String, String> files)
  {
    Response res = null;

    Log.e(TAG, "Serve uri : " + uri);

    for(Map.Entry<String, String> entry : header.entrySet())
      Log.d(TAG, "Header : key=" + entry.getKey() + " value=" + entry.getValue());

    for(Map.Entry<String, String> entry : parms.entrySet())
      Log.d(TAG, "Params : key=" + entry.getKey() + " value=" + entry.getValue());

    for(Map.Entry<String, String> entry : files.entrySet())
      Log.d(TAG, "Files : key=" + entry.getKey() + " value=" + entry.getValue());

    try
    {
      try
      {
        ServerObject obj = getFileServerObject(uri);

        Log.i(TAG, "Will serve " + obj.path);
        res = serveFile(new File(obj.path), obj.mime, header);
      }
      catch(InvalidIdentificatorException e)
      {
        return new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Error 404, file not found.");
      }

      if( res != null )
      {
        String version = "1.0";
        try {
          version = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
          Log.e(TAG, "Application version name not found");
        }

        // Some DLNA header option
        res.addHeader("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*");
        res.addHeader("contentFeatures.dlna.org", "");
        res.addHeader("transferMode.dlna.org", "Streaming");
        res.addHeader("Server", "DLNADOC/1.50 UPnP/1.0 Cling/2.0 DroidUPnP/"+version +" Android/" + Build.VERSION.RELEASE);
      }

      return res;
    }
    catch(Exception e)
    {
      Log.e(TAG, "Unexpected error while serving file");
      Log.e(TAG, "exception", e);
    }

    return new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "INTERNAL ERROR: unexpected error.");
  }
}




Java Source Code List

fi.iki.elonen.NanoHTTPD.java
fi.iki.elonen.ServerRunner.java
fi.iki.elonen.SimpleWebServer.java
org.droidupnp.DrawerFragment.java
org.droidupnp.Main.java
org.droidupnp.controller.cling.ContentDirectoryCommand.java
org.droidupnp.controller.cling.Factory.java
org.droidupnp.controller.cling.RendererCommand.java
org.droidupnp.controller.cling.ServiceController.java
org.droidupnp.controller.cling.ServiceListener.java
org.droidupnp.controller.upnp.IUpnpServiceController.java
org.droidupnp.controller.upnp.UpnpDebugListener.java
org.droidupnp.model.CObservable.java
org.droidupnp.model.cling.CDevice.java
org.droidupnp.model.cling.CRegistryListener.java
org.droidupnp.model.cling.RendererState.java
org.droidupnp.model.cling.TrackMetadata.java
org.droidupnp.model.cling.UpnpRegistry.java
org.droidupnp.model.cling.UpnpServiceController.java
org.droidupnp.model.cling.UpnpService.java
org.droidupnp.model.cling.didl.ClingAudioItem.java
org.droidupnp.model.cling.didl.ClingDIDLContainer.java
org.droidupnp.model.cling.didl.ClingDIDLItem.java
org.droidupnp.model.cling.didl.ClingDIDLObject.java
org.droidupnp.model.cling.didl.ClingDIDLParentContainer.java
org.droidupnp.model.cling.didl.ClingImageItem.java
org.droidupnp.model.cling.didl.ClingVideoItem.java
org.droidupnp.model.cling.localContent.AlbumContainer.java
org.droidupnp.model.cling.localContent.ArtistContainer.java
org.droidupnp.model.cling.localContent.AudioContainer.java
org.droidupnp.model.cling.localContent.CustomContainer.java
org.droidupnp.model.cling.localContent.DynamicContainer.java
org.droidupnp.model.cling.localContent.ImageContainer.java
org.droidupnp.model.cling.localContent.VideoContainer.java
org.droidupnp.model.mediaserver.ContentDirectoryService.java
org.droidupnp.model.mediaserver.MediaServer.java
org.droidupnp.model.upnp.ARendererState.java
org.droidupnp.model.upnp.CallableContentDirectoryFilter.java
org.droidupnp.model.upnp.CallableRendererFilter.java
org.droidupnp.model.upnp.ContentDirectoryDiscovery.java
org.droidupnp.model.upnp.DeviceDiscovery.java
org.droidupnp.model.upnp.DeviceListener.java
org.droidupnp.model.upnp.ICallableFilter.java
org.droidupnp.model.upnp.IContentDirectoryCommand.java
org.droidupnp.model.upnp.IDeviceDiscoveryObserver.java
org.droidupnp.model.upnp.IFactory.java
org.droidupnp.model.upnp.IRegistryListener.java
org.droidupnp.model.upnp.IRendererCommand.java
org.droidupnp.model.upnp.IRendererState.java
org.droidupnp.model.upnp.IServiceListener.java
org.droidupnp.model.upnp.IUpnpDevice.java
org.droidupnp.model.upnp.IUpnpRegistry.java
org.droidupnp.model.upnp.PeeringConnectionManager.java
org.droidupnp.model.upnp.RendererDiscovery.java
org.droidupnp.model.upnp.didl.DIDLDevice.java
org.droidupnp.model.upnp.didl.IDIDLContainer.java
org.droidupnp.model.upnp.didl.IDIDLItem.java
org.droidupnp.model.upnp.didl.IDIDLObject.java
org.droidupnp.model.upnp.didl.IDIDLParentContainer.java
org.droidupnp.view.ContentDirectoryDeviceFragment.java
org.droidupnp.view.ContentDirectoryDialog.java
org.droidupnp.view.ContentDirectoryEnabler.java
org.droidupnp.view.ContentDirectoryFragment.java
org.droidupnp.view.Content.java
org.droidupnp.view.DIDLObjectDisplay.java
org.droidupnp.view.DeviceDisplay.java
org.droidupnp.view.DeviceFragment.java
org.droidupnp.view.DeviceInfoDialog.java
org.droidupnp.view.PlaylistFragment.java
org.droidupnp.view.RendererDeviceFragment.java
org.droidupnp.view.RendererDialog.java
org.droidupnp.view.RendererFragment.java
org.droidupnp.view.ServiceDiscoveryFragment.java
org.droidupnp.view.SettingsActivity.java
org.droidupnp.view.UpnpDeviceListFragment.java