/* * Copyright 2010 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.stream; import java.util.HashMap; import android.app.Activity; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; /** * Handles the rendering of the WebView instance and the * mapping of app:// urls to their appropriate Handlers. * * @author yariv */ public class Dispatcher { // The WebView instance private WebView webView; // The app's main Activity private Activity activity; // Contains the webView object LinearLayout layout; // Has the webView been rendered? boolean isWebViewShown; // Holds mappings between handler names to their classes // (e.g. "login" -> LoginHandler.class) HashMap<String, Class> handlers; public Dispatcher(Activity activity) { this.activity = activity; handlers = new HashMap<String, Class>(); layout = new LinearLayout(activity); activity.addContentView( layout, new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); isWebViewShown = false; showWebView(); } /** * Adds a handler name to handler class mapping. This should be called * for each handler when the application starts up. * * @param name * @param clazz */ public void addHandler(String name, Class clazz) { this.handlers.put(name, clazz); } /** * Executes the handler associated with the given name. For example, * dispatcher.runHandler("login") would render the Login page in the * WebView instance. * * @param name */ public void runHandler(String name) { Class clazz = handlers.get(name); if (clazz != null) { try { Handler handler = (Handler)clazz.newInstance(); handler.setDispatcher(this); handler.go(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } } /** * Show the app's WebView instance. */ public void showWebView() { if (isWebViewShown) { return; } webView = new WebView(activity); webView.setWebViewClient(new AppWebViewClient()); webView.getSettings().setJavaScriptEnabled(true); layout.addView(webView, new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); isWebViewShown = true; } /** * Hide the app's WebView instance. This should be called if the * WebView instance is visible and the app wants to open another * WebView instance (e.g. for a Facebook dialog). Android doesn't * seem to be able to handle more than one WebView instance per * application. */ public void hideWebView() { layout.removeView(webView); isWebViewShown = false; } /** * Returns true if the WebView instance is visible. */ public boolean isWebViewShown() { return isWebViewShown; } /** * Loads the html string into the WebView instance. * * @param html */ public void loadData(String html) { webView.loadDataWithBaseURL( "http://nada", html, "text/html", "utf8", ""); } /** * Loads a file from the assets directory into the * WebView instance. * * @param file */ public void loadFile(String file) { webView.loadUrl(getAbsoluteUrl(file)); } /** * Returns the absolute URL for a local file. * * @param file */ public static String getAbsoluteUrl(String file) { return "file:///android_asset/" + file; } /** * Returns the Dispatcher's WebView instance. */ public WebView getWebView() { return webView; } /** * Returns the Dispatcher's Activity */ public Activity getActivity() { return activity; } /** * Enables the mapping of app:// urls to Handlers. * * @author yariv */ private class AppWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("app://")) { String handlerName = url.substring(6); runHandler(handlerName); return true; } return false; } } }