com.samsung.richnotification.RichNotification.java Source code

Java tutorial

Introduction

Here is the source code for com.samsung.richnotification.RichNotification.java

Source

/*
 * Copyright (c) 2015 Samsung Electronics, Co. Ltd.
 *
 * 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.samsung.richnotification;

import java.util.UUID;
import java.util.List;
import java.lang.IllegalArgumentException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.util.Log;

import com.samsung.android.sdk.SsdkUnsupportedException;
import com.samsung.android.sdk.richnotification.Srn;
import com.samsung.android.sdk.richnotification.SrnRichNotificationManager;
import com.samsung.android.sdk.richnotification.SrnRichNotificationManager.ErrorType;
import com.samsung.android.sdk.richnotification.SrnRichNotificationManager.EventListener;
import com.samsung.android.sdk.richnotification.SrnImageAsset;
import com.samsung.android.sdk.richnotification.SrnRichNotification;
import com.samsung.android.sdk.richnotification.templates.SrnPrimaryTemplate;
import com.samsung.android.sdk.richnotification.templates.SrnSecondaryTemplate;
import com.samsung.android.sdk.richnotification.SrnAction;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This class is responsible for sending rich Notification to the Gear.
 */
public class RichNotification extends CordovaPlugin implements EventListener {

    private SrnRichNotificationManager mRichNotificationManager;
    private Context mContext;
    private boolean mIsRichSupported = false;
    private CallbackContext mCallbackContext = null;
    private boolean pluginMetadata = false;

