1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.samplespellcheckerservice;
18 
19 import android.os.Build;
20 import android.service.textservice.SpellCheckerService;
21 import android.util.Log;
22 import android.view.textservice.SentenceSuggestionsInfo;
23 import android.view.textservice.SuggestionsInfo;
24 import android.view.textservice.TextInfo;
25 
26 import java.util.ArrayList;
27 
28 public class SampleSpellCheckerService extends SpellCheckerService {
29     private static final String TAG = SampleSpellCheckerService.class.getSimpleName();
30     private static final boolean DBG = true;
31 
32     @Override
createSession()33     public Session createSession() {
34         return new AndroidSpellCheckerSession();
35     }
36 
37     private static class AndroidSpellCheckerSession extends Session {
38 
isSentenceSpellCheckApiSupported()39         private boolean isSentenceSpellCheckApiSupported() {
40             // Note that the sentence level spell check APIs work on Jelly Bean or later.
41             return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
42         }
43 
44         private String mLocale;
45         @Override
onCreate()46         public void onCreate() {
47             mLocale = getLocale();
48         }
49 
50         /**
51          * This method should have a concrete implementation in all spell checker services.
52          * Please note that the default implementation of
53          * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}
54          * calls up this method. You may want to override
55          * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}
56          * by your own implementation if you'd like to provide an optimized implementation for
57          * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}.
58          */
59         @Override
onGetSuggestions(TextInfo textInfo, int suggestionsLimit)60         public SuggestionsInfo onGetSuggestions(TextInfo textInfo, int suggestionsLimit) {
61             if (DBG) {
62                 Log.d(TAG, "onGetSuggestions: " + textInfo.getText());
63             }
64             final String input = textInfo.getText();
65             final int length = input.length();
66             // Just a fake logic:
67             // length <= 3 for short words that we assume are in the fake dictionary
68             // length > 20 for too long words that we assume can't be recognized (such as CJK words)
69             final int flags = length <= 3 ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
70                     : length <= 20 ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0;
71             return new SuggestionsInfo(flags,
72                     new String[] {"aaa", "bbb", "Candidate for " + input, mLocale},
73                     textInfo.getCookie(), textInfo.getSequence());
74         }
75 
76         /**
77          * Please consider providing your own implementation of sentence level spell checking.
78          * Please note that this sample implementation is just a mock to demonstrate how a sentence
79          * level spell checker returns the result.
80          * If you don't override this method, the framework converts queries of
81          * {@link SpellCheckerService.Session#onGetSentenceSuggestionsMultiple(TextInfo[], int)}
82          * to queries of
83          * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)}
84          * by the default implementation.
85          */
86         @Override
onGetSentenceSuggestionsMultiple( TextInfo[] textInfos, int suggestionsLimit)87         public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(
88                 TextInfo[] textInfos, int suggestionsLimit) {
89             if (!isSentenceSpellCheckApiSupported()) {
90                 Log.e(TAG, "Sentence spell check is not supported on this platform, "
91                         + "but accidentially called.");
92                 return null;
93             }
94             final ArrayList<SentenceSuggestionsInfo> retval =
95                     new ArrayList<SentenceSuggestionsInfo>();
96             for (int i = 0; i < textInfos.length; ++i) {
97                 final TextInfo ti = textInfos[i];
98                 if (DBG) {
99                     Log.d(TAG, "onGetSentenceSuggestionsMultiple: " + ti.getText());
100                 }
101                 final String input = ti.getText();
102                 final int length = input.length();
103                 final SuggestionsInfo[] sis;
104                 final int[] lengths;
105                 final int[] offsets;
106                 if (input.equalsIgnoreCase("I wold like to here form you")) {
107                     // Return sentence level suggestion for this fixed input
108                     final int flags0 = SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO;
109                     final int flags1 = SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS
110                             | SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO;
111                     final int flags2 = flags1;
112                     final SuggestionsInfo si0 = new SuggestionsInfo(
113                             flags0, new String[] { "would" }, ti.getCookie(), ti.getSequence());
114                     final SuggestionsInfo si1 = new SuggestionsInfo(
115                             flags1, new String[] { "hear" }, ti.getCookie(), ti.getSequence());
116                     final SuggestionsInfo si2 = new SuggestionsInfo(
117                             flags2, new String[] { "from" }, ti.getCookie(), ti.getSequence());
118                     sis = new SuggestionsInfo[] {si0, si1, si2};
119                     offsets = new int[] { 2, 15, 20 };
120                     lengths = new int[] { 4, 4, 4 };
121                 } else {
122                     // Just a mock logic:
123                     // length <= 3 for short words that we assume are in the fake dictionary
124                     // length > 20 for too long words that we assume can't be recognized
125                     // (such as CJK words)
126                     final int flags = length <= 3 ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
127                             : length <= 20 ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0;
128                     final SuggestionsInfo si = new SuggestionsInfo(flags,
129                             new String[] {"aaa", "bbb", "Candidate for " + input, mLocale},
130                             ti.getCookie(), ti.getSequence());
131                     sis = new SuggestionsInfo[] { si };
132                     offsets = new int[] { 0 };
133                     lengths = new int[] { ti.getText().length() };
134                 }
135                 final SentenceSuggestionsInfo ssi =
136                         new SentenceSuggestionsInfo(sis, offsets, lengths);
137                 retval.add(ssi);
138             }
139             return retval.toArray(new SentenceSuggestionsInfo[0]);
140         }
141     }
142 }
143