Android Open Source - AndroidToArduinoSonicComms Sonic Service






From Project

Back to project page AndroidToArduinoSonicComms.

License

The source code is released under:

GNU General Public License

If you think the Android project AndroidToArduinoSonicComms listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright (c) 2012 rob@theultimatelabs.com.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html//from www  . j a v  a2s .  co m
 * 
 * Contributors:
 *     rob@theultimatelabs.com - initial API and implementation
 ******************************************************************************/
package com.theultimatelabs.sonic;

import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.util.HashMap;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder.AudioSource;
import android.media.RingtoneManager;
import android.net.DhcpInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.net.wifi.WifiManager.WifiLock;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;

//import com.theultimatelabs.intercom.TimeoutRunnable.ResponseDelayRunnable;

public class SonicService extends Service {
  
  private AudioRecord record;
  private AudioTrack track;
  //private final static int BUF_SIZE = 4096;
  //private Handler mTimeoutHandler;
  //private Handler mResponseDelayHandler;
  //private TimeoutRunnable mTimeoutRunnable;
  //private ResponseDelayRunnable mResponseDelayRunnable;
  //private PowerManager mPowerManager;
  
  //private final int STREAM_TYPE = AudioManager.STREAM_MUSIC;
  //private AudioManager audioManager;
  //private MulticastLock mMulticastLock;
  //private MediaPlayer mStartTalkBeep;
  //private MediaPlayer mStartListenBeep;
  //private boolean mStartTalkBeepSent = true;
  //private boolean mStopTalkBeepSent = true;
  //private static final double THRESHOLD = 0.75;
  //public final static String TAG = "IntercomService";
  //private static final long TIMEOUT = 20000; // 10 seconds
  //private static final long RESPONSE_DELAY = 100;

  @Override
  public void onCreate() {
    MyLog.v("onCreate");

    this.audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    this.audioOut = initializeAudioOut();
    this.audioIn = initializeAudioIn();
    
    /*mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
        | PowerManager.ACQUIRE_CAUSES_WAKEUP, "Intercom WakeLock");
    mWakeLock.setReferenceCounted(false);*/

    new AudioIn().start();
    new AudioOut().start();

    /*mTimeoutHandler = new Handler();
    mResponseDelayHandler = new Handler();
    mTimeoutRunnable = new TimeoutRunnable();
    mResponseDelayRunnable = new ResponseDelayRunnable();

    mStartTalkBeep = MediaPlayer.create(getApplicationContext(),
        R.raw.beep3);
    mStartListenBeep = MediaPlayer.create(getApplicationContext(),
        R.raw.opbeep);

    onStatusAll();*/

    /*
     * Log.v(TAG, "Setup RTP"); AudioManager audioManager = (AudioManager)
     * getApplicationContext() .getSystemService(Context.AUDIO_SERVICE);
     * audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
     * 
     * 
     * mAudioStream = new AudioStream(mLocalAddress);
     * Log.v(TAG,mAudioStream.toString()); //AudioCodec codec =
     * AudioCodec.getCodec(100, "AMR/8000", "mode-set=1");
     * //mAudioStream.setCodec(codec);
     * mAudioStream.setCodec(AudioCodec.PCMU);
     * mAudioStream.setMode(AudioStream.MODE_NORMAL);
     * 
     * mAudioGroup = new AudioGroup(); Log.v(TAG,mAudioGroup.toString());
     * mAudioGroup.setMode(AudioGroup.MODE_NORMAL);
     * Log.v(TAG,mAudioStream.toString());
     * Log.v(TAG,mAudioGroup.toString());
     * 
     * mAudioStream.join(mAudioGroup); Log.v(TAG,"RTP setup");
     * 
     * 
     * // AudioManager AudioManager audioManager = (AudioManager)
     * getSystemService(AUDIO_SERVICE);
     * audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
     * 
     * 
     * try {
     * Log.v(TAG,"Creating audio stream on "+mLocalAddress.toString());
     * mAudioStream = new AudioStream(mLocalAddress); } catch
     * (SocketException e) { Log.d("Quit", "Socket Error"); System.exit(1);
     * } mAudioStream.setMode(RtpStream.MODE_NORMAL);
     * mAudioStream.setCodec(AudioCodec.PCMU);
     * mAudioStream.associate(mBroadcastAddress
     * ,mAudioStream.getLocalPort());//8585);//this.createInet(192,168,0,7),
     * 8585);
     * 
     * // Initialize an AudioGroup and attach an AudioStream AudioGroup
     * main_grp = new AudioGroup();
     * main_grp.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
     * mAudioStream.join(main_grp); Log.d("Log","PORT: "+
     * mAudioStream.getLocalPort());
     */

  }
  
