This will be reported to the caller activity as an intent's extra on * {@link android.app.Activity#onActivityResult(int, int, Intent)}. */ public static final int STATUS_ERROR_NODE_NOT_FOUND = 1; /** * Error code indicating that an IO issue was encountered.. * *
This will be reported to the caller activity as an intent's extra on * {@link android.app.Activity#onActivityResult(int, int, Intent)}. */ public static final int STATUS_ERROR_IO_EXCEPTION = 2; /** * Error code indicating that the configuration provided in * {@link com.google.devrel.wcl.widgets.list.WearableListConfig} was not correct. * *
This will be reported to the caller activity as an intent's extra on * {@link android.app.Activity#onActivityResult(int, int, Intent)}. */ public static final int STATUS_ERROR_INVALID_CONFIGURATION = 3; /** * Error code indicating that the AudioRecord api encountered an issue while trying to record * the sound data from the microphone. * *
This will be reported to the caller activity as an intent's extra on * {@link android.app.Activity#onActivityResult(int, int, Intent)}. */ public static final int STATUS_ERROR_RECORDER_FAILED = 4; @ColorRes private int mOffColorResId = R.color.wcl_voice_recorder_off; @ColorRes private int mOnColorResId = R.color.wcl_voice_recorder_on; private boolean mRecording; private CircularButton mCircularButton; private WclSoundManager mSoundManager; private String mRecordingFileName; private WearManager mWearManager; private boolean mStreaming; private String mNodeId; private String mCapability; private MyWearableChannelOutputListener mChannelListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.wcl_recorder); mWearManager = WearManager.getInstance(); mCircularButton = (CircularButton) findViewById(R.id.button); mCircularButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WclRecorderActivity.this.toggleRecording(); } }); setAmbientEnabled(); } @Override protected void onStop() { if (mChannelListener != null) { mChannelListener.cleanUp(); mChannelListener = null; } if (mSoundManager != null) { mSoundManager.cleanUp(); mSoundManager = null; } super.onStop(); } @Override protected void onStart() { super.onStart(); setUpRecording(); } private void setUpRecording() { int rippleColor = R.color.wcl_voice_recorder_ripple; int micResource = R.drawable.wcl_voice_recorder_mic; mStreaming = false; Bundle extras = getIntent().getExtras(); if (extras != null) { mOffColorResId = extras.getInt(EXTRA_OFF_COLOR_RES_ID, R.color.wcl_voice_recorder_off); mOnColorResId = extras.getInt(EXTRA_ON_COLOR_RES_ID, R.color.wcl_voice_recorder_on); rippleColor = extras.getInt(EXTRA_RIPPLE_COLOR_RES_ID, R.color.wcl_voice_recorder_ripple); micResource = extras.getInt(EXTRA_MIC_RES_ID, R.drawable.wcl_voice_recorder_mic); mRecordingFileName = extras.getString(EXTRA_RECORDING_FILE_NAME); mStreaming = extras.getBoolean(EXTRA_STREAMING, false); mNodeId = extras.getString(EXTRA_NODE_ID); mCapability = extras.getString(EXTRA_NODE_CAPABILITY); } mCircularButton.setColor(ContextCompat.getColor(this, mOffColorResId)); mCircularButton.setRippleColor(rippleColor); mCircularButton.setImageResource(micResource); } private boolean isNodeSettingsValidForStreaming() { if (mCapability != null && mNodeId != null) { // we can't have both of these null Log.e(TAG, "When streaming, only one of nodeId or capability should be specified"); Intent intent = new Intent(); finishWithResult(intent, STATUS_ERROR_INVALID_CONFIGURATION); return false; } else if (mCapability == null && mNodeId == null) { Log.e(TAG, "When streaming, nodeId or capability should be specified"); Intent intent = new Intent(); finishWithResult(intent, STATUS_ERROR_INVALID_CONFIGURATION); return false; } return true; } private Node getNodeForStream() { if (mCapability != null) { Set nodes = mWearManager.getNodesForCapability(mCapability, new SingleNodeFilter(new NearbyFilter())); if (nodes.isEmpty()) { Log.e(TAG, "No node with the specified capability was found"); return null; } else { return nodes.iterator().next(); } } else { Node node = mWearManager.getNodeById(mNodeId); if (node == null) { Log.e(TAG, "No node with the specified node id was found"); return null; } else { return node; } } } private void toggleRecording() { if (mRecording) { // currently recording, so this click should stop recording mRecording = false; mSoundManager.stopRecording(); Intent intent = new Intent(); intent.putExtra(EXTRA_RECORDING_FILE_NAME, mRecordingFileName); finishWithResult(intent, STATUS_SUCCESS); } else { mCircularButton.setColor(ContextCompat.getColor(this, mOnColorResId)); if (mStreaming) { // we want to stream the data from microphone if (!isNodeSettingsValidForStreaming()) { return; } Node targetNode = getNodeForStream(); if (targetNode == null) { finishWithResult(new Intent(), STATUS_ERROR_NODE_NOT_FOUND); return; } mRecording = true; mSoundManager = new WclSoundManager(this); Utils.LOGD(TAG, "Targeting node: " + targetNode); if (mChannelListener != null) { mChannelListener.cleanUp(); } mChannelListener = new MyWearableChannelOutputListener(this, mSoundManager); new WearFileTransfer.Builder(targetNode) .setOnChannelOutputStreamListener(mChannelListener) .build() .requestOutputStream(); } else { // we want to save the MIC bytes to a file mSoundManager = new WclSoundManager(this); mRecording = true; mSoundManager.record(mRecordingFileName, new WclSoundManager.OnVoiceRecordingFinishedListener() { @Override public void onRecordingFinished(int reason, String reasonMessage) { finishWithRecorderError(reason); } }); } } } private void finishWithRecorderError(int reason) { Intent intent = new Intent(); switch (reason) { case WclSoundManager.ERROR_AUDIO_RECORD_FAILED: finishWithResult(intent, STATUS_ERROR_RECORDER_FAILED); break; case WclSoundManager.ERROR_INVALID_CONFIGURATION: finishWithResult(intent, STATUS_ERROR_INVALID_CONFIGURATION); break; } } private void finishWithResult(Intent intent, int status) { mSoundManager = null; mCircularButton.setColor(ContextCompat.getColor(this, mOffColorResId)); intent.putExtra(EXTRA_RECORDING_STATUS, status); setResult(RESULT_OK, intent); finish(); overridePendingTransition(0, android.R.anim.slide_out_right); } private static class MyWearableChannelOutputListener implements WearFileTransfer.OnWearableChannelOutputStreamListener { private WclRecorderActivity mActivity; private WclSoundManager mSoundManager; MyWearableChannelOutputListener(WclRecorderActivity activity, WclSoundManager soundManager) { mActivity = activity; mSoundManager = soundManager; } @Override public void onOutputStreamForChannelReady(int statusCode, Channel channel, OutputStream outputStream) { if (statusCode == WearableStatusCodes.SUCCESS) { mSoundManager.record(outputStream, new WclSoundManager.OnVoiceRecordingFinishedListener() { @Override public void onRecordingFinished(final int reason, String reasonMessage) { if (mActivity != null) { mActivity.finishWithRecorderError(reason); } } }); } else { Log.e(TAG, "Failed to open a channel, status code: " + statusCode); Intent intent = new Intent(); if (mActivity != null) { mActivity.finishWithResult(intent, STATUS_ERROR_IO_EXCEPTION); } cleanUp(); } } private void cleanUp() { mActivity = null; } } }