1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.inputmethod.deprecated.voice; 18 19 import com.android.inputmethod.compat.SharedPreferencesCompat; 20 import com.android.inputmethod.latin.R; 21 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.SharedPreferences; 25 import android.view.inputmethod.InputConnection; 26 27 import java.util.Calendar; 28 import java.util.HashMap; 29 import java.util.Map; 30 31 /** 32 * Logic to determine when to display hints on usage to the user. 33 */ 34 public class Hints { 35 public interface Display { 36 public void showHint(int viewResource); 37 } 38 39 private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN = 40 "voice_hint_num_unique_days_shown"; 41 private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN = 42 "voice_hint_last_time_shown"; 43 private static final String PREF_VOICE_INPUT_LAST_TIME_USED = 44 "voice_input_last_time_used"; 45 private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT = 46 "voice_punctuation_hint_view_count"; 47 private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7; 48 private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7; 49 50 private final Context mContext; 51 private final SharedPreferences mPrefs; 52 private final Display mDisplay; 53 private boolean mVoiceResultContainedPunctuation; 54 private int mSwipeHintMaxDaysToShow; 55 private int mPunctuationHintMaxDisplays; 56 57 // Only show punctuation hint if voice result did not contain punctuation. 58 static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION 59 = new HashMap<CharSequence, String>(); 60 static { 61 SPEAKABLE_PUNCTUATION.put(",", "comma"); 62 SPEAKABLE_PUNCTUATION.put(".", "period"); 63 SPEAKABLE_PUNCTUATION.put("?", "question mark"); 64 } 65 66 public Hints(Context context, SharedPreferences prefs, Display display) { 67 mContext = context; 68 mPrefs = prefs; 69 mDisplay = display; 70 71 ContentResolver cr = mContext.getContentResolver(); 72 mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt( 73 cr, 74 SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS, 75 DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW); 76 mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt( 77 cr, 78 SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS, 79 DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS); 80 } 81 82 public boolean showSwipeHintIfNecessary(boolean fieldRecommended) { 83 if (fieldRecommended && shouldShowSwipeHint()) { 84 showHint(R.layout.voice_swipe_hint); 85 return true; 86 } 87 88 return false; 89 } 90 91 public boolean showPunctuationHintIfNecessary(InputConnection ic) { 92 if (!mVoiceResultContainedPunctuation 93 && ic != null 94 && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT) 95 < mPunctuationHintMaxDisplays) { 96 CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0); 97 if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) { 98 showHint(R.layout.voice_punctuation_hint); 99 return true; 100 } 101 } 102 103 return false; 104 } 105 106 public void registerVoiceResult(String text) { 107 // Update the current time as the last time voice input was used. 108 SharedPreferences.Editor editor = mPrefs.edit(); 109 editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis()); 110 SharedPreferencesCompat.apply(editor); 111 112 mVoiceResultContainedPunctuation = false; 113 for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) { 114 if (text.indexOf(s.toString()) >= 0) { 115 mVoiceResultContainedPunctuation = true; 116 break; 117 } 118 } 119 } 120 121 private boolean shouldShowSwipeHint() { 122 final SharedPreferences prefs = mPrefs; 123 124 int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); 125 126 // If we've already shown the hint for enough days, we'll return false. 127 if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) { 128 129 long lastTimeVoiceWasUsed = prefs.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0); 130 131 // If the user has used voice today, we'll return false. (We don't show the hint on 132 // any day that the user has already used voice.) 133 if (!isFromToday(lastTimeVoiceWasUsed)) { 134 return true; 135 } 136 } 137 138 return false; 139 } 140 141 /** 142 * Determines whether the provided time is from some time today (i.e., this day, month, 143 * and year). 144 */ 145 private boolean isFromToday(long timeInMillis) { 146 if (timeInMillis == 0) return false; 147 148 Calendar today = Calendar.getInstance(); 149 today.setTimeInMillis(System.currentTimeMillis()); 150 151 Calendar timestamp = Calendar.getInstance(); 152 timestamp.setTimeInMillis(timeInMillis); 153 154 return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) && 155 today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) && 156 today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH)); 157 } 158 159 private void showHint(int hintViewResource) { 160 final SharedPreferences prefs = mPrefs; 161 162 int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); 163 long lastTimeHintWasShown = prefs.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0); 164 165 // If this is the first time the hint is being shown today, increase the saved values 166 // to represent that. We don't need to increase the last time the hint was shown unless 167 // it is a different day from the current value. 168 if (!isFromToday(lastTimeHintWasShown)) { 169 SharedPreferences.Editor editor = prefs.edit(); 170 editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1); 171 editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis()); 172 SharedPreferencesCompat.apply(editor); 173 } 174 175 if (mDisplay != null) { 176 mDisplay.showHint(hintViewResource); 177 } 178 } 179 180 private int getAndIncrementPref(String pref) { 181 final SharedPreferences prefs = mPrefs; 182 int value = prefs.getInt(pref, 0); 183 SharedPreferences.Editor editor = prefs.edit(); 184 editor.putInt(pref, value + 1); 185 SharedPreferencesCompat.apply(editor); 186 return value; 187 } 188 } 189