Search code examples
javaandroidclient-serverandroid-wifiwifi-direct

Android WiFi Direct - client/server - ECONNREFUSED (Connection refused) UPDATE


I have a problem with my Android client/server app. I would like to connect devices by WiFi Direct and send through some media files.

I made an Activity and Service for both Client and Server. Code is below.

ServerActivity:

import java.util.ArrayList;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WpsInfo;
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.PeerListListener;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ServerActivity extends Activity {

    private WifiP2pManager wifiManager;
    private Channel wifichannel;
    private BroadcastReceiver wifiServerReceiver;
    private IntentFilter wifiServerReceiverIntentFilter;
    private WifiP2pConfig config;
    private String deviceName;

    private Intent intent;

    PeerListListener myPeerListListener;
    ArrayList<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
    WifiP2pDeviceList peerList;

    TextView text;
    EditText et2;
    Button button1;
    ListView listView;
    ArrayAdapter<String> BTArrayAdapter;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.server_activity);

        // Block auto opening keyboard
        this.getWindow()
                .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

        listView = (ListView) findViewById(R.id.listView1);
        listView.setAdapter(BTArrayAdapter);

        wifiManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
        wifichannel = wifiManager.initialize(this, getMainLooper(), null);

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

        intent = null;

        registerReceiver(wifiServerReceiver, wifiServerReceiverIntentFilter);

        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                wifiManager.discoverPeers(wifichannel, null);
                wifiManager.requestPeers(wifichannel, new PeerListListener() {
                    @Override
                    public void onPeersAvailable(WifiP2pDeviceList peerList) {

                        peers.clear();
                        peers.addAll(peerList.getDeviceList());
                    }

                });

                for (int i = 0; i < peers.size(); i++) {
                    WifiP2pDevice device = peers.get(i);
                    deviceName = device.deviceName;
                    config = new WifiP2pConfig();
                    config.deviceAddress = device.deviceAddress;
                    config.wps.setup = WpsInfo.PBC;

                    wifiManager.connect(wifichannel, config, new ActionListener() {

                        @Override
                        public void onSuccess() {
                            Toast.makeText(
                                    getApplicationContext(),
                                    "Połączono z: " + deviceName + "\n Mac: "
                                            + config.deviceAddress, Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onFailure(int reason) {
                            Toast.makeText(getApplicationContext(), "Nie udało się połączyć",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
                }

                wifiManager.requestConnectionInfo(wifichannel,
                        new WifiP2pManager.ConnectionInfoListener() {

                            @Override
                            public void onConnectionInfoAvailable(final WifiP2pInfo info) {
                                // TODO Auto-generated method stub
                                String groupOwnerAddress = info.groupOwnerAddress.getHostAddress();

                                Toast.makeText(getApplicationContext(),
                                        "GroupOwnAddress: " + groupOwnerAddress, Toast.LENGTH_SHORT)
                                        .show();
                            }

                        });

                StartServer(null);

            }
        });
    }

    public void StartServer(View v) {
        // Construct our Intent specifying the Service

        intent = new Intent(this, ServerService.class);
        startService(intent);
    }

}

ServerService:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.widget.Toast;

public class ServerService extends IntentService {

    Handler mHandler;
    private int port = 2178;

    ServerSocket welcomeSocket = null;
    Socket socket = null;

    public ServerService() {
        super("ServerService");
        mHandler = new Handler();
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        try {
            mHandler.post(new DisplayToast(this, "Creating ServerSocket.."));
            welcomeSocket = new ServerSocket(port);
            welcomeSocket.setReuseAddress(true);
            mHandler.post(new DisplayToast(this, "Waiting for connection on port: "
                    + welcomeSocket.getLocalPort()));

            socket = welcomeSocket.accept();
            // while(true && flag){
            // socket = welcomeSocket.accept();
            mHandler.post(new DisplayToast(this, "Coneccted!"));

            // }

            mHandler.post(new DisplayToast(this, "Succes!"));
        } catch (IOException e) {
            mHandler.post(new DisplayToast(this, "IOException"));

        } catch (Exception e) {
            mHandler.post(new DisplayToast(this, "Exception"));

        }

        mHandler.post(new DisplayToast(this, "ServerService"));

    }

    /*
    public void onDestroy() {
        try {
            welcomeSocket.close();
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        stopSelf();
    }*/

}

class DisplayToast2 implements Runnable {
    private final Context mContext;
    String mText;

    public DisplayToast2(Context mContext, String text) {
        this.mContext = mContext;
        mText = text;
    }

    public void run() {
        Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
    }
}

ClientActivity:

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

public class ClientActivity extends Activity {

    Button button;
    private WifiP2pManager wifiManager;
    private Channel wifichannel;
    private BroadcastReceiver wifiClientReceiver;

    private IntentFilter wifiClientReceiverIntentFilter;
    private WifiP2pInfo wifiInfo;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.client_activity);

        // Block auto opening keyboard
        this.getWindow()
                .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        wifiManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);

        wifichannel = wifiManager.initialize(this, getMainLooper(), null);
        wifiClientReceiver = new WiFiClientBroadcastReceiver(wifiManager, wifichannel, this);

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

        wifiInfo = null;

        registerReceiver(wifiClientReceiver, wifiClientReceiverIntentFilter);

        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                StartClient(null);

            }
        });

    }

    public void setNetworkToReadyState(boolean status, WifiP2pInfo info, WifiP2pDevice device) {
        wifiInfo = info;
        // targetDevice = device;
        // connectedAndReadyToSendFile = status;
    }

    public void StartClient(View v) {

        Intent intent = new Intent(this, ClientService.class);
        intent.putExtra("wifiInfo", wifiInfo);

        if (wifiInfo == null) {
            Toast.makeText(this, "WifiInfo = null!", Toast.LENGTH_SHORT).show();
        }
        startService(intent);

    }

}

