Android Open Source - prim-ftpd Ftp Server Service






From Project

Back to project page prim-ftpd.

License

The source code is released under:

Apache License

If you think the Android project prim-ftpd 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

package org.primftpd;
// ww  w  .  j  av a 2  s.co m
import java.lang.ref.WeakReference;

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.listener.ListenerFactory;
import org.primftpd.filesystem.AndroidFileSystemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Process;
import android.widget.Toast;

/**
 * Implements an FTP server.
 */
public class FtpServerService extends Service
{
  public static final String BROADCAST_ACTION_COULD_NOT_START = "org.primftpd.CouldNotStartServer";

  protected static final int MSG_START = 1;
  protected static final int MSG_STOP = 2;

  protected final Logger logger = LoggerFactory.getLogger(getClass());

  private FtpServer ftpServer;
  private Looper serviceLooper;
  private ServiceHandler serviceHandler;
  private PrefsBean prefsBean;
  private WakeLock wakeLock;
  private NsdManager.RegistrationListener nsdRegistrationListener;

  /**
   * Handles starting and stopping of FtpServer.
   *
   */
  private final static class ServiceHandler extends Handler {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    private final WeakReference<FtpServerService> ftpServiceRef;

    public ServiceHandler(Looper looper, FtpServerService ftpService) {
      super(looper);
      this.ftpServiceRef = new WeakReference<FtpServerService>(ftpService);
    }
    @Override
    public void handleMessage(Message msg) {
      logger.debug("handleMessage()");

      FtpServerService ftpService = ftpServiceRef.get();
      if (ftpService == null) {
        logger.warn("ftpServiceRef is null");
        return;
      }

      int toDo = msg.arg1;
      if (toDo == MSG_START) {
        if (ftpService.ftpServer == null) {
          logger.debug("starting ftp server");

          // XXX set properties to prefer IPv4 to run in simulator
          System.setProperty("java.net.preferIPv4Stack", "true");
            System.setProperty("java.net.preferIPv6Addresses", "false");

            ftpService.launchFtpServer();

            if (ftpService.ftpServer != null) {
              ftpService.createStatusbarNotification();

            // acquire wake lock for CPU to still handle requests
            // note: PARTIAL_WAKE_LOCK is not enough
            logger.debug("acquiring wake lock");
            PowerManager powerMgr =
                (PowerManager) ftpService.getSystemService(POWER_SERVICE);
            ftpService.wakeLock = powerMgr.newWakeLock(
                PowerManager.SCREEN_DIM_WAKE_LOCK,
                "pFTPd");
            ftpService.wakeLock.acquire();

            if (ftpService.prefsBean.isAnnounce()) {
              ftpService.announceService();
            }
            } else {
              ftpService.stopSelf();

              // tell activity to update button states
              Intent intent = new Intent(BROADCAST_ACTION_COULD_NOT_START);
              ftpService.sendBroadcast(intent);
            }
        }

      } else if (toDo == MSG_STOP) {
        if (ftpService.ftpServer != null) {
          logger.debug("stopping ftp server");
          ftpService.ftpServer.stop();
          ftpService.ftpServer = null;

          if (ftpService.prefsBean.isAnnounce()) {
            ftpService.unannounceService();
          }
        }
        if (ftpService.ftpServer == null) {
          ftpService.removeStatusbarNotification();
        }
        if (ftpService.wakeLock != null) {
          logger.debug("releasing wake lock");
          ftpService.wakeLock.release();
          ftpService.wakeLock = null;
        }
        logger.debug("stopSelf");
        ftpService.stopSelf();
      }
    }
  }


  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public void onCreate() {
    HandlerThread thread = new HandlerThread(
      "ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
      thread.start();

      serviceLooper = thread.getLooper();
      serviceHandler = new ServiceHandler(serviceLooper, this);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    logger.debug("onStartCommand()");

    if (intent == null) {
      logger.warn("intent is null in onStartCommand()");

      return START_REDELIVER_INTENT;
    }

    // get parameters
    Bundle extras = intent.getExtras();
    prefsBean = (PrefsBean)extras.get(PrimitiveFtpdActivity.EXTRA_PREFS_BEAN);

    // send start message
    Message msg = serviceHandler.obtainMessage();
    msg.arg1 = MSG_START;
    serviceHandler.sendMessage(msg);

    // we don't want the system to kill the ftp server
    //return START_NOT_STICKY;
    return START_STICKY;
  }

  @Override
  public void onDestroy() {
    logger.debug("onDestroy()");

    Message msg = serviceHandler.obtainMessage();
    msg.arg1 = MSG_STOP;
    serviceHandler.sendMessage(msg);
  }

  /**
   * Creates Statusbar Notification.
   */
  protected void createStatusbarNotification() {
    // create pending intent
    Intent notificationIntent = new Intent(this, PrimitiveFtpdActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    // create notification
    int icon = R.drawable.ic_launcher;
    CharSequence tickerText = getText(R.string.serverRunning);
    CharSequence contentTitle = getText(R.string.notificationTitle);
    CharSequence contentText = tickerText;

    long when = System.currentTimeMillis();

    Notification notification = new Notification.Builder(getApplicationContext())
      .setTicker(tickerText)
      .setContentTitle(contentTitle)
      .setContentText(contentText)
      .setSmallIcon(icon)
      .setContentIntent(contentIntent)
      .setWhen(when)
      .build();


    // notification manager
    NotificationUtil.createStatusbarNotification(this, notification);
  }

  /**
   * Removes Statusbar Notification.
   */
  protected void removeStatusbarNotification() {
    NotificationUtil.removeStatusbarNotification(this);
  }

  /**
     * Launches FTP server.
     */
    protected void launchFtpServer() {
      ListenerFactory listenerFactory = new ListenerFactory();
      listenerFactory.setPort(prefsBean.getPort());

      FtpServerFactory serverFactory = new FtpServerFactory();
      serverFactory.addListener("default", listenerFactory.createListener());

      // user manager & file system
      serverFactory.setUserManager(new AndroidPrefsUserManager(prefsBean));
      serverFactory.setFileSystem(new AndroidFileSystemFactory());

      // XXX SSL
      // ssl listener
//      KeyStore keyStore = KeyStoreUtil.loadKeyStore(getResources());
//      if (keyStore != null) {
//        SslConfiguration sslConfig = KeyStoreUtil.createSslConfiguration(keyStore);
//        if (sslConfig != null) {
//          ListenerFactory sslListenerFactory = new ListenerFactory();
//          sslListenerFactory.setPort(prefsBean.getSslPort());
//          sslListenerFactory.setImplicitSsl(true);
//          sslListenerFactory.setSslConfiguration(sslConfig);
//          serverFactory.addListener("ssl", sslListenerFactory.createListener());
//        }
//      }

      // do start server
      ftpServer = serverFactory.createServer();
      try {
        ftpServer.start();
      } catch (Exception e) {
        // note: createServer() throws RuntimeExceptions, too
      logger.error("could not start server", e);

      ftpServer = null;

      String msg = getText(R.string.serverCouldNotBeStarted).toString();
      msg += e.getLocalizedMessage();
      Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
    }
    }

    /**
     * Register a DNS-SD service (to be discoverable through Bonjour/Avahi).
     */
    protected void announceService () {
    nsdRegistrationListener = new NsdManager.RegistrationListener() {
      @Override
      public void onServiceRegistered(NsdServiceInfo serviceInfo) {
        logger.debug("onServiceRegistered()");
      }
      @Override
      public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
        logger.debug("onRegistrationFailed()");
      }
      @Override
      public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
        logger.debug("onServiceUnregistered()");
      }
      @Override
      public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
        logger.debug("onUnregistrationFailed()");
      }
    };

