mank
mank

Reputation: 33

Cordova 3 Android plugin - how to call a function in main activity?

Edit: User QuickFix's answer worked for me. Code right at the bottom of this question.

I am trying to write a Cordova 3 Android plugin that makes normal and custom Toast. However, I am just a front-end developer and very new to Cordova and Android. I am still learning and would appreciate any help you can give.

So far I have managed to do these 2 tasks individually and successfully:

  1. write a function in the main activity that makes normal and custom Toast (the custom Toast is simply a RelativeLayout in /res/layout that shows an icon and some text).
  2. write a Cordova plugin by following Devgirl's tutorial: How to Write a PhoneGap 3.0 Plugin for Android.

My problem now is - how do I get the plugin to call the showCustomToast() function in the main activity? As you can see in Code block #2 below, I ran into the problem of how to even get the main activity so I could call showCustomToast(). Here is the extract of how I am currently doing this:

// Problem?
HelloCordova main = (HelloCordova) cordova.getActivity();  
main.showCustomToast(toastTitle, toastText, duration);

I have to cast cordova.getActivity() to HelloCordova, otherwise it won't recognise that it has the showCustomToast() function. But surely this is not the correct approach, although it does "work", ie, I am able to get custom Toast to show in the app. I just can't help but feel that I've gone about this completely the wrong way. It's not exactly a reusable plugin at the moment!

I would be very grateful if someone could set me on the right path of how to achieve this. For example, should I give up on the plugin completely and just do this instead?

This is my first Stackoverflow question so please let me know if I should change or clarify anything. Thank you for reading!!

Here's my existing code:

Code block #1

This HelloCordova class was automatically generated when starting a new Cordova project. I added the showCustomToast() function.

package io.cordova.hellocordova;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import org.apache.cordova.*;

public class HelloCordova extends CordovaActivity 
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        super.init();
        // Set by <content src="index.html" /> in config.xml
        super.loadUrl(Config.getStartUrl());
        //super.loadUrl("file:///android_asset/www/index.html")

    }
    public void showCustomToast(String toastTitleText, String toastDescText, int toastDuration) {
        Toast toast = new Toast(this);
        toast.setDuration(toastDuration);   

        LayoutInflater inflater = getLayoutInflater();
        View appearance = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toastRoot));
        toast.setView(appearance);

        TextView toastTitle = (TextView) appearance.findViewById(R.id.toastTitle);
        toastTitle.setText(toastTitleText);

        TextView toastDesc = (TextView) appearance.findViewById(R.id.toastDescription);
        toastDesc.setText(toastDescText);

        toast.show();
    }
}

Code block #2

The Java part of the Cordova plugin.

package com.example.plugins.toast;

//Problem?
import io.cordova.hellocordova.HelloCordova;

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

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

public class ToastPlugin extends CordovaPlugin {

    final String LOG_TAG = "ToastLog";
    public static final String ACTION_NORMAL_TOAST = "normalToast";
    public static final String ACTION_CUSTOM_TOAST = "customToast";

