Java tutorial
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.content_shell; import java.util.LinkedHashSet; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.drawable.ClipDrawable; import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; import android.view.View.OnTouchListener; import android.widget.TextView.OnEditorActionListener; import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; import org.chromium.content.browser.ContentView; import org.chromium.content.browser.ContentViewRenderView; import org.chromium.content.browser.LoadUrlParams; import org.chromium.ui.WindowAndroid; import org.json.JSONArray; import org.json.JSONException; /** * Container for the various UI components that make up a shell window. */ @JNINamespace("content") public class Shell extends LinearLayout implements OnTouchListener { private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200; GestureDetector gestureDetector; private Runnable mClearProgressRunnable = new Runnable() { @Override public void run() { mProgressDrawable.setLevel(0); } }; // TODO(jrg): a mContentView.destroy() call is needed, both upstream and downstream. private ContentView mContentView; private EditText mUrlTextView; private ImageButton mPrevButton; private ImageButton mNextButton; private ImageButton mRefreshButton; private ImageButton mHistoryButton; private ClipDrawable mProgressDrawable; private ContentViewRenderView mContentViewRenderView; private WindowAndroid mWindow; private View mToolbar; private boolean mLoading = false; SharedPreferences mPref; /** * Constructor for inflating via XML. */ public Shell(Context context, AttributeSet attrs) { super(context, attrs); mPref = PreferenceManager.getDefaultSharedPreferences(context); } /** * Set the SurfaceView being renderered to as soon as it is available. */ public void setContentViewRenderView(ContentViewRenderView contentViewRenderView) { FrameLayout contentViewHolder = (FrameLayout) findViewById(R.id.contentview_holder); if (contentViewRenderView == null) { if (mContentViewRenderView != null) { contentViewHolder.removeView(mContentViewRenderView); } } else { contentViewHolder.addView(contentViewRenderView, new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); } mContentViewRenderView = contentViewRenderView; } /** * @param window The owning window for this shell. */ public void setWindow(WindowAndroid window) { mWindow = window; } /** * @return Whether or not the Shell is loading content. */ public boolean isLoading() { return mLoading; } @Override protected void onFinishInflate() { super.onFinishInflate(); mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground(); initializeUrlField(); initializeNavigationButtons(); } private void initializeUrlField() { mUrlTextView = (EditText) findViewById(R.id.url); mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null || event.getKeyCode() != KeyEvent.KEYCODE_ENTER || event.getAction() != KeyEvent.ACTION_DOWN)) { return false; } loadUrl(mUrlTextView.getText().toString()); setKeyboardVisibilityForUrl(false); mContentView.requestFocus(); return true; } }); mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { setKeyboardVisibilityForUrl(hasFocus); mNextButton.setVisibility(hasFocus ? GONE : VISIBLE); mPrevButton.setVisibility(hasFocus ? GONE : VISIBLE); if (!hasFocus) { mUrlTextView.setText(mContentView.getUrl()); } } }); } /** * Loads an URL. This will perform minimal amounts of sanitizing of the URL to attempt to * make it valid. * * @param url The URL to be loaded by the shell. */ public void loadUrl(String url) { if (url == null) return; if (TextUtils.equals(url, mContentView.getUrl())) { mContentView.reload(); } else { updateHistory(url); mContentView.loadUrl(new LoadUrlParams(sanitizeUrl(url))); } mUrlTextView.clearFocus(); // TODO(aurimas): Remove this when crbug.com/174541 is fixed. mContentView.clearFocus(); mContentView.requestFocus(); } private void updateHistory(String url) { String json = mPref.getString("history", null); JSONArray array = new JSONArray(); if (json != null) { try { array = new JSONArray(json); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } LinkedHashSet<String> history = new LinkedHashSet<String>(); for (int i = 0; i < array.length(); i++) { try { history.add(array.getString(i)); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (history.contains(url)) { history.remove(url); } history.add(url); if (history.size() > 100) { String f = history.iterator().next(); history.remove(f); } array = new JSONArray(); for (String u : history) { array.put(u); } mPref.edit().putString("history", array.toString()).commit(); } /** * Given an URL, this performs minimal sanitizing to ensure it will be valid. * @param url The url to be sanitized. * @return The sanitized URL. */ public static String sanitizeUrl(String url) { if (url == null) return url; if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url; return url; } private void initializeNavigationButtons() { mToolbar = findViewById(R.id.toolbar); mPrevButton = (ImageButton) findViewById(R.id.prev); mPrevButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String url = mContentView.getUrl(); int a = url.lastIndexOf("page"); int b = a; String s = url.substring(a + 4); a = s.indexOf('.'); s = s.substring(0, a); int page = Integer.parseInt(s); String res = url.substring(0, b) + "page" + (page - 1) + ".html"; loadUrl(res); } }); mNextButton = (ImageButton) findViewById(R.id.next); mNextButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String url = mContentView.getUrl(); int a = url.lastIndexOf("page"); int b = a; String s = url.substring(a + 4); a = s.indexOf('.'); s = s.substring(0, a); int page = Integer.parseInt(s); String res = url.substring(0, b) + "page" + (page + 1) + ".html"; loadUrl(res); } }); mRefreshButton = (ImageButton) findViewById(R.id.reload); mRefreshButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mContentView.reload(); } }); mHistoryButton = (ImageButton) findViewById(R.id.history); mHistoryButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getContext(), HistoryActivity.class); //getContext().startActivity(intent); ((Activity) getContext()).startActivityForResult(intent, 42); } }); } @SuppressWarnings("unused") @CalledByNative private void onUpdateUrl(String url) { mUrlTextView.setText(url); } @SuppressWarnings("unused") @CalledByNative private void onLoadProgressChanged(double progress) { removeCallbacks(mClearProgressRunnable); mProgressDrawable.setLevel((int) (10000.0 * progress)); if (progress == 1.0) postDelayed(mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS); } @CalledByNative private void toggleFullscreenModeForTab(boolean enterFullscreen) { } @CalledByNative private boolean isFullscreenForTabOrPending() { return false; } @SuppressWarnings("unused") @CalledByNative private void setIsLoading(boolean loading) { mLoading = loading; } /** * Initializes the ContentView based on the native tab contents pointer passed in. * @param nativeTabContents The pointer to the native tab contents object. */ @SuppressWarnings("unused") @CalledByNative private void initFromNativeTabContents(int nativeTabContents) { gestureDetector = new GestureDetector(new GestureListener()); mContentView = ContentView.newInstance(getContext(), nativeTabContents, mWindow); mContentView.setOnTouchListener(this); if (mContentView.getUrl() != null) mUrlTextView.setText(mContentView.getUrl()); ((FrameLayout) findViewById(R.id.contentview_holder)).addView(mContentView, new FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); mContentView.requestFocus(); mContentViewRenderView.setCurrentContentView(mContentView); } /** * @return The {@link ContentView} currently shown by this Shell. */ public ContentView getContentView() { return mContentView; } private void setKeyboardVisibilityForUrl(boolean visible) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (visible) { imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT); } else { imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0); } } @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDown(MotionEvent e) { return false; } // event when double tap occurs @Override public boolean onDoubleTap(MotionEvent e) { if (mToolbar.isShown()) { mToolbar.setVisibility(View.GONE); } else { mToolbar.setVisibility(View.VISIBLE); } return true; } } }