  @Override
  public void onStart(Intent intent, int startId) {

    log.i("onStart");
    if (intent == null || intent.getAction() == null)
      return;
    log.i(intent.getAction());
    
    if (intent.getAction().equals("msg")) {
      DTMF()

    }

  }


  /*private void onTalk(boolean talkRequest) {

    mServerTalk = talkRequest;

    if (mServerTalk) {
      Log.i(TAG, "startTalk");

      synchronized (mState) {

        mStartTalkBeepSent = false;

        if (mState == SLEEP) {

          mWifiLock.acquire();
        } else if (mState == CLIENT) {
          Log.w(TAG, "Trying to talk while client");
        }
        mPrivate = false;
        mState = SERVER;
        mAudioRecord.startRecording();
        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
        // beep();

      }
    } else {
      Log.i(TAG, "stopTalk");

      synchronized (mState) {
        mStopTalkBeepSent = false;
        mAudioRecord.stop();
        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
        mPrivate = getSharedPreferences(PREFS, 0).getBoolean("private",
            false);
        if (mServerListen == false) {
          mState = SLEEP;
          mWifiLock.release();
          new Dismiss().start();
        }
      }

    }

    Intent status = new Intent(IntercomWidget.ACTION_STATUS);
    status.putExtra("talk", mServerTalk);
    status.putExtra("private", mPrivate);
    Log.v(TAG, "SendBroadcast");
    sendBroadcast(status);

  }*/

  /*private void stopAudio() {
    // mBroadcastAudioTrack.flush();
    // mBroadcastAudioTrack.pause();
    for (AudioTrack track : mAudioTracks.values()) {
      track.flush();
      track.pause();
    }
  }

  private void closeAudio() {
    mBroadcastAudioTrack.pause();
    mBroadcastAudioTrack.flush();
    stopAudio();
    mAudioTracks = new HashMap<InetAddress, AudioTrack>();
  }*/

  /*private void onListen(boolean listenRequest) {
    mServerListen = listenRequest;

    if (mServerListen) {
      Log.i(TAG, "startListen");

      synchronized (mState) {

        if (mState == SLEEP) {
          mWifiLock.acquire();
          new Wakeup().start();
          // byte buf[] = new byte[4096];
          // try {
          // mServerSocket.send(new DatagramPacket(buf, buf.length,
          // mBroadcastAddress, DST_PORT));
          // } catch (IOException e) {
          // e.printStackTrace();
          // }
        }

        mSilent = false;

      }
    } else {
      Log.i(TAG, "stopListen");
      synchronized (mState) {
        stopAudio();
        mSilent = getSharedPreferences(PREFS, 0).getBoolean("silent",
            false);
        if (mServerTalk == false) {
          mState = SLEEP;
          mWifiLock.release();
          new Dismiss().start();
        }

      }

    }
    Intent status = new Intent(IntercomWidget.ACTION_STATUS);
    status.putExtra("listen", mServerListen);
    status.putExtra("silent", mSilent);
    Log.v(TAG, "SendBroadcast");
    sendBroadcast(status);

  }*/

  


  private class Wakeup extends Thread {
    public final static String TAG = "Wakeup";

