From 9441f17c9b8543652cf83f0d91498a29eade49d7 Mon Sep 17 00:00:00 2001
From: FalsinSoft <falsinsoft@gmail.com>
Date: Mon, 7 Dec 2020 15:13:20 +0100
Subject: [PATCH] Improved tool for manage consent form

---
 Documentation/index.html                      |  43 +++++-
 .../QAndroidUserMessagingPlatform.cpp         |  40 +++++-
 .../QAndroidUserMessagingPlatform.h           |  26 ++--
 .../AndroidUserMessagingPlatform.java         | 132 ++++++++----------
 .../tools/AndroidUserMessagingPlatform.qml    |  64 ++++++---
 README.md                                     |   3 +
 6 files changed, 204 insertions(+), 104 deletions(-)

diff --git a/Documentation/index.html b/Documentation/index.html
index e070a68..652cc69 100644
--- a/Documentation/index.html
+++ b/Documentation/index.html
@@ -55,6 +55,7 @@
 									<li><a href="#GoogleAccount">GoogleAccount</a></li>
 									<li><a href="#GoogleDrive">GoogleDrive</a></li>
 									<li><a href="#Sharing">Sharing</a></li>
+									<li><a href="#UserMessagingPlatform">UserMessagingPlatform</a></li>
 									<li><a href="#System">System</a></li>
 								</ul>					
 							</nav>
@@ -87,7 +88,8 @@
     QTAT_PLAY_STORE \
     QTAT_GOOGLE_ACCOUNT \
     QTAT_GOOGLE_DRIVE \
-    QTAT_SHARING</pre>
+    QTAT_SHARING \
+    QTAT_USER_MESSAGING_PLATFORM</pre>
 	</li>
 								<li>In the <i>main()</i> body insert the call for initialize the library<br />
 	  <pre class="prettyprint">QtAndroidTools::initializeQmlTools();</pre>
@@ -704,6 +706,45 @@ QtAndroidSharing.getReceivedMultipleSharedBinaryData()</pre>
 						  <pre>QtAndroidSharing.shareFile(fileAvailable, mimeType, filePath)</pre>
 						  <p>In case the user want the file you have to set the <i>fileAvailable</i> as true and provide the other params. In the opposite case (the user refused) you have to call this function by set the first param as false without provide the other params.</p>
 						</div>						
