【问题标题】:Android FTP Server安卓 FTP 服务器
【发布时间】:2013-03-31 11:52:39
【问题描述】:

我正在使用以下code 将安卓设备设为 ftp 服务器(安卓内部存储)。我得到了os.android.NetworkOnMainThread 的例外。我试图将 onStart 代码放在AsyncTask 中,但应用程序从不执行并在启动时崩溃。任何有关 Android 上的 ftp 服务器的帮助都会很棒,因为我不知道如何让它工作。

这是MainActivity代码

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;
    }

这里是 ServerPI 代码

 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();
                    }
            }
    }
    }

我已经把代码放到AsyncTask里面了,就在这里

   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) {
      }
}

我在 onCreate 方法中调用 longOperation。应用在启动时崩溃是什么问题。

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

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

【问题讨论】:

    标签: android ftp sd-card


    【解决方案1】:

    可能是因为您没有在清单中设置权限?您必须设置互联网使用权限。

    如果这不起作用,请告诉我们是哪一行引发了异常。

    【讨论】:

    • 已经在manifest文件中设置了上网权限。
    • 第一个try catch块出现异常,表示socket连接永远不会打开,ip显示为0.0.0.0
    • 您的获取IP地址的命令似乎运行不正常。我用谷歌搜索,似乎它总是返回 0.0.0.0。检查这篇文章。你有一个关于如何获取IP地址stackoverflow.com/questions/7086734/how-to-get-my-ip-address的答案
    • 酷,让我检查一下并回复你。
    • 它确实显示了 ip 地址,但以十六进制格式显示 :) 我如何才能以字符串或数字计算它返回的内容?
    【解决方案2】:

    while(true){ incoming = s.accept(); ...} 你不能把它放在 OnStart() 中。这应该在一个线程中完成。所以ServerSocket s = null; 应该是你活动的一个变量。

    【讨论】:

    • 我应该如何把它放在一个单独的线程或异步任务中。你能给我举个例子吗?
    • 我创建了一个 AsyncTask 并且所有代码现在都在该任务主体中,我在 onCreate() 函数中调用 Async Task 执行方法,是否正确?它甚至没有启动就使应用程序崩溃。
    【解决方案3】:

    所以我在我的应用程序中使用了 Swiftp 应用程序(开源)作为服务,它帮助我完成了我的任务。感谢所有挺身而出提供帮助的人。如果有人想关注,这里是link

    【讨论】:

      【解决方案4】:

      请在此处发布您的代码。

      NetworkOnMainthreadException 发生是因为您可能在主 UI 线程上运行网络相关操作。为此,您应该使用 asynctask

      这仅适用于面向 Honeycomb SDK 或更高版本的应用程序。允许针对早期 SDK 版本的应用程序在其主事件循环线程上进行联网,但非常不鼓励这样做。

      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。检查标题下的主题The 4 Steps.

      asynctask@To use the tutorial in android 4.0.3 if had to work with AsynxTasc but i still dont work? 的工作示例。

      上面在 doInBakckground() 中进行了网络服务调用。返回结果并通过在 onPostExecute() 中的 textview 中设置结果来更新 ui。

      【讨论】:

      • 发布 logcat 你是否在 logcat 中遇到任何异常
      • 我没有得到任何异常,但在此:while(true){ incoming = s.accept(); executor.execute(new ServerPI(incoming)); } 它在这里停止执行并发生线程池执行器类错误。
      • doinBackground() 已在后台运行。为什么需要 executor.execute()?如果您想要并行执行,请不要使用 asynctask
      • 如果我不使用 AsyncTask 那么它会给我网络操作系统 onMainthread 异常,有没有其他方法来处理这个
      • 在 doInbackground() 中使用 asynctask 但不使用 executor.execute()。如果您希望并行执行不要使用 asyntask,请改用执行器。 developer.android.com/reference/java/util/concurrent/…
      【解决方案5】:

      android 3.0 更高版本的主线程中不能进行网络操作。使用 AsyncTask 进行此网络操作。 See this进一步解释

      【讨论】:

      • 我试图将代码放在后台异步任务中并在 onCreate 方法中执行,但应用程序在启动时崩溃了。
      • 在这种情况下,你得到的异常是什么
      • 它从不运行应用程序,因此无法排除异常。您可以发布任何异步任务的工作示例或编辑我上面的代码,以便我可以走上正轨
      • 我在 while(true){ incoming = s.accept(); executor.execute(new ServerPI(incoming)); } 这个。
      • 吐司不。您不能在 doInBackGround() 中使用 Toast(),因为它涉及 UI。也取消 String ip;并获取 ip,因为您现在知道这将无法正常工作。请展示你如何在 onCreate(); 中实例化和调用你的 asynctask;
      猜你喜欢
      • 2012-07-21
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多