2013-07-18 3 views
3

Я недавно реализовал wifi прямо в свой проект, моя цель - передать значение строки между двумя подключенными через wifidirect устройствами, когда какое-то из условий моего приложения удовлетворяет. Теперь я перечислил всех сверстников, а также сделал связь между выбранным peer.what моя идея заключается в передаче json-файла между устройствами. Перед тем, как попытаться выполнить эту идею, я пытаюсь передать файл изображения между двумя устройствами. i последовал за шагами от android wifidirect tutorial.list peers, а связь между сверстниками - это успех, но я не могу передать данные между устройствами. Следующим является мой код. FileTransferService.javaПередача данных между устройствами Android с использованием Wi-Fi Direct?

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

} 

} 

Manifest

<?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> 

Это файлы, используемые в моем коде .FORM учебник я обнаружил, что

новый FileServerAsyncTask (g etApplicationContext()) .execute();

, где вводные данные начинаются, поэтому, когда мне нужно выполнить этот поток asyn, так что мне кто-нибудь помогает, в какой части я совершил ошибку. Как я могу перенести файл между устройствами.

+0

Если вы используете один и тот же код по прямому примеру wi-fi, у вас не возникнет проблем с каким-либо процессом всей программы. Тем не менее, я бы сказал, что лучше отлаживать код, особенно для вашего метода copyFile. – misterbaykal

ответ

9

Код андроида из файла проекта demo wifi может передавать файл в однонаправленном виде. то есть. вы можете отправлять файлы только с сервера на сервер. Вам нужны модификации furthur, чтобы они работали в обоих направлениях.

EDIT 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; } 
     */ 
    } 
+0

Я не могу отправить изображение в обоих направлениях. на самом деле, я не могу получить IP-адрес клиента, то есть не групповой одноранговый узел. –

+0

где есть метод с именем ** getMACAddress ** .. ?? –

+0

Извините. Я обновил его с отсутствующей функцией. – Dipendra

1

Я думаю, что способ, которым вы инициализируете клиента, создает проблему.

Вы должны вызвать эту

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

после того, как соединение установлено, и проверить, если это клиент.

Теперь вы создаете клиентский сокет только в том случае, если это сервер (владелец группы) и всегда, когда вы вызываете, чтобы получить MAC-адрес.

Так что на стороне клиента вы не инициализируете сокет и так не можете получить файл.

После проверки демонстрации примера WifiDirect, предоставленной в SDK, вы можете получить больше информации.

Смежные вопросы