/** * This file is part of the Protect Baby Monitor. * * Protect Baby Monitor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Protect Baby Monitor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Protect Baby Monitor. If not, see . */ package protect.babymonitor; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.content.Context; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MonitorActivity extends Activity { final String TAG = "BabyMonitor"; NsdManager _nsdManager; NsdManager.RegistrationListener _registrationListener; Thread _serviceThread; private void serviceConnection(Socket socket) throws IOException { MonitorActivity.this.runOnUiThread(new Runnable() { @Override public void run() { final TextView statusText = (TextView) findViewById(R.id.textStatus); statusText.setText(R.string.streaming); } }); int frequency = 11025; int channelConfiguration = AudioFormat.CHANNEL_IN_MONO; int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding); AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, bufferSize); byte[] buffer = new byte[bufferSize*2]; try { audioRecord.startRecording(); OutputStream out = socket.getOutputStream(); socket.setSendBufferSize(bufferSize); Log.d(TAG, "Socket send buffer size: " + socket.getSendBufferSize()); while (socket.isConnected() && Thread.currentThread().isInterrupted() == false) { int read = audioRecord.read(buffer, 0, bufferSize); out.write(buffer, 0, read); } } finally { audioRecord.stop(); } } @Override protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "Baby monitor start"); _nsdManager = (NsdManager)this.getSystemService(Context.NSD_SERVICE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_monitor); _serviceThread = new Thread(new Runnable() { @Override public void run() { while(Thread.currentThread().isInterrupted() == false) { ServerSocket serverSocket = null; try { // Initialize a server socket on the next available port. serverSocket = new ServerSocket(0); // Store the chosen port. int localPort = serverSocket.getLocalPort(); // Register the service so that parent devices can // locate the child device registerService(localPort); // Wait for a parent to find us and connect Socket socket = serverSocket.accept(); Log.i(TAG, "Connection from parent device received"); // We now have a client connection. // Unregister so no other clients will // attempt to connect serverSocket.close(); serverSocket = null; unregisterService(); try { serviceConnection(socket); } finally { socket.close(); } } catch(IOException e) { Log.e(TAG, "Connection failed", e); } // If an exception was thrown before the connection // could be closed, clean it up if(serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { Log.e(TAG, "Failed to close stray connection", e); } serverSocket = null; } } } }); _serviceThread.start(); } @Override protected void onDestroy() { Log.i(TAG, "Baby monitor stop"); unregisterService(); if(_serviceThread != null) { _serviceThread.interrupt(); _serviceThread = null; } super.onDestroy(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.start, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private void registerService(int port) { NsdServiceInfo serviceInfo = new NsdServiceInfo(); serviceInfo.setServiceName("ProtectBabyMonitor"); serviceInfo.setServiceType("_babymonitor._tcp."); serviceInfo.setPort(port); _registrationListener = new NsdManager.RegistrationListener() { @Override public void onServiceRegistered(NsdServiceInfo NsdServiceInfo) { // Save the service name. Android may have changed it in order to // resolve a conflict, so update the name you initially requested // with the name Android actually used. final String serviceName = NsdServiceInfo.getServiceName(); Log.i(TAG, "Service name: " + serviceName); MonitorActivity.this.runOnUiThread(new Runnable() { @Override public void run() { final TextView statusText = (TextView) findViewById(R.id.textStatus); statusText.setText(R.string.waitingForParent); final TextView serviceText = (TextView) findViewById(R.id.textService); serviceText.setText(serviceName); } }); } @Override public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) { // Registration failed! Put debugging code here to determine why. Log.e(TAG, "Registration failed: " + errorCode); } @Override public void onServiceUnregistered(NsdServiceInfo arg0) { // Service has been unregistered. This only happens when you call // NsdManager.unregisterService() and pass in this listener. Log.i(TAG, "Unregistering service"); } @Override public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) { // Unregistration failed. Put debugging code here to determine why. Log.e(TAG, "Unregistration failed: " + errorCode); } }; _nsdManager.registerService( serviceInfo, NsdManager.PROTOCOL_DNS_SD, _registrationListener); } /** * Uhregistered the service and assigns the listener * to null. */ private void unregisterService() { if(_registrationListener != null) { Log.i(TAG, "Unregistering monitoring service"); _nsdManager.unregisterService(_registrationListener); _registrationListener = null; } } }