Closed badoualy closed 1 year ago
@badoualy
I also faces same error when setting data on people like below
mixPanel.people.set(JSONObject().apply {
put("name".addDollar(),user.vName)
put("email".addDollar(), user.vEmailId)
put(KEY_MOBILE_NUMBER, user.vMobileNumber)
put(KEY_INSTALLED_FROM, user.vReferalPlatform)
})
I get error as below
Caused by: java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Collections.java:1504)
It is crashing only in release build in debug build working fine.
I have already used pro guard for the Mix Panel SDK.
Please let me know if you find any solution for the same.
Thank you
UPDATE
I downgraded SDK version to 6.5.1 and it's working fine but events are not being logged in mixpanel dashboard
Indeed I forgot to mention it seems to be working fine on debug builds.
@chichi289 FYI I used the following bypass, that seems to work:
override suspend fun setPeople(properties: Map<String, Any?>) {
with(mixpanel.people) {
properties.keys.forEach { unset(it) }
setOnceMap(properties.filterValues { it != null })
}
}
setOnceMap
is not building a JsonObject like set
is doing, so the bug won't occur
@badoualy Thanks for the suggestions
I imported mix panel library as a module in project and checked the code which causes exception.
@Override
public void set(JSONObject properties) {
if (hasOptedOutTracking()) return;
try {
final JSONObject sendProperties = new JSONObject(mDeviceInfo);
for (final Iterator<?> iter = properties.keys(); iter.hasNext(); ) {
final String key = (String) iter.next();
sendProperties.put(key, properties.get(key));
}
final JSONObject message = stdPeopleMessage("$set", sendProperties);
recordPeopleMessage(message);
} catch (final JSONException e) {
MPLog.e(LOGTAG, "Exception setting people properties", e);
}
}
final JSONObject sendProperties = new JSONObject(mDeviceInfo);
Here mDeviceInfo is passed in JSONObject constructure which causes crash as it is constructed as unmodified map as below
mDeviceInfo = Collections.unmodifiableMap(deviceInfo);
So my guess is somewhere it is being modified.
If we remove mDeviceInfo from JSONObject constructor then code is compiled and worked fine in release app.
@badoualy setOnceMap is working as it is not using mDeviceInfo internally
@zihejia Please look into this and provide solutions for the same
Thank you
Ah indeed, it might be linked to a bad dependency. When checking the code, I had another version of JSONObject
that's actually not using the map directly, but adding each entry into its interval map (which wouldn't cause the issue)
public JSONObject(@NonNull Map copyFrom) {
this();
Map<?, ?> contentsTyped = (Map<?, ?>) copyFrom;
for (Map.Entry<?, ?> entry : contentsTyped.entrySet()) {
/*
* Deviate from the original by checking that keys are non-null and
* of the proper type. (We still defer validating the values).
*/
String key = (String) entry.getKey();
if (key == null) {
throw new NullPointerException("key == null");
}
nameValuePairs.put(key, wrap(entry.getValue()));
}
}
But I also have this version in my classpath:
public JSONObject(Map var1) {
this.map = (Map)(var1 == null ? new HashMap() : var1);
}
Not sure which one mixpanel is supposed to use. Maybe it's another dependency in our project that's overriding the dependency that mixpanel SDK is using?
Edit: ok so in my case, it looks like the socket-io
lib that I'm using is using the following dependency:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
which is the version using the map passed to the constructor as is without making a copy. So using an exclude module on the socket-io should fix the issue.
So the issue isn't actually with mixpanel SDK, but maybe a disclaimer about this could be nice in the setup doc
@badoualy Yes I have also used socket io library so after removing json from socket io it is working fine
implementation ('io.socket:socket.io-client:2.1.0'){
exclude group: 'org.json', module: 'json'
}
Thanks for the help @badoualy
Thanks guys for bringing this up and finding a solution. I've added this issue to the FAQ section of our documentation.
An exception is thrown when calling set on people SDK version: 6.5.2
In the mean time I tried to bypass by using
unset
on all properties, thensetOnceMap