Initial commit of NsdChat application
Change-Id: I157ddfe38b79f01e72e8b52fa16d666c92f08254
This commit is contained in:
18
samples/training/NsdChat/Android.mk
Normal file
18
samples/training/NsdChat/Android.mk
Normal file
@@ -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))
|
||||||
40
samples/training/NsdChat/AndroidManifest.xml
Normal file
40
samples/training/NsdChat/AndroidManifest.xml
Normal file
@@ -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>
|
||||||
26
samples/training/NsdChat/proguard.cfg
Normal file
26
samples/training/NsdChat/proguard.cfg
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
14
samples/training/NsdChat/project.properties
Normal file
14
samples/training/NsdChat/project.properties
Normal file
@@ -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
|
||||||
BIN
samples/training/NsdChat/res/drawable-hdpi/ic_launcher.png
Normal file
BIN
samples/training/NsdChat/res/drawable-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
BIN
samples/training/NsdChat/res/drawable-ldpi/ic_launcher.png
Normal file
BIN
samples/training/NsdChat/res/drawable-ldpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
BIN
samples/training/NsdChat/res/drawable-mdpi/ic_launcher.png
Normal file
BIN
samples/training/NsdChat/res/drawable-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.png
Normal file
BIN
samples/training/NsdChat/res/drawable-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
70
samples/training/NsdChat/res/layout/main.xml
Normal file
70
samples/training/NsdChat/res/layout/main.xml
Normal file
@@ -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>
|
||||||
26
samples/training/NsdChat/res/values/strings.xml
Normal file
26
samples/training/NsdChat/res/values/strings.xml
Normal file
@@ -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>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user