    @Override
    public boolean execute(String action, JSONArray args,
            CallbackContext callbackContext) throws JSONException {

        final JSONObject arg_object = args.getJSONObject(0);
        final String toastTitle = arg_object.getString("toastTitle");
        final String toastText = arg_object.getString("toastText");
        final String toastDuration = arg_object.getString("toastDuration");

        final CallbackContext ctx = callbackContext;

        try {
            if (ACTION_NORMAL_TOAST.equals(action)) {
                Log.d(LOG_TAG, "Normal toast: " + toastText);

                Runnable runnable = new Runnable() {
                    public void run() {
                        Context context = cordova.getActivity()
                                .getApplicationContext();
                        int duration = Toast.LENGTH_SHORT;
                        if (toastDuration.equals("LONG")) {
                            duration = Toast.LENGTH_LONG;
                        }
                        Toast.makeText(context, toastText, duration).show();
                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);

                callbackContext.success();
                return true;
            } else if (ACTION_CUSTOM_TOAST.equals(action)) {
                Log.d(LOG_TAG, "Custom toast: " + toastTitle + ": " + toastText);

                Runnable runnable = new Runnable() {
                    public void run() {
                        int duration = Toast.LENGTH_SHORT;
                        if (toastDuration.equals("LONG")) {
                            duration = Toast.LENGTH_LONG;
                        }
                        //Problem?
                        HelloCordova main = (HelloCordova) cordova
                                .getActivity();
                        main.showCustomToast(toastTitle, toastText, duration);
                        ctx.success();

                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);

                callbackContext.success();
                return true;
            }
            callbackContext.error("Invalid action");
            return false;
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            callbackContext.error(e.getMessage());
            return false;
        }
    }
}

Edit: Here is the solution that worked for me. As QuickFix mentioned in their answer below, the custom toast code is now in the plugin.

package com.example.plugins.toast;

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

import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class ToastPlugin extends CordovaPlugin {

    final String LOG_TAG = "ToastLog";
    public static final String ACTION_NORMAL_TOAST = "normalToast";
    public static final String ACTION_CUSTOM_TOAST = "customToast"; 

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        final JSONObject arg_object = args.getJSONObject(0);
        final String toastTitle = arg_object.getString("toastTitle");
        final String toastText = arg_object.getString("toastText");
        final String toastDuration = arg_object.getString("toastDuration");

        try {
            if (ACTION_NORMAL_TOAST.equals(action)) {

                Log.i(LOG_TAG, "[Normal toast] toastText: " + toastText);

                Runnable runnable = new Runnable() {
                    public void run() {
                        Context context = cordova.getActivity().getApplicationContext();
                        int duration = Toast.LENGTH_SHORT;
                        if (toastDuration.equals("LONG")) {
                            duration = Toast.LENGTH_LONG;
                        }
                        Toast.makeText(context, toastText, duration).show();
                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);
                callbackContext.success();
                return true;

            } else if (ACTION_CUSTOM_TOAST.equals(action)) {

                Log.i(LOG_TAG, "[Custom toast] toastTitle: " + toastTitle + "\n toastText: " + toastText);

                Runnable runnable = new Runnable() {
                    public void run() {
                        int duration = Toast.LENGTH_SHORT;
                        if (toastDuration.equals("LONG")) {
                            duration = Toast.LENGTH_LONG;
                        }

                        Context context = cordova.getActivity().getApplicationContext();

                        Toast toast = new Toast(context);
                        toast.setDuration(duration);    

                        LayoutInflater inflater = LayoutInflater.from(context);

                        Resources resources = context.getResources();                       
                        String packageName = context.getPackageName();

                        View appearance = inflater.inflate(resources.getIdentifier("toast_layout","layout",packageName),null);
                        toast.setView(appearance);

                        TextView toastTitleView = (TextView) appearance.findViewById(resources.getIdentifier("toastTitle","id",packageName));
                        toastTitleView.setText(toastTitle);

                        TextView toastDesc = (TextView) appearance.findViewById(resources.getIdentifier("toastDescription","id",packageName));
                        toastDesc.setText(toastText);

                        toast.show();
                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);
                callbackContext.success();
                return true;

            }
            callbackContext.error("Invalid action");
            return false;
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            callbackContext.error(e.getMessage());
            return false;
        }
    }
}

Upvotes: 3

Views: 6290

Answers (1)

QuickFix
QuickFix

Reputation: 11721

Maybe you could put showCustomToast inside the plugin instead of inside the app?

In that case you will have to replace in the function the R.layout.layoutname and R.id.viewname with

getApplication().getResources().getIdentifier("layoutname","layout",getApplication().getPackageName());

and

getApplication().getResources().getIdentifier("viewname","id",getApplication().getPackageName());

Upvotes: 7

Related Questions