/WebAccess/src/com/ideal/webreader/WebReaderActivity.java

http://eyes-free.googlecode.com/ · Java · 735 lines · 605 code · 83 blank · 47 comment · 141 complexity · baec17da732395fb068e1b9041d20271 MD5 · raw file

  1. /*
  2. * Copyright (C) 2010 The IDEAL Group
  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. package com.ideal.webreader;
  17. import com.ideal.webaccess.R;
  18. import com.ideal.webaccess.TtsContentProvider;
  19. import com.ideal.webaccess.Unzipper;
  20. import android.app.Activity;
  21. import android.app.AlertDialog;
  22. import android.app.AlertDialog.Builder;
  23. import android.content.ActivityNotFoundException;
  24. import android.content.ContentValues;
  25. import android.content.Context;
  26. import android.content.Intent;
  27. import android.content.SharedPreferences;
  28. import android.content.res.AssetFileDescriptor;
  29. import android.content.res.Resources;
  30. import android.database.Cursor;
  31. import android.gesture.Gesture;
  32. import android.gesture.GestureLibraries;
  33. import android.gesture.GestureLibrary;
  34. import android.gesture.GestureOverlayView;
  35. import android.gesture.Prediction;
  36. import android.gesture.GestureOverlayView.OnGesturePerformedListener;
  37. import android.graphics.Bitmap;
  38. import android.net.Uri;
  39. import android.os.Bundle;
  40. import android.os.Environment;
  41. import android.os.PowerManager;
  42. import android.os.Vibrator;
  43. import android.os.PowerManager.WakeLock;
  44. import android.preference.PreferenceManager;
  45. import android.provider.BaseColumns;
  46. import android.provider.Browser;
  47. import android.speech.tts.TextToSpeech;
  48. import android.util.Log;
  49. import android.view.KeyEvent;
  50. import android.view.Menu;
  51. import android.view.MenuItem;
  52. import android.view.MotionEvent;
  53. import android.view.View;
  54. import android.view.MenuItem.OnMenuItemClickListener;
  55. import android.view.View.OnKeyListener;
  56. import android.view.View.OnTouchListener;
  57. import android.webkit.ConsoleMessage;
  58. import android.webkit.URLUtil;
  59. import android.webkit.WebChromeClient;
  60. import android.webkit.WebSettings;
  61. import android.webkit.WebView;
  62. import android.webkit.WebViewClient;
  63. import android.widget.EditText;
  64. import android.widget.TextView;
  65. import android.widget.TextView.OnEditorActionListener;
  66. import java.io.File;
  67. import java.io.IOException;
  68. import java.io.InputStream;
  69. import java.util.ArrayList;
  70. /**
  71. * Main browser activity that uses a GestureOverlay to allow the user to
  72. * navigate the page content using touch screen gestures.
  73. */
  74. public class WebReaderActivity extends Activity implements OnGesturePerformedListener {
  75. private static final long[] VIBE_PATTERN = {
  76. 0, 10, 70, 80
  77. };
  78. private static final int PREFS_REQUEST_CODE = 42;
  79. private static final int BOOKMARKS_REQUEST_CODE = 43;
  80. private GestureOverlayView mGesturesView;
  81. private GestureLibrary mLibrary;
  82. private WebView mWebView;
  83. private String jsonlib = "";
  84. private String loaderScript = "";
  85. private String mLastTriedUrl = "";
  86. private TextToSpeech mTts;
  87. private Vibrator mVibe;
  88. private WakeLock mWakeLock;
  89. private SharedPreferences mPrefs;
  90. private AlertDialog mInputUrlAlertDialog;
  91. private AlertDialog mSearchAlertDialog;
  92. private ArrayList<String> mSessionHistory;
  93. private final WebViewClient mWebViewClient = new WebViewClient() {
  94. @Override
  95. public void onPageFinished(WebView view, String url) {
  96. boolean addUrlToHistory = true;
  97. if ((mSessionHistory.size() > 0)
  98. && (mSessionHistory.get(mSessionHistory.size() - 1).equals(url))) {
  99. addUrlToHistory = false;
  100. }
  101. if (addUrlToHistory) {
  102. mSessionHistory.add(url);
  103. }
  104. runScript(loaderScript);
  105. loadPrefs();
  106. }
  107. @Override
  108. public void onReceivedError(WebView view, int errorCode, String description,
  109. String failingUrl) {
  110. if (failingUrl.contains(mLastTriedUrl)) {
  111. doSearch(mLastTriedUrl.replace("http://", ""));
  112. mLastTriedUrl = "";
  113. }
  114. super.onReceivedError(view, errorCode, description, failingUrl);
  115. }
  116. @Override
  117. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  118. if (mTts != null) {
  119. mTts.speak("Loading", 2, null);
  120. }
  121. super.onPageStarted(view, url, favicon);
  122. }
  123. };
  124. /** Called when the activity is first created. */
  125. @Override
  126. public void onCreate(Bundle savedInstanceState) {
  127. super.onCreate(savedInstanceState);
  128. doSetup();
  129. mTts = new TextToSpeech(this, null);
  130. mVibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
  131. mSessionHistory = new ArrayList<String>();
  132. try {
  133. String customLoaderFilename = Environment.getExternalStorageDirectory()
  134. + "/ideal-webaccess/js/ideal-loader_custom.js";
  135. if (new File(customLoaderFilename).exists()) {
  136. loaderScript = Util.getRawString(getResources(), R.raw.idealwebaccess_custom);
  137. } else {
  138. loaderScript = Util.getRawString(getResources(), R.raw.idealwebaccess_webreader);
  139. }
  140. jsonlib = Util.getRawString(getResources(), R.raw.json2);
  141. } catch (Exception e) {
  142. Log.e("Greasemonkey", "Problem loading raw json library", e);
  143. }
  144. setContentView(R.layout.browser);
  145. mGesturesView = (GestureOverlayView) findViewById(R.id.gestureoverlayview);
  146. loadGestures();
  147. mGesturesView.addOnGesturePerformedListener(this);
  148. mGesturesView.setOnTouchListener(new OnTouchListener() {
  149. @Override
  150. public boolean onTouch(View v, MotionEvent event) {
  151. mVibe.vibrate(VIBE_PATTERN, -1);
  152. stopSpeech();
  153. return false;
  154. }
  155. });
  156. mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
  157. mWebView = (WebView) findViewById(R.id.webview);
  158. // Inject the defintion lookup script
  159. mWebView.addJavascriptInterface(new DefinitionLookupHelper(), "definitionLookupHelper");
  160. WebSettings settings = mWebView.getSettings();
  161. settings.setJavaScriptEnabled(true);
  162. settings
  163. .setLoadsImagesAutomatically(mPrefs.getBoolean("toggle_load_images_settings", true));
  164. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
  165. mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "WEB_READER");
  166. mWebView.setWebViewClient(mWebViewClient);
  167. // mWebView.setWebChromeClient(new WebChromeClient() {
  168. // public boolean onConsoleMessage(ConsoleMessage cm) {
  169. // Log.e("ChromeVox", cm.message() + " -- From line "
  170. // + cm.lineNumber() + " of "
  171. // + cm.sourceId() );
  172. // return true;
  173. // }
  174. // });
  175. String url = "";
  176. if (getIntent().getData() != null) {
  177. url = getIntent().getData().toString();
  178. }
  179. if (url.length() < 1) {
  180. url = "http://apps4android.org/web-reader-tutorial/index.htm";
  181. }
  182. mWebView.setOnKeyListener(new OnKeyListener(){
  183. @Override
  184. public boolean onKey(View v, int keyCode, KeyEvent event) {
  185. if (inWebReaderMode) {
  186. if (keyCode == KeyEvent.KEYCODE_M) {
  187. startAutoRead();
  188. return true;
  189. }
  190. }
  191. return false;
  192. }
  193. });
  194. mWebView.loadUrl(url);
  195. inWebReaderMode = false;
  196. }
  197. private void loadGestures() {
  198. try {
  199. mLibrary = GestureLibraries.fromFile(Environment.getExternalStorageDirectory()
  200. + "/ideal-webaccess/gestures");
  201. mLibrary.load();
  202. } catch (Exception e) {
  203. }
  204. if (mLibrary != null) {
  205. if (mLibrary.getGestureEntries().size() != 8) {
  206. mLibrary = null;
  207. }
  208. }
  209. if (mLibrary == null) {
  210. mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
  211. mLibrary.load();
  212. }
  213. }
  214. private void loadPrefs() {
  215. WebSettings settings = mWebView.getSettings();
  216. settings.setDefaultFontSize(Integer.parseInt(mPrefs.getString("text_size", "20")));
  217. // Lens settings
  218. // Commented out since the ChromeVox lens is not optimized for mobile.
  219. // if (mPrefs.getBoolean("toggle_use_lens_settings", true)) {
  220. // runScript("IDEAL_LENS_ENABLED=true;");
  221. // } else {
  222. // runScript("IDEAL_LENS_ENABLED=false;");
  223. // }
  224. runScript("IDEAL_LENS_ENABLED=false;");
  225. String lensFontColor = mPrefs.getString("lens_fg_color", "default");
  226. if (!lensFontColor.equals("default")) {
  227. runScript("IDEAL_LENS_TEXTCOLOR='" + lensFontColor + "';");
  228. } else {
  229. runScript("IDEAL_LENS_TEXTCOLOR='yellow';");
  230. }
  231. String lensBgColor = mPrefs.getString("lens_bg_color", "default");
  232. if (!lensBgColor.equals("default")) {
  233. runScript("IDEAL_LENS_BGCOLOR='" + lensBgColor + "';");
  234. } else {
  235. runScript("IDEAL_LENS_BGCOLOR='black';");
  236. }
  237. // Web page settings
  238. String fontColor = mPrefs.getString("text_fg_color", "default");
  239. if (!fontColor.equals("default")) {
  240. runScript("IDEAL_STYLE_FONTCOLOR='" + fontColor + "';");
  241. }
  242. String bgColor = mPrefs.getString("text_bg_color", "default");
  243. if (!bgColor.equals("default")) {
  244. runScript("IDEAL_STYLE_BGCOLOR='" + bgColor + "';");
  245. }
  246. String letterSpacing = mPrefs.getString("letter_spacing", "default");
  247. if (!letterSpacing.equals("default")) {
  248. runScript("IDEAL_STYLE_LETTERSPACING=" + letterSpacing + ";");
  249. }
  250. String lineSpacing = mPrefs.getString("line_spacing", "default");
  251. if (!lineSpacing.equals("default")) {
  252. runScript("IDEAL_STYLE_LINESPACING=" + lineSpacing + ";");
  253. }
  254. // Image settings
  255. if (mPrefs.getBoolean("toggle_ignore_image_alt_settings", false)) {
  256. runScript("IDEAL_IGNORE_ALTTEXT=true;");
  257. } else {
  258. runScript("IDEAL_IGNORE_ALTTEXT=false;");
  259. }
  260. settings
  261. .setLoadsImagesAutomatically(mPrefs.getBoolean("toggle_load_images_settings", true));
  262. }
  263. @Override
  264. public void onNewIntent(Intent intent) {
  265. // pull new url from query
  266. if ((intent != null) && (intent.getData() != null)) {
  267. String url = intent.getData().toString();
  268. mWebView.loadUrl(url);
  269. inWebReaderMode = false;
  270. }
  271. }
  272. @Override
  273. public void onResume() {
  274. super.onResume();
  275. if ((mWakeLock != null) && mPrefs.getBoolean("toggle_use_wakelock", false)) {
  276. mWakeLock.acquire();
  277. }
  278. }
  279. @Override
  280. public void onPause() {
  281. super.onPause();
  282. stopSpeech();
  283. if ((mWakeLock != null) && (mWakeLock.isHeld())) {
  284. mWakeLock.release();
  285. }
  286. }
  287. @Override
  288. public void onDestroy() {
  289. keepAutoReading = false;
  290. if (mWebView != null) {
  291. mWebView.stopLoading();
  292. }
  293. stopSpeech();
  294. if (mTts != null) {
  295. mTts.shutdown();
  296. }
  297. super.onDestroy();
  298. }
  299. @Override
  300. public boolean onKeyDown(int keyCode, KeyEvent event) {
  301. if (keyCode == KeyEvent.KEYCODE_SEARCH) {
  302. stopSpeech();
  303. showSearchDialog();
  304. return true;
  305. }
  306. if (mSessionHistory.size() > 1) {
  307. if (keyCode == KeyEvent.KEYCODE_BACK) {
  308. stopSpeech();
  309. return true;
  310. }
  311. }
  312. if ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN) || (keyCode == KeyEvent.KEYCODE_DPAD_UP)
  313. || (keyCode == KeyEvent.KEYCODE_DPAD_LEFT)
  314. || (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)) {
  315. if ((mWebView != null) && (mWebView.getHitTestResult() != null)) {
  316. speakDpadFocusedLink();
  317. }
  318. }
  319. return super.onKeyDown(keyCode, event);
  320. }
  321. // Search within the page for the link text since the HitTestResult only
  322. // contains the link type and the URL, not the actual link text.
  323. private void speakDpadFocusedLink() {
  324. String currentLink = mWebView.getHitTestResult().getExtra();
  325. if ((currentLink != null) && !currentLink.equals(lastSpokenLink)) {
  326. lastSpokenLink = currentLink;
  327. runScript("IDEAL_INTERFACE_SpeakLinkText('" + currentLink + "');");
  328. }
  329. }
  330. @Override
  331. public boolean onTrackballEvent(MotionEvent event) {
  332. if ((mWebView != null) && (mWebView.getHitTestResult() != null)) {
  333. speakDpadFocusedLink();
  334. }
  335. return super.onTrackballEvent(event);
  336. }
  337. private String lastSpokenLink = "";
  338. private void stopSpeech() {
  339. keepAutoReading = false;
  340. if (mTts != null) {
  341. mTts.speak(" ", 2, null);
  342. }
  343. }
  344. @Override
  345. public boolean onKeyUp(int keyCode, KeyEvent event) {
  346. if (mSessionHistory.size() > 1) {
  347. if (keyCode == KeyEvent.KEYCODE_BACK) {
  348. mSessionHistory.remove(mSessionHistory.size() - 1);
  349. mWebView.loadUrl(mSessionHistory.get(mSessionHistory.size() - 1));
  350. inWebReaderMode = false;
  351. return true;
  352. }
  353. }
  354. return super.onKeyUp(keyCode, event);
  355. }
  356. public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
  357. keepAutoReading = false;
  358. ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
  359. // We want at least one prediction
  360. if (predictions.size() > 0) {
  361. Prediction prediction = predictions.get(0);
  362. // We want at least some confidence in the result
  363. if (prediction.score > 1.0) {
  364. mVibe.vibrate(VIBE_PATTERN, -1);
  365. if (prediction.name.equals("next")) {
  366. runScript("IDEAL_INTERFACE_ReadNext();");
  367. } else if (prediction.name.equals("previous")) {
  368. runScript("IDEAL_INTERFACE_ReadPrevious();");
  369. } else if (prediction.name.equals("action")) {
  370. runScript("IDEAL_INTERFACE_ActOnCurrentElem();");
  371. } else if (prediction.name.equals("read all")) {
  372. startAutoRead();
  373. } else if (prediction.name.equals("up")) {
  374. runScript("IDEAL_INTERFACE_LessGranular();");
  375. } else if (prediction.name.equals("down")) {
  376. runScript("IDEAL_INTERFACE_MoreGranular();");
  377. } else if (prediction.name.equals("switch web reader mode")) {
  378. switchWebReaderMode();
  379. } else if (prediction.name.equals("add bookmark")) {
  380. bookmarkCurrentPage();
  381. } else if (prediction.name.equals("get definition")) {
  382. if (mTts != null) {
  383. mTts.speak("Looking up definition", 2, null);
  384. }
  385. runScript("IDEAL_INTERFACE_DefineCurrentPhrase();");
  386. }
  387. }
  388. }
  389. }
  390. private boolean inWebReaderMode = false;
  391. public void switchWebReaderMode() {
  392. if (inWebReaderMode) {
  393. inWebReaderMode = false;
  394. } else {
  395. inWebReaderMode = true;
  396. }
  397. runScript("IDEAL_INTERFACE_SwitchWebReaderMode();");
  398. }
  399. public void runScript(String script) {
  400. mWebView.loadUrl(String.format("javascript:(function() { %s %s })();", jsonlib, script));
  401. }
  402. @Override
  403. public boolean onCreateOptionsMenu(Menu menu) {
  404. super.onCreateOptionsMenu(menu);
  405. final Context self = this;
  406. MenuItem viewBookmarks = menu.add("View Bookmarks");
  407. viewBookmarks.setIcon(android.R.drawable.ic_menu_myplaces);
  408. viewBookmarks.setOnMenuItemClickListener(new OnMenuItemClickListener() {
  409. public boolean onMenuItemClick(MenuItem item) {
  410. Intent i = new Intent();
  411. i.setClass(self, BookmarksActivity.class);
  412. startActivityForResult(i, BOOKMARKS_REQUEST_CODE);
  413. return true;
  414. }
  415. });
  416. MenuItem gourl = menu.add("Go to URL");
  417. gourl.setIcon(R.drawable.ic_menu_goto);
  418. gourl.setOnMenuItemClickListener(new OnMenuItemClickListener() {
  419. public boolean onMenuItemClick(MenuItem item) {
  420. showInputUrlDialog();
  421. return true;
  422. }
  423. });
  424. MenuItem search = menu.add("Search");
  425. search.setIcon(android.R.drawable.ic_menu_search);
  426. search.setOnMenuItemClickListener(new OnMenuItemClickListener() {
  427. public boolean onMenuItemClick(MenuItem item) {
  428. showSearchDialog();
  429. return true;
  430. }
  431. });
  432. MenuItem settings = menu.add("Settings");
  433. settings.setIcon(android.R.drawable.ic_menu_manage);
  434. settings.setOnMenuItemClickListener(new OnMenuItemClickListener() {
  435. public boolean onMenuItemClick(MenuItem item) {
  436. Intent i = new Intent();
  437. i.setClass(self, PrefsActivity.class);
  438. startActivityForResult(i, PREFS_REQUEST_CODE);
  439. return true;
  440. }
  441. });
  442. MenuItem moreApps = menu.add("More Apps");
  443. moreApps.setIcon(android.R.drawable.ic_menu_search);
  444. moreApps.setOnMenuItemClickListener(new OnMenuItemClickListener() {
  445. public boolean onMenuItemClick(MenuItem item) {
  446. String marketUrl = "market://search?q=pub:\"IDEAL Group, Inc. Android Development Team\"";
  447. Intent i = new Intent(Intent.ACTION_VIEW);
  448. i.setData(Uri.parse(marketUrl));
  449. try {
  450. startActivity(i);
  451. } catch (ActivityNotFoundException anf) {
  452. }
  453. return true;
  454. }
  455. });
  456. return true;
  457. }
  458. public void showInputUrlDialog() {
  459. Builder inputUrlDialogBuilder = new Builder(this);
  460. EditText inputTextView = new EditText(this);
  461. inputTextView.setHint("Enter URL here");
  462. inputTextView.setOnEditorActionListener(new OnEditorActionListener() {
  463. @Override
  464. public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
  465. goToUrlOrSearch(v.getText().toString());
  466. mInputUrlAlertDialog.dismiss();
  467. return true;
  468. }
  469. });
  470. inputUrlDialogBuilder.setView(inputTextView);
  471. mInputUrlAlertDialog = inputUrlDialogBuilder.create();
  472. mInputUrlAlertDialog.show();
  473. }
  474. public void showSearchDialog() {
  475. Builder searchDialogBuilder = new Builder(this);
  476. EditText inputTextView = new EditText(this);
  477. inputTextView.setHint("Enter search term here");
  478. inputTextView.setOnEditorActionListener(new OnEditorActionListener() {
  479. @Override
  480. public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
  481. doSearch(v.getText().toString());
  482. mSearchAlertDialog.dismiss();
  483. return true;
  484. }
  485. });
  486. searchDialogBuilder.setView(inputTextView);
  487. mSearchAlertDialog = searchDialogBuilder.create();
  488. mSearchAlertDialog.show();
  489. }
  490. private void goToUrlOrSearch(String target) {
  491. String workingUrl = target;
  492. if (!URLUtil.isValidUrl(workingUrl)) {
  493. workingUrl = "http://" + workingUrl;
  494. }
  495. if (!URLUtil.isValidUrl(workingUrl)) {
  496. workingUrl = "";
  497. }
  498. if (workingUrl.length() > 0) {
  499. mLastTriedUrl = target;
  500. mWebView.loadUrl(workingUrl);
  501. inWebReaderMode = false;
  502. } else {
  503. doSearch(target);
  504. }
  505. }
  506. private void doSearch(String query) {
  507. mWebView.loadUrl("http://www.google.com/m?q=" + query);
  508. inWebReaderMode = false;
  509. }
  510. private boolean keepAutoReading = false;
  511. private void startAutoRead() {
  512. keepAutoReading = true;
  513. runAutoReader();
  514. }
  515. private void runAutoReader() {
  516. new Thread(new Runnable() {
  517. @Override
  518. public void run() {
  519. if (keepAutoReading) {
  520. if (!TtsContentProvider.isSpeaking) {
  521. try {
  522. Thread.sleep(1000);
  523. } catch (InterruptedException e) {
  524. e.printStackTrace();
  525. }
  526. if (!TtsContentProvider.isSpeaking) {
  527. runScript("IDEAL_INTERFACE_ReadNext();");
  528. }
  529. }
  530. try {
  531. Thread.sleep(1000);
  532. } catch (InterruptedException e) {
  533. e.printStackTrace();
  534. }
  535. runAutoReader();
  536. }
  537. }
  538. }).start();
  539. }
  540. @Override
  541. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  542. if (requestCode == PREFS_REQUEST_CODE) {
  543. loadGestures();
  544. mWebView.reload();
  545. } else if (requestCode == BOOKMARKS_REQUEST_CODE) {
  546. if (resultCode == Activity.RESULT_OK) {
  547. String url = data.getStringExtra("URL");
  548. // Safety check to avoid double-running our own script
  549. if (!url.startsWith("javascript:")) {
  550. mWebView.loadUrl(url);
  551. inWebReaderMode = false;
  552. }
  553. }
  554. }
  555. super.onActivityResult(requestCode, resultCode, data);
  556. }
  557. public void bookmarkCurrentPage() {
  558. if (mWebView == null) {
  559. return;
  560. }
  561. String bookmarkTitle = mWebView.getTitle();
  562. String bookmarkUrl = mWebView.getUrl();
  563. if (bookmarkUrl.length() < 1) {
  564. return;
  565. }
  566. if (bookmarkTitle.length() < 1) {
  567. bookmarkTitle = bookmarkUrl;
  568. }
  569. String[] columnStrings = {
  570. BaseColumns._ID, Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL,
  571. Browser.BookmarkColumns.BOOKMARK, Browser.BookmarkColumns.VISITS
  572. };
  573. boolean alreadyBookmarked = false;
  574. Cursor c = getContentResolver().query(Browser.BOOKMARKS_URI, columnStrings, null, null,
  575. null);
  576. if (c != null) {
  577. boolean keepGoing = c.moveToFirst();
  578. while (keepGoing) {
  579. if ((c.getString(3) != null) && (c.getString(3).equals("1"))
  580. && (c.getString(1) != null) && (c.getString(1).equals(bookmarkTitle))
  581. && (c.getString(2) != null) && (c.getString(2).equals(bookmarkUrl))) {
  582. alreadyBookmarked = true;
  583. }
  584. keepGoing = c.moveToNext();
  585. }
  586. }
  587. if (!alreadyBookmarked) {
  588. ContentValues bookmarkletContent = new ContentValues();
  589. bookmarkletContent.put(Browser.BookmarkColumns.TITLE, bookmarkTitle);
  590. bookmarkletContent.put(Browser.BookmarkColumns.URL, bookmarkUrl);
  591. bookmarkletContent.put(Browser.BookmarkColumns.BOOKMARK, 1);
  592. bookmarkletContent.put(Browser.BookmarkColumns.VISITS, 9999);
  593. getContentResolver().insert(Browser.BOOKMARKS_URI, bookmarkletContent);
  594. }
  595. mTts.speak("Bookmark added", 2, null);
  596. }
  597. final class DefinitionLookupHelper {
  598. public void lookup(String phrase) {
  599. DefinitionLookup.lookupAndSpeak(phrase, mTts);
  600. }
  601. }
  602. // Does the initial setup tasks:
  603. // Unzips needed JS files.
  604. // Adds government resource sites bookmark.
  605. private void doSetup() {
  606. try {
  607. Resources res = getResources();
  608. AssetFileDescriptor jsZipFd = res.openRawResourceFd(R.raw.ideal_js);
  609. InputStream stream = jsZipFd.createInputStream();
  610. (new Thread(new dataCheckAndUnzip(stream))).start();
  611. } catch (IOException e) {
  612. e.printStackTrace();
  613. }
  614. boolean hasResourceSites = false;
  615. final String[] columnStrings = {
  616. BaseColumns._ID, Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL,
  617. Browser.BookmarkColumns.BOOKMARK, Browser.BookmarkColumns.VISITS
  618. };
  619. String bookmarkTitle = "Government Mobile Websites";
  620. String bookmarkUrl = "http://apps4android.org/govt/";
  621. Cursor c = getContentResolver().query(Browser.BOOKMARKS_URI, columnStrings, null, null,
  622. null);
  623. if (c != null) {
  624. boolean keepGoing = c.moveToFirst();
  625. while (keepGoing) {
  626. if ((c.getString(3) != null) && (c.getString(3).equals("1"))
  627. && (c.getString(1) != null) && (c.getString(1).equals(bookmarkTitle))
  628. && (c.getString(2) != null) && (c.getString(2).equals(bookmarkUrl))) {
  629. hasResourceSites = true;
  630. }
  631. keepGoing = c.moveToNext();
  632. }
  633. }
  634. if (!hasResourceSites) {
  635. ContentValues bookmarkletContent = new ContentValues();
  636. bookmarkletContent.put(Browser.BookmarkColumns.TITLE, bookmarkTitle);
  637. bookmarkletContent.put(Browser.BookmarkColumns.URL, bookmarkUrl);
  638. bookmarkletContent.put(Browser.BookmarkColumns.BOOKMARK, 1);
  639. bookmarkletContent.put(Browser.BookmarkColumns.VISITS, 9999);
  640. getContentResolver().insert(Browser.BOOKMARKS_URI, bookmarkletContent);
  641. }
  642. }
  643. private class dataCheckAndUnzip implements Runnable {
  644. public InputStream stream;
  645. public dataCheckAndUnzip(InputStream is) {
  646. stream = is;
  647. }
  648. public void run() {
  649. Unzipper.doDataCheckAndUnzip(stream);
  650. }
  651. }
  652. }