+						<div class="section-txt" id="UserMessagingPlatform">
+							<h3>UserMessagingPlatform</h3>
+							<p>Under the Google <a href="https://www.google.com/about/company/user-consent-policy/" target="_blank">EU User Consent Policy</a>, you must make certain disclosures to your users in the European Economic Area (EEA) along with the UK and obtain their consent to use cookies or other local storage, where legally required, and to use personal data (such as AdID) to serve ads. This policy reflects the requirements of the EU ePrivacy Directive and the General Data Protection Regulation (GDPR).</p>
+							<p>This tool support the use of the UMP SDK but for a clear explanation about how to use this SDK and how to configure the consent form you have to read the official guide <a href="https://developers.google.com/admob/ump/android/quick-start" target="_blank">here</a>. At first you must to request the consent form that can be or not be available for the zone your current user is:</p>
+							<pre class="prettyprint">Connections {
+    target: QtAndroidUserMessagingPlatform
+    function onConsentFormRequestResult(eventId)
+    {
+        switch(eventId)
+        {
+            case QtAndroidUserMessagingPlatform.CONSENT_FORM_INFO_UPDATE_FAILURE:
+                ....
+                break;
+            case QtAndroidUserMessagingPlatform.CONSENT_FORM_NOT_AVAILABLE:
+                ....
+                break;
+            case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_SUCCESS:
+                ....
+                break;
+            case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_FAILURE:
+                ....
+                break;
+        }
+}
+		
+QtAndroidUserMessagingPlatform.requestConsentForm()</pre>
+							
+							<p>Once request process finish the signal <i>consentFormRequestResult()</i> is emitted with the results. Any event different from CONSENT_FORM_LOAD_SUCCESS means the form is not available for various reasons. Once obtained the form is necessary to check if it must be showed to the user. You can get such information as follow:</p>
+							<pre>QtAndroidUserMessagingPlatform.consentStatus()</pre>
+							<p>Possible returned values are:</p>
+							<pre>QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN
+QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED
+QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED
+QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED</pre>
+							<p>If the status is different from CONSENT_FORM_STATUS_REQUIRED you don't need to show the form. On the contrary, in case of form required or if the user want to change his preferences you can show the form using the call:</p>
+							<pre>QtAndroidUserMessagingPlatform.showConsentForm()</pre>
+							<p>The event <i>consentFormClosed()</i> will inform you when the user closed the form and your app is ready to go. After the user accepted the form some data will be saved in the device and the form will not be required anymore. However if you want to reset these data for restart from scratch you can use the call:</p>
+							<pre>QtAndroidUserMessagingPlatform.resetConsentInformation()</pre>
+							<p>This will clean all saved data.</p>
 						<div class="section-txt" id="System">
 							<h3>System</h3>
 							<p>Currently this tool export only the system paths.</p>
diff --git a/QtAndroidTools/QAndroidUserMessagingPlatform.cpp b/QtAndroidTools/QAndroidUserMessagingPlatform.cpp
index 6d62091..f9b3eee 100644
--- a/QtAndroidTools/QAndroidUserMessagingPlatform.cpp
+++ b/QtAndroidTools/QAndroidUserMessagingPlatform.cpp
@@ -34,7 +34,8 @@ QAndroidUserMessagingPlatform::QAndroidUserMessagingPlatform() : m_javaUserMessa
     if(m_javaUserMessagingPlatform.isValid())
     {
         const JNINativeMethod jniMethod[] = {
-            {"consentFormShowResult", "(I)V", reinterpret_cast<void *>(&QAndroidUserMessagingPlatform::deviceConsentFormShowResult)},
+            {"consentFormRequestResult", "(I)V", reinterpret_cast<void*>(&QAndroidUserMessagingPlatform::deviceConsentFormRequestResult)},
+            {"consentFormClosed", "()V", reinterpret_cast<void*>(&QAndroidUserMessagingPlatform::deviceConsentFormClosed)},
         };
         QAndroidJniEnvironment jniEnv;
         jclass objectClass;
@@ -58,25 +59,54 @@ QAndroidUserMessagingPlatform* QAndroidUserMessagingPlatform::instance()
     return m_pInstance;
 }
 
-void QAndroidUserMessagingPlatform::deviceConsentFormShowResult(JNIEnv *env, jobject thiz, int eventId)
+void QAndroidUserMessagingPlatform::deviceConsentFormRequestResult(JNIEnv *env, jobject thiz, int eventId)
 {
     Q_UNUSED(env)
     Q_UNUSED(thiz)
 
     if(m_pInstance != nullptr)
     {
-        Q_EMIT m_pInstance->consentFormShowResult(eventId);
+        Q_EMIT m_pInstance->consentFormRequestResult(eventId);
     }
 }
 
-void QAndroidUserMessagingPlatform::showConsentFormIfRequired()
+void QAndroidUserMessagingPlatform::deviceConsentFormClosed(JNIEnv *env, jobject thiz)
+{
+    Q_UNUSED(env)
+    Q_UNUSED(thiz)
+
+    if(m_pInstance != nullptr)
+    {
+        Q_EMIT m_pInstance->consentFormClosed();
+    }
+}
+
+void QAndroidUserMessagingPlatform::requestConsentForm()
 {
     if(m_javaUserMessagingPlatform.isValid())
     {
-        m_javaUserMessagingPlatform.callMethod<void>("showConsentFormIfRequired");
+        m_javaUserMessagingPlatform.callMethod<void>("requestConsentForm");
     }
 }
 
+int QAndroidUserMessagingPlatform::consentStatus()
+{
+    if(m_javaUserMessagingPlatform.isValid())
+    {
+        return m_javaUserMessagingPlatform.callMethod<jint>("consentStatus");
+    }
+    return CONSENT_FORM_STATUS_UNKNOWN;
+}
+
+bool QAndroidUserMessagingPlatform::showConsentForm()
+{
+    if(m_javaUserMessagingPlatform.isValid())
+    {
+        return m_javaUserMessagingPlatform.callMethod<jboolean>("showConsentForm");
+    }
+    return false;
+}
+
 void QAndroidUserMessagingPlatform::resetConsentInformation()
 {
     if(m_javaUserMessagingPlatform.isValid())
diff --git a/QtAndroidTools/QAndroidUserMessagingPlatform.h b/QtAndroidTools/QAndroidUserMessagingPlatform.h
index 47c2438..1d78a2e 100644
--- a/QtAndroidTools/QAndroidUserMessagingPlatform.h
+++ b/QtAndroidTools/QAndroidUserMessagingPlatform.h
@@ -30,35 +30,43 @@ class QAndroidUserMessagingPlatform : public QObject
 {
     Q_DISABLE_COPY(QAndroidUserMessagingPlatform)
     Q_ENUMS(CONSENT_STATUS)
+    Q_ENUMS(REQUEST_RESULT)
     Q_OBJECT
 
     QAndroidUserMessagingPlatform();
 
 public:
     enum CONSENT_STATUS
+    {
+        CONSENT_FORM_STATUS_UNKNOWN = 0,
+        CONSENT_FORM_STATUS_REQUIRED = 1,
+        CONSENT_FORM_STATUS_NOT_REQUIRED = 2,
+        CONSENT_FORM_STATUS_OBTAINED = 3,
+    };
+    enum REQUEST_RESULT
     {
         CONSENT_FORM_INFO_UPDATE_FAILURE = 0,
         CONSENT_FORM_NOT_AVAILABLE = 1,
-        CONSENT_FORM_STATUS_UNKNOWN = 2,
-        CONSENT_FORM_STATUS_REQUIRED = 3,
-        CONSENT_FORM_STATUS_NOT_REQUIRED = 4,
-        CONSENT_FORM_STATUS_OBTAINED = 5,
-        CONSENT_FORM_LOAD_FAILURE = 6,
-        CONSENT_FORM_DISMISSED = 7
+        CONSENT_FORM_LOAD_SUCCESS = 2,
+        CONSENT_FORM_LOAD_FAILURE = 3
     };
 
     static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine);
     static QAndroidUserMessagingPlatform* instance();
 
-    Q_INVOKABLE void showConsentFormIfRequired();
+    Q_INVOKABLE void requestConsentForm();
+    Q_INVOKABLE int consentStatus();
+    Q_INVOKABLE bool showConsentForm();
     Q_INVOKABLE void resetConsentInformation();
 
 Q_SIGNALS:
-    void consentFormShowResult(int eventId);
+    void consentFormRequestResult(int eventId);
+    void consentFormClosed();
 
 private:
     const QAndroidJniObject m_javaUserMessagingPlatform;
     static QAndroidUserMessagingPlatform *m_pInstance;
 
-    static void deviceConsentFormShowResult(JNIEnv *env, jobject thiz, int eventId);
+    static void deviceConsentFormRequestResult(JNIEnv *env, jobject thiz, int eventId);
+    static void deviceConsentFormClosed(JNIEnv *env, jobject thiz);
 };
diff --git a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidUserMessagingPlatform.java b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidUserMessagingPlatform.java
index 8bf8b2c..1f82361 100644
--- a/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidUserMessagingPlatform.java
+++ b/QtAndroidTools/src/com/falsinsoft/qtandroidtools/AndroidUserMessagingPlatform.java
@@ -40,6 +40,7 @@ public class AndroidUserMessagingPlatform
     private final ConsentInformation mConsentInformation;
     private final ConsentListener mConsentListener;
     private final Activity mActivityInstance;
+    private int mConsentStatus = ConsentInformation.ConsentStatus.UNKNOWN;
     private ConsentForm mConsentForm = null;
 
     public AndroidUserMessagingPlatform(Activity activityInstance)
@@ -49,42 +50,7 @@ public class AndroidUserMessagingPlatform
         mActivityInstance = activityInstance;
     }
 
