美文网首页Android安卓硬件
android wifi 点对点传输

android wifi 点对点传输

作者: changchengfeng | 来源:发表于2016-12-17 13:01 被阅读1823次

    WiFi点对点传输不用连接网络和热点,可进行近距离通信,比蓝牙传输要远,速度更快。

    1.初始化

    1.1配置权限

    Android点对点传输只能在Android 4.0 (API level 14)以后的版本中使用;

    <uses-sdk android:minSdkVersion="14" />
    <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" />
    

    也可以在代码中进行判断 是否支持WiFi点对点传输 定义一个接收WIFI_P2P_STATE_CHANGED_ACTION 的IntentFiltert的BroadcastReceiver

    @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) {
                // Wifi P2P is enabled
            } else {
                // Wi-Fi P2P is not enabled
            }
        }
        ...
    }
    

    1.2获取 WifiP2pManager.Channel

    WifiP2pManager mManager;
    Channel mChannel;
    BroadcastReceiver mReceiver;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState){
        ...
            mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
            mChannel = mManager.initialize(this, getMainLooper(), null);
            mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel);
        ...
    }
    
    
    

    1.3创建广播接收器接收Wi-Fi P2P Intents

      IntentFilter mIntentFilter;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState){
        ...
            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);
        ...
    }
    
    
    public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
    
        private WifiP2pManager mManager;
        private Channel mChannel;
    
        public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel) {
            super();
            this.mManager = manager;
            this.mChannel = channel;
     
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
    
            if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
              //判断是否支持 wifi点对点传输
            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
         // 查找到设备列表
            } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
               //获取到连接状态改变的详细信息
            } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
              //自身设备信息改变
            }
        }
    }
    
    

    1.4注册BroadcastReceiver

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

    2.查找设备

    mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            ...
        }
    
        @Override
        public void onFailure(int reasonCode) {
            ...
        }
    });
    

    3.发现设备

    系统会发送一条WIFI_P2P_PEERS_CHANGED_ACTION广播,然后调用 requestPeers在myPeerListListener获取设备列表

    PeerListListener myPeerListListener;
    ...
    if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
    
        if (mManager != null) {
         
          mManager.requestPeers(mChannel, myPeerListListener);
        }
    }
    
    

    4.连接设备

    WifiP2pDevice device;
    WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = device.deviceAddress;
    config.wps.setup = WpsInfo.PBC;
    mManager.connect(mChannel, config, new ActionListener() {
    
        @Override
        public void onSuccess() {
            //success logic
        }
    
        @Override
        public void onFailure(int reason) {
            //failure logic
        }
    });
    
    

    5.获取连接状态信息

    连接后会系统会发送WIFI_P2P_CONNECTION_CHANGED_ACTION广播可在此处获取NetworkInfo,然后调用requestConnectionInfo获取连接信息

    else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
    
                if (manager == null) {
                    return;
                }
    
                NetworkInfo networkInfo = intent
                        .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
    
                if (networkInfo.isConnected()) {
                    manager.requestConnectionInfo(channel, myConnectionInfoListener);
                } else {  
                }
    }
    
    
    //在myConnectionInfoListener回调onConnectionInfoAvailable方法中获取到WifiP2pInfo
    
       myConnectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
    
                @Override
                public void onConnectionInfoAvailable(WifiP2pInfo info) {
    
                    if (info != null) {
                        mInfo = info;
                        if (info.groupFormed && info.isGroupOwner) {
                            new FileServerAsyncTask(MainActivity.this, MainActivity.this.findViewById(R.id.status_text))
                                    .execute();
                        } else if (info.groupFormed) {
    
                        }
    
    
    
                    }
                }
            };
    
    

    6.传输数据

    6.1服务器端(info.isGroupOwner作为服务器端)新建AsyncTask绑定端口等待连接,接收到图片数据后进行展示:

     public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
    
            private Context context;
    
    
            public FileServerAsyncTask(Context context, View statusText) {
                this.context = context;
            }
    
            @Override
            protected String doInBackground(Void... params) {
                try {
                    ServerSocket serverSocket = new ServerSocket(8988);
                    Socket client = serverSocket.accept();
    
                    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();
                    InputStream inputstream = client.getInputStream();
                    copyFile(inputstream, new FileOutputStream(f));
                    serverSocket.close();
                    return f.getAbsolutePath();
                } catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                    return null;
                }
            }
    
            @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);
                }
            }
        }
    

    6.2客户端:发送图片给服务器端

     Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                            intent.setType("image/*");
                            startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
    
      @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
    
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                Intent serviceIntent = new Intent(this, FileTransferService.class);
                serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
                serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
                serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
                        mInfo.groupOwnerAddress.getHostAddress());
                serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
                startService(serviceIntent);
            }
    
    
        }
    
    
    public static class FileTransferService extends IntentService {
    
            private static final int SOCKET_TIMEOUT = 3600;
            public static String ACTION_SEND_FILE = "android.intent.action.SEND_FILE";
            public static String EXTRAS_FILE_PATH = "extras_file_path";
            public static String EXTRAS_GROUP_OWNER_ADDRESS = "extras_group_owner_address";
            public static String EXTRAS_GROUP_OWNER_PORT = "extras_group_owner_port";
    
    
            public FileTransferService(String name) {
                super(name);
            }
    
            public FileTransferService() {
                super("FileTransferService");
    
            }
    
            @Override
            protected void onHandleIntent(@Nullable 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 {
                        socket.bind(null);
                        socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
                        OutputStream stream = socket.getOutputStream();
                        ContentResolver cr = context.getContentResolver();
                        InputStream is = null;
                        try {
                            is = cr.openInputStream(Uri.parse(fileUri));
                        } catch (FileNotFoundException e) {
                            Log.d(TAG, e.toString());
                        }
                        copyFile(is, stream);
                    } catch (IOException e) {
                    } finally {
                        if (socket != null) {
                            if (socket.isConnected()) {
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    // Give up
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
    
                }
            }
        }
    
      public static boolean copyFile(InputStream inputStream, OutputStream out) {
            byte buf[] = new byte[1024];
            int len;
            try {
                while ((len = inputStream.read(buf)) != -1) {
                    out.write(buf, 0, len);
    
                }
                out.close();
                inputStream.close();
            } catch (IOException e) {
          
                return false;
            }
            return true;
        }
    
    

    7.断开连接

    if (mManager != null) {
    
         if (mDevice == null
                 || mDevice.status == WifiP2pDevice.CONNECTED) {
    
             mManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {
    
                 @Override
                 public void onFailure(int reasonCode) {
                     Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
    
                 }
    
                 @Override
                 public void onSuccess() {
                     btnSearch.setText("search");
                 }
    
             });
         } else if (mDevice.status == WifiP2pDevice.AVAILABLE
                 || mDevice.status == WifiP2pDevice.INVITED) {
    
             mManager.cancelConnect(mChannel, new WifiP2pManager.ActionListener() {
    
                 @Override
                 public void onSuccess() {
                     btnSearch.setText("search");
                     Toast.makeText(MainActivity.this, "Aborting connection",
                             Toast.LENGTH_SHORT).show();
                 }
    
                 @Override
                 public void onFailure(int reasonCode) {
                     Toast.makeText(MainActivity.this,
                             "Connect abort request failed. Reason Code: " + reasonCode,
                             Toast.LENGTH_SHORT).show();
                 }
             });
         }
     }
    

    看到评论需要源码
    源码下载地址

    相关文章

      网友评论

      • 或许丶有时候:楼主你好,能发一篇这个源码给我吗?
        44d3387e09f3:@changchengfeng 你好,我想请问一下这样子iOS 也能连接吗?
        changchengfeng:@我弟是个程序员 刚上传了源码,写的比较简单,只能单向传输,你可以自己完善。
        我弟是个程序员:有源码吗?这短时间也是要搞这个相关的:innocent:

      本文标题:android wifi 点对点传输

      本文链接:https://www.haomeiwen.com/subject/xcwnmttx.html