Android FTP Server

2019-03-14 07:42发布

问题:

I am using the following code to make the android device a ftp server (Android Internal storage). I am getting the exception of os.android.NetworkOnMainThread. I have tried to put the onStart code in the AsyncTask but app never executes and crashes on launch. Any help regarding the ftp server on Android will be great as i have no idea how to get it working.

Here is the MainActivity Code

package com.googlecode.simpleftp;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;


public class FTPServer extends Activity {
    private static int COMMAND_PORT = 2121;
    static final int DIALOG_ALERT_ID = 0;
    private static ExecutorService executor  = Executors.newCachedThreadPool();

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.my_menu, menu);
            return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {    
            // Handle item selection    
            switch (item.getItemId()) {
                    case R.id.new_game:    
                            System.out.println("New game button is pressed!");
                            //newGame();        
                            return true;    
                    case R.id.quit:        
                            System.out.println("Quit button is pressed!");
                            showDialog(DIALOG_ALERT_ID);        
                            return true;    
                    default:        
                            return super.onOptionsItemSelected(item);    }
    }

    @Override
    protected Dialog onCreateDialog(int id){
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Are you sure you want to exit?")
            .setCancelable(false).setPositiveButton("yes", new DialogInterface.OnClickListener(){
                    @Override
                    public void onClick(DialogInterface dialog, int id){
                            FTPServer.this.finish();
                    }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();

                    }
            });
            AlertDialog alert = builder.create();
            return alert;
    }

HEre is the ServerPI Code

 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.net.Socket;

 public class ServerPI implements Runnable{
    private Socket clientSocket;
    private BufferedReader in;
    private PrintWriter out;

    private String baseDir;
    private String relativeDir;
    private String absoluteDir;
    private String fileName;
    private String filePath;

    public ServerPI(Socket incoming) throws IOException{
            this.clientSocket = incoming;
            in = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
            out = new PrintWriter(this.clientSocket.getOutputStream(), true);

            baseDir = new File("").getAbsolutePath();

            relativeDir = "/";
            absoluteDir = baseDir + relativeDir;
            fileName = "";
            filePath = absoluteDir + "/" + fileName;
    }

    private void readCommandLoop() throws IOException {
            String line = null;
            reply(220, "Welcome to the SimpleFTP server!");
            while((line = in.readLine()) != null){
                    int replyCode = executeCommand(line.trim());
                    if(replyCode == 221){
                            return;
                    }
            }
    }

    private int executeCommand(String trim) {
            // TODO Auto-generated method stub
            return 0;
    }

    public int reply(int statusCode, String statusMessage){
            out.println(statusCode + " " + statusMessage);
            return statusCode;
    }

    @Override
    public void run(){
            try{
                    this.readCommandLoop();
            } catch (IOException e){
                    e.printStackTrace();
            }
            finally {
                    try {
                            if(in != null){
                                    in.close();
                                    in = null;
                            }
                            if(out != null){
                                    out.close();
                                    out = null;
                            }
                            if (clientSocket != null){
                                    clientSocket.close();
                                    clientSocket = null;
                            }
                    }
                    catch (IOException e){
                            e.printStackTrace();
                    }
            }
    }
    }

I have put the code in the AsyncTask, here it is

   private class LongOperation extends AsyncTask<String, Void, String> {

      @Override
      protected String doInBackground(String... params) {
           ServerSocket s = null;
    Socket incoming = null;

    try{
            s = new ServerSocket(COMMAND_PORT);
            String ip = (s.getInetAddress()).getHostAddress();
            Context context = this.getApplicationContext();
            CharSequence text = ip;
            int duration = Toast.LENGTH_LONG;

            Toast toast = Toast.makeText(context, text, duration);
            Thread.sleep(1000);
            toast.show();
            while(true){
                    incoming = s.accept();
                    executor.execute(new ServerPI(incoming));
            }
    }
    catch(Exception e){
            System.out.println(e.toString());
            e.printStackTrace();
    }
    finally{
            try
                    {
                            if(incoming != null)incoming.close();
                    }
                    catch(IOException ignore)
                    {
                            //ignore
                    }

                    try
                    {
                            if (s!= null)
                            {
                                    s.close();
                            }
                    }
                    catch(IOException ignore)
                    {
                            //ignore
                    }
    }

            return "Executed";
      }      

      @Override
      protected void onPostExecute(String result) {               
      }

      @Override
      protected void onPreExecute() {
      }

      @Override
      protected void onProgressUpdate(Void... values) {
      }
}

Iam calling the longOpertation in onCreate method. What is the problem that the app crashes on launch.

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_fullscreen);
            new LongOperation().execute();
    }

回答1:

Maybe because you didn't set up the permissions in the manifest? You've to set permission for internet usage.

If this doesn't work, please tell us which line is it throwing the exception.



回答2:

while(true){ incoming = s.accept(); ...} You cannot put that in OnStart(). That should be done in a thread. So ServerSocket s = null; should be a variable of you activity.



回答3:

Using the Swiftp application (open source) as a service in my application helped me to acheive my task. Thanks for everyones help. Here is the link if someone wants to follow



回答4:

You can not do network operation in main thread in android 3.0 higher. Use AsyncTask for this network operation. See this for further explanation



回答5:

Please post your code here.

NetworkOnMainthreadException occurs because you maybe running Network related operation on the Main UI Thread. You should use asynctask for this purpose

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.

http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

class TheTask extends AsyncTask<Void,Void,Void>
{
protected void onPreExecute()
  {           super.onPreExecute();
             //display progressdialog.
  }  

protected void doInBackground(Void ...params)//return result here
{  
//http request. do not update ui here
//call webservice
//return result here
return null;
 } 

protected void onPostExecute(Void result)//result of doInBackground is passed a parameter
{     
    super.onPostExecute(result);
    //dismiss progressdialog.
    //update ui using the result returned form doInbackground()
} 
}

http://developer.android.com/reference/android/os/AsyncTask.html. Check the topic under the heading The 4 Steps.

A working example of asynctask @ To use the tutorial in android 4.0.3 if had to work with AsynxTasc but i still dont work?.

The above makes a webserive call in doInBakckground(). Returns result and updates the ui by setting the result in textview in onPostExecute().