• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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