/ocr/ocrservice/src/com/googlecode/eyesfree/ocr/intent/LanguagesActivity.java

http://eyes-free.googlecode.com/ · Java · 362 lines · 261 code · 77 blank · 24 comment · 26 complexity · 0282eaf9ffe7df3271cd69b335e5d05b MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 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. package com.googlecode.eyesfree.ocr.intent;
  17. import android.app.Activity;
  18. import android.app.AlertDialog;
  19. import android.app.Dialog;
  20. import android.content.BroadcastReceiver;
  21. import android.content.Context;
  22. import android.content.DialogInterface;
  23. import android.content.Intent;
  24. import android.content.IntentFilter;
  25. import android.content.SharedPreferences;
  26. import android.content.res.Configuration;
  27. import android.os.Bundle;
  28. import android.util.Log;
  29. import android.view.LayoutInflater;
  30. import android.view.View;
  31. import android.view.ViewGroup;
  32. import android.widget.AdapterView;
  33. import android.widget.AdapterView.OnItemClickListener;
  34. import android.widget.ArrayAdapter;
  35. import android.widget.ListView;
  36. import android.widget.TextView;
  37. import android.widget.Toast;
  38. import com.googlecode.eyesfree.ocr.R;
  39. import com.googlecode.eyesfree.ocr.client.Intents;
  40. import com.googlecode.eyesfree.ocr.client.Language;
  41. import com.googlecode.eyesfree.ocr.client.Ocr;
  42. import java.io.File;
  43. import java.util.Collection;
  44. import java.util.List;
  45. import java.util.TreeSet;
  46. /**
  47. * Displays available and installed languages, allows downloading of new
  48. * language packs.
  49. *
  50. * @author alanv@google.com (Alan Viverette)
  51. */
  52. public class LanguagesActivity extends Activity {
  53. private static final String TAG = "LanguagesActivity";
  54. private static final String XML_SOURCE =
  55. "http://eyes-free.googlecode.com/svn/trunk/thirdparty/tesseract/languages.xml";
  56. private static final String DATA_SOURCE =
  57. "http://eyes-free.googlecode.com/svn/trunk/thirdparty/tesseract/";
  58. private List<Language> mAvailable;
  59. private LanguageAdapter mAdapter;
  60. private ListView mListView;
  61. private File mTessdata;
  62. private IntentFilter mFilter;
  63. private IntentFilter mFilter2;
  64. private SharedPreferences mPrefs;
  65. private Ocr mOcr;
  66. private boolean mInitialized = false;
  67. @Override
  68. protected void onCreate(Bundle savedInstanceState) {
  69. super.onCreate(savedInstanceState);
  70. mFilter = new IntentFilter();
  71. mFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
  72. mFilter.addDataScheme("file");
  73. mFilter2 = new IntentFilter();
  74. mFilter2.addAction(Intents.Actions.LANGUAGES_UPDATED);
  75. mPrefs = getPreferences(MODE_PRIVATE);
  76. mAdapter = new LanguageAdapter(this);
  77. mAdapter.setNotifyOnChange(true);
  78. Ocr.InitCallback initCallback = new Ocr.InitCallback() {
  79. @Override
  80. public void onInitialized(int status) {
  81. updateLanguages();
  82. mInitialized = true;
  83. }
  84. };
  85. mOcr = new Ocr(this, initCallback, true);
  86. onConfigurationChanged(getResources().getConfiguration());
  87. }
  88. @Override
  89. public void onConfigurationChanged(Configuration newConfig) {
  90. super.onConfigurationChanged(newConfig);
  91. setContentView(R.layout.manage);
  92. mListView = (ListView) findViewById(R.id.list_languages);
  93. mListView.setAdapter(mAdapter);
  94. mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  95. mListView.setOnItemClickListener(itemClickListener);
  96. }
  97. @Override
  98. protected void onResume() {
  99. super.onResume();
  100. if (mInitialized) {
  101. updateLanguages();
  102. }
  103. registerReceiver(broadcastReceiver, mFilter);
  104. registerReceiver(broadcastReceiver, mFilter2);
  105. }
  106. @Override
  107. protected void onPause() {
  108. unregisterReceiver(broadcastReceiver);
  109. super.onPause();
  110. }
  111. @Override
  112. public void onDestroy() {
  113. mOcr.release();
  114. super.onDestroy();
  115. }
  116. private void updateLanguages() {
  117. mTessdata = mOcr.getTessdata();
  118. mAvailable = mOcr.getAvailableLanguages();
  119. final String xmlPref = getString(R.string.xml_cache_pref);
  120. final String cachedXml = mPrefs.getString(xmlPref, null);
  121. new XmlLoader(this, mAvailable) {
  122. @Override
  123. protected void onPostExecute(final TreeSet<LanguageData> result) {
  124. // Show results on-screen
  125. onLoad(result);
  126. // Cache resulting XML in preferences
  127. if (result != null) {
  128. final String cachedXml = getCachedXml();
  129. if (cachedXml != null) {
  130. final SharedPreferences.Editor editor = mPrefs.edit();
  131. editor.putString(xmlPref, cachedXml);
  132. editor.commit();
  133. }
  134. }
  135. super.onPostExecute(result);
  136. }
  137. }.setCachedXml(cachedXml).execute(XML_SOURCE);
  138. }
  139. private void onLoad(TreeSet<LanguageData> languages) {
  140. if (languages == null) {
  141. Toast.makeText(this, R.string.manage_error, Toast.LENGTH_LONG).show();
  142. return;
  143. }
  144. mAdapter.clear();
  145. mAdapter.addAll(languages);
  146. }
  147. private void showConfirm(String text, DialogInterface.OnClickListener onClick) {
  148. Dialog dialog = new AlertDialog.Builder(this).setCancelable(true).setMessage(text)
  149. .setPositiveButton(getString(android.R.string.yes), onClick)
  150. .setNegativeButton(getString(android.R.string.cancel), null).create();
  151. dialog.setOwnerActivity(this);
  152. dialog.show();
  153. }
  154. private void installLanguage(final LanguageData data) {
  155. Log.i(TAG, "Installing " + data.name + "...");
  156. new LanguageLoader(this, DATA_SOURCE, mTessdata) {
  157. @Override
  158. protected void onPostExecute(final LanguageData result) {
  159. // Show results on-screen
  160. onInstall(result, getCanceled());
  161. super.onPostExecute(result);
  162. }
  163. }.execute(data);
  164. }
  165. private void onInstall(LanguageData data, boolean canceled) {
  166. int resId;
  167. if (data != null) {
  168. data.installed = true;
  169. mAdapter.notifyDataSetChanged();
  170. mOcr.reloadLanguages();
  171. resId = R.string.install_completed;
  172. } else if (canceled) {
  173. resId = R.string.install_canceled;
  174. } else {
  175. resId = R.string.install_failed;
  176. }
  177. String message = getString(resId, data.name);
  178. Toast.makeText(this, message, Toast.LENGTH_LONG).show();
  179. }
  180. private void promptUninstallLanguage(final LanguageData data) {
  181. DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
  182. @Override
  183. public void onClick(DialogInterface dialog, int which) {
  184. if (which == DialogInterface.BUTTON_POSITIVE) {
  185. Thread uninstaller = new Thread() {
  186. @Override
  187. public void run() {
  188. uninstallLanguageAsync(data);
  189. }
  190. };
  191. uninstaller.start();
  192. }
  193. }
  194. };
  195. String message = getString(R.string.uninstall_confirm, data.name);
  196. showConfirm(message, onClickListener);
  197. }
  198. private void uninstallLanguageAsync(final LanguageData data) {
  199. final File installed = new File(mTessdata, data.iso6392 + ".traineddata");
  200. final boolean success = installed.delete();
  201. runOnUiThread(new Runnable() {
  202. @Override
  203. public void run() {
  204. onUninstall(data, success);
  205. }
  206. });
  207. }
  208. private void onUninstall(LanguageData data, boolean success) {
  209. int resId;
  210. if (success) {
  211. data.installed = false;
  212. mAdapter.notifyDataSetChanged();
  213. mOcr.reloadLanguages();
  214. resId = R.string.uninstall_completed;
  215. } else {
  216. resId = R.string.uninstall_failed;
  217. }
  218. String message = getString(resId, data.name);
  219. Toast.makeText(this, message, Toast.LENGTH_LONG).show();
  220. }
  221. private class LanguageAdapter extends ArrayAdapter<LanguageData> {
  222. private final int mColorRed;
  223. public LanguageAdapter(Context context) {
  224. super(context, 0);
  225. mColorRed = context.getResources().getColor(R.color.red);
  226. }
  227. @Override
  228. public View getView(int position, View convertView, ViewGroup parent) {
  229. LanguageData data = getItem(position);
  230. LayoutInflater inflate = LayoutInflater.from(getContext());
  231. View view = inflate.inflate(R.layout.language, null);
  232. ((TextView) view.findViewById(R.id.text_size)).setText(data.size);
  233. ((TextView) view.findViewById(R.id.text_iso6392)).setText(data.iso6392);
  234. ((TextView) view.findViewById(R.id.text_name)).setText(data.name);
  235. TextView installed = ((TextView) view.findViewById(R.id.text_installed));
  236. installed.setText(data.installed ? R.string.installed : R.string.not_installed);
  237. if (!data.installed) {
  238. installed.setTextColor(mColorRed);
  239. }
  240. return view;
  241. }
  242. public void addAll(Collection<? extends LanguageData> items) {
  243. for (LanguageData item : items) {
  244. add(item);
  245. }
  246. }
  247. }
  248. static class LanguageData implements Comparable<LanguageData> {
  249. String size;
  250. String file;
  251. String iso6392;
  252. String name;
  253. boolean installed;
  254. boolean hidden;
  255. @Override
  256. public int compareTo(LanguageData another) {
  257. return name.compareTo(another.name);
  258. }
  259. }
  260. private final OnItemClickListener itemClickListener = new OnItemClickListener() {
  261. @Override
  262. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  263. LanguageData data = mAdapter.getItem(position);
  264. if (data == null) {
  265. return;
  266. }
  267. if (!data.installed) {
  268. installLanguage(data);
  269. } else {
  270. promptUninstallLanguage(data);
  271. }
  272. }
  273. };
  274. private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  275. @Override
  276. public void onReceive(Context context, Intent intent) {
  277. if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
  278. finish();
  279. } else if (mInitialized
  280. && intent.getAction().equals(Intents.Actions.LANGUAGES_UPDATED)) {
  281. updateLanguages();
  282. }
  283. }
  284. };
  285. }