PageRenderTime 59ms CodeModel.GetById 14ms app.highlight 38ms RepoModel.GetById 2ms app.codeStats 0ms

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