我最近在我的项目中实现了 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();
}
}
}
}
}
}
}
主要活动.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();
}
}
显现
<?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>
这些是我的代码中使用的文件。形成我发现的教程
新的 FileServerAsyncTask(getApplicationContext()) .execute();
传入数据开始接受的地方,所以当我需要执行这个异步线程时,任何人都可以帮助我在哪个部分犯了错误。如何在设备之间传输文件。