diff options
author | kaiyiz <kaiyiz@codeaurora.org> | 2014-04-18 16:13:11 +0800 |
---|---|---|
committer | cretin45 <cretin45@gmail.com> | 2014-12-15 14:50:29 -0800 |
commit | 7710deff8caa5443190849297189f82dfe98bd6f (patch) | |
tree | 5cdb6d38fcfa44c9a63a34af94118a605201489b | |
parent | 345afa5ed50b47fe9aa18476a6d3102261725164 (diff) | |
download | android_packages_apps_Gallery2-7710deff8caa5443190849297189f82dfe98bd6f.tar.gz android_packages_apps_Gallery2-7710deff8caa5443190849297189f82dfe98bd6f.tar.bz2 android_packages_apps_Gallery2-7710deff8caa5443190849297189f82dfe98bd6f.zip |
Gallery2: Add audio output switcher between headset/speaker
There is no audio output switcher between headset/speaker.
Add the audio output switcher button to menu list in order to
let user use this function.
CRs-Fixed: 650867
Change-Id: I16f5fdc74a76ee55557ba87b0145e51165f0408a
-rw-r--r-- | AndroidManifest.xml | 18 | ||||
-rw-r--r-- | res/values-zh-rCN/codeaurora_strings.xml | 5 | ||||
-rw-r--r-- | res/values/codeaurora_strings.xml | 5 | ||||
-rwxr-xr-x | src/org/codeaurora/gallery3d/video/ExtensionHelper.java | 32 | ||||
-rw-r--r-- | src/org/codeaurora/gallery3d/video/SpeakerHooker.java | 210 |
5 files changed, 268 insertions, 2 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 679ca0408..6136da96d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,4 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + Not a Contribution. + + Copyright (C) 2007 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. +--> <manifest android:versionCode="40030" android:versionName="1.1.40030" @@ -19,6 +36,7 @@ <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> + <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> diff --git a/res/values-zh-rCN/codeaurora_strings.xml b/res/values-zh-rCN/codeaurora_strings.xml index b1b2dbeb4..d046f3f1b 100644 --- a/res/values-zh-rCN/codeaurora_strings.xml +++ b/res/values-zh-rCN/codeaurora_strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -38,6 +38,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <string name="loop">"循环"</string> <string name="single">"单次"</string> <string name="stereo">"立体声"</string> + <string name="speaker_on">扬声器 开</string> + <string name="speaker_off">扬声器 关</string> + <string name="speaker_need_headset">请先插入耳机!</string> <string name="single_track">"单声道"</string> <string name="media_detail">"媒体详情"</string> <string name="input_url">"输入 URL"</string> diff --git a/res/values/codeaurora_strings.xml b/res/values/codeaurora_strings.xml index 386d2b11a..941365252 100644 --- a/res/values/codeaurora_strings.xml +++ b/res/values/codeaurora_strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -38,6 +38,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <string name="loop">"Loop"</string> <string name="single">"Single"</string> <string name="stereo">"Stereo"</string> + <string name="speaker_on">Speaker ON</string> + <string name="speaker_off">Speaker OFF</string> + <string name="speaker_need_headset">Please plug in headset first!</string> <string name="single_track">"Single track"</string> <string name="media_detail">"Media details"</string> <string name="input_url">"Input URL"</string> diff --git a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java index 2ff61a4e5..b5156100b 100755 --- a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java +++ b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java @@ -1,3 +1,31 @@ +/* +Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ package org.codeaurora.gallery3d.video; import android.content.Context; @@ -20,6 +48,7 @@ public class ExtensionHelper { boolean stereo = context.getResources().getBoolean(R.bool.stereo); boolean streaming = context.getResources().getBoolean(R.bool.streaming); boolean playlist = context.getResources().getBoolean(R.bool.playlist); + boolean speaker = context.getResources().getBoolean(R.bool.speaker); if (loop == true) { group.addHooker(new LoopVideoHooker()); // add it for common feature. @@ -35,6 +64,9 @@ public class ExtensionHelper { group.addHooker(new MovieListHooker()); // add it for common feature. group.addHooker(new StepOptionSettingsHooker()); } + if (speaker == true) { + group.addHooker(new SpeakerHooker()); + } return group; } } diff --git a/src/org/codeaurora/gallery3d/video/SpeakerHooker.java b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java new file mode 100644 index 000000000..9bf534872 --- /dev/null +++ b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java @@ -0,0 +1,210 @@ +/* +Copyright (c) 2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package org.codeaurora.gallery3d.video; + +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; + +import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.media.AudioSystem; +import android.os.Bundle; + +import com.android.gallery3d.R; + +public class SpeakerHooker extends MovieHooker { + + private static final int MENU_SPEAKER = 1; + + private AudioManager mAudioManager; + + private MenuItem mMenuSpeakerButton; + + private boolean mIsHeadsetOn = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initAudioManager(); + } + + private void initAudioManager() { + if (mAudioManager == null) { + mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + } + } + + @Override + public void onDestroy() { + turnSpeakerOff(); + super.onDestroy(); + } + + @Override + public void onResume() { + super.onResume(); + registerHeadSetReceiver(); + } + + private void registerHeadSetReceiver() { + final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); + intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); + intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); + intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY); + getContext().registerReceiver(mHeadSetReceiver, intentFilter); + } + + @Override + public void onPause() { + unregisterHeadSetReceiver(); + super.onPause(); + } + + private void unregisterHeadSetReceiver() { + try { + getContext().unregisterReceiver(mHeadSetReceiver); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private final BroadcastReceiver mHeadSetReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (mAudioManager == null) { + initAudioManager(); + } + if (action.equals(Intent.ACTION_HEADSET_PLUG)) { + mIsHeadsetOn = (intent.getIntExtra("state", 0) == 1) + || mAudioManager.isBluetoothA2dpOn(); + } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED) + || action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { + final int deviceClass = ((BluetoothDevice) + intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)) + .getBluetoothClass().getDeviceClass(); + if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) + || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { + mIsHeadsetOn = action.equals(BluetoothDevice.ACTION_ACL_CONNECTED) + || mAudioManager.isWiredHeadsetOn(); + } + } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { + mIsHeadsetOn = false; + } + updateSpeakerButton(); + if (!mIsHeadsetOn) { + turnSpeakerOff(); + } + } + }; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + mMenuSpeakerButton = menu.add(0, getMenuActivityId(MENU_SPEAKER), 0, R.string.speaker_on); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + super.onOptionsItemSelected(item); + switch (getMenuOriginalId(item.getItemId())) { + case MENU_SPEAKER: + changeSpeakerState(); + return true; + default: + return false; + } + } + + private void changeSpeakerState() { + if (isSpeakerOn()) { + turnSpeakerOff(); + } else { + if (mIsHeadsetOn) { + turnSpeakerOn(); + } else { + Toast.makeText(getContext(), getContext().getString(R.string.speaker_need_headset), + Toast.LENGTH_SHORT).show(); + } + } + updateSpeakerButton(); + } + + private void turnSpeakerOn() { + if (mAudioManager == null) { + initAudioManager(); + } + mAudioManager.setSpeakerphoneOn(true); + AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, + AudioSystem.FORCE_SPEAKER); + } + + private void turnSpeakerOff() { + if (mAudioManager == null) { + initAudioManager(); + } + AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, + AudioSystem.FORCE_NONE); + mAudioManager.setSpeakerphoneOn(false); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + updateSpeakerButton(); + return true; + } + + private void updateSpeakerButton() { + if (mMenuSpeakerButton != null) { + if (isSpeakerOn()) { + mMenuSpeakerButton.setTitle(R.string.speaker_off); + } else { + mMenuSpeakerButton.setTitle(R.string.speaker_on); + } + } + } + + private boolean isSpeakerOn() { + boolean isSpeakerOn = false; + if (mAudioManager == null) { + initAudioManager(); + } + isSpeakerOn = mAudioManager.isSpeakerphoneOn(); + return isSpeakerOn; + } + +} |