【问题标题】:Read data received to android phone from a PC读取从 PC 接收到安卓手机的数据
【发布时间】:2014-05-26 07:07:26
【问题描述】:

我需要实施一种解决方案来从安卓设备中读取数据,通过 USB 电缆连接到 PC。即连接到 PC 的手机将通过另一个 android 设备通过 NFC 接收数据,其中 PC - C# 程序必须从插入的 android 手机读取接收到的数据,如下所示。 p>

[PC]<----(2. read data) usb cable----[android phone]<-----NFC (1. transmit string)-----[android phone]

我已经通过NFC 使用这里的链接-http://developer.android.com/guide/topics/connectivity/nfc/nfc.html 实现了数据传输。但是,当它通过NFC 接收内容(小字符串消息)时,我可以找到任何关于从 android 手机读取数据的参考。

我尝试了很多 Google 搜索,但由于我是该领域的新手,所以最终还是空手而归。如果各位专家能指出一些关于如何完成这项任务的教程/代码 sn-ps/参考资料,我将不胜感激。

如果这个问题重复或含糊不清,请见谅。我是这个领域的新手,不知道寻找在线帮助的关键字。

谢谢你:)

【问题讨论】:

  • 在我看来,这与 NFC 或第三个设备没有太大关系。您希望 PC 上的程序从通过 USB 电缆连接到该 PC 的 Android 设备读取数据。或者您可能希望 Android 设备向 PC 发送数据?
  • @greenapps 谢谢您的回复先生.. 是的,这是我的目标..C# 应该轮询NFC messages received 到连接的android 设备,或者连接的android 设备应该send datac# program 一次receives an NFC message 先生.. :) 这可能吗?你知道怎么做吗?
  • 为什么要用USB线连接?
  • @greenapps 我认为 C# 应用程序以这种方式检索数据会更容易..还有另一种可能/简单的方法吗?
  • 最简单的方法是wifi。只是服务器/客户端。如果你说 C# 应该检索数据,那么这些数据在 android 上存储/处理在哪里?

标签: c# android usb nfc


【解决方案1】:

我认为这是你应该做的。收到来自 NFC 的数据后,将其存储在 SD 卡中的预定义位置。同时运行一个连续线程来为该特定文件执行 adb pull。如果 adb pull 下载了文件,你就完成了。

