android - 使用 wifi direct 在 Android 设备之间传输数据?

标签 android server-side file-transfer wifi-direct

我最近在我的项目中实现了 wifi direct,我的目标是当我的某些应用程序条件满足时,在两个 wifidirect 连接的设备之间传递字符串值。现在我已经列出了所有对等点,并在选定的对等点之间建立了连接。我的我的想法是在设备之间传递一个 json 文件。所以在尝试执行该想法之前,我尝试在两个设备之间传递一个图像文件。我按照 android wifidirect 教程中的步骤进行操作。列出对等点并且对等点之间的连接是成功的但我无法在设备之间传递数据。下面是我的代码。 文件传输服务.java

package jing.app.directwifi;

import android.app.IntentService;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
 import android.util.Log;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;


/**
 * A service that process each file transfer request i.e Intent by opening a
 * socket connection with the WiFi Direct Group Owner and writing the file
 */
public class FileTransferService extends IntentService {

private static final int SOCKET_TIMEOUT = 5000;
public static final String ACTION_SEND_FILE = "jing.app.directwifi.SEND_FILE";
public static final String EXTRAS_FILE_PATH = "file_url";
public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";

public FileTransferService(String name) {
    super(name);
}

public FileTransferService() {
    super("FileTransferService");
}

/*
 * (non-Javadoc)
 * @see android.app.IntentService#onHandleIntent(android.content.Intent)
 */
@Override
protected void onHandleIntent(Intent intent) {

    Context context = getApplicationContext();
    if (intent.getAction().equals(ACTION_SEND_FILE)) {
        String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
        String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
        Socket socket = new Socket();
        int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);

        try {
           // Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
            socket.bind(null);
            socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);

            Log.d("connected", "Client socket - " + socket.isConnected());
            OutputStream stream = socket.getOutputStream();
            ContentResolver cr = context.getContentResolver();
            InputStream is = null;
            try {
                is = cr.openInputStream(Uri.parse(fileUri));
            } catch (FileNotFoundException e) {
                Log.d("exp", e.toString());
            }
           MainActivity.copyFile(is, stream);
            Log.d("exp" ,"Client: Data written");
        } catch (IOException e) {
            Log.e("exp", e.getMessage());
        } finally {
            if (socket != null) {
                if (socket.isConnected()) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        // Give up
                        e.printStackTrace();
                    }
                }
            }
        }

    }
}
}

主要 Activity .java

package jing.app.directwifi;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;





import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
 import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.os.AsyncTask;
import android.os.Bundle;
 import android.os.Environment;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener,   android.content.DialogInterface.OnClickListener, ConnectionInfoListener {

private WifiP2pManager mManager;
private Channel mChannel;
private BroadcastReceiver mReceiver;
private IntentFilter mIntentFilter;

private Button mDiscover;
private TextView mDevices;
public ArrayAdapter mAdapter;
private ArrayList<WifiP2pDevice> mDeviceList = new ArrayList<WifiP2pDevice>();
protected static final int CHOOSE_FILE_RESULT_CODE = 20;
int flag=0;
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mDiscover = (Button) findViewById(R.id.discover);
    mDiscover.setOnClickListener(this);

    mDevices = (TextView) findViewById(R.id.peers);

    mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    mChannel = mManager.initialize(this, getMainLooper(), null);
    mReceiver = new WiFiDirectReceiver(mManager, mChannel, this);

    mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);


}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(mReceiver);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private class WiFiDirectReceiver extends BroadcastReceiver {

    private WifiP2pManager mManager;
    private Channel mChannel;
    private MainActivity mActivity;

    public WiFiDirectReceiver(WifiP2pManager manager, Channel channel, MainActivity activity) {
        super();
        mManager = manager;
        mChannel = channel;
        mActivity = activity;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {

            int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
            if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                   String title = "ANDROID_ID[" + getAndroid_ID() + "]";
                   title += "   MAC[" + getMACAddress() + "]";
                Toast.makeText(mActivity, "Wi-Fi Direct is enabled."+title, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(mActivity, "Wi-Fi Direct is disabled.", Toast.LENGTH_SHORT).show();
            }

        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

            if (mManager != null) {
                mManager.requestPeers(mChannel, new PeerListListener() {

                    @Override
                    public void onPeersAvailable(WifiP2pDeviceList peers) {
                        if (peers != null) {
                            mDeviceList.addAll(peers.getDeviceList());
                            ArrayList<String> deviceNames = new ArrayList<String>();
                            for (WifiP2pDevice device : mDeviceList) {
                                deviceNames.add(device.deviceName);
                            }
                            if (deviceNames.size() > 0) {
                                mAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1, deviceNames);
                                if(flag==0)
                                {
                                    flag=1;
                                showDeviceListDialog();
                                }
                            } else {
                                Toast.makeText(mActivity, "Device list is empty.", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                });
            }

        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {


        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {

        }
    }

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.discover:
        onDiscover();
        break;
    }
}

private void onDiscover() {
    mManager.discoverPeers(mChannel, new ActionListener() {

        @Override
        public void onSuccess() {
            Toast.makeText(MainActivity.this, "Discover peers successfully.", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onFailure(int reason) {
            Toast.makeText(MainActivity.this, "Discover peers failed.", Toast.LENGTH_SHORT).show();
        }
    });
}

private void showDeviceListDialog() {
    DeviceListDialog deviceListDialog = new DeviceListDialog();
    deviceListDialog.show(getFragmentManager(), "devices");
}

private class DeviceListDialog extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Select a device")
               .setSingleChoiceItems(mAdapter, 0, MainActivity.this)
               .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }

               });

        return builder.create();
    }

}

@Override
public void onClick(DialogInterface dialog, int which) {
    onDeviceSelected(which);
    dialog.dismiss();
}

private void onDeviceSelected(int which) {
    WifiP2pDevice device = mDeviceList.get(which);
    if (device == null) {
        return;
    }

    WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = device.deviceAddress;
    mManager.connect(mChannel, config, new ActionListener() {

        @Override
        public void onSuccess() {
            Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT).show();
              Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
              intent.setType("image/*");
              startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
        }

        @Override
        public void onFailure(int reason) {
            Toast.makeText(MainActivity.this, "Failed to connect", Toast.LENGTH_SHORT).show();
        }
    });
}
/**
 * ANDROID_ID
 */