    NsdServiceInfo serviceInfo  = new NsdServiceInfo();
    serviceInfo.setServiceName("primitive ftpd");
    serviceInfo.setServiceType("_ftp._tcp.");
    serviceInfo.setPort(prefsBean.getPort());

    NsdManager nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);

    nsdManager.registerService(
      serviceInfo,
      NsdManager.PROTOCOL_DNS_SD,
      nsdRegistrationListener);
  }

  protected void unannounceService () {
    NsdManager nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);
    nsdManager.unregisterService(nsdRegistrationListener);
  }
}




Java Source Code List

org.primftpd.AndroidPrefsUserManager.java
org.primftpd.EncryptingEditTextPreference.java
org.primftpd.FtpPrefsActivity.java
org.primftpd.FtpPrefsFragment.java
org.primftpd.FtpServerService.java
org.primftpd.NotificationUtil.java
org.primftpd.PrefsBean.java
org.primftpd.PrimitiveFtpdActivity.java
org.primftpd.filesystem.AndroidFileSystemFactory.java
org.primftpd.filesystem.AndroidFileSystemView.java
org.primftpd.filesystem.AndroidFtpFile.java
org.primftpd.util.EncryptionUtil.java
org.primftpd.util.KeyStoreUtil.java
org.primftpd.util.StringUtils.java
org.slf4j.ILoggerFactory.java
org.slf4j.IMarkerFactory.java
org.slf4j.LoggerFactory.java
org.slf4j.Logger.java
org.slf4j.MDC.java
org.slf4j.MarkerFactory.java
org.slf4j.Marker.java
org.slf4j.helpers.BasicMDCAdapter.java
org.slf4j.helpers.BasicMarkerFactory.java
org.slf4j.helpers.BasicMarker.java
org.slf4j.helpers.FormattingTuple.java
org.slf4j.helpers.MarkerIgnoringBase.java
org.slf4j.helpers.MessageFormatter.java
org.slf4j.helpers.NOPLoggerFactory.java
org.slf4j.helpers.NOPLogger.java
org.slf4j.helpers.NOPMDCAdapter.java
org.slf4j.helpers.NamedLoggerBase.java
org.slf4j.helpers.SubstituteLoggerFactory.java
org.slf4j.helpers.Util.java
org.slf4j.impl.AndroidLoggerFactory.java
org.slf4j.impl.AndroidLogger.java
org.slf4j.impl.StaticLoggerBinder.java
org.slf4j.impl.StaticMDCBinder.java
org.slf4j.impl.StaticMarkerBinder.java
org.slf4j.spi.LocationAwareLogger.java
org.slf4j.spi.LoggerFactoryBinder.java
org.slf4j.spi.MDCAdapter.java
org.slf4j.spi.MarkerFactoryBinder.java