diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java index d71535c2..129868fa 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java @@ -17,13 +17,13 @@ import com.onesignal.OSSubscriptionStateChanges; import com.onesignal.OneSignal; import com.onesignal.OneSignal.EmailUpdateError; -import com.onesignal.OneSignal.EmailUpdateHandler; import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; @@ -160,6 +160,12 @@ private void setAppId(MethodCall call, Result reply) { } private void addObservers() { + // Clean observers before setting, avoid being call twice + OneSignal.removeSubscriptionObserver(this); + OneSignal.removeEmailSubscriptionObserver(this); + OneSignal.removeSMSSubscriptionObserver(this); + OneSignal.removePermissionObserver(this); + OneSignal.addSubscriptionObserver(this); OneSignal.addEmailSubscriptionObserver(this); OneSignal.addSMSSubscriptionObserver(this); @@ -225,28 +231,7 @@ private void getDeviceState(Result reply) { private void postNotification(MethodCall call, final Result reply) { JSONObject json = new JSONObject((Map) call.arguments); - OneSignal.postNotification(json, new OneSignal.PostNotificationResponseHandler() { - @Override - public void onSuccess(JSONObject response) { - try { - replySuccess(reply, OneSignalSerializer.convertJSONObjectToHashMap(response)); - } catch (JSONException e) { - replyError(reply, "OneSignal", "Encountered an error attempting to deserialize server response: " + e.getMessage(), null); - } - } - - @Override - public void onFailure(final JSONObject response) { - try { - replyError(reply, "OneSignal", - "Encountered an error attempting to post notification: " + response.toString(), - OneSignalSerializer.convertJSONObjectToHashMap(response)); - } catch (JSONException e) { - OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, - "Encountered an error attempting to deserialize server response: " + e.getMessage()); - } - } - }); + OneSignal.postNotification(json, new OSFlutterPostNotificationHandler(flutterRegistrar, channel, reply, "postNotification")); } private void promptLocation(Result reply) { @@ -263,80 +248,22 @@ private void setEmail(MethodCall call, final Result reply) { String email = call.argument("email"); String emailAuthHashToken = call.argument("emailAuthHashToken"); - OneSignal.setEmail(email, emailAuthHashToken, new EmailUpdateHandler() { - @Override - public void onSuccess() { - replySuccess(reply, null); - } - - @Override - public void onFailure(EmailUpdateError error) { - replyError(reply, "OneSignal", - "Encountered an error setting email: " + error.getMessage(), - null); - } - }); + OneSignal.setEmail(email, emailAuthHashToken, new OSFlutterEmailHandler(flutterRegistrar, channel, reply, "setEmail")); } private void logoutEmail(final Result reply) { - OneSignal.logoutEmail(new EmailUpdateHandler() { - @Override - public void onSuccess() { - replySuccess(reply, null); - } - - @Override - public void onFailure(EmailUpdateError error) { - replyError(reply, "OneSignal", - "Encountered an error loggoing out of email: " + error.getMessage(), - null); - } - }); + OneSignal.logoutEmail(new OSFlutterEmailHandler(flutterRegistrar, channel, reply, "logoutEmail")); } private void setSMSNumber(MethodCall call, final Result reply) { String smsNumber = call.argument("smsNumber"); String smsAuthHashToken = call.argument("smsAuthHashToken"); - OneSignal.setSMSNumber(smsNumber, smsAuthHashToken, new OneSignal.OSSMSUpdateHandler() { - @Override - public void onSuccess(JSONObject result) { - try { - replySuccess(reply, OneSignalSerializer.convertJSONObjectToHashMap(result)); - } catch (JSONException e) { - OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, - "Encountered an error attempting to deserialize server response for setSMSNumber: " + e.getMessage()); - } - } - - @Override - public void onFailure(OneSignal.OSSMSUpdateError error) { - replyError(reply, "OneSignal", - "Encountered an error setting SMS Number: " + error.getMessage(), - null); - } - }); + OneSignal.setSMSNumber(smsNumber, smsAuthHashToken, new OSFlutterSMSHandler(flutterRegistrar, channel, reply, "setSMSNumber")); } private void logoutSMSNumber(final Result reply) { - OneSignal.logoutSMSNumber(new OneSignal.OSSMSUpdateHandler() { - @Override - public void onSuccess(JSONObject result) { - try { - replySuccess(reply, OneSignalSerializer.convertJSONObjectToHashMap(result)); - } catch (JSONException e) { - OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, - "Encountered an error attempting to deserialize server response for logoutSMSNumber: " + e.getMessage()); - } - } - - @Override - public void onFailure(OneSignal.OSSMSUpdateError error) { - replyError(reply, "OneSignal", - "Encountered an error logging out SMS number: " + error.getMessage(), - null); - } - }); + OneSignal.logoutSMSNumber(new OSFlutterSMSHandler(flutterRegistrar, channel, reply, "logoutSMSNumber")); } private void setLanguage(MethodCall call, final Result result) { @@ -355,45 +282,11 @@ private void setExternalUserId(MethodCall call, final Result result) { if (authHashToken != null && authHashToken.length() == 0) authHashToken = null; - OneSignal.setExternalUserId(externalUserId, authHashToken, new OneSignal.OSExternalUserIdUpdateCompletionHandler() { - @Override - public void onSuccess(JSONObject results) { - try { - replySuccess(result, OneSignalSerializer.convertJSONObjectToHashMap(results)); - } catch (JSONException e) { - OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, - "Encountered an error attempting to deserialize server response for setExternalUserId: " + e.getMessage()); - } - } - - @Override - public void onFailure(OneSignal.ExternalIdError error) { - replyError(result, "OneSignal", - "Encountered an error setting external id: " + error.getMessage(), - null); - } - }); + OneSignal.setExternalUserId(externalUserId, authHashToken, new OSFlutterExternalUserIdHandler(flutterRegistrar, channel, result, "setExternalUserId")); } private void removeExternalUserId(final Result result) { - OneSignal.removeExternalUserId(new OneSignal.OSExternalUserIdUpdateCompletionHandler() { - @Override - public void onSuccess(JSONObject results) { - try { - replySuccess(result, OneSignalSerializer.convertJSONObjectToHashMap(results)); - } catch (JSONException e) { - OneSignal.onesignalLog(OneSignal.LOG_LEVEL.ERROR, - "Encountered an error attempting to deserialize server response for removeExternalUserId: " + e.getMessage()); - } - } - - @Override - public void onFailure(OneSignal.ExternalIdError error) { - replyError(result, "OneSignal", - "Encountered an error removing external id: " + error.getMessage(), - null); - } - }); + OneSignal.removeExternalUserId(new OSFlutterExternalUserIdHandler(flutterRegistrar, channel, result, "removeExternalUserId")); } private void initNotificationOpenedHandlerParams() { @@ -503,4 +396,140 @@ public void notificationWillShowInForeground(OSNotificationReceivedEvent notific } } + static class OSFlutterEmailHandler extends OSFlutterHandler + implements OneSignal.EmailUpdateHandler { + + OSFlutterEmailHandler(PluginRegistry.Registrar flutterRegistrar, MethodChannel channel, Result res, String methodName) { + super(flutterRegistrar, channel, res, methodName); + } + + @Override + public void onSuccess() { + if (this.replySubmitted.getAndSet(true)) { + OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "OneSignal " + methodName + " handler called twice, ignoring!"); + return; + } + + replySuccess(result, null); + } + + @Override + public void onFailure(EmailUpdateError error) { + if (this.replySubmitted.getAndSet(true)) + return; + + replyError(result, "OneSignal", + "Encountered an error when " + methodName + ": " + error.getMessage(), + null); + } + } + + static class OSFlutterSMSHandler extends OSFlutterHandler + implements OneSignal.OSSMSUpdateHandler { + + OSFlutterSMSHandler(PluginRegistry.Registrar flutterRegistrar, MethodChannel channel, Result res, String methodName) { + super(flutterRegistrar, channel, res, methodName); + } + + @Override + public void onSuccess(JSONObject results) { + if (this.replySubmitted.getAndSet(true)) { + OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "OneSignal " + methodName + " handler called twice, ignoring! response: " + results); + return; + } + + try { + replySuccess(result, OneSignalSerializer.convertJSONObjectToHashMap(results)); + } catch (JSONException e) { + replyError(result, "OneSignal", "Encountered an error attempting to deserialize server response for " + methodName + ": " + e.getMessage(), null); + } + } + + @Override + public void onFailure(OneSignal.OSSMSUpdateError error) { + if (this.replySubmitted.getAndSet(true)) + return; + + replyError(result, "OneSignal", "Encountered an error when " + methodName + " (" + error.getType() + "): " + error.getMessage(), null); + } + } + + static class OSFlutterExternalUserIdHandler extends OSFlutterHandler + implements OneSignal.OSExternalUserIdUpdateCompletionHandler { + + OSFlutterExternalUserIdHandler(PluginRegistry.Registrar flutterRegistrar, MethodChannel channel, Result res, String methodName) { + super(flutterRegistrar, channel, res, methodName); + } + + @Override + public void onSuccess(JSONObject results) { + if (this.replySubmitted.getAndSet(true)) { + OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "OneSignal " + methodName + " handler called twice, ignoring! response: " + results); + return; + } + + try { + replySuccess(result, OneSignalSerializer.convertJSONObjectToHashMap(results)); + } catch (JSONException e) { + replyError(result, "OneSignal", "Encountered an error attempting to deserialize server response for " + methodName + ": " + e.getMessage(), null); + } + } + + @Override + public void onFailure(OneSignal.ExternalIdError error) { + if (this.replySubmitted.getAndSet(true)) + return; + + replyError(result, "OneSignal", "Encountered an error when " + methodName + " (" + error.getType() + "): " + error.getMessage(), null); + } + } + + static class OSFlutterPostNotificationHandler extends OSFlutterHandler + implements OneSignal.PostNotificationResponseHandler { + + OSFlutterPostNotificationHandler(PluginRegistry.Registrar flutterRegistrar, MethodChannel channel, Result res, String methodName) { + super(flutterRegistrar, channel, res, methodName); + } + + @Override + public void onSuccess(JSONObject results) { + if (this.replySubmitted.getAndSet(true)) { + OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "OneSignal " + methodName + " handler called twice, ignoring! response: " + results); + return; + } + + try { + replySuccess(result, OneSignalSerializer.convertJSONObjectToHashMap(results)); + } catch (JSONException e) { + replyError(result, "OneSignal", "Encountered an error attempting to deserialize server response for " + methodName + ": " + e.getMessage(), null); + } + } + + @Override + public void onFailure(JSONObject response) { + if (this.replySubmitted.getAndSet(true)) { + OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "OneSignal " + methodName + " handler called twice, ignoring! response: " + response); + return; + } + + try { + replyError(result, "OneSignal", "Encountered an error attempting to " + methodName + " " + response.toString(), OneSignalSerializer.convertJSONObjectToHashMap(response)); + } catch (JSONException jsonException) { + replyError(result, "OneSignal", "Encountered an error attempting to deserialize server response " + methodName + " " + jsonException.getMessage(), null); + } + } + } + + static class OSFlutterHandler extends FlutterRegistrarResponder { + protected final Result result; + protected final String methodName; + protected final AtomicBoolean replySubmitted = new AtomicBoolean(false); + + OSFlutterHandler(PluginRegistry.Registrar flutterRegistrar, MethodChannel channel, Result res, String methodName) { + this.flutterRegistrar = flutterRegistrar; + this.channel = channel; + this.result = res; + this.methodName = methodName; + } + } }