-    public void showConsentFormIfRequired()
-    {
-        requestConsentInfoUpdate();
-    }
-
-    public void resetConsentInformation()
-    {
-        mConsentInformation.reset();
-    }
-
-    private void requestConsentInfoUpdate()
-    {
-        final ConsentRequestParameters params = new ConsentRequestParameters.Builder().build();
-        mConsentInformation.requestConsentInfoUpdate(mActivityInstance, params, mConsentListener, mConsentListener);
-    }
-
-    private void loadConsentForm()
-    {
-        if(mConsentInformation.isConsentFormAvailable())
-        {
-            mActivityInstance.runOnUiThread(new Runnable()
-            {
-                @Override
-                public void run()
-                {
-                    UserMessagingPlatform.loadConsentForm(mActivityInstance, mConsentListener, mConsentListener);
-                }
-            });
-        }
-        else
-        {
-            consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
-        }
-    }
-
-    private void showConsentForm()
+    public boolean showConsentForm()
     {
         if(mConsentForm != null)
         {
@@ -96,11 +62,45 @@ public class AndroidUserMessagingPlatform
                     mConsentForm.show(mActivityInstance, mConsentListener);
                 }
             });
+
+            return true;
         }
-        else
+
+        return false;
+    }
+
+    public void resetConsentInformation()
+    {
+        mConsentInformation.reset();
+    }
+
+    public void requestConsentForm()
+    {
+        final ConsentRequestParameters params = new ConsentRequestParameters.Builder().build();
+        mConsentInformation.requestConsentInfoUpdate(mActivityInstance, params, mConsentListener, mConsentListener);
+    }
+
+    public int consentStatus()
+    {
+        int status = CONSENT_FORM_STATUS_UNKNOWN;
+
+        switch(mConsentStatus)
         {
-            consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
+            case ConsentInformation.ConsentStatus.REQUIRED:
+                status = CONSENT_FORM_STATUS_REQUIRED;
+                break;
+            case ConsentInformation.ConsentStatus.NOT_REQUIRED:
+                status = CONSENT_FORM_STATUS_NOT_REQUIRED;
+                break;
+            case ConsentInformation.ConsentStatus.OBTAINED:
+                status = CONSENT_FORM_STATUS_OBTAINED;
+                break;
+            case ConsentInformation.ConsentStatus.UNKNOWN:
+                status = CONSENT_FORM_STATUS_UNKNOWN;
+                break;
         }
+
+        return status;
     }
 
     private class ConsentListener implements ConsentInformation.OnConsentInfoUpdateSuccessListener,
