napolitano / cordova-plugin-intent

Plugin for apache cordova (Android Only) that allows interaction with the intent.
MIT License
84 stars 88 forks source link

Parcelled data in Extra not unpacked #1

Closed SverrirValgeirsson closed 8 years ago

SverrirValgeirsson commented 8 years ago

Hi. Thanks for the great plugin!.

I have noticed that in some cases the intent data (when sending URL from chrome) comes parcelled and then doesn't get unpacked (looking at the data it just shows: extras : Bundle[mParcelledData.dataSize=664] )

I made a small hack to fix it for me by just pulling out the data to a string but I'm not sending it as pull request as I think there must be a more elegant solution ;)


try {
        intentJSON = new JSONObject();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if(items != null) {
                intentJSON.put("clipItems", new JSONArray(items));
            }
        }

// change to ensure all data is pulled from extras StringBuilder str = new StringBuilder(); Bundle bundle = intent.getExtras(); if (bundle != null) { Set keys = bundle.keySet(); Iterator it = keys.iterator(); while (it.hasNext()) { String key = it.next(); str.append(key); str.append(":"); str.append(bundle.get(key)); str.append("\n\r"); } } intentJSON.put("bundle",str.toString()); // end of change intentJSON.put("type", intent.getType());

alyrik commented 8 years ago

@Sveppi, could you please explain exactly where to add this fragment?

I made it like this: (IntentPlugin.java)

try {
    intentJSON = new JSONObject();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    ...
    }

    StringBuilder str = new StringBuilder();
    Bundle bundle = intent.getExtras();
    if (bundle != null) {
        Set keys = bundle.keySet();
        Iterator it = keys.iterator();
        while (it.hasNext()) {
            String key = it.next();
            str.append(key);
            str.append(":");
            str.append(bundle.get(key));
            str.append("\n\r");
        }
    }
    intentJSON.put("bundle",str.toString());
    intentJSON.put("type", intent.getType());
    intentJSON.put("extras", intent.getExtras());
    intentJSON.put("action", intent.getAction());
    intentJSON.put("categories", intent.getCategories());
    intentJSON.put("flags", intent.getFlags());
    intentJSON.put("component", intent.getComponent());
    intentJSON.put("data", intent.getData());
    intentJSON.put("package", intent.getPackage());

    return intentJSON;
}

But it causes errors while building: error: cannot find symbol Bundle bundle = intent.getExtras(); error: cannot find symbol Iterator it = keys.iterator();

SverrirValgeirsson commented 8 years ago

Here’s my modified file. You need to add a couple of imports. import java.util.Iterator; import android.os.Bundle;

BR Sverrir

20 feb. 2016 kl. 23:18 skrev alyrik notifications@github.com:

@Sveppi https://github.com/Sveppi, could you please explain exactly where to add this fragment?

I made it like this: (IntentPlugin.java)

try { intentJSON = new JSONObject();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
...
}

StringBuilder str = new StringBuilder();
Bundle bundle = intent.getExtras();
if (bundle != null) {
    Set keys = bundle.keySet();
    Iterator it = keys.iterator();
    while (it.hasNext()) {
        String key = it.next();
        str.append(key);
        str.append(":");
        str.append(bundle.get(key));
        str.append("\n\r");
    }
}
intentJSON.put("bundle",str.toString());
intentJSON.put("type", intent.getType());
intentJSON.put("extras", intent.getExtras());
intentJSON.put("action", intent.getAction());
intentJSON.put("categories", intent.getCategories());
intentJSON.put("flags", intent.getFlags());
intentJSON.put("component", intent.getComponent());
intentJSON.put("data", intent.getData());
intentJSON.put("package", intent.getPackage());

return intentJSON;

} But it causes errors while building: error: cannot find symbol Bundle bundle = intent.getExtras(); error: cannot find symbol Iterator it = keys.iterator();

— Reply to this email directly or view it on GitHub https://github.com/napolitano/cordova-plugin-intent/issues/1#issuecomment-186691786.

alyrik commented 8 years ago

It's a pity now there's another one:

error: incompatible types: Object cannot be converted to String
    String key = it.next();
alyrik commented 8 years ago

Fixed it in such a way:

String key = (String) it.next();
richmartin commented 8 years ago

I also hit this issue. My fix was to convert the Bundle to a JSONObject before adding it as the 'extras' field:

In method getIntentJson change the intentJSON.put("extras", intent.getExtras()); line to: intentJSON.put("extras", toJsonObject(intent.getExtras()));

and then add the following two static methods to the class:

  private static JSONObject toJsonObject(Bundle bundle) {
    try {
      return (JSONObject) toJsonValue(bundle);
    } catch (JSONException e) {
      throw new IllegalArgumentException("Cannot convert bundle to JSON: " + e.getMessage(), e);
    }
  }

  private static Object toJsonValue(final Object value) throws JSONException {
    if (value == null) {
      return null;
    } else if (value instanceof Bundle) {
      final Bundle bundle = (Bundle) value;
      final JSONObject result = new JSONObject();
      for (final String key : bundle.keySet()) {
        result.put(key, toJsonValue(bundle.get(key)));
      }
      return result;
    } else if (value.getClass().isArray()) {
      final JSONArray result = new JSONArray();
      int length = Array.getLength(value);
      for (int i = 0; i < length; ++i) {
        result.put(i, toJsonValue(Array.get(value, i)));
      }
      return result;
    } else if (
        value instanceof String
            || value instanceof Boolean
            || value instanceof Integer
            || value instanceof Long
            || value instanceof Double) {
      return value;
    } else {
      return String.valueOf(value);
    }
  }

I believe that should convert any type of content from the Bundle correctly into the JSONObject so you can read it as JSON back in JS land.

Edit: I just created a Pull Request to share this fix back to the main branch: https://github.com/napolitano/cordova-plugin-intent/pull/4

napolitano commented 8 years ago

Thanks for the pull request. I will review it within the next days and add some more changes to the plugin.

SverrirValgeirsson commented 8 years ago

The fix in #4 is much better than the one I initially proposed. Closing the issue.