    private static final String META_DATA = "com.samsung.cordova.richnotification";
    private static final String TAG = "RichNotification";
    private static final String RICHNOTI = "RichNotiPlugin";

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
        String mPackageName = cordova.getActivity().getPackageName();
        PackageManager pm = cordova.getActivity().getPackageManager();
        try {
            ApplicationInfo ai = pm.getApplicationInfo(mPackageName, PackageManager.GET_META_DATA);
            if (ai.metaData != null) {
                pluginMetadata = ai.metaData.getBoolean(META_DATA);
            }
        } catch (NameNotFoundException e) {
        }
        IntentFilter filter = new IntentFilter("com.samsung.cordova.richnotification.remote_input_receiver");
        if (richRemoteInputReceiver != null) {
            cordova.getActivity().getApplicationContext().registerReceiver(richRemoteInputReceiver, filter);
        }
    }

    /**
      * This method will initialize RichNotification on the device.
      *
      */
    private boolean initRichNotification(CallbackContext callbackContext) {
        if (Log.isLoggable(RICHNOTI, Log.DEBUG))
            Log.d(TAG, "Initializing RichNotification...");

        // This function takes care of error callbacks
        if (!isRichNotificationSupported(callbackContext)) {
            return false;
        } else if (mRichNotificationManager == null) {
            mRichNotificationManager = new SrnRichNotificationManager(mContext);
            mRichNotificationManager.start();
            mRichNotificationManager.registerRichNotificationListener(this);
        }

        boolean isConnected = mRichNotificationManager.isConnected();
        if (!isConnected) {
            Log.e(TAG, "Cannot send RichNotification. Device not connected.");
            callbackContext.error(RichNotificationHelper.DEVICE_NOT_CONNECTED);
            return false;
        } else {
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Initialization complete. Device is connected.");
        }

        return true;
    }

    /**
     * Checks if the device supports RichNotification feature.
     *
     * @param callbackContext
     *            The callback id used when calling back into JavaScript.
     * @return true if the RichNotification is supported or false if not supported.
     *
     */
    private boolean isRichNotificationSupported(CallbackContext callbackContext) {
        if (mIsRichSupported)
            return true;

        if (Log.isLoggable(RICHNOTI, Log.DEBUG))
            Log.d(TAG, "Checking RichNotification support...");
        Srn srn = new Srn();
        try {
            // Initialize an instance of Srn.
            srn.initialize(mContext);
        } catch (SsdkUnsupportedException e) {
            // Error handling
            if (e.getType() == SsdkUnsupportedException.VENDOR_NOT_SUPPORTED) {
                Log.e(TAG, "Initialization error. Vendor is not Samsung.");
                callbackContext.error(RichNotificationHelper.VENDOR_NOT_SUPPORTED);
            } else if (e.getType() == SsdkUnsupportedException.DEVICE_NOT_SUPPORTED) {
                Log.e(TAG, "Initialization error. Device not supported.");
                callbackContext.error(RichNotificationHelper.DEVICE_NOT_SUPPORTED);
            } else if (e.getType() == SsdkUnsupportedException.LIBRARY_NOT_INSTALLED) {
                Log.e(TAG, "Initialization error. Device not supported.");
                callbackContext.error(RichNotificationHelper.LIBRARY_NOT_INSTALLED);
            } else if (e.getType() == SsdkUnsupportedException.LIBRARY_UPDATE_IS_RECOMMENDED) {
                Log.e(TAG, "Initialization error. Device not supported.");
                callbackContext.error(RichNotificationHelper.LIBRARY_UPDATE_IS_RECOMMENDED);
            } else if (e.getType() == SsdkUnsupportedException.LIBRARY_UPDATE_IS_REQUIRED) {
                Log.e(TAG, "Initialization error. Device not supported.");
                callbackContext.error(RichNotificationHelper.LIBRARY_UPDATE_IS_REQUIRED);
            } else {
                Log.e(TAG, "Initialization error.");
                callbackContext.error("Initialization error");
            }
            return false;
        }
        mIsRichSupported = true;
        return true;
    }

    /**
     * Checks if the device is registered to the event listeners.
     *
     * @param callbackContext
     *            The callback id used when calling back into JavaScript.
     * @return true if the registration was successful or false if the registration was unsuccessful.
     *
     */
    private boolean registerRichNotificationEventListeners(CallbackContext callbackContext) {
        // This function takes care of error callbacks
        if (!isRichNotificationSupported(callbackContext)) {
            return false;
        }
        mCallbackContext = callbackContext;
        return true;
    }

    /**
     * This function will send a new notification or will update the notification sent.
     *
     * @param data
    *            The JSONArray with parameters required for sending the notification.
     * @param callbackContext
     *            The callback id used when calling back into JavaScript.
     * @return true if the notification is sent or false if the notification is not sent.
     *
     */
    private boolean sendRichNotification(JSONArray data, CallbackContext callbackContext) throws JSONException {
        RichNotificationOptions options = null;
        SrnPrimaryTemplate primaryTemplate = null;
        SrnSecondaryTemplate secondaryTemplate = null;

        // This function takes care of error callbacks
        if (!initRichNotification(callbackContext)) {
            Log.e(TAG, "Initialization failed.");
            return false;
        }

        if (Log.isLoggable(RICHNOTI, Log.DEBUG))
            Log.d(TAG, "Creating the notification.");

        // Fetch options from the data object
        options = new RichNotificationOptions(data);
        options.printLogs();

        SrnRichNotification noti = null;
        UUID uuid = null;

        try {
            uuid = UUID.fromString(options.uuid);
        } catch (IllegalArgumentException invalidUUID) {
            Log.e(TAG, "Invalid UUID supplied. Creating a new notification.");
            options.uuid = null;
        }

        if (options.uuid == null)
            noti = new SrnRichNotification(mContext);
        else
            noti = new SrnRichNotification(mContext, uuid);

        // Set notification icon
        if (!options.notificationIcon.isEmpty()) {
            Bitmap notiIconBit = RichNotificationHelper.getIconBitmap(mContext,
                    "file://" + options.notificationIcon);
            SrnImageAsset notiIconAsst = new SrnImageAsset(mContext, "notiIcon", notiIconBit);
            noti.setIcon(notiIconAsst);
        }

        noti.setAlertType(options.alertType, options.popupType);

        noti.setReadout(options.readoutTitle, options.readout);
        noti.setTitle(options.notificationTitle);

        primaryTemplate = RichNotificationHelper.createPrimaryTemplate(mContext, options);
        secondaryTemplate = RichNotificationHelper.createSecondaryTemplate(mContext, options);

        noti.setPrimaryTemplate(primaryTemplate);

        if (secondaryTemplate != null)
            noti.setSecondaryTemplate(secondaryTemplate);

        // Action related
        List<SrnAction> actionList = RichNotificationHelper.createActions(mContext, callbackContext, options);
        if (actionList != null) {
            noti.addActions(actionList);
        } else {
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Actions not defined");
        }

        try {
            options.uuid = mRichNotificationManager.notify(noti).toString();

            JSONObject successMsg = new JSONObject();
            successMsg.put("returnType", RichNotificationHelper.RETURN_TYPE_NOTIFICATION_SENT);
            successMsg.put("returnValue", options.uuid);

            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Notification sent. UUID: " + options.uuid);
            PluginResult sentResult = new PluginResult(PluginResult.Status.OK, successMsg);
            sentResult.setKeepCallback(true);
            callbackContext.sendPluginResult(sentResult);
            return true;
        } catch (SecurityException secEx) {
            Log.e(TAG, "Permission denied");
            callbackContext.error(RichNotificationHelper.PERMISSION_DENIED);
            return false;
        }
    }

    /**
     * This function will delete a specific notification or will delete all the notification sent 
     * in a particular session.
     *
     * @param uuid
    *            The string parameter required for dismissing the notification.
     * @param callbackContext
     *            The callback id used when calling back into JavaScript.
     * @return true if the notification is dismissed or falses if the notification is not dismissed.
     *
     */
    private boolean dismissRichNotification(String uuid, CallbackContext callbackContext) {
        try {
            if (!isRichNotificationSupported(callbackContext)) {
                return false;
            } else if (mRichNotificationManager == null) {
                callbackContext.error(RichNotificationHelper.NOTIFICATION_MANAGER_NOT_STARTED);
                return false;
            } else if (!mRichNotificationManager.isConnected()) {
                callbackContext.error(RichNotificationHelper.DEVICE_NOT_CONNECTED);
                return false;
            } else if (uuid == null || uuid.isEmpty()) {
                callbackContext.error(RichNotificationHelper.INVALID_UUID);
                return false;
            } else if (uuid.equalsIgnoreCase("all")) {
                mRichNotificationManager.dismissAll();
            } else {
                UUID dismissID = UUID.fromString(uuid);
                mRichNotificationManager.dismiss(dismissID);
            }
        } catch (IllegalArgumentException invalidUUID) {
            Log.e(TAG, "Invalid UUID: " + uuid);
            callbackContext.error(RichNotificationHelper.INVALID_UUID);
            return false;
        }

        callbackContext.success();
        return true;
    }

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action
     *            The action to execute.
     * @param data
     *            JSONArray of arguments for the plugin.
     * @param callbackContext
     *            The callback id used when calling back into JavaScript.
     * @return A PluginResult object with a status and message.
     */
    @Override
    public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

        if (Log.isLoggable(RICHNOTI, Log.DEBUG))
            Log.d(TAG, "execute(): callbackID - " + callbackContext.getCallbackId());
        mContext = this.cordova.getActivity();

        // Do not allow apis if metadata is missing
        if (!pluginMetadata) {
            callbackContext.error("METADATA_MISSING");
            Log.e(TAG, "Metadata is missing");
            return false;
        }

        if (action.equals("isSupported")) {
            if (isRichNotificationSupported(callbackContext)) {
                callbackContext.success();
                return true;
            }
            return false;
        }

        else if (action.equals("registerEventListeners")) {
            return registerRichNotificationEventListeners(callbackContext);
        }

        else if (action.equals("send")) {
            return sendRichNotification(data, callbackContext);
        }

        else if (action.equals("dismiss")) {
            String uuid = data.getString(0); // There will be just one array-element i.e. the UUID
            return dismissRichNotification(uuid, callbackContext);
        }

        else if (action.equals("isConnected")) {
            // initRichNotification will throw the DEVICE_NOT_CONNECTED error
            if (!initRichNotification(callbackContext)) {
                Log.e(TAG, "Initialization failed.");
                return false;
            } else {
                if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                    Log.d(TAG, "Connected to gear");
                callbackContext.success();
                return true;
            }
        }
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (richRemoteInputReceiver != null) {
            try {
                this.cordova.getActivity().unregisterReceiver(richRemoteInputReceiver);
                richRemoteInputReceiver = null;
            } catch (IllegalArgumentException e) {
                //not an error case
                if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                    Log.d(TAG, "unregistering receiver in onDestroy: " + e.getMessage());
                e.printStackTrace();
            }
        }
    };

    BroadcastReceiver richRemoteInputReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "RemoteInputReceiver: Received input from gear");

            String callbackID = intent.getStringExtra("callbackID");
            String actionID = intent.getStringExtra("actionID");
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "onNewIntent: actionID - " + actionID);
            String inputActionData = intent.getStringExtra("extra_action_data");

            JSONObject gearInputReturn = new JSONObject();

            try {
                gearInputReturn.put("returnType", RichNotificationHelper.RETURN_TYPE_REMOTE_INPUT);
                gearInputReturn.put("returnValue", inputActionData);
                gearInputReturn.put("actionID", actionID);
            } catch (JSONException jse) {
                Log.d(TAG, "Gear input invalid");
                return;
            }
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Data to be sent to JS: " + inputActionData);
            PluginResult result = new PluginResult(PluginResult.Status.OK, gearInputReturn);
            result.setKeepCallback(true);
            RichNotification.this.webView.sendPluginResult(result, callbackID);
        }
    };

    @Override
    public void onError(UUID arg0, ErrorType arg1) {
    }

    @Override
    //On RichNotification Read in the gear
    public void onRead(UUID arg0) {
        if (mCallbackContext == null)
            return;
        try {
            JSONObject eventMsg = new JSONObject();
            eventMsg.put("returnType", RichNotificationHelper.RETURN_TYPE_NOTIFICATION_READ);
            eventMsg.put("returnValue", arg0.toString());
            PluginResult sentResult = new PluginResult(PluginResult.Status.OK, eventMsg);
            sentResult.setKeepCallback(true);
            mCallbackContext.sendPluginResult(sentResult);
        } catch (JSONException jse) {
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Gear input invalid");
            return;
        }
    }

    @Override
    //On RichNotification Removed from the gear
    public void onRemoved(UUID arg0) {
        if (mCallbackContext == null)
            return;
        try {
            JSONObject eventMsg = new JSONObject();
            eventMsg.put("returnType", RichNotificationHelper.RETURN_TYPE_NOTIFICATION_REMOVED);
            eventMsg.put("returnValue", arg0.toString());
            PluginResult sentResult = new PluginResult(PluginResult.Status.OK, eventMsg);
            sentResult.setKeepCallback(true);
            mCallbackContext.sendPluginResult(sentResult);
        } catch (JSONException jse) {
            if (Log.isLoggable(RICHNOTI, Log.DEBUG))
                Log.d(TAG, "Gear input invalid");
            return;
        }
    }
}