2

こんにちは、私はしばらくこれに苦労しており、解決策を見つけることができません。

Java では、次のコードが機能します。

InetAddress serverAddr = InetAddress.getByName("myservice.local");
Socket socket = new Socket(serverAddr,  PoolServerAddress.DEFAULT_PORT);

Androidでも同じことが機能しません。「.local」を削除して、必要な権限をすべてマニフェストに追加しようとしました。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

また、そのコードを実行する前にマルチキャスト ロックを追加しようとしましたが、これを解決する方法はありません。

次の例外が発生します。

06-03 13:18:14.438: W/System.err(31636): java.net.UnknownHostException: Unable to    

resolve host <server_name>: No address associated with hostname

06-03 13:18:14.438: W/System.err(31636):    at 

java.net.InetAddress.lookupHostByName(InetAddress.java:434)

06-03 13:18:14.438: W/System.err(31636):    at 

java.net.InetAddress.getAllByNameImpl(InetAddress.java:239)

06-03 13:18:14.438: W/System.err(31636):    at    

java.net.InetAddress.getByName(InetAddress.java:292)

06-03 13:18:14.438: W/System.err(31636):    at 

com.example.jelly_test.MainActivity.connect(MainActivity.java:113)

06-03 13:18:14.438: W/System.err(31636):    at      

com.example.jelly_test.MainActivity$ResolvingThread.run(MainActivity.java:71)

06-03 13:18:14.438: W/System.err(31636): Caused by: libcore.io.GaiException:     

getaddrinfo 

failed: EAI_NODATA (No address associated with hostname)

06-03 13:18:14.438: W/System.err(31636):    at libcore.io.Posix.getaddrinfo(Native 

Method)

06-03 13:18:14.438: W/System.err(31636):    at 

libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:55)

06-03 13:18:14.438: W/System.err(31636):    at 

java.net.InetAddress.lookupHostByName(InetAddress.java:415)

06-03 13:18:14.438: W/System.err(31636):    ... 4 mor

サービスの代わりに ip を提供すると機能しますが、名前を提供できるようにする必要があります。また、名前をIPに解決するJmDNSを追加しようとしましたが、遅く、オフィスの内部サービスでのみ機能しますが、一部のサービスはネットワークの外部にありますが、AndroidではなくJavaバージョンで引き続きアクセスできます. 他に試すことができるものはありますか?アイデアが不足しているので、どうもありがとう....!

編集:私の問題は、Android にバグがあり、 myservice.company.com などのFQDNのみを受け入れるという事実によるものだと思います。

4

1 に答える 1

0

ここで要求されているのは、この問題を一時的に解決するために私が見つけたオプションです。最新の Android バージョン (執筆時点では 4.4) でも、バグはまだ修正されていません。

質問に示されているすべての必要なアクセス許可をマニフェストに追加してください。

オプション 1: JmDNS ライブラリを使用して、利用可能なサーバーのリストを検出し、自分のサーバーを見つけます。方法がわからない場合は、こちらのチュートリアルを参照してください: http://home.heeere.com/tech-androidjmdns.html この方法は遅く、一部のサービスが表示されないことがわかりました (zeroconf でアドバタイズする必要があります)。

オプション 2: name.local の代わりに name.comany.com などの完全修飾ドメイン名を入力するようにユーザーに依頼します。

オプション 3: これは実際にはハックですが、FQDN のタイプが someName.myComp.com であり、ユーザーが someName.local と入力したことがわかっている場合は、「.local」を削除して、ドメインが何であるかを推測する必要があります。

private String getTargetIp(String host) {

    System.out.println("Will try to create socket with "+host);

    MulticastLock multicastLock = null;
    String ipToReturn = null;
    Socket socket = null;
    try {

        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        multicastLock = wifiManager.createMulticastLock("any_name");
        multicastLock.acquire();
        DhcpInfo info = wifiManager.getDhcpInfo();

        int ip = info.ipAddress;
        InetAddress local = getInetAddress(ip);
        String localHostName = local.getCanonicalHostName();
        Log.d(TAG, "Device ip addr1 = "+local +" name= "+localHostName);
        String[] temp = localHostName.split("\\.");

        //replace the first part with our name and obtain FQDN
        String targetFullHostName=localHostName.replace(temp[0], host);
        Log.d(TAG, "targetFullHostName = "+targetFullHostName);

        //this is not mandatory but here we are trying to retrieve the ip address
        //it maybe also a way to check if we guessed right
        InetAddress serverAddr = InetAddress
                .getByName(targetFullHostName);
        socket = new Socket(serverAddr,
                PoolServerAddress.DEFAULT_PORT);
        ipToReturn = socket.getInetAddress().getHostAddress();

        Log.d(TAG, "socket remote address=" + ipToReturn);

    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }catch(Exception e){
        Log.e(TAG, "Other Exception");
    }

    finally {
        if (multicastLock != null)
            multicastLock.release();

        if(socket!=null)
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
    return ipToReturn;

}

オプション 4: API レベル 16 以降では、Android Service Discovery リスナーを使用して、利用可能なサービスを一覧表示し、探しているサービスを見つけることができます。これは JmDNS と同様の方法で機能します。すべてのサービスを検出し、リストから自分のサービスを見つけようとします。ドキュメントへのリンクは次のとおりです

于 2014-01-22T18:55:00.517 に答える