如何继续使用SSDP在Android上搜索本地网络上的设备?

时间:2017-01-23 18:12:44

标签: java android

我正在开发一个应用程序,它在启动时使用SSDP连接到服务器并检索它的IP地址。 SSDP类不是由我开发的,所以我也对那里的任何重构建议持开放态度,但对于这个问题,我正在尝试实现使用SSDP继续搜索服务器的逻辑,同时避免任何崩溃或超时异常被抛出

目前,我的演示者类使用私有的AsyncTask类来获取服务器的响应(在评论中称为MOTA或OTA站):

private class SearchAction extends AsyncTask<Void,Void,String>{
    Context context;

    SearchAction(Context context){
        this.context = context;
    }

    protected void onPreExecute(){
        view.changeVisibility(true);
    }

    @Override
    protected String doInBackground(Void... params) {
        //Get IP Address from MOTA Station
        SSDP ssdp = new SSDP();
        String ip = ssdp.request();
        Log.d(TAG,"IP Address is: "+ ip);
        return ip;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    protected void onPostExecute(String ip_address){
        Log.d(TAG, "IP address is:  " + ip_address);


        if (Objects.equals(ip_address, "")) {

            view.changeVisibility(false);
            // TODO: give choice to user to enter IP address manually
        }else {
            //otherwise go to MainActivity directly
            Intent intent = new Intent(context, Main2Activity.class);
            intent.putExtra("IP", ip_address);
            view.navigateToMainActivity(intent);

        }
    }
}

SSDP类看起来像这样:

公共课SSDP {

public String tag = "SSDP";

//m-search string for specific OTA board
private static final String query =
        "M-SEARCH * HTTP/1.1\r\n" +
                "HOST: 239.255.255.250:1900\r\n"+
                "MAN: \"ssdp:discover\"\r\n"+
                "MX: 1\r\n"+
                "ST: urn:schemas-upnp-org:device:MediaServer:1\r\n"+  // Use for OTA Board
                //"ST: ssdp:all\r\n"+  // Use this for all UPnP Devices
                "\r\n";
private static final int port = 1900;

//ssdp to find IP address from server
public String request(){
    //response is to contain the server response in String type
    //initialize send data and receive data in bytes
    String response="";
    byte[] sendData = new byte[1024];
    byte[] receiveData = new byte[1024];
    //transfer m-search string in bytes
    sendData = query.getBytes();
    //wrap m-search data, multicast address and port number to the send package
    DatagramPacket sendPacket = null;
    try {
        sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.250"), port);
    } catch (UnknownHostException e) {
        Log.d(tag,"Unknown Host Exception Thrown after creating DatagramPacket to send to server");
        e.printStackTrace();
    }
    //create socket to transport data
    DatagramSocket clientSocket = null;
    try {
        clientSocket = new DatagramSocket();
    } catch (SocketException e) {
        Log.d(tag, "Socket Exception thrown when creating socket to transport data");
        e.printStackTrace();
    }
    //send out data
    try {
        if (clientSocket != null) {
            //time out is important
            clientSocket.setSoTimeout(10000);
            clientSocket.send(sendPacket);
        }
    } catch (IOException e) {
        Log.d(tag, "IOException thrown when sending data to socket");
        e.printStackTrace();
    }
    // receive data
    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
    try {
        if (clientSocket != null) {
            clientSocket.receive(receivePacket);
        }
    } catch (IOException e) {
        Log.d(tag,"IOException thrown when receiving data");
        e.printStackTrace();
    }
    //the target package should not be empty
    //try three times

    for (int i =0; i<3; i++){
        Log.d(tag,"Checking target package to see if its empty on iteration#: "+i);
        response = new String(receivePacket.getData());
        Log.d(tag,"Response contains: "+response);
        if (response.contains("Location:")){
            break;
        }
    }


    String adress = "";
    //filter IP address from "Location"
    Matcher ma = Pattern.compile("Location: (.*)").matcher(response);
    if (ma.find()){
        adress+=ma.group(1);
        adress = adress.split("/")[2].split(":")[0];
    }

    return adress;

}
}

我的问题是,在从服务器收到响应之前,如何重复调用request()(或者request()的特定部分)?

1 个答案:

答案 0 :(得分:0)

我使用Timer Task每5秒执行一次AsyncTask。

private Runnable ssdpTimerTask = new Runnable() {
        @Override
        public void run() {
            startStationSearch();
            Log.d(TAG,"Running SSDP search - iteration: "+ssdpIteration);
            ssdpIteration++;
            mHandler.postDelayed(ssdpTimerTask,5000);
        }
    };