From e7a0b1076f5e2ccf4c2a84dc58e97a296e83b4d0 Mon Sep 17 00:00:00 2001 From: Clark Scheff Date: Wed, 9 Jul 2014 15:49:03 -0700 Subject: Add component selection for sounds. Change-Id: Ib72c4c3a97bde11a6a5547c1c8f15b3e5059bb1a --- .../media_sound__selector_preview.png | Bin 0 -> 3300 bytes .../component_selection_sounds_pager_item.xml | 8 ++ res/layout/sound_component_selection_item.xml | 26 +++++ res/values/colors.xml | 2 +- res/values/dimens.xml | 1 + res/values/styles.xml | 8 ++ .../theme/chooserv2/ComponentSelector.java | 89 +++++++++++++++ src/org/cyanogenmod/theme/util/AudioUtils.java | 127 +++++++++++++++++++++ 8 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 res/drawable-xxhdpi/media_sound__selector_preview.png create mode 100644 res/layout/component_selection_sounds_pager_item.xml create mode 100644 res/layout/sound_component_selection_item.xml create mode 100644 src/org/cyanogenmod/theme/util/AudioUtils.java diff --git a/res/drawable-xxhdpi/media_sound__selector_preview.png b/res/drawable-xxhdpi/media_sound__selector_preview.png new file mode 100644 index 0000000..bcac6c2 Binary files /dev/null and b/res/drawable-xxhdpi/media_sound__selector_preview.png differ diff --git a/res/layout/component_selection_sounds_pager_item.xml b/res/layout/component_selection_sounds_pager_item.xml new file mode 100644 index 0000000..08d0c56 --- /dev/null +++ b/res/layout/component_selection_sounds_pager_item.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/res/layout/sound_component_selection_item.xml b/res/layout/sound_component_selection_item.xml new file mode 100644 index 0000000..693840e --- /dev/null +++ b/res/layout/sound_component_selection_item.xml @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 0b3eda6..6cf5ff8 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -33,6 +33,6 @@ #e6212121 #80cccccc #40000000 - #44a7ff + #50acff #d6d6d8 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 8642e78..85b6d0f 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -26,6 +26,7 @@ 80dp 112dp 203dp + 120dp 48dp @dimen/component_selection_content_width 80dp diff --git a/res/values/styles.xml b/res/values/styles.xml index 285155d..dd2376b 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -144,4 +144,12 @@ 2 + + diff --git a/src/org/cyanogenmod/theme/chooserv2/ComponentSelector.java b/src/org/cyanogenmod/theme/chooserv2/ComponentSelector.java index 897f83a..30ce474 100644 --- a/src/org/cyanogenmod/theme/chooserv2/ComponentSelector.java +++ b/src/org/cyanogenmod/theme/chooserv2/ComponentSelector.java @@ -16,6 +16,7 @@ package org.cyanogenmod.theme.chooserv2; import android.content.Context; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.Cursor; @@ -23,6 +24,8 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; +import android.media.MediaPlayer; +import android.media.RingtoneManager; import android.os.Bundle; import android.provider.Settings; import android.provider.ThemesContract; @@ -49,13 +52,17 @@ import android.widget.TextView; import android.widget.Toast; import com.viewpagerindicator.PageIndicator; import org.cyanogenmod.theme.chooser.R; +import org.cyanogenmod.theme.util.AudioUtils; import org.cyanogenmod.theme.util.ThemedTypefaceHelper; import java.util.HashMap; +import static android.provider.ThemesContract.ThemesColumns.MODIFIES_ALARMS; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_BOOT_ANIM; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_LAUNCHER; +import static android.provider.ThemesContract.ThemesColumns.MODIFIES_NOTIFICATIONS; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_OVERLAYS; +import static android.provider.ThemesContract.ThemesColumns.MODIFIES_RINGTONES; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_STATUS_BAR; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_NAVIGATION_BAR; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_ICONS; @@ -74,6 +81,9 @@ public class ComponentSelector extends LinearLayout private static final int LOADER_ID_STYLE = 104; private static final int LOADER_ID_WALLPAPER = 105; private static final int LOADER_ID_BOOTANIMATIONS = 106; + private static final int LOADER_ID_RINGTONE = 107; + private static final int LOADER_ID_NOTIFICATION = 108; + private static final int LOADER_ID_ALARM = 109; private Context mContext; private LayoutInflater mInflater; @@ -91,6 +101,8 @@ public class ComponentSelector extends LinearLayout private OnItemClickedListener mListener; + private MediaPlayer mMediaPlayer; + public ComponentSelector(Context context, AttributeSet attrs) { super(context, attrs); @@ -122,6 +134,7 @@ public class ComponentSelector extends LinearLayout public void onAnimationRepeat(Animation animation) { } }); + mMediaPlayer = new MediaPlayer(); } @Override @@ -135,6 +148,9 @@ public class ComponentSelector extends LinearLayout // set navbar_padding to GONE if no on screen navigation bar is available if (!hasNavigationBar()) findViewById(R.id.navbar_padding).setVisibility(View.GONE); + setNumItemsPerPage(2); + setComponentType(MODIFIES_RINGTONES); + show(); } public void setComponentType(String component) { @@ -177,6 +193,7 @@ public class ComponentSelector extends LinearLayout public void hide() { startAnimation(mAnimateOut); + if (mMediaPlayer != null && mMediaPlayer.isPlaying()) mMediaPlayer.stop(); } private boolean hasNavigationBar() { @@ -205,6 +222,15 @@ public class ComponentSelector extends LinearLayout if (MODIFIES_BOOT_ANIM.equals(component)) { return LOADER_ID_BOOTANIMATIONS; } + if (MODIFIES_RINGTONES.equals(component)) { + return LOADER_ID_RINGTONE; + } + if (MODIFIES_NOTIFICATIONS.equals(component)) { + return LOADER_ID_NOTIFICATION; + } + if (MODIFIES_ALARMS.equals(component)) { + return LOADER_ID_ALARM; + } return -1; } @@ -289,6 +315,15 @@ public class ComponentSelector extends LinearLayout ThemesColumns.PKG_NAME }; break; + case LOADER_ID_RINGTONE: + selection = MODIFIES_RINGTONES + "=?"; + break; + case LOADER_ID_NOTIFICATION: + selection = MODIFIES_NOTIFICATIONS + "=?"; + break; + case LOADER_ID_ALARM: + selection = MODIFIES_ALARMS + "=?"; + break; default: return null; } @@ -318,6 +353,8 @@ public class ComponentSelector extends LinearLayout public class CursorPagerAdapter extends PagerAdapter { LinearLayout.LayoutParams mItemParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f); + LinearLayout.LayoutParams mSoundItemParams = + new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1.0f); private Cursor mCursor; private int mItemsPerPage; HashMap mTypefaceHelpers = @@ -357,6 +394,16 @@ public class ComponentSelector extends LinearLayout if (MODIFIES_BOOT_ANIM.equals(mComponentType)) { newBootanimationView(mCursor, v, position); } + if (MODIFIES_RINGTONES.equals(mComponentType) || + MODIFIES_NOTIFICATIONS.equals(mComponentType) || + MODIFIES_ALARMS.equals(mComponentType)) { + v = (ViewGroup) mInflater.inflate(R.layout.component_selection_sounds_pager_item, + container, false); + if (v instanceof LinearLayout) { + ((LinearLayout) v).setWeightSum(mItemsPerPage); + } + newSoundView(mCursor, v, position, mComponentType); + } container.addView(v); return v; } @@ -567,6 +614,48 @@ public class ComponentSelector extends LinearLayout } } + private void newSoundView(Cursor cursor, ViewGroup parent, int position, String component) { + for (int i = 0; i < mItemsPerPage; i++) { + int index = position * mItemsPerPage + i; + if (cursor.getCount() <= index) continue; + cursor.moveToPosition(index); + View v = mInflater.inflate(R.layout.sound_component_selection_item, parent, + false); + final int pkgNameIndex = cursor.getColumnIndex(ThemesContract.ThemesColumns.PKG_NAME); + + setTitle(((TextView) v.findViewById(R.id.title)), cursor); + v.setTag(cursor.getString(pkgNameIndex)); + v.setOnClickListener(mItemClickListener); + parent.addView(v, mSoundItemParams); + View playButton = v.findViewById(R.id.play_button); + playButton.setTag(cursor.getString(pkgNameIndex)); + playButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int type; + String pkgName = (String) v.getTag(); + if (mComponentType.equals(MODIFIES_RINGTONES)) { + type = RingtoneManager.TYPE_RINGTONE; + } else if (mComponentType.equals(MODIFIES_NOTIFICATIONS)) { + type = RingtoneManager.TYPE_NOTIFICATION; + } else { + type = RingtoneManager.TYPE_ALARM; + } + try { + if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + } + AudioUtils.loadThemeAudible(mContext, type, pkgName, + mMediaPlayer); + mMediaPlayer.start(); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + }); + } + } + private void addDivider(ViewGroup parent) { final Resources res = getResources(); View v = mInflater.inflate(R.layout.component_divider, parent, false); diff --git a/src/org/cyanogenmod/theme/util/AudioUtils.java b/src/org/cyanogenmod/theme/util/AudioUtils.java new file mode 100644 index 0000000..214f02e --- /dev/null +++ b/src/org/cyanogenmod/theme/util/AudioUtils.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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 org.cyanogenmod.theme.util; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ThemeUtils; +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.content.res.ThemeConfig; +import android.media.MediaPlayer; +import android.media.RingtoneManager; +import android.util.Log; + +import java.io.File; +import java.io.IOException; + +public class AudioUtils { + private static final String TAG = AudioUtils.class.getSimpleName(); + + public static void loadThemeAudible(Context context, int type, String pkgName, MediaPlayer mp) + throws PackageManager.NameNotFoundException { + if (ThemeConfig.HOLO_DEFAULT.equals(pkgName)) { + loadSystemAudible(type, mp); + return; + } + PackageInfo pi = context.getPackageManager().getPackageInfo(pkgName, 0); + Context themeCtx = context.createPackageContext(pkgName, 0); + if (pi.isLegacyThemeApk) { + loadLegacyThemeAudible(themeCtx, type, pi, mp); + return; + } + AssetManager assetManager = themeCtx.getAssets(); + String assetPath; + switch (type) { + case RingtoneManager.TYPE_ALARM: + assetPath = "alarms"; + break; + case RingtoneManager.TYPE_NOTIFICATION: + assetPath = "notifications"; + break; + case RingtoneManager.TYPE_RINGTONE: + assetPath = "ringtones"; + break; + default: + assetPath = null; + break; + } + if (assetPath != null) { + try { + String[] assetList = assetManager.list(assetPath); + if (assetList != null && assetList.length > 0) { + AssetFileDescriptor afd = assetManager.openFd(assetPath + + File.separator + assetList[0]); + if (mp != null) { + mp.reset(); + mp.setDataSource(afd.getFileDescriptor(), + afd.getStartOffset(), afd.getLength()); + mp.prepare(); + } + } + } catch (IOException e) { + Log.e(TAG, "Unable to load sound for " + pkgName, e); + } + } + } + + public static void loadLegacyThemeAudible(Context themeCtx, int type, PackageInfo pi, + MediaPlayer mp) { + if (pi.legacyThemeInfos == null || pi.legacyThemeInfos.length == 0) + return; + AssetManager assetManager = themeCtx.getAssets(); + String assetPath; + switch (type) { + case RingtoneManager.TYPE_NOTIFICATION: + assetPath = pi.legacyThemeInfos[0].notificationFileName; + break; + case RingtoneManager.TYPE_RINGTONE: + assetPath = pi.legacyThemeInfos[0].ringtoneFileName; + break; + default: + assetPath = null; + break; + } + if (assetPath != null) { + try { + AssetFileDescriptor afd = assetManager.openFd(assetPath); + if (mp != null) { + mp.reset(); + mp.setDataSource(afd.getFileDescriptor(), + afd.getStartOffset(), afd.getLength()); + mp.prepare(); + } + } catch (IOException e) { + Log.e(TAG, "Unable to load legacy sound for " + pi.packageName, e); + } + } + } + + public static void loadSystemAudible(int type, MediaPlayer mp) { + final String audiblePath = ThemeUtils.getDefaultAudiblePath(type); + if (audiblePath != null && (new File(audiblePath)).exists()) { + try { + mp.reset(); + mp.setDataSource(audiblePath); + mp.prepare(); + } catch (IOException e) { + Log.e(TAG, "Unable to load system sound " + audiblePath, e); + } + } + } + +} -- cgit v1.1