@@ -114,69 +114,59 @@ public class AndroidUserMessagingPlatform
         {
             if(mConsentInformation.isConsentFormAvailable())
             {
-                loadConsentForm();
+                mActivityInstance.runOnUiThread(new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        UserMessagingPlatform.loadConsentForm(mActivityInstance, mConsentListener, mConsentListener);
+                    }
+                });
             }
             else
             {
-                consentFormShowResult(CONSENT_FORM_NOT_AVAILABLE);
+                consentFormRequestResult(CONSENT_FORM_NOT_AVAILABLE);
             }
         }
 
         @Override
         public void onConsentInfoUpdateFailure(FormError formError)
         {
-            consentFormShowResult(CONSENT_FORM_INFO_UPDATE_FAILURE);
+            consentFormRequestResult(CONSENT_FORM_INFO_UPDATE_FAILURE);
         }
 
         @Override
         public void onConsentFormLoadSuccess(ConsentForm consentForm)
         {
-            final int consentStatus = mConsentInformation.getConsentStatus();
-
+            mConsentStatus = mConsentInformation.getConsentStatus();
             mConsentForm = consentForm;
-            if(consentStatus == ConsentInformation.ConsentStatus.REQUIRED)
-            {
-                showConsentForm();
-            }
-            else
-            {
-                int eventId = CONSENT_FORM_STATUS_UNKNOWN;
 
-                switch(consentStatus)
-                {
-                    case ConsentInformation.ConsentStatus.NOT_REQUIRED:
-                        eventId = CONSENT_FORM_STATUS_NOT_REQUIRED;
-                        break;
-                    case ConsentInformation.ConsentStatus.OBTAINED:
-                        eventId = CONSENT_FORM_STATUS_OBTAINED;
-                        break;
-                }
-
-                consentFormShowResult(eventId);
-            }
+            consentFormRequestResult(CONSENT_FORM_LOAD_SUCCESS);
         }
 
         @Override
         public void onConsentFormLoadFailure(FormError formError)
         {
-            consentFormShowResult(CONSENT_FORM_LOAD_FAILURE);
+            consentFormRequestResult(CONSENT_FORM_LOAD_FAILURE);
         }
 
         @Override
         public void onConsentFormDismissed(@Nullable FormError formError)
         {
-            consentFormShowResult(CONSENT_FORM_DISMISSED);
+            consentFormClosed();
         }
     }
 
     private static final int CONSENT_FORM_INFO_UPDATE_FAILURE = 0;
     private static final int CONSENT_FORM_NOT_AVAILABLE = 1;
-    private static final int CONSENT_FORM_STATUS_UNKNOWN = 2;
-    private static final int CONSENT_FORM_STATUS_REQUIRED = 3;
-    private static final int CONSENT_FORM_STATUS_NOT_REQUIRED = 4;
-    private static final int CONSENT_FORM_STATUS_OBTAINED = 5;
-    private static final int CONSENT_FORM_LOAD_FAILURE = 6;
-    private static final int CONSENT_FORM_DISMISSED = 7;
+    private static final int CONSENT_FORM_LOAD_SUCCESS = 2;
+    private static final int CONSENT_FORM_LOAD_FAILURE = 3;
 
-    private static native void consentFormShowResult(int eventId);
+    private static final int CONSENT_FORM_STATUS_UNKNOWN = 0;
+    private static final int CONSENT_FORM_STATUS_REQUIRED = 1;
+    private static final int CONSENT_FORM_STATUS_NOT_REQUIRED = 2;
+    private static final int CONSENT_FORM_STATUS_OBTAINED = 3;
+
+    private static native void consentFormRequestResult(int eventId);
+    private static native void consentFormClosed();
 }