ClientService:

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pInfo;
import android.os.Handler;
import android.widget.Toast;

public class ClientService extends IntentService {

    Handler mHandler;
    private WifiP2pInfo wifiInfo;
    private int port = 2178;

    Socket clientSocket = null;
    OutputStream os = null;

    public ClientService() {
        super("ClientService");
        mHandler = new Handler();

    }

    @Override
    protected void onHandleIntent(Intent intent) {

        wifiInfo = (WifiP2pInfo) intent.getExtras().get("wifiInfo");

        InetAddress targetIP = wifiInfo.groupOwnerAddress;
        clientSocket = new Socket();

        if(wifiInfo.isGroupOwner)
        {
            try {
                mHandler.post(new DisplayToast(this, "Try to connect: /N IP: " + targetIP + "/nPort: " +port));

                clientSocket.connect(new InetSocketAddress(targetIP, port));

                mHandler.post(new DisplayToast(this, "Connected!"));

                //os = clientSocket.getOutputStream();

            } catch (IOException e) {
                mHandler.post(new DisplayToast(this, "serwer IOException: " + e.getMessage()));

            } catch (Exception e) {
                mHandler.post(new DisplayToast(this, "serwer Exception"));

            }
        }else{
            mHandler.post(new DisplayToast(this, "Group owner = " + wifiInfo.isGroupOwner));
        }


    }

    /*
    public void onDestroy()
    {

        try {
            os.close();
            clientSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        stopSelf();
    }*/
}

class DisplayToast implements Runnable {
    private final Context mContext;
    String mText;

    public DisplayToast(Context mContext, String text) {
        this.mContext = mContext;
        mText = text;
    }

    public void run() {
        Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    android:versionCode="1"
    android:versionName="1.0" >

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

    <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_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

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

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".ServerService"
            android:exported="false" />
        <service
            android:name=".ClientService"
            android:exported="false" />

        <activity android:name=".ServerActivity" >
        </activity>
        <activity android:name=".ClientActivity" >
        </activity>
    </application>

</manifest>

I am using two phones with WiFi Direct (Samsung GT-I9505 Android 4.4.2 and Samsung GT-I8190N Adroid 4.1.2). First of all I turned off all connections (BT, WIFI) and then connected by WiFi Direct. GT-I9505 is Server and other one is Client. While establishing a connection IOException error appears:

IOException: failed to connect to /192.168.49.1 (port 2178): connect failed: ECONNREFUSED (Connection refused)

I tried to use plenty of others Pors but nothing works. What I did wrong?

Thank you in advance for any help!

UPDATE:

I noticed that when I disconnect WiFi direct and connect again but in other direction it works but only for moment.


Solution

  • the main issue with your code is that you do need to make it event driven, in the current state I'm surprised that it even does anything really.

    So, please try making it to something like following: 1. Start Discovering peers, once you get Peers Changed event, then do requestPeers 2. if you need some listener etc. to be ready for you on the other side, then you likely would identify those devices by advertising a service, so next look start discovery for services. 3. After you get service discovered, start 5-second timer to wait for any additional, reset the timer after each service discovered, and once the timer finally gets to run uninterrupted 5 seconds, you likely have discovered all services available at that time. 4. Select ONE service and connect to that device (you can not have multiple connection really). 5. Once you get event that you are connected, then use requestConnectionInfo to get info for the connection.

    Then do remember that before you start you need to create the local service, so the other side can see it. Then, if your device gets selected as Group owner, you could keep the advertisement on, and let more clients connect to you. But if you are selected as Client, then you can not have incoming connections, so you should get rid of the advertisement.