【讨论】:

    【解决方案2】:

    首先,我不是C#程序员,所以请原谅我从MSDN examples page复制粘贴一个C#套接字客户端。

    基本上,如果您想通过USB与Android应用程序通信,您需要通过adb(Android调试桥)指示您的手机创建端口转发,然后您可以使用普通的TCP/IP套接字建立流通信与您的客户。

    首先,您必须在您的 PC 上安装正确的驱动程序(您可以在您的制造商网站上找到它们),这样当您运行 adb devices 时,您的手机就会被正确识别:

    C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb devices
    List of devices attached
    039d78fa2518e606        device
    

    接下来您需要在 Android 端设置端口转发,以便您 PC 上本地主机上的套接字连接将正确转发到手机上的本地主机。这也是通过adb 完成的:

    C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward tcp:6000 tcp:6000
    

    验证是否成功:

    C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward --list
    039d78fa2518e606 tcp:6000 tcp:6000
    

    现在您可以在 Android 端创建一个常规的套接字服务器应用程序。我很抱歉这个例子非常简单(我很晚才注意到这个问题,没有时间实现正确的通信协议)。但这应该向您展示如何在客户端和主机之间传输字符串,并且您可以实现必要的循环,或者如果需要更复杂的传输协议。

    基本上这只是默认的 Android 项目,添加了 1 个类,在单独的线程中运行(GUI 和网络活动不能在同一线程中运行)。

    所以,我们的 MainActivity.java 看起来像这样:

    package com.example.dataexchange;
    
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.app.ActionBar;
    import android.support.v4.app.Fragment;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.os.Build;
    
    public class MainActivity extends ActionBarActivity {
    
    SocketHandler server;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        Log.v("jlumme", "Main/ start network task");
    
        new Thread(new Runnable() {
            public void run() {
                server = new SocketHandler(6000);
                server.run();
            }
        }).start();
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
    
        public PlaceholderFragment() {
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
        }
    }
    }
    

    通常的东西,我们只是在一个单独的线程中启动我们的SocketHandler 类。 SocketThread 类如下所示:

    package com.example.dataexchange;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import android.util.Log;
    
    public class SocketHandler implements Runnable {
    
    private Socket socket;
    private ServerSocket server;
    private PrintWriter out;
    private BufferedReader in;
    
    private int socketPort;
    SocketHandler(int port) {
        socketPort = port;
    }
    
    @Override
    public void run() {
    
        Log.v("jlumme", "Socket thread has started");
        String inputText;
    
        // TODO Auto-generated method stub
        try {
            Log.v("jlumme", "Starting socket server ");
    
            server = new ServerSocket(6000);
            socket = server.accept();
    
            Log.v("jlumme", "Client connected");
    
            out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); 
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));                
    
            while ((inputText = in.readLine()) != null) {
                Log.v("jlumme", "Received:" + inputText);
                out.println("you wrote:" + inputText);
            }
    
            Log.v("jlumme", "connection established");
    
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    }
    

    基本上在run() 方法中,您启动一​​个新的SocketServer,并开始等待客户。客户端连接后,您可以双向设置流缓冲区,并开始等待消息(任何以换行符结尾的,'\n' 都可以)。

    在 C# 方面,应用程序非常简单。它连接到localhost 端口6000 并发送一行:

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    public class SynchronousSocketClient
    {
    
    public static void StartClient() {
        // Data buffer for incoming data.
        byte[] bytes = new byte[1024];
    
        // Connect to a remote device.
        try {
    
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);
    
            // Create a TCP/IP  socket.
            Socket sender = new Socket(AddressFamily.InterNetwork, 
                SocketType.Stream, ProtocolType.Tcp );
    
            // Connect the socket to the remote endpoint. Catch any errors.
            try {
                sender.Connect(remoteEP);
    
                Console.WriteLine("Socket connected to {0}",
                    sender.RemoteEndPoint.ToString());
    
                // Encode the data string into a byte array.
                byte[] msg = Encoding.ASCII.GetBytes("This is a test\n");
    
                // Send the data through the socket.
                int bytesSent = sender.Send(msg);
    
                // Receive the response from the remote device.
                int bytesRec = sender.Receive(bytes);
                Console.WriteLine("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes,0,bytesRec));
    
                // Release the socket.
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();
    
            } catch (ArgumentNullException ane) {
                Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
            } catch (SocketException se) {
                Console.WriteLine("SocketException : {0}",se.ToString());
            } catch (Exception e) {
                Console.WriteLine("Unexpected exception : {0}", e.ToString());
            }
    
        } catch (Exception e) {
            Console.WriteLine( e.ToString());
        }
    }
    
    public static int Main(String[] args)
    {
        StartClient();
        return 0;
    }
    }
    

    如果在执行C#程序时,会发送this is a test字符串给客户端,客户端会回显:

    c:\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\bin\Debug>ConsoleApplication2.exe
    Socket connected to 127.0.0.1:6000
    Echoed test = you wrote:This is a test
    

    我想在赏金关闭之前达到最后期限,所以目前没有适当的消息处理,并且 c# 将立即退出(而 Android 端会对此感到困惑),对此我深表歉意。但是我认为一旦你运行了这个例子,你就可以很容易地将它扩展到你的需要,并实现必要的逻辑来处理终止和其他东西..

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      另一种方法是监控 logcat 输出:您的应用程序可以将消息写入通过您的应用程序监控的 logcat 输出。

      来自this SO question 的示例代码以及this other question 上的其他讨论

      但是@Sagar 提到的似乎也很明智,如果做得好,可以防止任何数据丢失。使用 logcat 方法,如果它断开连接,那么在断开连接期间传输的任何数据都将丢失。

      【讨论】:

        【解决方案4】:

        您可以设置HTTPListener,然后在预定义端口上向目标 PC 的 IP 地址发出 HTTP 请求。您需要提前配置 Android 应用程序以将请求发送到特定 IP 地址或扫描一系列 IP 地址以查找正确的地址(在这种情况下,您的侦听器需要响应“搜索”-类型请求)。

        本质上,您是在 C# 中创建一个 mini-REST 服务。然后你可以issue REST API calls from your Android app

        【讨论】:

          猜你喜欢
          • 2012-04-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多