diff --git a/QtAndroidToolsDemo/tools/AndroidUserMessagingPlatform.qml b/QtAndroidToolsDemo/tools/AndroidUserMessagingPlatform.qml
index 7d8b4ea..528041a 100644
--- a/QtAndroidToolsDemo/tools/AndroidUserMessagingPlatform.qml
+++ b/QtAndroidToolsDemo/tools/AndroidUserMessagingPlatform.qml
@@ -9,7 +9,7 @@ Page {
 
     Connections {
         target: QtAndroidUserMessagingPlatform
-        function onConsentFormShowResult(eventId)
+        function onConsentFormRequestResult(eventId)
         {
             switch(eventId)
             {
@@ -19,26 +19,17 @@ Page {
                 case QtAndroidUserMessagingPlatform.CONSENT_FORM_NOT_AVAILABLE:
                     consentFormShowResult.text = "CONSENT_FORM_NOT_AVAILABLE";
                     break;
-                case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN:
-                    consentFormShowResult.text = "CONSENT_FORM_STATUS_UNKNOWN";
-                    break;
-                case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED:
-                    consentFormShowResult.text = "CONSENT_FORM_STATUS_REQUIRED";
-                    break;
-                case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED:
-                    consentFormShowResult.text = "CONSENT_FORM_STATUS_NOT_REQUIRED";
-                    break;
-                case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED:
-                    consentFormShowResult.text = "CONSENT_FORM_STATUS_OBTAINED";
+                case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_SUCCESS:
+                    consentFormShowResult.text = "CONSENT_FORM_LOAD_SUCCESS";
                     break;
                 case QtAndroidUserMessagingPlatform.CONSENT_FORM_LOAD_FAILURE:
                     consentFormShowResult.text = "CONSENT_FORM_LOAD_FAILURE";
                     break;
-                case QtAndroidUserMessagingPlatform.CONSENT_FORM_DISMISSED:
-                    consentFormShowResult.text = "CONSENT_FORM_DISMISSED";
-                    break;
             }
         }
+        function onConsentFormClosed()
+        {
+        }
     }
 
     Column {
@@ -46,7 +37,7 @@ Page {
         spacing: 5
 
         Label {
-            id: consentFormShowResult
+            id: consentFormRequestResult
             width: parent.width
             horizontalAlignment: Text.AlignHCenter
             font.pixelSize: 15
@@ -54,8 +45,45 @@ Page {
         }
         Button {
             anchors.horizontalCenter: parent.horizontalCenter
-            text: "showConsentFormIfRequired"
-            onClicked: QtAndroidUserMessagingPlatform.showConsentFormIfRequired()
+            text: "requestConsentForm"
+            onClicked: QtAndroidUserMessagingPlatform.requestConsentForm()
+        }
+
+        Label {
+            id: consentStatus
+            width: parent.width
+            horizontalAlignment: Text.AlignHCenter
+            font.pixelSize: 15
+            text: "-----"
+        }
+        Button {
+            anchors.horizontalCenter: parent.horizontalCenter
+            text: "consentStatus"
+            onClicked: {
+                var status = QtAndroidUserMessagingPlatform.consentStatus();
+
+                switch(eventId)
+                {
+                    case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_UNKNOWN:
+                        consentStatus.text = "CONSENT_FORM_STATUS_UNKNOWN";
+                        break;
+                    case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_REQUIRED:
+                        consentStatus.text = "CONSENT_FORM_STATUS_REQUIRED";
+                        break;
+                    case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_NOT_REQUIRED:
+                        consentStatus.text = "CONSENT_FORM_STATUS_NOT_REQUIRED";
+                        break;
+                    case QtAndroidUserMessagingPlatform.CONSENT_FORM_STATUS_OBTAINED:
+                        consentStatus.text = "CONSENT_FORM_STATUS_OBTAINED";
+                        break;
+                }
+            }
+        }
+
+        Button {
+            anchors.horizontalCenter: parent.horizontalCenter
+            text: "showConsentForm"
+            onClicked: QtAndroidUserMessagingPlatform.showConsentForm()
         }
 
         Button {
diff --git a/README.md b/README.md
index 1c23239..afddd20 100644
--- a/README.md
+++ b/README.md
@@ -52,5 +52,8 @@ Allow access to Google Drive files and folders
 **Sharing**  
 Allow to use the Android sharing operation  
 
+**UserMessagingPlatform**  
+Allow to manage consent form  
+
 **System**  
 Export methods for get some system info