1 /* 2 * Copyright (C) 2009 Google Inc. 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.latin; 18 19 import com.android.inputmethod.voice.SettingsUtil; 20 21 import android.content.ContentResolver; 22 import android.content.Context; 23 import android.content.SharedPreferences; 24 import android.preference.PreferenceManager; 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 { showHint(int viewResource)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 Context mContext; 51 private Display mDisplay; 52 private boolean mVoiceResultContainedPunctuation; 53 private int mSwipeHintMaxDaysToShow; 54 private int mPunctuationHintMaxDisplays; 55 56 // Only show punctuation hint if voice result did not contain punctuation. 57 static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION 58 = new HashMap<CharSequence, String>(); 59 static { 60 SPEAKABLE_PUNCTUATION.put(",", "comma"); 61 SPEAKABLE_PUNCTUATION.put(".", "period"); 62 SPEAKABLE_PUNCTUATION.put("?", "question mark"); 63 } 64 Hints(Context context, Display display)65 public Hints(Context context, Display display) { 66 mContext = context; 67 mDisplay = display; 68 69 ContentResolver cr = mContext.getContentResolver(); 70 mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt( 71 cr, 72 SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS, 73 DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW); 74 mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt( 75 cr, 76 SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS, 77 DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS); 78 } 79 showSwipeHintIfNecessary(boolean fieldRecommended)80 public boolean showSwipeHintIfNecessary(boolean fieldRecommended) { 81 if (fieldRecommended && shouldShowSwipeHint()) { 82 showHint(R.layout.voice_swipe_hint); 83 return true; 84 } 85 86 return false; 87 } 88 showPunctuationHintIfNecessary(InputConnection ic)89 public boolean showPunctuationHintIfNecessary(InputConnection ic) { 90 if (!mVoiceResultContainedPunctuation 91 && ic != null 92 && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT) 93 < mPunctuationHintMaxDisplays) { 94 CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0); 95 if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) { 96 showHint(R.layout.voice_punctuation_hint); 97 return true; 98 } 99 } 100 101 return false; 102 } 103 registerVoiceResult(String text)104 public void registerVoiceResult(String text) { 105 // Update the current time as the last time voice input was used. 106 SharedPreferences.Editor editor = 107 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 108 editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis()); 109 SharedPreferencesCompat.apply(editor); 110 111 mVoiceResultContainedPunctuation = false; 112 for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) { 113 if (text.indexOf(s.toString()) >= 0) { 114 mVoiceResultContainedPunctuation = true; 115 break; 116 } 117 } 118 } 119 shouldShowSwipeHint()120 private boolean shouldShowSwipeHint() { 121 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); 122 123 int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); 124 125 // If we've already shown the hint for enough days, we'll return false. 126 if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) { 127 128 long lastTimeVoiceWasUsed = sp.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0); 129 130 // If the user has used voice today, we'll return false. (We don't show the hint on 131 // any day that the user has already used voice.) 132 if (!isFromToday(lastTimeVoiceWasUsed)) { 133 return true; 134 } 135 } 136 137 return false; 138 } 139 140 /** 141 * Determines whether the provided time is from some time today (i.e., this day, month, 142 * and year). 143 */ isFromToday(long timeInMillis)144 private boolean isFromToday(long timeInMillis) { 145 if (timeInMillis == 0) return false; 146 147 Calendar today = Calendar.getInstance(); 148 today.setTimeInMillis(System.currentTimeMillis()); 149 150 Calendar timestamp = Calendar.getInstance(); 151 timestamp.setTimeInMillis(timeInMillis); 152 153 return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) && 154 today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) && 155 today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH)); 156 } 157 showHint(int hintViewResource)158 private void showHint(int hintViewResource) { 159 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); 160 161 int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); 162 long lastTimeHintWasShown = sp.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0); 163 164 // If this is the first time the hint is being shown today, increase the saved values 165 // to represent that. We don't need to increase the last time the hint was shown unless 166 // it is a different day from the current value. 167 if (!isFromToday(lastTimeHintWasShown)) { 168 SharedPreferences.Editor editor = sp.edit(); 169 editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1); 170 editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis()); 171 SharedPreferencesCompat.apply(editor); 172 } 173 174 if (mDisplay != null) { 175 mDisplay.showHint(hintViewResource); 176 } 177 } 178 getAndIncrementPref(String pref)179 private int getAndIncrementPref(String pref) { 180 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); 181 int value = sp.getInt(pref, 0); 182 SharedPreferences.Editor editor = sp.edit(); 183 editor.putInt(pref, value + 1); 184 SharedPreferencesCompat.apply(editor); 185 return value; 186 } 187 } 188