org.xwalk.runtime.extension.XWalkExtensionManager.java Source code

Java tutorial

Introduction

Here is the source code for org.xwalk.runtime.extension.XWalkExtensionManager.java

Source

// Copyright (c) 2013 Intel Corporation. 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.xwalk.runtime.extension;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.Class;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xwalk.runtime.extension.api.contacts.Contacts;
import org.xwalk.runtime.extension.api.device_capabilities.DeviceCapabilities;
import org.xwalk.runtime.extension.api.messaging.Messaging;
import org.xwalk.runtime.extension.api.presentation.PresentationExtension;
import org.xwalk.runtime.extension.api.screenorientation.ScreenOrientationExtension;

/**
 * This internal class acts a manager to manage extensions.
 */
public class XWalkExtensionManager implements XWalkExtensionContext {
    private final static String TAG = "XWalkExtensionManager";
    private final static String EXTENSION_CONFIG_FILE = "extensions-config.json";
    // This class name is from runtime client. Need to keep consistency with it.
    private final static String EXTENSION_CONTEXT_CLIENT_CLASS_NAME = "org.xwalk.app.runtime.extension.XWalkExtensionContextClient";

    private final Context mContext;
    private final Activity mActivity;

    private final HashMap<String, XWalkExtensionBridge> mExtensions = new HashMap<String, XWalkExtensionBridge>();
    // This variable is to set whether to load external extensions. The default is true.
    private boolean mLoadExternalExtensions;

    public XWalkExtensionManager(Context context, Activity activity) {
        mContext = context;
        mActivity = activity;
        mLoadExternalExtensions = true;
    }

    @Override
    public void registerExtension(XWalkExtension extension) {
        if (mExtensions.get(extension.getExtensionName()) != null) {
            Log.e(TAG, extension.getExtensionName() + "is already registered!");
            return;
        }

        XWalkExtensionBridge bridge = XWalkExtensionBridgeFactory.createInstance(extension);
        mExtensions.put(extension.getExtensionName(), bridge);
    }

    @Override
    public void unregisterExtension(String name) {
        XWalkExtensionBridge bridge = mExtensions.get(name);
        if (bridge != null) {
            mExtensions.remove(name);
            bridge.onDestroy();
        }
    }

    @Override
    public Context getContext() {
        return mContext;
    }

    @Override
    public Activity getActivity() {
        return mActivity;
    }

    @Override
    public void postMessage(XWalkExtension extension, int instanceID, String message) {
        XWalkExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
        if (bridge != null)
            bridge.postMessage(instanceID, message);
    }

    public void broadcastMessage(XWalkExtension extension, String message) {
        XWalkExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
        if (bridge != null)
            bridge.broadcastMessage(message);
    }

    public void onResume() {
        for (XWalkExtensionBridge extension : mExtensions.values()) {
            extension.onResume();
        }
    }

    public void onPause() {
        for (XWalkExtensionBridge extension : mExtensions.values()) {
            extension.onPause();
        }
    }

    public void onDestroy() {
        for (XWalkExtensionBridge extension : mExtensions.values()) {
            extension.onDestroy();
        }
        mExtensions.clear();
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        for (XWalkExtensionBridge extension : mExtensions.values()) {
            extension.onActivityResult(requestCode, resultCode, data);
        }
    }

    public void loadExtensions() {
        loadInternalExtensions();
        loadExternalExtensions();
    }

    public void setAllowExternalExtensions(boolean load) {
        mLoadExternalExtensions = load;
    }

    private void loadInternalExtensions() {
        // Create all extension instances directly here. The internal extension will register
        // itself and add itself to XWalkExtensionManager.mExtensions automatically.
        // The following sample shows how to create an extension that named Device:
        //    String jsApiContent = "";
        //    try {
        //        jsApiContent = getAssetsFileContent(mContext.getAssets(), Device.JS_API_PATH);
        //        new Device(jsApiContent, mExtensionContextImpl);
        //    } catch(IOException e) {
        //        Log.e(TAG, "Failed to read js API file of internal extension: Device");
        //    }
        {
            String jsApiContent = "";
            try {
                jsApiContent = getAssetsFileContent(mContext.getAssets(), PresentationExtension.JS_API_PATH);
                // Load PresentationExtension as an internal extension.
                new PresentationExtension(PresentationExtension.NAME, jsApiContent, this);
            } catch (IOException e) {
                Log.e(TAG, "Failed to read JS API file: " + PresentationExtension.JS_API_PATH);
            }
        }

        {
            String jsApiContent = ScreenOrientationExtension.getInsertedString();
            try {
                jsApiContent += getAssetsFileContent(mContext.getAssets(), ScreenOrientationExtension.JS_API_PATH);
                new ScreenOrientationExtension(ScreenOrientationExtension.NAME, jsApiContent,
                        ScreenOrientationExtension.JS_ENTRY_POINTS, this);
            } catch (IOException e) {
                Log.e(TAG, "Failed to read JS API file: " + ScreenOrientationExtension.JS_API_PATH);
            }
        }

        {
            String jsApiContent = "";
            try {
                jsApiContent = getAssetsFileContent(mContext.getAssets(), Contacts.JS_API_PATH);
                new Contacts(jsApiContent, this);
            } catch (IOException e) {
                Log.e(TAG, "Failed to read JS API file: " + Contacts.JS_API_PATH);
            }
        }

        {
            String jsApiContent = "";
            try {
                jsApiContent = getAssetsFileContent(mContext.getAssets(), DeviceCapabilities.JS_API_PATH);
                new DeviceCapabilities(jsApiContent, this);
            } catch (IOException e) {
                Log.e(TAG, "Failed to read JS API file: " + DeviceCapabilities.JS_API_PATH);
            }
        }
        {
            String jsApiContent = "";
            try {
                jsApiContent = getAssetsFileContent(mContext.getAssets(), Messaging.JS_API_PATH);
                new Messaging(jsApiContent, this);
            } catch (IOException e) {
                Log.e(TAG, "Failed to read JS API file: " + Messaging.JS_API_PATH);
            }
        }
    }

