| /* |
| * Copyright (C) 2009 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.android.scoaudiotest; |
| |
| import android.app.Activity; |
| import android.bluetooth.BluetoothAdapter; |
| import android.bluetooth.BluetoothDevice; |
| import android.bluetooth.BluetoothHeadset; |
| import android.bluetooth.BluetoothProfile; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.res.AssetFileDescriptor; |
| import android.media.AudioManager; |
| import android.media.MediaPlayer; |
| import android.media.MediaRecorder; |
| import android.os.Bundle; |
| import android.os.Environment; |
| import android.os.Handler; |
| import android.speech.tts.TextToSpeech; |
| import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener; |
| import android.util.Log; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.widget.ArrayAdapter; |
| import android.widget.CheckBox; |
| import android.widget.CompoundButton; |
| import android.widget.CompoundButton.OnCheckedChangeListener; |
| import android.widget.EditText; |
| import android.widget.ImageButton; |
| import android.widget.ImageView; |
| import android.widget.Spinner; |
| import android.widget.TextView; |
| import android.widget.ToggleButton; |
| |
| import java.io.File; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| |
| public class ScoAudioTest extends Activity { |
| |
| final static String TAG = "ScoAudioTest"; |
| |
| AudioManager mAudioManager; |
| AudioManager mAudioManager2; |
| boolean mForceScoOn; |
| ToggleButton mScoButton; |
| ToggleButton mVoiceDialerButton; |
| boolean mVoiceDialerOn; |
| String mLastRecordedFile; |
| SimpleMediaController mMediaControllers[] = new SimpleMediaController[2]; |
| private TextToSpeech mTts; |
| private HashMap<String, String> mTtsParams; |
| private int mOriginalVoiceVolume; |
| EditText mSpeakText; |
| boolean mTtsInited; |
| private Handler mHandler; |
| private static final String UTTERANCE = "utterance"; |
| private static Intent sVoiceCommandIntent; |
| private File mSampleFile; |
| ToggleButton mTtsToFileButton; |
| private boolean mTtsToFile; |
| private int mCurrentMode; |
| Spinner mModeSpinner; |
| private BluetoothHeadset mBluetoothHeadset; |
| private BluetoothDevice mBluetoothHeadsetDevice; |
| TextView mScoStateTxt; |
| TextView mVdStateTxt; |
| |
| private final BroadcastReceiver mReceiver = new ScoBroadcastReceiver(); |
| |
| public ScoAudioTest() { |
| Log.e(TAG, "contructor"); |
| } |
| |
| /** Called when the activity is first created. */ |
| @Override |
| public void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| |
| setContentView(R.layout.scoaudiotest); |
| |
| mScoStateTxt = findViewById(R.id.scoStateTxt); |
| mVdStateTxt = findViewById(R.id.vdStateTxt); |
| |
| IntentFilter intentFilter = |
| new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); |
| intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); |
| intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); |
| registerReceiver(mReceiver, intentFilter); |
| |
| mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); |
| mAudioManager2 = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE); |
| mHandler = new Handler(); |
| |
| mMediaControllers[0] = new SimplePlayerController(this, R.id.playPause1, R.id.stop1, |
| R.raw.sine440_mo_16b_16k, AudioManager.STREAM_BLUETOOTH_SCO); |
| TextView name = findViewById(R.id.playPause1Text); |
| name.setText("VOICE_CALL stream"); |
| |
| mScoButton = (ToggleButton)findViewById(R.id.ForceScoButton); |
| mScoButton.setOnCheckedChangeListener(mForceScoChanged); |
| mForceScoOn = false; |
| mScoButton.setChecked(mForceScoOn); |
| |
| mVoiceDialerButton = (ToggleButton)findViewById(R.id.VoiceDialerButton); |
| mVoiceDialerButton.setOnCheckedChangeListener(mVoiceDialerChanged); |
| mVoiceDialerOn = false; |
| mVoiceDialerButton.setChecked(mVoiceDialerOn); |
| |
| |
| mMediaControllers[1] = new SimpleRecordController(this, R.id.recStop1, 0, "Sco_record_"); |
| mTtsInited = false; |
| mTts = new TextToSpeech(this, new TtsInitListener()); |
| mTtsParams = new HashMap<String, String>(); |
| mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_STREAM, |
| String.valueOf(AudioManager.STREAM_BLUETOOTH_SCO)); |
| mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, |
| UTTERANCE); |
| |
| mSpeakText = findViewById(R.id.speakTextEdit); |
| mSpeakText.setOnKeyListener(mSpeakKeyListener); |
| mSpeakText.setText("sco audio test sentence"); |
| mTtsToFileButton = (ToggleButton)findViewById(R.id.TtsToFileButton); |
| mTtsToFileButton.setOnCheckedChangeListener(mTtsToFileChanged); |
| mTtsToFile = true; |
| mTtsToFileButton.setChecked(mTtsToFile); |
| |
| mModeSpinner = findViewById(R.id.modeSpinner); |
| ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, |
| android.R.layout.simple_spinner_item, mModeStrings); |
| adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
| mModeSpinner.setAdapter(adapter); |
| mModeSpinner.setOnItemSelectedListener(mModeChanged); |
| mCurrentMode = mAudioManager.getMode(); |
| mModeSpinner.setSelection(mCurrentMode); |
| |
| mBluetoothHeadsetDevice = null; |
| BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); |
| if (btAdapter != null) { |
| btAdapter.getProfileProxy(this, mBluetoothProfileServiceListener, |
| BluetoothProfile.HEADSET); |
| } |
| |
| sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND); |
| sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| mTts.shutdown(); |
| unregisterReceiver(mReceiver); |
| if (mBluetoothHeadset != null) { |
| BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); |
| if (btAdapter != null) { |
| btAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); |
| } |
| } |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| // mForceScoOn = false; |
| // mScoButton.setChecked(mForceScoOn); |
| mMediaControllers[0].stop(); |
| mMediaControllers[1].stop(); |
| mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, |
| mOriginalVoiceVolume, 0); |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| mLastRecordedFile = ""; |
| mMediaControllers[0].mFileName = ""; |
| mOriginalVoiceVolume = mAudioManager.getStreamVolume( |
| AudioManager.STREAM_BLUETOOTH_SCO); |
| setVolumeControlStream(AudioManager.STREAM_BLUETOOTH_SCO); |
| mCurrentMode = mAudioManager.getMode(); |
| mModeSpinner.setSelection(mCurrentMode); |
| } |
| |
| private OnCheckedChangeListener mForceScoChanged |
| = new OnCheckedChangeListener(){ |
| @Override |
| public void onCheckedChanged(CompoundButton buttonView, |
| boolean isChecked) { |
| if (mForceScoOn != isChecked) { |
| mForceScoOn = isChecked; |
| AudioManager mngr = mAudioManager; |
| boolean useVirtualCall = false; |
| CheckBox box = findViewById(R.id.useSecondAudioManager); |
| if (box.isChecked()) { |
| Log.i(TAG, "Using 2nd audio manager"); |
| mngr = mAudioManager2; |
| } |
| box = findViewById(R.id.useVirtualCallCheckBox); |
| useVirtualCall = box.isChecked(); |
| |
| if (mForceScoOn) { |
| if (useVirtualCall) { |
| Log.e(TAG, "startBluetoothScoVirtualCall() IN"); |
| mngr.startBluetoothScoVirtualCall(); |
| Log.e(TAG, "startBluetoothScoVirtualCall() OUT"); |
| } else { |
| Log.e(TAG, "startBluetoothSco() IN"); |
| mngr.startBluetoothSco(); |
| Log.e(TAG, "startBluetoothSco() OUT"); |
| } |
| } else { |
| Log.e(TAG, "stopBluetoothSco() IN"); |
| mngr.stopBluetoothSco(); |
| Log.e(TAG, "stopBluetoothSco() OUT"); |
| } |
| } |
| } |
| }; |
| |
| private OnCheckedChangeListener mVoiceDialerChanged |
| = new OnCheckedChangeListener(){ |
| @Override |
| public void onCheckedChanged(CompoundButton buttonView, |
| boolean isChecked) { |
| if (mVoiceDialerOn != isChecked) { |
| mVoiceDialerOn = isChecked; |
| if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { |
| if (mVoiceDialerOn) { |
| mBluetoothHeadset.startVoiceRecognition(mBluetoothHeadsetDevice); |
| } else { |
| mBluetoothHeadset.stopVoiceRecognition(mBluetoothHeadsetDevice); |
| } |
| } |
| } |
| } |
| }; |
| |
| private OnCheckedChangeListener mTtsToFileChanged |
| = new OnCheckedChangeListener(){ |
| @Override |
| public void onCheckedChanged(CompoundButton buttonView, |
| boolean isChecked) { |
| mTtsToFile = isChecked; |
| } |
| }; |
| |
| private class SimpleMediaController implements OnClickListener { |
| int mPlayPauseButtonId; |
| int mStopButtonId; |
| Context mContext; |
| ImageView mPlayPauseButton; |
| int mPlayImageResource; |
| int mPauseImageResource; |
| String mFileNameBase; |
| String mFileName; |
| int mFileResId; |
| |
| SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, String fileName) { |
| mContext = context; |
| mPlayPauseButtonId = playPausebuttonId; |
| mStopButtonId = stopButtonId; |
| mFileNameBase = fileName; |
| mPlayPauseButton = findViewById(playPausebuttonId); |
| ImageButton stop = findViewById(stopButtonId); |
| |
| mPlayPauseButton.setOnClickListener(this); |
| mPlayPauseButton.requestFocus(); |
| if (stop != null) { |
| stop.setOnClickListener(this); |
| } |
| } |
| |
| SimpleMediaController(Context context, int playPausebuttonId, int stopButtonId, int fileResId) { |
| mContext = context; |
| mPlayPauseButtonId = playPausebuttonId; |
| mStopButtonId = stopButtonId; |
| mFileNameBase = ""; |
| mFileResId = fileResId; |
| mPlayPauseButton = findViewById(playPausebuttonId); |
| ImageButton stop = findViewById(stopButtonId); |
| |
| mPlayPauseButton.setOnClickListener(this); |
| mPlayPauseButton.requestFocus(); |
| if (stop != null) { |
| stop.setOnClickListener(this); |
| } |
| } |
| |
| @Override |
| public void onClick(View v) { |
| if (v.getId() == mPlayPauseButtonId) { |
| playOrPause(); |
| } else if (v.getId() == mStopButtonId) { |
| stop(); |
| } |
| } |
| |
| public void playOrPause() { |
| } |
| |
| public void stop() { |
| } |
| |
| public boolean isPlaying() { |
| return false; |
| } |
| |
| public void updatePlayPauseButton() { |
| mPlayPauseButton.setImageResource(isPlaying() ? mPauseImageResource : mPlayImageResource); |
| } |
| } |
| |
| private class SimplePlayerController extends SimpleMediaController { |
| private MediaPlayer mMediaPlayer; |
| private int mStreamType; |
| SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, String fileName, int stream) { |
| super(context, playPausebuttonId, stopButtonId, fileName); |
| |
| mPlayImageResource = android.R.drawable.ic_media_play; |
| mPauseImageResource = android.R.drawable.ic_media_pause; |
| mStreamType = stream; |
| mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" + |
| mFileNameBase + "_" + ".wav"; |
| } |
| |
| SimplePlayerController(Context context, int playPausebuttonId, int stopButtonId, int fileResId, int stream) { |
| super(context, playPausebuttonId, stopButtonId, fileResId); |
| |
| mPlayImageResource = android.R.drawable.ic_media_play; |
| mPauseImageResource = android.R.drawable.ic_media_pause; |
| mStreamType = stream; |
| mFileName = ""; |
| } |
| |
| @Override |
| public void playOrPause() { |
| Log.e(TAG, "playOrPause playing: "+((mMediaPlayer == null)?false:!mMediaPlayer.isPlaying())+ |
| " mMediaPlayer: "+mMediaPlayer+ |
| " mFileName: "+mFileName+ |
| " mLastRecordedFile: "+mLastRecordedFile); |
| if (mMediaPlayer == null || !mMediaPlayer.isPlaying()){ |
| if (mMediaPlayer == null) { |
| if (mFileName != mLastRecordedFile) { |
| mFileName = mLastRecordedFile; |
| Log.e(TAG, "new recorded file: "+mFileName); |
| } |
| try { |
| mMediaPlayer = new MediaPlayer(); |
| if (mFileName.equals("")) { |
| Log.e(TAG, "Playing from resource"); |
| AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(mFileResId); |
| mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); |
| afd.close(); |
| } else { |
| Log.e(TAG, "Playing file: "+mFileName); |
| mMediaPlayer.setDataSource(mFileName); |
| } |
| mMediaPlayer.setAudioStreamType(mStreamType); |
| mMediaPlayer.prepare(); |
| mMediaPlayer.setLooping(true); |
| } catch (Exception ex) { |
| Log.e(TAG, "mMediaPlayercreate failed:", ex); |
| mMediaPlayer.release(); |
| mMediaPlayer = null; |
| } |
| |
| if (mMediaPlayer != null) { |
| mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { |
| @Override |
| public void onCompletion(MediaPlayer mp) { |
| updatePlayPauseButton(); |
| } |
| }); |
| } |
| } |
| if (mMediaPlayer != null) { |
| mMediaPlayer.start(); |
| } |
| } else { |
| mMediaPlayer.pause(); |
| } |
| updatePlayPauseButton(); |
| } |
| @Override |
| public void stop() { |
| if (mMediaPlayer != null) { |
| mMediaPlayer.stop(); |
| mMediaPlayer.release(); |
| mMediaPlayer = null; |
| } |
| updatePlayPauseButton(); |
| } |
| |
| @Override |
| public boolean isPlaying() { |
| if (mMediaPlayer != null) { |
| return mMediaPlayer.isPlaying(); |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| private class SimpleRecordController extends SimpleMediaController { |
| private MediaRecorder mMediaRecorder; |
| private int mFileCount = 0; |
| private int mState = 0; |
| SimpleRecordController(Context context, int playPausebuttonId, int stopButtonId, String fileName) { |
| super(context, playPausebuttonId, stopButtonId, fileName); |
| Log.e(TAG, "SimpleRecordController cstor"); |
| mPlayImageResource = R.drawable.record; |
| mPauseImageResource = R.drawable.stop; |
| } |
| |
| @Override |
| public void playOrPause() { |
| if (mState == 0) { |
| setup(); |
| try { |
| mMediaRecorder.start(); |
| mState = 1; |
| } catch (Exception e) { |
| Log.e(TAG, "Could start MediaRecorder: ", e); |
| mMediaRecorder.release(); |
| mMediaRecorder = null; |
| mState = 0; |
| } |
| } else { |
| try { |
| mMediaRecorder.stop(); |
| mMediaRecorder.reset(); |
| } catch (Exception e) { |
| Log.e(TAG, "Could not stop MediaRecorder: ", e); |
| mMediaRecorder.release(); |
| mMediaRecorder = null; |
| } finally { |
| mState = 0; |
| } |
| } |
| updatePlayPauseButton(); |
| } |
| |
| public void setup() { |
| Log.e(TAG, "SimpleRecordController setup()"); |
| if (mMediaRecorder == null) { |
| mMediaRecorder = new MediaRecorder(); |
| } |
| mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); |
| mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); |
| mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); |
| mFileName = Environment.getExternalStorageDirectory().toString() + "/music/" + |
| mFileNameBase + "_" + ++mFileCount + ".amr"; |
| mLastRecordedFile = mFileName; |
| Log.e(TAG, "recording to file: "+mLastRecordedFile); |
| mMediaRecorder.setOutputFile(mFileName); |
| try { |
| mMediaRecorder.prepare(); |
| } |
| catch (Exception e) { |
| Log.e(TAG, "Could not prepare MediaRecorder: ", e); |
| mMediaRecorder.release(); |
| mMediaRecorder = null; |
| } |
| } |
| |
| @Override |
| public void stop() { |
| if (mMediaRecorder != null) { |
| try { |
| mMediaRecorder.stop(); |
| } catch (Exception e) { |
| Log.e(TAG, "Could not stop MediaRecorder: ", e); |
| } finally { |
| mMediaRecorder.release(); |
| mMediaRecorder = null; |
| } |
| } |
| updatePlayPauseButton(); |
| } |
| |
| @Override |
| public boolean isPlaying() { |
| if (mState == 1) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| class TtsInitListener implements TextToSpeech.OnInitListener { |
| @Override |
| public void onInit(int status) { |
| // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR. |
| Log.e(TAG, "onInit for tts"); |
| if (status != TextToSpeech.SUCCESS) { |
| // Initialization failed. |
| Log.e(TAG, "Could not initialize TextToSpeech."); |
| return; |
| } |
| |
| if (mTts == null) { |
| Log.e(TAG, "null tts"); |
| return; |
| } |
| |
| int result = mTts.setLanguage(Locale.US); |
| if (result == TextToSpeech.LANG_MISSING_DATA || |
| result == TextToSpeech.LANG_NOT_SUPPORTED) { |
| // Lanuage data is missing or the language is not supported. |
| Log.e(TAG, "Language is not available."); |
| return; |
| } |
| mTts.setOnUtteranceCompletedListener(new MyUtteranceCompletedListener(UTTERANCE)); |
| mTtsInited = true; |
| } |
| } |
| |
| class MyUtteranceCompletedListener implements OnUtteranceCompletedListener { |
| private final String mExpectedUtterance; |
| |
| public MyUtteranceCompletedListener(String expectedUtteranceId) { |
| mExpectedUtterance = expectedUtteranceId; |
| } |
| |
| @Override |
| public void onUtteranceCompleted(String utteranceId) { |
| Log.e(TAG, "onUtteranceCompleted " + utteranceId); |
| if (mTtsToFile) { |
| if (mSampleFile != null && mSampleFile.exists()) { |
| MediaPlayer mediaPlayer = new MediaPlayer(); |
| try { |
| mediaPlayer.setDataSource(mSampleFile.getPath()); |
| mediaPlayer.setAudioStreamType(AudioManager.STREAM_BLUETOOTH_SCO); |
| mediaPlayer.prepare(); |
| } catch (Exception ex) { |
| Log.e(TAG, "mMediaPlayercreate failed:", ex); |
| mediaPlayer.release(); |
| mediaPlayer = null; |
| } |
| |
| if (mediaPlayer != null) { |
| mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { |
| @Override |
| public void onCompletion(MediaPlayer mp) { |
| mp.release(); |
| if (mSampleFile != null && mSampleFile.exists()) { |
| mSampleFile.delete(); |
| mSampleFile = null; |
| } |
| mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, |
| mOriginalVoiceVolume, 0); |
| // Debug.stopMethodTracing(); |
| } |
| }); |
| mediaPlayer.start(); |
| } |
| } else { |
| Log.e(TAG, "synthesizeToFile did not create file"); |
| } |
| } else { |
| mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, |
| mOriginalVoiceVolume, 0); |
| // Debug.stopMethodTracing(); |
| } |
| |
| Log.e(TAG, "end speak, volume: "+mOriginalVoiceVolume); |
| } |
| } |
| |
| |
| private View.OnKeyListener mSpeakKeyListener |
| = new View.OnKeyListener() { |
| @Override |
| public boolean onKey(View v, int keyCode, KeyEvent event) { |
| if (event.getAction() == KeyEvent.ACTION_DOWN) { |
| switch (keyCode) { |
| case KeyEvent.KEYCODE_DPAD_CENTER: |
| case KeyEvent.KEYCODE_ENTER: |
| if (!mTtsInited) { |
| Log.e(TAG, "Tts not inited "); |
| return false; |
| } |
| mOriginalVoiceVolume = mAudioManager.getStreamVolume( |
| AudioManager.STREAM_BLUETOOTH_SCO); |
| Log.e(TAG, "start speak, volume: "+mOriginalVoiceVolume); |
| mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, |
| mOriginalVoiceVolume/2, 0); |
| |
| // we now have SCO connection and TTS, so we can start. |
| mHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| // Debug.startMethodTracing("tts"); |
| |
| if (mTtsToFile) { |
| if (mSampleFile != null && mSampleFile.exists()) { |
| mSampleFile.delete(); |
| mSampleFile = null; |
| } |
| mSampleFile = new File(Environment.getExternalStorageDirectory(), "mytts.wav"); |
| mTts.synthesizeToFile(mSpeakText.getText().toString(), mTtsParams, mSampleFile.getPath()); |
| } else { |
| mTts.speak(mSpeakText.getText().toString(), |
| TextToSpeech.QUEUE_FLUSH, |
| mTtsParams); |
| } |
| } |
| }); |
| return true; |
| } |
| } |
| return false; |
| } |
| }; |
| |
| private static final String[] mModeStrings = { |
| "NORMAL", "RINGTONE", "IN_CALL", "IN_COMMUNICATION" |
| }; |
| |
| private Spinner.OnItemSelectedListener mModeChanged |
| = new Spinner.OnItemSelectedListener() { |
| @Override |
| public void onItemSelected(android.widget.AdapterView av, View v, |
| int position, long id) { |
| if (mCurrentMode != position) { |
| mCurrentMode = position; |
| mAudioManager.setMode(mCurrentMode); |
| } |
| } |
| |
| @Override |
| public void onNothingSelected(android.widget.AdapterView av) { |
| } |
| }; |
| |
| private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = |
| new BluetoothProfile.ServiceListener() { |
| @Override |
| public void onServiceConnected(int profile, BluetoothProfile proxy) { |
| mBluetoothHeadset = (BluetoothHeadset) proxy; |
| List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); |
| if (deviceList.size() > 0) { |
| mBluetoothHeadsetDevice = deviceList.get(0); |
| } else { |
| mBluetoothHeadsetDevice = null; |
| } |
| } |
| @Override |
| public void onServiceDisconnected(int profile) { |
| if (mBluetoothHeadset != null) { |
| List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices(); |
| if (devices.size() == 0) { |
| mBluetoothHeadsetDevice = null; |
| } |
| mBluetoothHeadset = null; |
| } |
| } |
| }; |
| |
| private int mChangedState = -1; |
| private int mUpdatedState = -1; |
| private int mUpdatedPrevState = -1; |
| |
| private class ScoBroadcastReceiver extends BroadcastReceiver { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| |
| if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { |
| int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); |
| mVdStateTxt.setText(Integer.toString(state)); |
| Log.e(TAG, "BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED: "+state); |
| } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)) { |
| mChangedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); |
| Log.e(TAG, "ACTION_SCO_AUDIO_STATE_CHANGED: "+mChangedState); |
| mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ |
| " updated: "+Integer.toString(mUpdatedState)+ |
| " prev updated: "+Integer.toString(mUpdatedPrevState)); |
| } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { |
| mUpdatedState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); |
| mUpdatedPrevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1); |
| Log.e(TAG, "ACTION_SCO_AUDIO_STATE_UPDATED, state: "+mUpdatedState+" prev state: "+mUpdatedPrevState); |
| mScoStateTxt.setText("changed: "+Integer.toString(mChangedState)+ |
| " updated: "+Integer.toString(mUpdatedState)+ |
| " prev updated: "+Integer.toString(mUpdatedPrevState)); |
| if (mForceScoOn && mUpdatedState == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { |
| mForceScoOn = false; |
| mScoButton.setChecked(mForceScoOn); |
| mAudioManager.stopBluetoothSco(); |
| } |
| } |
| } |
| } |
| |
| } |