    // Some devices, like the Nexus Galaxy, won't wakeup to broadcast
    // packets,
    // so we send a single empty packet to every client on the subnet.
    @Override
    public void run() {
      Log.i(TAG, "Running wifi wakeup!");
      byte buf[] = new byte[2];
      buf[0] = buf[1] = 1;
      byte[] subnet = mBroadcastAddress.getAddress();
      // Log.i(TAG,String.format("subnet[0] = %x subnet[4] = %x",
      // subnet[0], subnet[3]));
      for (int i = 1; i < 254; i++) {
        subnet[3] = (byte) i;// i;
        Log.v(TAG, String.format("Wakeup %d", i));
        try {
          mServerSocket.send(new DatagramPacket(buf, 2, InetAddress
              .getByAddress(subnet), DATA_DST_PORT));
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      Log.d(TAG, "Running wifi wakeup done");
    }
  }

  private class Dismiss extends Thread {
    public final static String TAG = "Dismiss";

    @Override
    public void run() {
      Log.i(TAG, "Running wifi dismiss");
      byte buf[] = new byte[2];
      buf[0] = buf[1] = 0;
      try {
        mServerSocket.send(new DatagramPacket(buf, 2,
            mBroadcastAddress, DATA_DST_PORT));
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  public class ControlIn extends Thread {

    public final static String TAG = "ControlIn";

    public void run() {

      byte[] buf = new byte[128];

      DatagramPacket pkt = new DatagramPacket(buf, 128);

      while (!this.isInterrupted()) {

        try {
          mCtrlReceiveSocket.receive(pkt);
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          Log.e(TAG, "Error receiving packet");
          return;
        }
      }
    }
  }

  private void serverAudioIn(byte[] buf, int N, double rms) throws UnknownHostException, IOException {

    if (mStartTalkBeepSent == false) {
      try {
        InputStream beepStream = getResources().openRawResource(
            R.raw.beep3);
        int len = beepStream.available();
        byte[] beepBuf = new byte[len];

        beepStream.read(beepBuf);
        mServerSocket.send(new DatagramPacket(beepBuf, len, InetAddress
            .getByName("224.0.0.10"), DATA_DST_PORT));
      } catch (Exception e) {
        e.printStackTrace();
        Log.e(TAG, "Error sending start talk beep");
      }

      mStartTalkBeepSent = true;

    } else if (mStopTalkBeepSent == false) {
      try {
        InputStream beepStream = getResources().openRawResource(
            R.raw.beep2);
        int len = beepStream.available();
        byte[] beepBuf = new byte[len];

        beepStream.read(beepBuf);
        mServerSocket.send(new DatagramPacket(beepBuf, len, InetAddress
            .getByName("224.0.0.10"), DATA_DST_PORT));
      } catch (Exception e) {
        e.printStackTrace();
        Log.e(TAG, "Error sending start talk beep");
      }

      mStopTalkBeepSent = true;
    } 
    
    if (rms > THRESHOLD && mServerTalk) {
        mServerSocket.send(new DatagramPacket(buf,
            N, InetAddress
                .getByName("224.0.0.10"),
            DATA_DST_PORT));
    }  

  }
  
  private void clientAudioIn(byte[] buf, int N, double rms) throws IOException {
    if (rms > THRESHOLD && !mPrivate) {
      // Only send small packets
      for (int i = 0; i < N; i += 256) {
        int len = Math.min(N - i, 256);
        mClientSocket.send(new DatagramPacket(
            buf, i, len, mServerAddress,
            DATA_DST_PORT));
      }
    }
  }

  public class AudioIn extends Thread {

    public final static String TAG = "AudioIn";

    @Override
    public void run() {

      try {

        while (!this.isInterrupted()) {

          byte[] buf = new byte[BUF_SIZE];
          int N = mAudioRecord.read(buf, 0, buf.length);

          if (N > 0) {

            double rms = 0;
            for (int i = 0; i < N; i += 2) {
              /*
               * ByteBuffer bb = ByteBuffer.allocate(2);
               * bb.order(ByteOrder.LITTLE_ENDIAN);
               * bb.put(buf[i]); bb.put(buf[i+1]); short pcm =
               * bb.getShort(0); rms += Math.pow(pcm, 2);
               */
              rms += (double) buf[i + 1] * buf[i + 1];
            }
            rms = Math.sqrt(rms / N);

            Log.v(TAG, String.format(
                "Got mic buffer of %d bytes with rms = %f", N,
                rms));

            if(mState==SERVER) {
              serverAudioIn(buf, N, rms);
            }
            else if (mState==CLIENT){
              clientAudioIn(buf, N, rms);
            }
            else {
              Log.e(TAG, "Recording while sleeping");
              gotoSleep();              
            }
          } else {
            try {
              Thread.sleep(100);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }

        }
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.e(TAG, "Error recording audio");
      } finally {
        mAudioRecord.stop();
      }
    }
  }
  
  private void resetTimeout() {
    mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
    mTimeoutHandler.postDelayed(mTimeoutRunnable, TIMEOUT);
  }
  
  private void wakeupAudioOut(DatagramPacket pkt) {
    if (pkt.getPort() == SERVER_DATA_DST_PORT) {
      Log.i(TAG, "Now in CLIENT mode");
      
      mState = CLIENT;
      
      mWakeLock.acquire();
      mWifiLock.acquire();
      mMulticastLock.acquire();

      Intent status = new Intent(IntercomWidget.ACTION_STATUS);
      mServerAddress = pkt.getAddress();

      if (!mSilent) {
        mBroadcastAudioTrack.flush();
        status.putExtra("listen", true);
      }

      if (!mPrivate) {
        mAudioRecord.startRecording();
        status.putExtra("talk", true);
      }

      mAudioManager.setStreamVolume(STREAM_TYPE,
          mAudioManager.getStreamMaxVolume(STREAM_TYPE),
          0);

      mStartListenBeep.start();

      sendBroadcast(status);
      
      mBroadcastAudioTrack.play();
      
    }
    else if (pkt.getPort() == CLIENT_DATA_SRC_PORT) {
      Log.e(TAG, "Got packet from client while sleeping");
    }
  }
  
  private void serverAudioOut(DatagramPacket pkt) {
    if(pkt.getPort() == SERVER_DATA_DST_PORT) {
      Log.e(TAG,"Server got packet from server\n");
      //Ignore it
    }
    else if (pkt.getPort() == CLIENT_DATA_SRC_PORT) {
      
      if (!mAudioTracks.containsKey(pkt.getAddress())) {
        Log.i(TAG, "open new track for "
            + pkt.getAddress().toString());
        AudioTrack track = initializeAudioOut();
        track.play();
        mAudioTracks.put(pkt.getAddress(), track);
      }
      if (mServerListen) {
        // Log.i(TAG,mAudioTracks.get(pkt.getAddress()).getS)
        AudioTrack track = mAudioTracks.get(pkt.getAddress());
        track.write(pkt.getData(), 0, pkt.getLength());
      }
    }
    
  }

  private void clientAudioOut(DatagramPacket pkt){
    
    if (pkt.getPort() == SERVER_DATA_DST_PORT) {
      
      if (mState == CLIENT) {
        Log.v(TAG, "In client mode, got packet from server");
        
        resetTimeout();

        // Delay response to cut down on traffic
        mAudioRecord.stop();
        mResponseDelayHandler
            .removeCallbacks(mResponseDelayRunnable);
        mResponseDelayHandler.postDelayed(
            mResponseDelayRunnable, RESPONSE_DELAY);

        if (!mSilent && pkt.getLength() > 2) {
          mBroadcastAudioTrack.write(pkt.getData(), 0,
              pkt.getLength());
                          // the last buffer
        } else if (pkt.getLength() == 2) {
          if (pkt.getData()[0] == 0) {
            gotoSleep();
          } else if (pkt.getData()[0] == 1) {

          }
        }
      } 
      
    }
    else if (pkt.getPort() == CLIENT_DATA_SRC_PORT) {
      Log.w(TAG,
          "Received client packets while in client mode, ignoring");
    }
  }
  public class AudioOut extends Thread {

    public final static String TAG = "AudioOut";

    @Override
    public void run() {

      byte[] buf = new byte[BUF_SIZE];

      DatagramPacket pkt = new DatagramPacket(buf, BUF_SIZE);

      while (!this.isInterrupted()) {

        try {
          mDataReceiveSocket.receive(pkt);
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          Log.e(TAG, "Error receiving packet");
          return;
        }

        if (pkt.getAddress().equals(mLocalAddress))
          continue;

        Log.v(TAG, String.format(
            "Received %d byte udp packet from %s local=%s port=%d",
            pkt.getLength(), pkt.getAddress().toString(),
            mLocalAddress.toString(), pkt.getPort()));

        if(mState==SERVER) {
          serverAudioOut(pkt);
        }
        else if(mState==CLIENT) {
          clientAudioOut(pkt);
        }
        else if (mState==SLEEP) {
          wakeupAudioOut(pkt);
        }
        // synchronized (mState) {
      }
    }
  }

  class TimeoutRunnable implements Runnable {

    public void run() {
      Log.i(TAG, "TimeOut");
      gotoSleep();
    }

  };

  void gotoSleep() {
    synchronized (mState) {
      // if (mState != SLEEP) {
      mState = SLEEP;
      closeAudio();
      mAudioRecord.stop();
      if (mWakeLock.isHeld()) {
        mWakeLock.release();
      }
      if (mWifiLock.isHeld()) {
        mWifiLock.release();
      }
      if (mMulticastLock.isHeld()) {
        mMulticastLock.release();
      }
      Intent status = new Intent(IntercomWidget.ACTION_STATUS);
      mServerTalk = mServerListen = false;
      status.putExtra("talk", mServerTalk);
      status.putExtra("listen", mServerListen);
      sendBroadcast(status);
    }
  }

  class ResponseDelayRunnable implements Runnable {

    public void run() {
      Log.i(TAG, "ResponseDelayRunnable");
      synchronized (mState) {
        mAudioRecord.startRecording();
      }
    }
  };

  public InetAddress getLocalAddress() throws IOException {
    WifiManager wifi = (WifiManager) this
        .getSystemService(Context.WIFI_SERVICE);
    int local = wifi.getDhcpInfo().ipAddress;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
      quads[k] = (byte) ((local >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
  }

  public InetAddress getBroadcastAddress() throws IOException {
    WifiManager wifi = (WifiManager) this
        .getSystemService(Context.WIFI_SERVICE);
    DhcpInfo dhcp = wifi.getDhcpInfo();
    // handle null somehow

    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
      quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
  }

  public void beep() {
    Uri soundUri = RingtoneManager
        .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    MediaPlayer mMediaPlayer = new MediaPlayer();
    try {
      mMediaPlayer.setDataSource(getApplicationContext(), soundUri);
    } catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalStateException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    final AudioManager audioManager = (AudioManager) getApplicationContext()
        .getSystemService(Context.AUDIO_SERVICE);
    if (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != 0) {
      mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
      mMediaPlayer.setLooping(false);
      try {
        mMediaPlayer.prepare();
      } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      mMediaPlayer.start();
    }
  }

  private AudioTrack initializeAudioOut() {
    int minBufSize = AudioTrack.getMinBufferSize(8000,
        AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

    Log.w(TAG, String.format("AudioOut minBufSize %d", minBufSize));
    assert BUF_SIZE >= minBufSize;

    return new AudioTrack(STREAM_TYPE, 8000, AudioFormat.CHANNEL_OUT_MONO,
        AudioFormat.ENCODING_PCM_16BIT, minBufSize,
        AudioTrack.MODE_STREAM);

  }

  private boolean initializeAudioIn() {
    int minBufSize = AudioRecord.getMinBufferSize(8000,
        AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);

    Log.w(TAG, String.format("AudioIn minBufSize %d", minBufSize));
    assert BUF_SIZE >= minBufSize;

    mAudioRecord = new AudioRecord(AudioSource.VOICE_COMMUNICATION, 8000,
        AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
        minBufSize);

    return true;
  }

  @Override
  public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
  }

}




Java Source Code List

com.theultimatelabs.sonic.SonicActivity.java
com.theultimatelabs.sonic.SonicService.java
com.theultimatelabs.sonic.log.java