summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlamefire <alex@grundis.de>2014-06-05 18:00:34 +0200
committerFlamefire <alex@grundis.de>2014-10-29 14:48:54 +0100
commit951cc1efc7da193faa0769c5818f6848b9baf0dc (patch)
tree734febc3b7768fbc7a1df31cb721bb70f87328ae
parenta8059acb634796c0b8d15c3bd1aed6469c763425 (diff)
downloadandroid_packages_apps_DeskClock-951cc1efc7da193faa0769c5818f6848b9baf0dc.tar.gz
android_packages_apps_DeskClock-951cc1efc7da193faa0769c5818f6848b9baf0dc.tar.bz2
android_packages_apps_DeskClock-951cc1efc7da193faa0769c5818f6848b9baf0dc.zip
Add option to change timer alert sound
The default alert sound is sometimes quite annoying PS1: Rebase and save the last picked value as default PS6: WS fixes Change-Id: I239e0d56a1562ba2c0fbff92fdf907d1147fb402
-rw-r--r--res/layout/time_setup_view.xml25
-rw-r--r--res/values/cm_arrays.xml5
-rw-r--r--res/values/cm_strings.xml1
-rw-r--r--src/com/android/deskclock/TimerRingService.java12
-rw-r--r--src/com/android/deskclock/timer/TimerFragment.java145
-rw-r--r--src/com/android/deskclock/timer/TimerObj.java20
-rw-r--r--src/com/android/deskclock/timer/TimerReceiver.java6
7 files changed, 201 insertions, 13 deletions
diff --git a/res/layout/time_setup_view.xml b/res/layout/time_setup_view.xml
index ea3c392b7..a81026ed0 100644
--- a/res/layout/time_setup_view.xml
+++ b/res/layout/time_setup_view.xml
@@ -64,6 +64,31 @@
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="@color/hairline"/>
+ <TextView
+ android:id="@+id/choose_ringtone"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="6dp"
+ android:gravity="center_vertical"
+ android:textAlignment="viewStart"
+ style="@style/body"
+ android:background="@drawable/item_background"
+ android:clickable="true"
+ android:textColor="@color/clock_white"
+ android:ellipsize="marquee"
+ android:scrollHorizontally="true"
+ android:singleLine="true"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:drawableStart="@drawable/ic_ringtone"
+ android:drawablePadding="2dp"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true"
+ />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="@color/hairline"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml
index 753a5b429..1584fc68c 100644
--- a/res/values/cm_arrays.xml
+++ b/res/values/cm_arrays.xml
@@ -34,4 +34,9 @@
<item>@string/alarm_type_ringtone</item>
<item>@string/alarm_type_random</item>
</string-array>
+
+ <string-array name="timer_ringtone_picker_entries" translatable="false">
+ <item>@string/alarm_type_ringtone</item>
+ <item>@string/alarm_type_default</item>
+ </string-array>
</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 35a6af081..f79da840f 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -79,6 +79,7 @@
<!-- Alarm types -->
<string name="alarm_type_ringtone">Ringtone</string>
<string name="alarm_type_random">Randomly</string>
+ <string name="alarm_type_default">Default</string>
<!-- Warn Silent Alarm title -->
<string name="warn_silent_alarm_title">Alarm volume is silent</string>
diff --git a/src/com/android/deskclock/TimerRingService.java b/src/com/android/deskclock/TimerRingService.java
index 0bc269b54..b3c8b019e 100644
--- a/src/com/android/deskclock/TimerRingService.java
+++ b/src/com/android/deskclock/TimerRingService.java
@@ -24,7 +24,6 @@ import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
-import android.media.RingtoneManager;
import android.net.Uri;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
@@ -40,6 +39,8 @@ public class TimerRingService extends Service implements AudioManager.OnAudioFoc
private TelephonyManager mTelephonyManager;
private int mInitialCallState;
+ public final static String RINGTONE = "RINGTONE";
+
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
@@ -86,7 +87,7 @@ public class TimerRingService extends Service implements AudioManager.OnAudioFoc
return START_NOT_STICKY;
}
- play();
+ play(Uri.parse(intent.getStringExtra(RINGTONE)));
// Record the initial call state here so that the new alarm has the
// newest state.
mInitialCallState = mTelephonyManager.getCallState();
@@ -97,7 +98,7 @@ public class TimerRingService extends Service implements AudioManager.OnAudioFoc
// Volume suggested by media team for in-call alarms.
private static final float IN_CALL_VOLUME = 0.125f;
- private void play() {
+ private void play(Uri ringtone) {
if (mPlaying) {
return;
@@ -130,10 +131,13 @@ public class TimerRingService extends Service implements AudioManager.OnAudioFoc
mMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
setDataSourceFromResource(getResources(), mMediaPlayer,
R.raw.in_call_alarm);
- } else {
+ } else if (ringtone.equals(Uri.EMPTY)) {
+ // Default sound
AssetFileDescriptor afd = getAssets().openFd("sounds/Timer_Expire.ogg");
mMediaPlayer.setDataSource(
afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ } else {
+ mMediaPlayer.setDataSource(getApplication(), ringtone);
}
startAlarm(mMediaPlayer);
} catch (Exception ex) {
diff --git a/src/com/android/deskclock/timer/TimerFragment.java b/src/com/android/deskclock/timer/TimerFragment.java
index 700168bec..4efc9065e 100644
--- a/src/com/android/deskclock/timer/TimerFragment.java
+++ b/src/com/android/deskclock/timer/TimerFragment.java
@@ -19,15 +19,21 @@ package com.android.deskclock.timer;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
@@ -52,25 +58,27 @@ import com.android.deskclock.LabelDialogFragment;
import com.android.deskclock.R;
import com.android.deskclock.TimerSetupView;
import com.android.deskclock.Utils;
+import com.android.deskclock.widget.sgv.GridAdapter;
+import com.android.deskclock.widget.sgv.SgvAnimationHelper.AnimationIn;
+import com.android.deskclock.widget.sgv.SgvAnimationHelper.AnimationOut;
+import com.android.deskclock.widget.sgv.StaggeredGridView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
-import com.android.deskclock.widget.sgv.SgvAnimationHelper.AnimationIn;
-import com.android.deskclock.widget.sgv.SgvAnimationHelper.AnimationOut;
-import com.android.deskclock.widget.sgv.StaggeredGridView;
-import com.android.deskclock.widget.sgv.GridAdapter;
-
public class TimerFragment extends DeskClockFragment
implements OnClickListener, OnSharedPreferenceChangeListener {
private static final String TAG = "TimerFragment";
private static final String KEY_SETUP_SELECTED = "_setup_selected";
private static final String KEY_ENTRY_STATE = "entry_state";
+ public static final String KEY_TIMER_SOUND = "timer_sound";
public static final String GOTO_SETUP_VIEW = "deskclock.timers.gotosetup";
+ private static final int REQUEST_CODE_RINGTONE = 1;
+
private Bundle mViewState = null;
private StaggeredGridView mTimersList;
private View mTimersListPage;
@@ -86,6 +94,10 @@ public class TimerFragment extends DeskClockFragment
private NotificationManager mNotificationManager;
private OnEmptyListListener mOnEmptyListListener;
private View mLastVisibleView = null; // used to decide if to set the view or animate to it.
+ private TextView mRingtone;
+
+ private Uri mRingtoneUri = null;
+ private Bundle mRingtoneTitleCache = new Bundle();
public TimerFragment() {
}
@@ -487,6 +499,7 @@ public class TimerFragment extends DeskClockFragment
}
TimerObj t = new TimerObj(timerLength * 1000);
t.mState = TimerObj.STATE_RUNNING;
+ t.setRingtone(mRingtoneUri);
mAdapter.addTimer(t);
updateTimersState(t, Timers.START_TIMER);
gotoTimersView();
@@ -524,9 +537,128 @@ public class TimerFragment extends DeskClockFragment
mNotificationManager = (NotificationManager)
getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
+ mRingtone = (TextView) v.findViewById(R.id.choose_ringtone);
+ mRingtone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ launchRingTonePicker();
+ }
+ });
+ String ringtone = mPrefs.getString(KEY_TIMER_SOUND, "");
+ if (ringtone == null || ringtone.isEmpty())
+ mRingtoneUri = null;
+ else
+ mRingtoneUri = Uri.parse(ringtone);
+ updateRingtoneText();
+
return v;
}
+ private void updateRingtoneText() {
+ String ringtone;
+ if (mRingtoneUri == null) {
+ ringtone = getResources().getString(R.string.alarm_type_default);
+ } else {
+ ringtone = getRingToneTitle(mRingtoneUri);
+ if (ringtone == null) {
+ ringtone = getResources().getString(R.string.alarm_type_default);
+ }
+ }
+ mRingtone.setText(ringtone);
+ mRingtone.setContentDescription(
+ getResources().getString(R.string.ringtone_description) + " " + ringtone);
+ }
+
+ /**
+ * Does a read-through cache for ringtone titles.
+ *
+ * @param uri The uri of the ringtone.
+ * @return The ringtone title. {@literal null} if no matching ringtone
+ * found.
+ */
+ private String getRingToneTitle(Uri uri) {
+ // Try the cache first
+ String title = mRingtoneTitleCache.getString(uri.toString());
+ if (title == null) {
+ // This is slow because a media player is created during Ringtone
+ // object creation.
+ Ringtone ringTone = RingtoneManager.getRingtone(getActivity(), uri);
+ if (ringTone != null) {
+ title = ringTone.getTitle(getActivity());
+ }
+ if (title != null) {
+ mRingtoneTitleCache.putString(uri.toString(), title);
+ }
+ }
+ return title;
+ }
+
+ private void launchRingTonePicker() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.alarm_picker_title).setItems(
+ R.array.timer_ringtone_picker_entries,
+
+ new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case 0:
+ launchSingleRingTonePicker();
+ break;
+ case 1:
+ mRingtoneUri = null;
+ SharedPreferences.Editor editor = mPrefs.edit();
+ editor.putString(KEY_TIMER_SOUND, "");
+ editor.apply();
+ updateRingtoneText();
+ break;
+ }
+ }
+ });
+ AlertDialog d = builder.create();
+ d.show();
+ }
+
+ private void launchSingleRingTonePicker() {
+ // Save current view state
+ mViewState = new Bundle();
+ saveViewState(mViewState);
+
+ final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, mRingtoneUri);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
+ startActivityForResult(intent, REQUEST_CODE_RINGTONE);
+ }
+
+ private void saveRingtoneUri(Intent intent) {
+ mRingtoneUri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+
+ // Save the last selected ringtone as the default for new alarms
+ if (mRingtoneUri != null) {
+ RingtoneManager.setActualDefaultRingtoneUri(
+ getActivity(), RingtoneManager.TYPE_ALARM, mRingtoneUri);
+ }
+ SharedPreferences.Editor editor = mPrefs.edit();
+ editor.putString(KEY_TIMER_SOUND, mRingtoneUri == null ? "" : mRingtoneUri.toString());
+ editor.apply();
+ updateRingtoneText();
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ switch (requestCode) {
+ case REQUEST_CODE_RINGTONE:
+ saveRingtoneUri(data);
+ break;
+ default:
+ Log.w(TAG, "Unhandled request code in onActivityResult: " + requestCode);
+ }
+ }
+ }
+
@Override
public void onDestroyView() {
mViewState = new Bundle();
@@ -606,7 +738,7 @@ public class TimerFragment extends DeskClockFragment
super.onPause();
stopClockTicks();
if (mAdapter != null) {
- mAdapter.saveGlobalState ();
+ mAdapter.saveGlobalState();
}
mPrefs.unregisterOnSharedPreferenceChangeListener(this);
// This is called because the lock screen was activated, the window stay
@@ -721,6 +853,7 @@ public class TimerFragment extends DeskClockFragment
mTimerSetup.updateDeleteButton();
mLastVisibleView = mTimerSetup;
}
+
private void gotoTimersView() {
if (mLastVisibleView == null || mLastVisibleView.getId() == R.id.timers_list_page) {
mTimerSetup.setVisibility(View.GONE);
diff --git a/src/com/android/deskclock/timer/TimerObj.java b/src/com/android/deskclock/timer/TimerObj.java
index 66aee5952..506a5deea 100644
--- a/src/com/android/deskclock/timer/TimerObj.java
+++ b/src/com/android/deskclock/timer/TimerObj.java
@@ -18,6 +18,7 @@ package com.android.deskclock.timer;
import android.content.Context;
import android.content.SharedPreferences;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
@@ -49,6 +50,7 @@ public class TimerObj implements Parcelable {
public int mState;
public String mLabel;
public boolean mDeleteAfterUse;
+ private Uri mRingtone;
public static final int STATE_RUNNING = 1;
public static final int STATE_STOPPED = 2;
@@ -65,6 +67,7 @@ public class TimerObj implements Parcelable {
private static final String PREF_STATE = "timer_state_";
private static final String PREF_LABEL = "timer_label_";
private static final String PREF_DELETE_AFTER_USE = "delete_after_use_";
+ private static final String PREF_RINGTONE = "ringtone_";
private static final String PREF_TIMERS_LIST = "timers_list";
@@ -102,6 +105,8 @@ public class TimerObj implements Parcelable {
editor.putString(key, mLabel);
key = PREF_DELETE_AFTER_USE + id;
editor.putBoolean(key, mDeleteAfterUse);
+ key = PREF_RINGTONE + id;
+ editor.putString(key, mRingtone.toString());
editor.apply();
}
@@ -122,6 +127,8 @@ public class TimerObj implements Parcelable {
mLabel = prefs.getString(key, "");
key = PREF_DELETE_AFTER_USE + id;
mDeleteAfterUse = prefs.getBoolean(key, false);
+ key = PREF_RINGTONE + id;
+ mRingtone = Uri.parse(prefs.getString(key, ""));
}
public void deleteFromSharedPref(SharedPreferences prefs) {
@@ -146,6 +153,8 @@ public class TimerObj implements Parcelable {
editor.remove(key);
key = PREF_DELETE_AFTER_USE + id;
editor.remove(key);
+ key = PREF_RINGTONE + id;
+ editor.remove(key);
editor.commit();
//dumpTimersFromSharedPrefs(prefs);
}
@@ -165,6 +174,7 @@ public class TimerObj implements Parcelable {
dest.writeLong(mSetupLength);
dest.writeInt(mState);
dest.writeString(mLabel);
+ dest.writeString(mRingtone.toString());
}
public TimerObj(Parcel p) {
@@ -175,6 +185,7 @@ public class TimerObj implements Parcelable {
mSetupLength = p.readLong();
mState = p.readInt();
mLabel = p.readString();
+ mRingtone = Uri.parse(p.readString());
}
public TimerObj() {
@@ -198,6 +209,7 @@ public class TimerObj implements Parcelable {
mStartTime = Utils.getTimeNow();
mTimeLeft = mOriginalLength = mSetupLength = length;
mLabel = "";
+ mRingtone = Uri.EMPTY;
}
public long updateTimeLeft(boolean forceUpdate) {
@@ -237,6 +249,13 @@ public class TimerObj implements Parcelable {
return mStartTime + mOriginalLength;
}
+ public Uri getRingtone() {
+ return mRingtone;
+ }
+
+ public void setRingtone(Uri ringTone) {
+ mRingtone = ringTone == null ? Uri.EMPTY : ringTone;
+ }
public static void getTimersFromSharedPrefs(
SharedPreferences prefs, ArrayList<TimerObj> timers) {
@@ -278,7 +297,6 @@ public class TimerObj implements Parcelable {
SharedPreferences prefs, ArrayList<TimerObj> timers) {
if (timers.size() > 0) {
for (int i = 0; i < timers.size(); i++) {
- TimerObj t = timers.get(i);
timers.get(i).writeToSharedPref(prefs);
}
}
diff --git a/src/com/android/deskclock/timer/TimerReceiver.java b/src/com/android/deskclock/timer/TimerReceiver.java
index 86cdb04e6..28c60085b 100644
--- a/src/com/android/deskclock/timer/TimerReceiver.java
+++ b/src/com/android/deskclock/timer/TimerReceiver.java
@@ -99,10 +99,12 @@ public class TimerReceiver extends BroadcastReceiver {
t.mState = TimerObj.STATE_TIMESUP;
t.writeToSharedPref(prefs);
- // Play ringtone by using TimerRingService service with a default alarm.
+ // Play ringtone by using TimerRingService service with the selected
+ // alarm.
Log.d(TAG, "playing ringtone");
Intent si = new Intent();
si.setClass(context, TimerRingService.class);
+ si.putExtra(TimerRingService.RINGTONE, t.getRingtone().toString());
context.startService(si);
// Update the in-use notification
@@ -348,7 +350,7 @@ public class TimerReceiver extends BroadcastReceiver {
return null;
}
- long hundreds, seconds, minutes, hours;
+ long seconds, minutes, hours;
seconds = timeLeft / 1000;
minutes = seconds / 60;
seconds = seconds - minutes * 60;