赞
踩
FmMainActivity.java 主界面
FmService.java 核心
FmNative.java 调用JNI和底层通信
1 ) 搜台
2)收藏
3)耳机/外放播放
4 ) 切台
5)定时关闭
6)飞行模式
不插入耳机启动FM,是不能播放FM,会提示 “请插入耳机”
在FmMainActivity.java-->onCreate()中会加载布局
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ......
- initUiComponent();
- ......
-
- }
FmMainActivity.java-->initUiComponent()
- private void initUiComponent() {
- ......
- mMainLayout = (LinearLayout) findViewById(R.id.main_view);
- mNoHeadsetLayout = (RelativeLayout) findViewById(R.id.no_headset);
- ......
-
- }
这里加载了两个布局no_headset和main_view,main_view是插入耳机正常收听时的界面,no_headset是不插入耳机时的提示界面,我们现在先分析no_headset
在FmMainActivity.java-->changeToNoHeadsetLayout()中会将mMainLayout隐藏掉,将mNoHeadsetLayout设置成visible
- /**
- * change to no headset layout
- */
- private void changeToNoHeadsetLayout() {
- ......
- mMainLayout.setVisibility(View.GONE);
- ......
-
- mNoHeadsetLayout.setVisibility(View.VISIBLE);
- ......
- }
接下来看下changeToNoHeadsetLayout()是在哪儿调用的
- @Override
- public void onStart() {
- super.onStart();
- ......
-
- } else if (isAntennaAvailable()) {
- changeToMainLayout();
- } else {
- changeToNoHeadsetLayout();
- }
-
- ......
- }
可以看到是通过isAntennaAvailable()来判断是否有耳机
FmMainActivity.java-->isAntennaAvailable()
- private boolean isAntennaAvailable() {
- if (FmUtils.supportShortAntenna) {
- return true;
- } else {
- return isWiredHeadsetOn();
- //mAudioManager.isWiredHeadsetOn();
- }
- }
FmMainActivity.java-->isWiredHeadsetOn()
- private boolean isWiredHeadsetOn() {
- //bug939562 return true ,Only wired headset is plugged in
- AudioDeviceInfo[] audioDeviceInfo = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
- for (AudioDeviceInfo info : audioDeviceInfo) {
- //wired headset(with mic or not) is pluged in
- if ((info.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET)||(info.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES)){
- Log.d(TAG,"Wired headset is exist");
- return true;
- }
- }
- return false;
- //return true ,type-c or wired headset is plugged in
- //mAudioManager.isWiredHeadsetOn();
- }
可以看到启动app的时候,是通过AudioDeviceInfo的tpye来判断是否插入了耳机
到插入耳机的时候,会切换到main_view这个界面,下面看下这个流程
再看耳机插入监听流程前,需要先讲下FmService的启动流程
- @Override
- public void onStart() {
- super.onStart();
- ......
- if (null == startForegroundService(new Intent(FmMainActivity.this, FmService.class))) {
- Log.e(TAG, "onStart, cannot start FM service");
- return;
- }
- mIsServiceStarted = true;
- mIsServiceBinded = bindService(new Intent(FmMainActivity.this, FmService.class),
- mServiceConnection, Context.BIND_AUTO_CREATE);
- ......
-
- }
在FmService onBind()成功后,后就会调用ServiceConnection里的onServiceConnected()方法
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
-
- /**
- * called by system when bind service
- *
- * @param className component name
- * @param service service binder
- */
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- mService = ((FmService.ServiceBinder) service).getService();
- if (null == mService) {
- Log.e(TAG, "onServiceConnected, mService is null");
- finish();
- return;
- }
- Log.d(TAG, "onServiceConnected, mService is not null");
- refreshRDSVisiable();
- mService.registerFmRadioListener(mFmRadioListener);
- mService.setFmActivityForground(mIsActivityForeground);
- // bug568587, new feature FM new UI
- mService.setTimerListenr(new MyTimeCountListener());
-
- if (!mService.isServiceInited()) {
- mService.initService();
- powerUpFm();
- } else {
- if (mService.isDeviceOpen()) {
- updateMenuStatus();
- } else {
- // Normal case will not come here
- // Need to exit FM for this case
- exitService();
- finish();
- }
- }
- }
- /**
- * When unbind service will call this method
- *
- * @param className The component name
- */
- @Override
- public void onServiceDisconnected(ComponentName className) {
- }
- };
在这里会调用FmService.java-->registerFmRadioListener()监听mFmRadioListener
- private FmListener mFmRadioListener = new FmListener() {
- @Override
- public void onCallBack(Bundle bundle) {
- int flag = bundle.getInt(FmListener.CALLBACK_FLAG);
- if (flag == FmListener.MSGID_FM_EXIT) {
- mHandler.removeCallbacksAndMessages(null);
- }
-
- // remove tag message first, avoid too many same messages in queue.
- Message msg = mHandler.obtainMessage(flag);
- msg.setData(bundle);
- mHandler.removeMessages(flag);
- mHandler.sendMessage(msg);
- }
- };
FmListener是个接口,FmMainActivity.java实现了这个接口
再反过来看FmService.java-->registerFmRadioListener()
- public void registerFmRadioListener(FmListener callback) {
- synchronized (mRecords) {
- // register callback in AudioProfileService, if the callback is
- // exist, just replace the event.
- Record record = null;
- int hashCode = callback.hashCode();
- final int n = mRecords.size();
- for (int i = 0; i < n; i++) {
- record = mRecords.get(i);
- if (hashCode == record.mHashCode) {
- return;
- }
- }
- record = new Record();
- record.mHashCode = hashCode;
- record.mCallback = callback;
- mRecords.add(record);
- }
- }
这里会把FmListener add到一个list里,因为在FmFavoriteActivity FmMainActivity FmRecordActivity 中都会注册监听这个接口
在FmService.java中有个内部广播接收器FmServiceBroadcastReceiver extends BroadcastReceiver,在FmServiceBroadcastReceiver里会监听Intent.ACTION_HEADSET_PLUG事件
监听到后,调用switchAntennaAsync()
- public void switchAntennaAsync(int antenna) {
- final int bundleSize = 1;
- mFmServiceHandler.removeMessages(FmListener.MSGID_SWITCH_ANTENNA);
-
- Bundle bundle = new Bundle(bundleSize);
- bundle.putInt(FmListener.SWITCH_ANTENNA_VALUE, antenna);
- Message msg = mFmServiceHandler.obtainMessage(FmListener.MSGID_SWITCH_ANTENNA);
- msg.setData(bundle);
- mFmServiceHandler.sendMessage(msg);
- }
- case FmListener.MSGID_SWITCH_ANTENNA:
- bundle = msg.getData();
- int value = bundle.getInt(FmListener.SWITCH_ANTENNA_VALUE);
-
- // if ear phone insert, need dismiss plugin earphone
- // dialog
- // if earphone plug out and it is not play recorder
- // state, show plug dialog.
-
- bundle.putInt(FmListener.CALLBACK_FLAG,
- FmListener.MSGID_SWITCH_ANTENNA);
- bundle.putBoolean(FmListener.KEY_IS_SWITCH_ANTENNA, (0 == value));
- notifyActivityStateChanged(bundle);
- break;
- private void notifyActivityStateChanged(Bundle bundle) {
- if (!mRecords.isEmpty()) {
- synchronized (mRecords) {
- Iterator<Record> iterator = mRecords.iterator();
- while (iterator.hasNext()) {
- Record record = (Record) iterator.next();
-
- FmListener listener = record.mCallback;
-
- if (listener == null) {
- iterator.remove();
- return;
- }
-
- listener.onCallBack(bundle);
- }
- }
- }
- }
到这里就回到了FmMainActivity.java-->FmListener .java-->onCallBack()
- private FmListener mFmRadioListener = new FmListener() {
- @Override
- public void onCallBack(Bundle bundle) {
- int flag = bundle.getInt(FmListener.CALLBACK_FLAG);
- if (flag == FmListener.MSGID_FM_EXIT) {
- mHandler.removeCallbacksAndMessages(null);
- }
-
- // remove tag message first, avoid too many same messages in queue.
- Message msg = mHandler.obtainMessage(flag);
- msg.setData(bundle);
- mHandler.removeMessages(flag);
- mHandler.sendMessage(msg);
- }
- };
从bundle里传过来是MSGID_SWITCH_ANTENNA
- case FmListener.MSGID_SWITCH_ANTENNA:
- ......
- if (hasAntenna) {
- cancelNoHeadsetAnimation();
- if (mIsActivityForeground) {
- playMainAnimation();
- } else {
- changeToMainLayout();
- }
- ......
点击FmFavoriteActivity.java界面的menu菜单,点击刷新
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.fm_station_list_refresh:
- if ((null != mService) && (!mService.isSeeking())) {
- onOptionsItemSelectedScan(false);
- }
- break;
-
- }
- return super.onOptionsItemSelected(item);
- }
FmFavoriteActivity.java-->onOptionsItemSelectedScan()
- private void onOptionsItemSelectedScan(boolean fromCurrent) {
- if (null != mService) {
- showTipView(true);
- if (fromCurrent) {
- mService.startScanAsyncFromCurrent(mCurrentStationItem.stationFreq);
- } else {
- mService.startScanAsync();
- }
- }
- }
FmService.java-->startScanAsync()
- /**
- * Scan stations
- */
- public void startScanAsync() {
- mFmServiceHandler.removeMessages(FmListener.MSGID_SCAN_FINISHED);
- mFmServiceHandler.sendEmptyMessage(FmListener.MSGID_SCAN_FINISHED);
- }
- // start scan
- case FmListener.MSGID_SCAN_FINISHED:
- ......
- stations = startScan(start_freq);
- /**
- * @}
- */
- }
- private int[] startScan(int start_freq) {
- ......
- stations = mFmManager.autoScan(start_freq);
- ......
- return stations;
- }
FmManagerSelect.java -->autoScan()
- public int[] autoScan(int start_freq) {
- if (mIsUseBrcmFmChip) {
- return mFmManagerForBrcm.autoScanStation(start_freq);
- } else {
- short[] stationsInShort = null;
- int[] stations = null;
- stationsInShort = FmNative.autoScan(start_freq);
- if (null != stationsInShort) {
- int size = stationsInShort.length;
- stations = new int[size];
- for (int i = 0; i < size; i++) {
- stations[i] = stationsInShort[i];
- }
- }
- return stations;
- }
- }
这里就调用到FmNative.java-->autoScan()
static native short[] autoScan(int start_freq);
扫描成功后,会将扫描到的数据插入到数据库中
- private int[] updateStations(int[] stations) {
- Log.d(TAG, "updateStations.firstValidstation:" + Arrays.toString(stations));
- int firstValidstation = mCurrentStationItem.stationFreq;
- FmStation.cleanSearchedStations(mContext);
- int stationNum = batchInsertStationToDb(stations, null);
-
- int searchedNum = (stations == null ? 0 : stations.length);
- Log.d(TAG, "updateStations.firstValidstation:" + firstValidstation +
- ",searchedNum:" + searchedNum);
- return (new int[]{
- firstValidstation, searchedNum
- });
- }
-
-
- private int batchInsertStationToDb(int[] stations, List<FmStationItem> favoriteList) {
- if (null == stations) return 0;
- ArrayList<ContentProviderOperation> ops = new ArrayList<>();
- ContentResolver resolver = mContext.getContentResolver();
- for (int i = 0; i < stations.length; i++) {
- if (!FmUtils.isValidStation(stations[i]) || FmStation.isFavoriteStation(mContext, stations[i])) {
- Log.d(TAG, "station is favorite : " + stations[i]);
- continue;
- }
- ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(Station.CONTENT_URI);
- op.withYieldAllowed(false);
- Log.d(TAG, "station : " + stations[i]);
- ContentValues values = new ContentValues();
- values.clear();
- values.put(Station.FREQUENCY, stations[i]);
- values.put(Station.IS_SHOW, Station.IS_SCAN);
- op.withValues(values);
- ops.add(op.build());
- }
- Log.d(TAG, "ops size : " + ops.size());
- int stationNum = ops.size();
- if (stationNum > 0) {
- try {
- ContentProviderResult[] result = resolver.applyBatch(FmStation.AUTHORITY, ops);
- ops.clear();
- Log.d(TAG, "batch opreate db result count : " + result.length);
- } catch (Exception e) {
- Log.d(TAG, "Batch operate exception");
- e.printStackTrace();
- }
- } else {
- mContext.getContentResolver().notifyChange(FmStation.Station.CONTENT_URI, null);
- }
- return stationNum;
- }
搜索成功后,调用FmService.java-->notifyCurrentActivityStateChanged()通知FmFavoriteActivity.java更新界面
- private void refreshFmFavorityList(Cursor cursor) {
- if (cursor == null) {
- return;
- }
- mFavoriteList.clear();
- mOtherList.clear();
- mAllStationSet.clear();
- for (int i = 0; i < cursor.getCount(); i++) {
- FmStationItem item = new FmStationItem();
- if (cursor.moveToFirst()) {
- cursor.moveToPosition(i);
- item.stationFreq = cursor.getInt(cursor
- .getColumnIndex(FmStation.Station.FREQUENCY));
- item.stationName = cursor.getString(cursor
- .getColumnIndex(FmStation.Station.STATION_NAME));
- item.rt = cursor.getString(cursor
- .getColumnIndex(FmStation.Station.RADIO_TEXT));
- item.isFavorite = cursor.getInt(cursor
- .getColumnIndex(FmStation.Station.IS_FAVORITE));
- item.isShow = cursor.getInt(cursor
- .getColumnIndex(FmStation.Station.IS_SHOW));
- item.ps = cursor.getString(cursor
- .getColumnIndex(FmStation.Station.PROGRAM_SERVICE));
- if (item.isFavorite == 0) {
- mOtherList.add(item);
- } else {
- mFavoriteList.add(item);
- }
- mAllStationSet.add(item.stationFreq);
- }
- }
- checkSelectedStationSet();
- mMyAdapter.notifyDataSetChanged();
- Log.d(TAG, "refreshFmFavorityList mAllStationSet.size:" + mAllStationSet.size());
- }
通过MyFavoriteAdapter的notifyDataSetChanged()来刷新界面
- viewHolder.mImgLayout.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- /* bug568587, new feature FM new UI @{ */
- if (0 == isFavorite) {
- showToast(getString(R.string.toast_channel_added));
- addFavorite(stationFreq);
- } else {
- showToast(getString(R.string.toast_channel_deleted));
- deleteFromFavorite(stationFreq);
- }
- /* @} */
- }
- });
- /**
- * Add searched station as favorite station
- */
- public void addFavorite(int stationFreq) {
- // TODO it's on UI thread, change to sub thread
- // update the station name and station type in database
- // according the frequency
- operateFmFavoriteStation(stationFreq, ACTION_ADD_FAVORITE_TYPE);
- }
- private void operateFmFavoriteStation(int stationFreq, int type) {
- MyAsyncTask operateTask = new MyAsyncTask();
- operateTask.execute(ACTION_OPERATE_TYPE, stationFreq, type);
- }
- class MyAsyncTask extends AsyncTask<Integer, Void, Cursor> {
- @Override
- protected Cursor doInBackground(Integer... params) {
- Log.d(TAG, "operate database type:" + params[0]);
- if (params[0] == ACTION_QUERY_TYPE) {
- Cursor cursor = getData();
- return cursor;
- } else {
- Log.d(TAG, "stationFreq=" + params[1]);
- operateData(params[1], params[2]);
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(Cursor cursor) {
- refreshFmFavorityList(cursor);
- if (cursor != null) {
- cursor.close();
- }
- }
- }
- private void operateData(int stationFreq, int type) {
- switch (type) {
- case ACTION_ADD_FAVORITE_TYPE:
- FmStation.addToFavorite(mContext, stationFreq);
- break;
- case ACTION_REMOVE_FROM_FAVORITE_TYPE:
- FmStation.removeFromFavorite(mContext, stationFreq);
- break;
-
- }
- /**
- * update db to mark it is a favorite frequency
- *
- * @param context The context
- * @param frequency The target frequency
- */
- public static void addToFavorite(Context context, int frequency) {
- ContentValues values = new ContentValues(1);
- values.put(Station.IS_FAVORITE, true);
- values.put(Station.IS_SHOW,Station.IS_SCAN);
- context.getContentResolver().update(
- Station.CONTENT_URI,
- values,
- Station.FREQUENCY + "=?",
- new String[] {
- String.valueOf(frequency)
- });
- }
FmMainActivity.java
- case R.id.play_button:
- /**
- * bug500046, for monkey test.
- *
- * @{
- */
- if (null == mService) {
- Log.e(TAG, "onClick case playbutton, mService is null");
- return;
- }
- /**
- * @}
- */
- if (mService.getPowerStatus() == FmService.POWER_UP) {
- if(mService.isMuted()){
- mService.setMuteAsync(false,false);
- }else{
- powerDownFm();
- }
- } else {
- powerUpFm();
- }
- break;
- default:
- Log.d(TAG, "mButtonClickListener.onClick, invalid view id");
- break;
FmMainActivity.java -- >powerUpFm()
- /**
- * Power up FM
- */
- private void powerUpFm() {
- if(FmUtils.isAirplane(this)){
- changeToAirPlaneLayout();
- }else{
- refreshImageButton(false);
- refreshActionMenuItem(false);
- refreshPopupMenuItem(false);
- refreshPlayButton(false);
- mService.powerUpAsync(FmUtils.computeFrequency(mCurrentStationItem.stationFreq));
- }
- }
发送MSGID_POWERUP_FINISHED
- public void powerUpAsync(float frequency) {
- final int bundleSize = 1;
- mFmServiceHandler.removeMessages(FmListener.MSGID_POWERUP_FINISHED);
- mFmServiceHandler.removeMessages(FmListener.MSGID_POWERDOWN_FINISHED);
- Bundle bundle = new Bundle(bundleSize);
- bundle.putFloat(FM_FREQUENCY, frequency);
- Message msg = mFmServiceHandler.obtainMessage(FmListener.MSGID_POWERUP_FINISHED);
- msg.setData(bundle);
- mFmServiceHandler.sendMessage(msg);
- }
FmService.java -->powerUpAsync()
-
- // power up
- case FmListener.MSGID_POWERUP_FINISHED:
- bundle = msg.getData();
- handlePowerUp(bundle);
- break;
FmService.java -->handlePowerUp()
- private void handlePowerUp(Bundle bundle) {
- boolean isPowerUp = false;
- boolean isSwitch = true;
- float curFrequency = bundle.getFloat(FM_FREQUENCY);
-
- if (FmUtils.isAirplane(this)) {
- Log.d(TAG, "handlePowerUp, airplane is on");
- return;
- }
- boolean isAntennaAvailable = isAntennaAvailable();
- if (!FmUtils.supportShortAntenna) {
- if (!isAntennaAvailable) {
- Log.d(TAG, "handlePowerUp, earphone is not ready");
- bundle = new Bundle(2);
- bundle.putInt(FmListener.CALLBACK_FLAG, FmListener.MSGID_SWITCH_ANTENNA);
- bundle.putBoolean(FmListener.KEY_IS_SWITCH_ANTENNA, false);
- notifyActivityStateChanged(bundle);
- return;
- }
- } else {
- Log.d(TAG, "handlePowerUp: wether earphone is plugged in -->" + isAntennaAvailable);
- switchAntenna(isAntennaAvailable ? 0 : 1);
- }
- if (powerUp(curFrequency)) {
- if (FmUtils.isFirstTimePlayFm(mContext)) {
- isPowerUp = firstPlaying(curFrequency);
- FmUtils.setIsFirstTimePlayFm(mContext);
- } else {
- /**
- * Bug546461 Tune radio again after power down then power up for brcm. Orig:
- * isPowerUp = playFrequency(curFrequency);
- * @{
- */
- if (mFmManager.tuneRadioAgain(curFrequency)) {
- isPowerUp = playFrequency(curFrequency);
- }
- /**
- * @}
- */
- }
- mPausedByTransientLossOfFocus = false;
- }
- bundle = new Bundle(1);
- bundle.putInt(FmListener.CALLBACK_FLAG, FmListener.MSGID_POWERUP_FINISHED);
- notifyActivityStateChanged(bundle);
- }
FmService.java -->playFrequency()
- private boolean playFrequency(float frequency) {
- Log.d(TAG, "playFrequency");
- updatePlayingNotification();
- // Start the RDS thread if RDS is supported.
- // RDS function should be open status.
- if (isRdsSupported() && FmUtils.isRDSOpen(mContext)) {
- startRdsThread();
- }
-
- //bug492835, FM audio route change. if (!mWakeLock.isHeld()) { mWakeLock.acquire(); }
- if (mIsSpeakerUsed) {
- setForceUse(mIsSpeakerUsed);
- }
- enableFmAudio(true);
- setRds(true);
- setMute(false);
-
- return (mPowerStatus == POWER_UP);
- }
FmService.java -->enableFmAudio()
- private void enableFmAudio(boolean enable) {
- Log.d(TAG, "enableFmAudio:" + enable);
- if (enable) {
- if ((mPowerStatus != POWER_UP) || !mIsAudioFocusHeld) {
- Log.d(TAG, "enableFmAudio, current not available return.mIsAudioFocusHeld:"
- + mIsAudioFocusHeld);
- return;
- }
-
- ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
- mAudioManager.listAudioPatches(patches);
- if (mAudioPatch == null) {
- Log.d(TAG, "mAudioPatch == null");
- if (isPatchMixerToEarphone(patches)) {
- int status;
- stopRender();
- status = createAudioPatch();
- if (status != AudioManager.SUCCESS) {
- Log.d(TAG, "enableFmAudio: fallback as createAudioPatch failed");
- startRender();
- }
- } else {
- startRender();
- }
- }
- } else {
- releaseAudioPatch();
- stopRender();
- }
- }
FmService.java -->startRender()
- private synchronized void startRender() {
- //bug492835, FM audio route change.
- mFmManager.setAudioPathEnable(AudioPath.FM_AUDIO_PATH_HEADSET, true);
- mMediaSessionManager.setOnMediaKeyListener(mMediaKeyListener, null);
- Log.d(TAG, "startRender,setOnMediaKeyListener");
- mIsRender = true;
- synchronized (mRenderLock) {
- mRenderLock.notify();
- }
- }
FmManagerSelect.java -->setAudioPathEnable()
- public boolean setAudioPathEnable(AudioPath path, boolean enable) {
- if (mIsUseBrcmFmChip) {
- if (enable) {
- mFmManagerForBrcm.setAudioMode(FmAudioModeForBrcm.FM_AUDIO_MODE_BLEND);
- //AudioSystem.setDeviceConnectionState(AudioManager.DEVICE_OUT_FM_HEADSET,
- // AudioSystem.DEVICE_STATE_AVAILABLE, "", "");
- mAudioManager.setDeviceConnectionStateForFM(AudioManager.DEVICE_OUT_FM_HEADSET,
- AudioSystem.DEVICE_STATE_AVAILABLE, "", "");
- } else {
- //AudioSystem.setDeviceConnectionState(AudioManager.DEVICE_OUT_FM_HEADSET,
- // AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "");
- mAudioManager.setDeviceConnectionStateForFM(AudioManager.DEVICE_OUT_FM_HEADSET,
- AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "");
- }
- return mFmManagerForBrcm.setAudioPath(convertAudioPathForBrcm(path));
- } else {
- if (enable) {
- //AudioSystem.setDeviceConnectionState(AudioManager.DEVICE_OUT_FM_HEADSET,
- mAudioManager.setDeviceConnectionStateForFM(AudioManager.DEVICE_OUT_FM_HEADSET,
- AudioSystem.DEVICE_STATE_AVAILABLE, "", "");
- return true;
- } else {
- //AudioSystem.setDeviceConnectionState(AudioManager.DEVICE_OUT_FM_HEADSET,
- mAudioManager.setDeviceConnectionStateForFM(AudioManager.DEVICE_OUT_FM_HEADSET,
- AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "");
- return true;
- }
-
- }
- }
AudioManager.java-->setDeviceConnectionStateForFM()
- public void setDeviceConnectionStateForFM(int device, int state,
- String device_address, String device_name) {
- final IAudioService service = getService();
- try {
- service.setDeviceConnectionStateForFM(device, state, device_address, device_name,mICallBack);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in setDeviceConnectionStateForFM ", e);
- }
- }
录音是FmRecordActivity
点击start,调用 mService.startRecordingAsync();
- /**
- * Start recording
- */
- public void startRecordingAsync() {
- mFmServiceHandler.removeMessages(FmListener.MSGID_STARTRECORDING_FINISHED);
- mFmServiceHandler.sendEmptyMessage(FmListener.MSGID_STARTRECORDING_FINISHED);
- }
- case FmListener.MSGID_STARTRECORDING_FINISHED:
- startRecording();
- break;
- public void startRecording(Context context) {
- mRecordTime = 0;
- Uri dir = null;
- FileDescriptor fd = null;
- Uri externalStorageUri=null;
-
- /**
- * Bug529776 Check the main card state Original Android code:
- *
- * @{ // Check external storage if
- * (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
- * Log.e(TAG, "startRecording, no external storage available");
- * setError(ERROR_SDCARD_NOT_PRESENT); return; } /** @}
- */
- if (FmUtils.isExternalStorage()) {
- externalStorageUri =FmUtils.getCurrentAccessUri(FmUtils.FM_RECORD_STORAGE_PATH_NAME);
- }
-
- String recordingSdcard = FmUtils.getDefaultStoragePath();
- Log.d(TAG,"externalStorageUri="+externalStorageUri+" recordingSdcard="+recordingSdcard);
-
- /**
- * bug474747, recording path selection.
- *
- * @{
- */
- if (recordingSdcard == null
- || recordingSdcard.isEmpty()
- || (FmUtils.FM_RECORD_STORAGE_PATH_SDCARD.equals(FmUtils.FM_RECORD_STORAGE_PATH_NAME) && !Environment.MEDIA_MOUNTED
- .equals(EnvironmentEx.getExternalStoragePathState()))) {
- Log.e(TAG, "startRecording, no sdcard storage available");
- setError(ERROR_SDCARD_NOT_PRESENT);
- return;
- }
- /**
- * @}
- */
-
- // check whether have sufficient storage space, if not will notify
- // caller error message
- if (!FmUtils.hasEnoughSpace(recordingSdcard)) {
- setError(ERROR_SDCARD_INSUFFICIENT_SPACE);
- Log.e(TAG, "startRecording, SD card does not have sufficient space!!");
- return;
- }
-
- // get external storage directory
- File sdDir = new File(recordingSdcard);
- File recordingDir = new File(sdDir, FM_RECORD_FOLDER);
- // exist a file named FM Recording, so can't create FM recording folder
- if (recordingDir.exists() && !recordingDir.isDirectory()) {
- Log.e(TAG, "startRecording, a file with name \"" + FM_RECORD_FOLDER + "\" already exists!!");
- setError(ERROR_SDCARD_WRITE_FAILED);
- return;
- } else if (!recordingDir.exists()) { // try to create recording folder
- if (FmUtils.isExternalStorage()) {
- dir = getPathUri(context,recordingDir,externalStorageUri);
- } else {
- boolean mkdirResult = recordingDir.mkdir();
- if (!mkdirResult) { // create recording file failed
- setError(ERROR_RECORDER_INTERNAL);
- return;
- }
- }
- } else {
- if (FmUtils.isExternalStorage()) {
- dir = getPathUri(context,recordingDir,externalStorageUri);
- }
- }
- // create recording temporary file
- long curTime = System.currentTimeMillis();
- Date date = new Date(curTime);
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMddyyyy_HHmmss",
- Locale.ENGLISH);
- String time = simpleDateFormat.format(date);
- StringBuilder stringBuilder = new StringBuilder();
- /**
- * bug474741, recording format selection.
- *
- * @{
- */
- if (GLOBAL_RECORD_FORMAT_FLAG == 1) {
- stringBuilder.append(".").append(time).append(RECORDING_FILE_EXTENSION_3GPP).append(".tmp");
- } else if(GLOBAL_RECORD_FORMAT_FLAG == 2) {
- stringBuilder.append(".").append(time).append(RECORDING_FILE_EXTENSION_MP3).append(".tmp");
- } else {
- stringBuilder.append(".").append(time).append(RECORDING_FILE_EXTENSION_AMR).append(".tmp");
- }
- /**
- * @}
- */
- String name = stringBuilder.toString();
- mRecordFile = new File(recordingDir, name);
- if (FmUtils.isExternalStorage()) {
- try {
- Uri fileDoc = DocumentsContract.createDocument(context.getContentResolver(),dir
- ,DocumentsContract.Document.COLUMN_MIME_TYPE,name);
- FmUtils.saveTmpFileUri(fileDoc.toString());
- mPfd = context.getContentResolver().openFileDescriptor(fileDoc,"w");
- fd = mPfd.getFileDescriptor();
- if(fd == null) {
- Log.e(TAG,"fd is NULL");
- throw new IllegalArgumentException("Memory related error");
- }
- } catch(FileNotFoundException e) {
- Log.d(TAG,""+e);
- }
- } else {
- try {
- if (mRecordFile.createNewFile()) {
- Log.d(TAG, "startRecording, createNewFile success with path "
- + mRecordFile.getPath());
- }
- } catch (IOException e) {
- Log.e(TAG, "startRecording, IOException while createTempFile: " + e);
- e.printStackTrace();
- setError(ERROR_SDCARD_WRITE_FAILED);
- return;
- }
- }
- // set record parameter and start recording
- try {
- mRecorder = new MediaRecorder();
- mRecorder.setOnErrorListener(this);
- mRecorder.setOnInfoListener(this);
- // mRecorder.setAudioSource(MediaRecorder.AudioSource.RADIO_TUNER);
- mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- /**
- * bug474741, recording format selection. Original Android code:
- * mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- * mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); final int samplingRate =
- * 44100; mRecorder.setAudioSamplingRate(samplingRate); final int bitRate = 128000;
- * mRecorder.setAudioEncodingBitRate(bitRate); final int audiochannels = 2;
- * mRecorder.setAudioChannels(audiochannels);
- *
- * @{
- */
- if (1 == GLOBAL_RECORD_FORMAT_FLAG) {
- Log.d(TAG, "global_record_format: 3gpp");
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- mRecorder.setAudioSamplingRate(44100);
- mRecorder.setAudioEncodingBitRate(128000);
- } else if(2 == GLOBAL_RECORD_FORMAT_FLAG) {
- Log.d(TAG, "global_record_format: mp3");
- mRecorder.setOutputFormat(11);
- mRecorder.setAudioEncoder(7);
- mRecorder.setAudioSamplingRate(44100);
- mRecorder.setAudioEncodingBitRate(320000);
- mRecorder.setAudioChannels(2);
- } else {
- Log.d(TAG, "global_record_format: amr_nb");
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
- mRecorder.setAudioSamplingRate(8000);
- mRecorder.setAudioEncodingBitRate(5900);
- }
- /**
- * @}
- */
- if (FmUtils.isExternalStorage()) {
- mRecorder.setOutputFile(fd);
- } else {
- mRecorder.setOutputFile(mRecordFile.getAbsolutePath());
- }
- mRecorder.prepare();
- mRecordStartTime = SystemClock.elapsedRealtime();
- mRecorder.start();
- mIsRecordingFileSaved = false;
- mFileListener= new FileListener(recordingDir.getPath());
- mFileListener.startWatching();
-
- } catch (IllegalStateException e) {
- Log.e(TAG, "startRecording, IllegalStateException while starting recording!", e);
- setError(ERROR_RECORDER_INTERNAL);
- return;
- } catch (IOException e) {
- Log.e(TAG, "startRecording, IOException while starting recording!", e);
- setError(ERROR_RECORDER_INTERNAL);
- return;
- }
- setState(STATE_RECORDING);
- }
-
- /**
- *Listening whether recording file is delete or not.
- *@}
- */
- private class FileListener extends FileObserver {
- public FileListener(String path) {
- super(path, FileObserver.MOVED_FROM | FileObserver.DELETE);
- Log.d(TAG, "FileListener path="+path);
- }
- @Override
- public void onEvent(int event, String path) {
- Log.d(TAG, "onEvent: event = "+event+"; path = "+path);
- switch (event) {
- case FileObserver.MOVED_FROM:
- case FileObserver.DELETE:
- if (path == null) {
- return ;
- }
- if ( getTmpFileName().equals(path)) {
- Log.d(TAG, "recording tmp file is deleted");
- discardRecording();
- }
- break;
- default:
- break;
- }
- }
- }
-
- private void stopRecorder() {
-
- ......
- mRecorder.stop();
- ......
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。