private String getAndroid_ID() {
    return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
}

/**
 * Wi-Fi MAC
 */
private String getMACAddress() {
    WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    WifiInfo wifiInfo = manager.getConnectionInfo();
    String mac = wifiInfo.getMacAddress();

    // After the group negotiation, we assign the group owner as the file
    // server. The file server is single threaded, single connection server
    // socket.

        new FileServerAsyncTask(getApplicationContext())
                .execute();





    return mac;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    // User has picked an image. Transfer it to group owner i.e peer using
    // FileTransferService.
    Uri uri = data.getData();

  Log.d("intent", "Intent----------- " + uri);
    Intent serviceIntent = new Intent(MainActivity.this, FileTransferService.class);
    serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
    serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
    serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
            getMACAddress());
    serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
    startService(serviceIntent);
}
/**
 * A simple server socket that accepts connection and writes some data on
 * the stream.
 */
public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {

    private Context context;


    /**
     * @param context
     * @param statusText
     */
    public FileServerAsyncTask(Context context) {
        this.context = context;

    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            System.out.println("insideeeeeeeeeeeeeeeeeeeeeeee");
            ServerSocket serverSocket = new ServerSocket(8988);
            Log.d("Server: Socket opened", "Server: Socket opened");
            Socket client = serverSocket.accept();
            Log.d("Server: connection done", "Server: connection done");
            final File f = new File(Environment.getExternalStorageDirectory() + "/"
                    + context.getPackageName() + "/wifip2pshared-" +   System.currentTimeMillis()
                    + ".jpg");

            File dirs = new File(f.getParent());
            if (!dirs.exists())
                dirs.mkdirs();
            f.createNewFile();

            Log.d("server: copying files ", "server: copying files " + f.toString());
            InputStream inputstream = client.getInputStream();
            copyFile(inputstream, new FileOutputStream(f));
            serverSocket.close();
            return f.getAbsolutePath();
        } catch (IOException e) {
            Log.e("exp", e.getMessage());
            System.out.println(":iooo:"+e);
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
     */
    @Override
    protected void onPostExecute(String result) {
        if (result != null) {

            Intent intent = new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + result), "image/*");
            context.startActivity(intent);
        }

    }

    /*
     * (non-Javadoc)
     * @see android.os.AsyncTask#onPreExecute()
     */
    @Override
    protected void onPreExecute() {

    }

}
public static boolean copyFile(InputStream inputStream, OutputStream out) {
    byte buf[] = new byte[1024];
    int len;
    long startTime=System.currentTimeMillis();

    try {
        while ((len = inputStream.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
        out.close();
        inputStream.close();
        long endTime=System.currentTimeMillis()-startTime;
        Log.v("","Time taken to transfer all bytes is : "+endTime);

    } catch (IOException e) {
        Log.d("exp", e.toString());
        return false;
    }
    return true;
}

@Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
    // TODO Auto-generated method stub

    Toast.makeText(getApplicationContext(), "connectioninfoo", 3000).show();

}

}

