summaryrefslogtreecommitdiffstats
path: root/samples/training
diff options
context:
space:
mode:
authorAlexander Lucas <alexlucas@google.com>2012-06-18 16:25:19 -0700
committerAlexander Lucas <alexlucas@google.com>2012-06-18 16:25:19 -0700
commit8a8046a91865f972d38809d6f0a8c2f4d56fb17e (patch)
tree70d394122f70792e85eafc2c6d77684063b414b5 /samples/training
parent35c48dcfe16d8b43fb17524ccc6167d9b11114d2 (diff)
downloadandroid_development-8a8046a91865f972d38809d6f0a8c2f4d56fb17e.tar.gz
android_development-8a8046a91865f972d38809d6f0a8c2f4d56fb17e.tar.bz2
android_development-8a8046a91865f972d38809d6f0a8c2f4d56fb17e.zip
Initial commit of NsdChat application
Change-Id: I157ddfe38b79f01e72e8b52fa16d666c92f08254
Diffstat (limited to 'samples/training')
-rw-r--r--samples/training/NsdChat/Android.mk18
-rw-r--r--samples/training/NsdChat/AndroidManifest.xml40
-rw-r--r--samples/training/NsdChat/proguard.cfg26
-rw-r--r--samples/training/NsdChat/project.properties14
-rw-r--r--samples/training/NsdChat/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--samples/training/NsdChat/res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--samples/training/NsdChat/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--samples/training/NsdChat/res/layout/main.xml70
-rw-r--r--samples/training/NsdChat/res/values/strings.xml26
-rw-r--r--samples/training/NsdChat/src/com/example/android/nsdchat/ChatConnection.java286
-rw-r--r--samples/training/NsdChat/src/com/example/android/nsdchat/NsdChatActivity.java125
-rw-r--r--samples/training/NsdChat/src/com/example/android/nsdchat/NsdHelper.java172
13 files changed, 777 insertions, 0 deletions
diff --git a/samples/training/NsdChat/Android.mk b/samples/training/NsdChat/Android.mk
new file mode 100644
index 000000000..8cea77b15
--- /dev/null
+++ b/samples/training/NsdChat/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := NsdChat
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/training/NsdChat/AndroidManifest.xml b/samples/training/NsdChat/AndroidManifest.xml
new file mode 100644
index 000000000..bb5e73c7c
--- /dev/null
+++ b/samples/training/NsdChat/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.nsdchat"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+ <uses-permission android:required="true" android:name="android.permission.INTERNET"/>
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name="com.example.android.nsdchat.NsdChatActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/samples/training/NsdChat/proguard.cfg b/samples/training/NsdChat/proguard.cfg
new file mode 100644
index 000000000..52f242d8a
--- /dev/null
+++ b/samples/training/NsdChat/proguard.cfg
@@ -0,0 +1,26 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Keep onClickListeners.
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
diff --git a/samples/training/NsdChat/project.properties b/samples/training/NsdChat/project.properties
new file mode 100644
index 000000000..9b84a6b4b
--- /dev/null
+++ b/samples/training/NsdChat/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
diff --git a/samples/training/NsdChat/res/drawable-hdpi/ic_launcher.png b/samples/training/NsdChat/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 000000000..96a442e5b
--- /dev/null
+++ b/samples/training/NsdChat/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/NsdChat/res/drawable-ldpi/ic_launcher.png b/samples/training/NsdChat/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 000000000..99238729d
--- /dev/null
+++ b/samples/training/NsdChat/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/NsdChat/res/drawable-mdpi/ic_launcher.png b/samples/training/NsdChat/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 000000000..359047dfa
--- /dev/null
+++ b/samples/training/NsdChat/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.png b/samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..71c6d760f
--- /dev/null
+++ b/samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/training/NsdChat/res/layout/main.xml b/samples/training/NsdChat/res/layout/main.xml
new file mode 100644
index 000000000..e516458f1
--- /dev/null
+++ b/samples/training/NsdChat/res/layout/main.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="96dp"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/advertise_btn"
+ android:layout_width="96dp"
+ android:layout_height="64dp"
+ android:onClick="clickAdvertise"
+ android:text="@string/register" />
+
+ <Button
+ android:id="@+id/discover_btn"
+ android:layout_width="96dp"
+ android:layout_height="64dp"
+ android:onClick="clickDiscover"
+ android:text="@string/discover" />
+
+ <Button
+ android:id="@+id/connect_btn"
+ android:layout_width="96dp"
+ android:layout_height="64dp"
+ android:onClick="clickConnect"
+ android:text="@string/connect" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="fill_parent"
+ android:layout_height="200dp"
+ android:focusable="true" />
+
+ <EditText
+ android:id="@+id/chatInput"
+ android:layout_width="fill_parent"
+ android:layout_height="80dp"
+ android:inputType="text"
+ android:singleLine="true" />
+
+ <Button
+ android:id="@+id/send_btn"
+ android:layout_width="96dp"
+ android:layout_height="64dp"
+ android:onClick="clickSend"
+ android:text="@string/send" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/samples/training/NsdChat/res/values/strings.xml b/samples/training/NsdChat/res/values/strings.xml
new file mode 100644
index 000000000..1e15e362d
--- /dev/null
+++ b/samples/training/NsdChat/res/values/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+
+ <string name="app_name">NsdChat</string>
+
+ <string name="connect">Connect</string>
+ <string name="discover">Discover</string>
+ <string name="register">Register</string>
+ <string name="send">Send</string>
+
+</resources>
diff --git a/samples/training/NsdChat/src/com/example/android/nsdchat/ChatConnection.java b/samples/training/NsdChat/src/com/example/android/nsdchat/ChatConnection.java
new file mode 100644
index 000000000..80aa9fd7c
--- /dev/null
+++ b/samples/training/NsdChat/src/com/example/android/nsdchat/ChatConnection.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.nsdchat;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class ChatConnection {
+
+ private Handler mUpdateHandler;
+ private ChatServer mChatServer;
+ private ChatClient mChatClient;
+
+ private static final String TAG = "ChatConnection";
+
+ private Socket mSocket;
+ private int mPort = -1;
+
+ public ChatConnection(Handler handler) {
+ mUpdateHandler = handler;
+ mChatServer = new ChatServer(handler);
+ }
+
+ public void tearDown() {
+ mChatServer.tearDown();
+ mChatClient.tearDown();
+ }
+
+ public void connectToServer(InetAddress address, int port) {
+ mChatClient = new ChatClient(address, port);
+ }
+
+ public void sendMessage(String msg) {
+ if (mChatClient != null) {
+ mChatClient.sendMessage(msg);
+ }
+ }
+
+ public int getLocalPort() {
+ return mPort;
+ }
+
+ public void setLocalPort(int port) {
+ mPort = port;
+ }
+
+
+ public synchronized void updateMessages(String msg, boolean local) {
+ Log.e(TAG, "Updating message: " + msg);
+
+ if (local) {
+ msg = "me: " + msg;
+ } else {
+ msg = "them: " + msg;
+ }
+
+ Bundle messageBundle = new Bundle();
+ messageBundle.putString("msg", msg);
+
+ Message message = new Message();
+ message.setData(messageBundle);
+ mUpdateHandler.sendMessage(message);
+
+ }
+
+ private synchronized void setSocket(Socket socket) {
+ Log.d(TAG, "setSocket being called.");
+ if (socket == null) {
+ Log.d(TAG, "Setting a null socket.");
+ }
+ if (mSocket != null) {
+ if (mSocket.isConnected()) {
+ try {
+ mSocket.close();
+ } catch (IOException e) {
+ // TODO(alexlucas): Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ mSocket = socket;
+ }
+
+ private Socket getSocket() {
+ return mSocket;
+ }
+
+ private class ChatServer {
+ ServerSocket mServerSocket = null;
+ Thread mThread = null;
+
+ public ChatServer(Handler handler) {
+ mThread = new Thread(new ServerThread());
+ mThread.start();
+ }
+
+ public void tearDown() {
+ mThread.interrupt();
+ try {
+ mServerSocket.close();
+ } catch (IOException ioe) {
+ Log.e(TAG, "Error when closing server socket.");
+ }
+ }
+
+ class ServerThread implements Runnable {
+
+ @Override
+ public void run() {
+
+ try {
+ // Since discovery will happen via Nsd, we don't need to care which port is
+ // used. Just grab an available one and advertise it via Nsd.
+ mServerSocket = new ServerSocket(0);
+ setLocalPort(mServerSocket.getLocalPort());
+
+ while (!Thread.currentThread().isInterrupted()) {
+ Log.d(TAG, "ServerSocket Created, awaiting connection");
+ setSocket(mServerSocket.accept());
+ Log.d(TAG, "Connected.");
+ if (mChatClient == null) {
+ int port = mSocket.getPort();
+ InetAddress address = mSocket.getInetAddress();
+ connectToServer(address, port);
+ }
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error creating ServerSocket: ", e);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private class ChatClient {
+
+ private InetAddress mAddress;
+ private int PORT;
+
+ private final String CLIENT_TAG = "ChatClient";
+
+ private Thread mSendThread;
+ private Thread mRecThread;
+
+ public ChatClient(InetAddress address, int port) {
+
+ Log.d(CLIENT_TAG, "Creating chatClient");
+ this.mAddress = address;
+ this.PORT = port;
+
+ mSendThread = new Thread(new SendingThread());
+ mSendThread.start();
+ }
+
+ class SendingThread implements Runnable {
+
+ BlockingQueue<String> mMessageQueue;
+ private int QUEUE_CAPACITY = 10;
+
+ public SendingThread() {
+ mMessageQueue = new ArrayBlockingQueue<String>(QUEUE_CAPACITY);
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (getSocket() == null) {
+ setSocket(new Socket(mAddress, PORT));
+ Log.d(CLIENT_TAG, "Client-side socket initialized.");
+
+ } else {
+ Log.d(CLIENT_TAG, "Socket already initialized. skipping!");
+ }
+
+ mRecThread = new Thread(new ReceivingThread());
+ mRecThread.start();
+
+ } catch (UnknownHostException e) {
+ Log.d(CLIENT_TAG, "Initializing socket failed, UHE", e);
+ } catch (IOException e) {
+ Log.d(CLIENT_TAG, "Initializing socket failed, IOE.", e);
+ }
+
+ while (true) {
+ try {
+ String msg = mMessageQueue.take();
+ sendMessage(msg);
+ } catch (InterruptedException ie) {
+ Log.d(CLIENT_TAG, "Message sending loop interrupted, exiting");
+ }
+ }
+ }
+ }
+
+ class ReceivingThread implements Runnable {
+
+ @Override
+ public void run() {
+
+ BufferedReader input;
+ try {
+ input = new BufferedReader(new InputStreamReader(
+ mSocket.getInputStream()));
+ while (!Thread.currentThread().isInterrupted()) {
+
+ String messageStr = null;
+ messageStr = input.readLine();
+ if (messageStr != null) {
+ Log.d(CLIENT_TAG, "Read from the stream: " + messageStr);
+ updateMessages(messageStr, false);
+ } else {
+ Log.d(CLIENT_TAG, "The nulls! The nulls!");
+ break;
+ }
+ }
+ input.close();
+
+ } catch (IOException e) {
+ Log.e(CLIENT_TAG, "Server loop error: ", e);
+ }
+ }
+ }
+
+ public void tearDown() {
+ try {
+ getSocket().close();
+ } catch (IOException ioe) {
+ Log.e(CLIENT_TAG, "Error when closing server socket.");
+ }
+ }
+
+ public void sendMessage(String msg) {
+ try {
+ Socket socket = getSocket();
+ if (socket == null) {
+ Log.d(CLIENT_TAG, "Socket is null, wtf?");
+ } else if (socket.getOutputStream() == null) {
+ Log.d(CLIENT_TAG, "Socket output stream is null, wtf?");
+ }
+
+ PrintWriter out = new PrintWriter(
+ new BufferedWriter(
+ new OutputStreamWriter(getSocket().getOutputStream())), true);
+ out.println(msg);
+ out.flush();
+ updateMessages(msg, true);
+ } catch (UnknownHostException e) {
+ Log.d(CLIENT_TAG, "Unknown Host", e);
+ } catch (IOException e) {
+ Log.d(CLIENT_TAG, "I/O Exception", e);
+ } catch (Exception e) {
+ Log.d(CLIENT_TAG, "Error3", e);
+ }
+ Log.d(CLIENT_TAG, "Client sent message: " + msg);
+ }
+ }
+}
diff --git a/samples/training/NsdChat/src/com/example/android/nsdchat/NsdChatActivity.java b/samples/training/NsdChat/src/com/example/android/nsdchat/NsdChatActivity.java
new file mode 100644
index 000000000..47ee09893
--- /dev/null
+++ b/samples/training/NsdChat/src/com/example/android/nsdchat/NsdChatActivity.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.nsdchat;
+
+import android.app.Activity;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.example.android.nsdchat.NsdHelper;
+
+public class NsdChatActivity extends Activity {
+
+ NsdHelper mNsdHelper;
+
+ private TextView mStatusView;
+ private Handler mUpdateHandler;
+
+ public static final String TAG = "NsdChat";
+
+ ChatConnection mConnection;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ mStatusView = (TextView) findViewById(R.id.status);
+
+ mUpdateHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ String chatLine = msg.getData().getString("msg");
+ addChatLine(chatLine);
+ }
+ };
+
+ mConnection = new ChatConnection(mUpdateHandler);
+
+ mNsdHelper = new NsdHelper(this);
+ mNsdHelper.initializeNsd();
+
+ }
+
+ public void clickAdvertise(View v) {
+ // Register service
+ if(mConnection.getLocalPort() > -1) {
+ mNsdHelper.registerService(mConnection.getLocalPort());
+ } else {
+ Log.d(TAG, "ServerSocket isn't bound.");
+ }
+ }
+
+ public void clickDiscover(View v) {
+ mNsdHelper.discoverServices();
+ }
+
+ public void clickConnect(View v) {
+ NsdServiceInfo service = mNsdHelper.getChosenServiceInfo();
+ if (service != null) {
+ Log.d(TAG, "Connecting.");
+ mConnection.connectToServer(service.getHost(),
+ service.getPort());
+ } else {
+ Log.d(TAG, "No service to connect to!");
+ }
+ }
+
+ public void clickSend(View v) {
+ EditText messageView = (EditText) this.findViewById(R.id.chatInput);
+ if (messageView != null) {
+ String messageString = messageView.getText().toString();
+ if (!messageString.isEmpty()) {
+ mConnection.sendMessage(messageString);
+ }
+ messageView.setText("");
+ }
+ }
+
+ public void addChatLine(String line) {
+ mStatusView.append("\n" + line);
+ }
+
+ @Override
+ protected void onPause() {
+ if (mNsdHelper != null) {
+ mNsdHelper.stopDiscovery();
+ }
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mNsdHelper != null) {
+ mNsdHelper.discoverServices();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ mNsdHelper.tearDown();
+ mConnection.tearDown();
+ super.onDestroy();
+ }
+}
diff --git a/samples/training/NsdChat/src/com/example/android/nsdchat/NsdHelper.java b/samples/training/NsdChat/src/com/example/android/nsdchat/NsdHelper.java
new file mode 100644
index 000000000..568a79bbd
--- /dev/null
+++ b/samples/training/NsdChat/src/com/example/android/nsdchat/NsdHelper.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.nsdchat;
+
+import android.content.Context;
+import android.net.nsd.NsdServiceInfo;
+import android.net.nsd.NsdManager;
+import android.util.Log;
+
+public class NsdHelper {
+
+ Context mContext;
+
+ NsdManager mNsdManager;
+ NsdManager.ResolveListener mResolveListener;
+ NsdManager.DiscoveryListener mDiscoveryListener;
+ NsdManager.RegistrationListener mRegistrationListener;
+
+ public static final String SERVICE_TYPE = "_http._tcp.";
+
+ public static final String TAG = "NsdHelper";
+ public String mServiceName = "NsdChat";
+
+ NsdServiceInfo mService;
+
+ public NsdHelper(Context context) {
+ mContext = context;
+ mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
+ }
+
+ public void initializeNsd() {
+ initializeResolveListener();
+ initializeDiscoveryListener();
+ initializeRegistrationListener();
+
+ //mNsdManager.init(mContext.getMainLooper(), this);
+
+ }
+
+ public void initializeDiscoveryListener() {
+ mDiscoveryListener = new NsdManager.DiscoveryListener() {
+
+ @Override
+ public void onDiscoveryStarted(String regType) {
+ Log.d(TAG, "Service discovery started");
+ }
+
+ @Override
+ public void onServiceFound(NsdServiceInfo service) {
+ Log.d(TAG, "Service discovery success" + service);
+ if (!service.getServiceType().equals(SERVICE_TYPE)) {
+ Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
+ } else if (service.getServiceName().equals(mServiceName)) {
+ Log.d(TAG, "Same machine: " + mServiceName);
+ } else if (service.getServiceName().contains(mServiceName)){
+ mNsdManager.resolveService(service, mResolveListener);
+ }
+ }
+
+ @Override
+ public void onServiceLost(NsdServiceInfo service) {
+ Log.e(TAG, "service lost" + service);
+ if (mService == service) {
+ mService = null;
+ }
+ }
+
+ @Override
+ public void onDiscoveryStopped(String serviceType) {
+ Log.i(TAG, "Discovery stopped: " + serviceType);
+ }
+
+ @Override
+ public void onStartDiscoveryFailed(String serviceType, int errorCode) {
+ Log.e(TAG, "Discovery failed: Error code:" + errorCode);
+ mNsdManager.stopServiceDiscovery(this);
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(String serviceType, int errorCode) {
+ Log.e(TAG, "Discovery failed: Error code:" + errorCode);
+ mNsdManager.stopServiceDiscovery(this);
+ }
+ };
+ }
+
+ public void initializeResolveListener() {
+ mResolveListener = new NsdManager.ResolveListener() {
+
+ @Override
+ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Log.e(TAG, "Resolve failed" + errorCode);
+ }
+
+ @Override
+ public void onServiceResolved(NsdServiceInfo serviceInfo) {
+ Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
+
+ if (serviceInfo.getServiceName().equals(mServiceName)) {
+ Log.d(TAG, "Same IP.");
+ return;
+ }
+ mService = serviceInfo;
+ }
+ };
+ }
+
+ public void initializeRegistrationListener() {
+ mRegistrationListener = new NsdManager.RegistrationListener() {
+
+ @Override
+ public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) {
+ mServiceName = NsdServiceInfo.getServiceName();
+ }
+
+ @Override
+ public void onRegistrationFailed(NsdServiceInfo arg0, int arg1) {
+ }
+
+ @Override
+ public void onServiceUnregistered(NsdServiceInfo arg0) {
+ }
+
+ @Override
+ public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ }
+
+ };
+ }
+
+ public void registerService(int port) {
+ NsdServiceInfo serviceInfo = new NsdServiceInfo();
+ serviceInfo.setPort(port);
+ serviceInfo.setServiceName(mServiceName);
+ serviceInfo.setServiceType(SERVICE_TYPE);
+
+ mNsdManager.registerService(
+ serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
+
+ }
+
+ public void discoverServices() {
+ mNsdManager.discoverServices(
+ SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
+ }
+
+ public void stopDiscovery() {
+ mNsdManager.stopServiceDiscovery(mDiscoveryListener);
+ }
+
+ public NsdServiceInfo getChosenServiceInfo() {
+ return mService;
+ }
+
+ public void tearDown() {
+ mNsdManager.unregisterService(mRegistrationListener);
+ }
+}