    private void loadExternalExtensions() {
        if (!mLoadExternalExtensions)
            return;

        // Read extensions-config.json and create external extensions.
        String configFileContent;
        try {
            configFileContent = getAssetsFileContent(mActivity.getAssets(), EXTENSION_CONFIG_FILE);
        } catch (IOException e) {
            Log.e(TAG, "Failed to read extensions-config.json");
            return;
        }

        // Initialize the context for external extensions.
        XWalkExtensionContextWrapper contextWrapper = new XWalkExtensionContextWrapper(this);
        Object contextClient = createExtensionContextClient(contextWrapper);

        try {
            JSONArray jsonFeatures = new JSONArray(configFileContent);
            int extensionCount = jsonFeatures.length();
            for (int i = 0; i < extensionCount; i++) {
                JSONObject jsonObject = jsonFeatures.getJSONObject(i);
                String name = jsonObject.getString("name");
                String className = jsonObject.getString("class");
                String jsApiFile = jsonObject.getString("jsapi");

                // Load the content of the JavaScript file.
                String jsApi;
                try {
                    jsApi = getAssetsFileContent(mActivity.getAssets(), jsApiFile);
                } catch (IOException e) {
                    Log.e(TAG, "Failed to read the file " + jsApiFile);
                    return;
                }

                if (name != null && className != null && jsApi != null) {
                    createExternalExtension(name, className, jsApi, contextClient, contextWrapper);
                }
            }
        } catch (JSONException e) {
            Log.e(TAG, "Failed to parse extensions-config.json");
        }
    }

    private String getAssetsFileContent(AssetManager assetManager, String fileName) throws IOException {
        String result = "";
        InputStream inputStream = null;
        try {
            inputStream = assetManager.open(fileName);
            int size = inputStream.available();
            byte[] buffer = new byte[size];
            inputStream.read(buffer);
            result = new String(buffer);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return result;
    }

    private Object createExtensionContextClient(XWalkExtensionContextWrapper contextWrapper) {
        Activity activity = contextWrapper.getActivity();
        try {
            Class<?> clazz = activity.getClassLoader().loadClass(EXTENSION_CONTEXT_CLIENT_CLASS_NAME);
            Constructor<?> constructor = clazz.getConstructor(Activity.class, Object.class);
            return constructor.newInstance(activity, contextWrapper);
        } catch (ClassNotFoundException e) {
            handleException(e);
        } catch (IllegalAccessException e) {
            handleException(e);
        } catch (InstantiationException e) {
            handleException(e);
        } catch (InvocationTargetException e) {
            handleException(e);
        } catch (NoSuchMethodException e) {
            handleException(e);
        }
        return null;
    }

    private void createExternalExtension(String name, String className, String jsApi, Object contextClient,
            XWalkExtensionContextWrapper contextWrapper) {
        Activity activity = contextWrapper.getActivity();
        try {
            Class<?> clazz = activity.getClassLoader().loadClass(className);
            Constructor<?> constructor = clazz.getConstructor(String.class, String.class, contextClient.getClass());
            constructor.newInstance(name, jsApi, contextClient);
        } catch (ClassNotFoundException e) {
            handleException(e);
        } catch (IllegalAccessException e) {
            handleException(e);
        } catch (InstantiationException e) {
            handleException(e);
        } catch (InvocationTargetException e) {
            handleException(e);
        } catch (NoSuchMethodException e) {
            handleException(e);
        }
    }

    private static void handleException(Exception e) {
        // TODO(yongsheng): Handle exceptions here.
        Log.e(TAG, "Error in calling methods of external extensions. " + e.toString());
    }
}