list

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jing.app.directwifi"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="14"
    android:targetSdkVersion="16" />

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Market filtering -->
<uses-feature
    android:name="android.hardware.wifi.direct"
    android:required="true" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="jing.app.directwifi.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!-- Used for transferring files  after a successful connection -->
    <service
        android:name=".FileTransferService"
        android:enabled="true" />
</application>

</manifest>

这些是我的代码中使用的文件。形成了我发现的教程

new FileServerAsyncTask(getApplicationContext()) .execute();

开始接受传入数据的地方,所以当我需要执行这个异步线程时,所以任何人都可以帮助我在哪一部分我犯了错误。我如何在设备之间传输文件。

最佳答案

演示 wifi direct 项目中的 android 代码能够单向传递文件。 IE。您只能将文件从客户端发送到服务器。您需要进一步修改才能使其双向工作。

编辑 2:

为此,您需要知道两个已连接对等点的 IP 地址。使用我根据各种来源制作的以下功能,并在适当的地方进行修改。

    public static String getIpAddress() {
    try {
        List<NetworkInterface> interfaces = Collections
                .list(NetworkInterface.getNetworkInterfaces());
        /*
         * for (NetworkInterface networkInterface : interfaces) { Log.v(TAG,
         * "interface name " + networkInterface.getName() + "mac = " +
         * getMACAddress(networkInterface.getName())); }
         */

        for (NetworkInterface intf : interfaces) {
            if (!getMACAddress(intf.getName()).equalsIgnoreCase(
                    Globals.thisDeviceAddress)) {
                // Log.v(TAG, "ignore the interface " + intf.getName());
                // continue;
            }
            if (!intf.getName().contains("p2p"))
                continue;

            Log.v(TAG,
                    intf.getName() + "   " + getMACAddress(intf.getName()));

            List<InetAddress> addrs = Collections.list(intf
                    .getInetAddresses());

            for (InetAddress addr : addrs) {
                // Log.v(TAG, "inside");

                if (!addr.isLoopbackAddress()) {
                    // Log.v(TAG, "isnt loopback");
                    String sAddr = addr.getHostAddress().toUpperCase();
                    Log.v(TAG, "ip=" + sAddr);

                    boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);

                    if (isIPv4) {
                        if (sAddr.contains("192.168.49.")) {
                            Log.v(TAG, "ip = " + sAddr);
                            return sAddr;
                        }
                    }

                }

            }
        }

    } catch (Exception ex) {
        Log.v(TAG, "error in parsing");
    } // for now eat exceptions
    Log.v(TAG, "returning empty ip address");
    return "";
}

public static String getMACAddress(String interfaceName) {
        try {
            List<NetworkInterface> interfaces = Collections
                    .list(NetworkInterface.getNetworkInterfaces());

            for (NetworkInterface intf : interfaces) {
                if (interfaceName != null) {
                    if (!intf.getName().equalsIgnoreCase(interfaceName))
                        continue;
                }
                byte[] mac = intf.getHardwareAddress();
                if (mac == null)
                    return "";
                StringBuilder buf = new StringBuilder();
                for (int idx = 0; idx < mac.length; idx++)
                    buf.append(String.format("%02X:", mac[idx]));
                if (buf.length() > 0)
                    buf.deleteCharAt(buf.length() - 1);
                return buf.toString();
            }
        } catch (Exception ex) {
        } // for now eat exceptions
        return "";
        /*
         * try { // this is so Linux hack return
         * loadFileAsString("/sys/class/net/" +interfaceName +
         * "/address").toUpperCase().trim(); } catch (IOException ex) { return
         * null; }
         */
    }

关于android - 使用 wifi direct 在 Android 设备之间传输数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17715283/

相关文章:

java - 使用 jackson 和 parcelable 解析嵌套的自定义对象数组

javascript - 客户端和服务器端编程有什么区别?

javascript - 允许 javascript 访问服务器端变量,MVC4

networking - 在两台相邻计算机之间传输文件的最快方法

java - 如何解析带有过滤器的Api

滚动时 Android ListView 背景颜色更改 - colorCacheHint 未修复问题

android - 使用现有证书为 React Native Android 应用程序生成签名的 apk

javascript - 用于客户端和服务器端渲染的模板语言

Perl Net::SFTP::Foreign 从远程服务器获取最新文件

http - Emacs Lisp - 如何通过 HTTP 传输二进制文件?