تنفيذ Google Analytics for Firebase في Android Webview

1 المقدمة

آخر تحديث: 2022-02-03

8cef5cc6581b73d0.png

ما ستتعلمه

  • كيفية إنشاء عرض ويب بسيط جدًا على Android
  • كيفية إرسال أحداث Webview إلى Firebase

ماذا ستحتاج

  • تم تنفيذ مشروع Firebase مع Analytics SDK
  • أندرويد ستوديو الإصدار 4.2+.
  • محاكي Android مع Android 5.0+.
  • الإلمام بلغة البرمجة جافا.
  • الإلمام بلغة البرمجة جافا سكريبت.

2. قم بإنشاء عرض ويب بسيط على الويب في Android

إضافة عرض ويب في تخطيط النشاط

لإضافة WebView إلى تطبيقك في التخطيط، قم بإضافة التعليمة البرمجية التالية إلى ملف XML لتخطيط نشاطك:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".WebActivity"
>
  <WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  />
</androidx.constraintlayout.widget.ConstraintLayout>;

إضافة عرض ويب في onCreate()

لتحميل صفحة ويب في WebView، استخدم LoadUrl(). يجب إنشاء Webview على النشاط الأسود، على سبيل المثال سأقوم بتنفيذ ذلك على طريقة onCreate:

public class WebActivity extends AppCompatActivity {
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);
        // Navigate to site
        myWebView.loadUrl("https://bittererhu.glitch.me");
 }
}

ولكن قبل أن ينجح هذا الأمر، يجب أن يتمتع تطبيقك بإمكانية الوصول إلى الإنترنت. للوصول إلى الإنترنت، اطلب إذن الإنترنت في ملف البيان الخاص بك. على سبيل المثال:

<uses-permission android:name="android.permission.INTERNET" />

هذا هو كل ما تحتاجه لعرض WebView الأساسي الذي يعرض صفحة ويب.

استخدام جافا سكريبت في Webviews

إذا كانت صفحة الويب التي تخطط لتحميلها في WebView الخاص بك تستخدم JavaScript، فيجب عليك تمكين JavaScript لـ WebView الخاص بك. بمجرد تمكين JavaScript، يمكنك أيضًا إنشاء واجهات بين رمز التطبيق الخاص بك ورمز JavaScript الخاص بك.

يتم تعطيل JavaScript في WebView افتراضيًا. يمكنك تمكينه من خلال إعدادات WebSettings المرفقة بـ WebView الخاص بك. يمكنك استرداد إعدادات WebSettings باستخدام getSettings()، ثم تمكين JavaScript باستخدام setJavaScriptEnabled().

على سبيل المثال:

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

النشاط المحدث :

public class WebActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);
        WebView myWebView = (WebView) findViewById(R.id.webview);
        if(myWebView != null) {
            WebSettings webSettings = myWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
        }
        // Navigate to site
        myWebView.loadUrl("https://bittererhu.glitch.me");
  }
}

be627fcc51a6179f.png

3. تنفيذ واجهة جافا سكريبت الجسرية

معالج جافا سكريبت

تتمثل الخطوة الأولى في استخدام Google Analytics في WebView في إنشاء وظائف JavaScript لإعادة توجيه الأحداث وخصائص المستخدم إلى التعليمات البرمجية الأصلية. يوضح المثال التالي كيفية القيام بذلك بطريقة متوافقة مع التعليمات البرمجية الأصلية لكل من Android وApple:

في هذا المثال، قمت بإنشاء ملف Javascript باسم script.js والذي يتضمن ما يلي:

function logEvent(name, params) {
  if (!name) {
    return;
  }
  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'logEvent',
      name: name,
      parameters: params
    };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}


function setUserProperty(name, value) {
  if (!name || !value) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.setUserProperty(name, value);
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'setUserProperty',
      name: name,
      value: value
   };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}

الواجهة الأصلية

لاستدعاء كود Android الأصلي من JavaScript، قم بتنفيذ فئة باستخدام الأساليب المميزة @JavaScriptInterface : في المثال أدناه قمت بإنشاء فئة Java جديدة تسمى: AnalyticsWebInterfcae.java:

public class AnalyticsWebInterface {

    public static final String TAG = "AnalyticsWebInterface";
    private FirebaseAnalytics mAnalytics;

    public AnalyticsWebInterface(Context context) {
        mAnalytics = FirebaseAnalytics.getInstance(context);
    }

    @JavascriptInterface
    public void logEvent(String name, String jsonParams) {
        LOGD("logEvent:" + name);
        mAnalytics.logEvent(name, bundleFromJson(jsonParams));
    }

    @JavascriptInterface
    public void setUserProperty(String name, String value) {
        LOGD("setUserProperty:" + name);
        mAnalytics.setUserProperty(name, value);
    }

    private void LOGD(String message) {
        // Only log on debug builds, for privacy
        if (BuildConfig.DEBUG) {
            Log.d(TAG, message);
        }
    }

    private Bundle bundleFromJson(String json) {
        // ...
    }
}

Once you have created the native interface, register it with your WebView so that it is visible to JavaScript code running in the WebView:

// Only add the JavaScriptInterface on API version JELLY_BEAN_MR1 and above, due to
// security concerns, see link below for more information:
// https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    mWebView.addJavascriptInterface(
            new AnalyticsWebInterface(this), AnalyticsWebInterface.TAG);
} else {
    Log.w(TAG, "Not adding JavaScriptInterface, API Version: " + Build.VERSION.SDK_INT);
}

الكود النهائي :

// [START analytics_web_interface]
public class AnalyticsWebInterface {

    public static final String TAG = "AnalyticsWebInterface";
    private FirebaseAnalytics mAnalytics;

    public AnalyticsWebInterface(Context context) {
        mAnalytics = FirebaseAnalytics.getInstance(context);
    }
    @JavascriptInterface
    public void logEvent(String name, String jsonParams) {
        LOGD("logEvent:" + name);
        mAnalytics.logEvent(name, bundleFromJson(jsonParams));
    }
    @JavascriptInterface
    public void setUserProperty(String name, String value) {
        LOGD("setUserProperty:" + name);
        mAnalytics.setUserProperty(name, value);
    }
    private void LOGD(String message) {
        // Only log on debug builds, for privacy
        if (BuildConfig.DEBUG) {
            Log.d(TAG, message);
        }
    }
    private Bundle bundleFromJson(String json) {
        // [START_EXCLUDE]
        if (TextUtils.isEmpty(json)) {
            return new Bundle();
        }

        Bundle result = new Bundle();
        try {
            JSONObject jsonObject = new JSONObject(json);
            Iterator<String> keys = jsonObject.keys();

            while (keys.hasNext()) {
                String key = keys.next();
                Object value = jsonObject.get(key);
                if (value instanceof String) {
                    result.putString(key, (String) value);
                } else if (value instanceof Integer) {
                    result.putInt(key, (Integer) value);
                } else if (value instanceof Double) {
                    result.putDouble(key, (Double) value);
                } else {
                    Log.w(TAG, "Value for key " + key + " not one of [String, Integer, Double]");
                }
            }
        } catch (JSONException e) {
            Log.w(TAG, "Failed to parse JSON, returning empty Bundle.", e);
            return new Bundle();
        }
        return result;
        // [END_EXCLUDE]
    }

لقد قمت الآن بإعداد واجهة Javascript، وأنت الآن جاهز لبدء إرسال الأحداث التحليلية.

4. إرسال الأحداث من خلال الواجهة

كما ترون هنا، فإن عرض الويب الخاص بي بسيط للغاية ويحتوي على ثلاثة أزرار، اثنان منهما سيقومان بتسجيل حدث والآخر سيقومان بتسجيل خاصية المستخدم:

7a00ed1192151b19.png

بمجرد النقر على الأزرار، سيتم استدعاء ملف "script.js" الخاص بي وتنفيذ التعليمات البرمجية التالية:

document.getElementById("event1").addEventListener("click", function() {
    console.log("event1");
    logEvent("event1", { foo: "bar", baz: 123 });
});

document.getElementById("event2").addEventListener("click", function() {
  console.log("event2");
    logEvent("event2", { size: 123.456 });
});

document.getElementById("userprop").addEventListener("click", function() {
    console.log("userprop");
    setUserProperty("userprop", "custom_value");
});

ملف script.js النهائي:

/* If you're feeling fancy you can add interactivity 
    to your site with Javascript */

// prints "hi" in the browser's dev tools console
console.log("hi");

// [START log_event]
function logEvent(name, params) {
  if (!name) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'logEvent',
      name: name,
      parameters: params
    };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}
// [END log_event]

// [START set_user_property]
function setUserProperty(name, value) {
  if (!name || !value) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.setUserProperty(name, value);
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'setUserProperty',
      name: name,
      value: value
   };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}
// [END set_user_property]

document.getElementById("event1").addEventListener("click", function() {
    console.log("event1");
    logEvent("event1", { foo: "bar", baz: 123 });
});

document.getElementById("event2").addEventListener("click", function() {
  console.log("event2");
    logEvent("event2", { size: 123.456 });
});

document.getElementById("userprop").addEventListener("click", function() {
    console.log("userprop");
    setUserProperty("userprop", "custom_value");
});

هذه هي الطريقة الأساسية لإرسال الأحداث إلى Analytics

5. تصحيح أحداث Webview في Firebase

يعمل تصحيح أخطاء أحداث Webview في تطبيقك بنفس طريقة تصحيح أخطاء أي جزء أصلي من SDK الخاص بك:

لتمكين وضع التصحيح، يرجى استخدام الأوامر التالية في وحدة تحكم Android studio الخاصة بك:

adb shell setprop debug.firebase.analytics.app package_name

بمجرد الانتهاء، يمكنك اختبار ورؤية أحداث Webview الخاصة بك وهي تنبض بالحياة:

d230debf4ccfddad.png

6. تهانينا

تهانينا، لقد نجحت في إنشاء عرض ويب في تطبيق Android الخاص بك. يمكنك إرسال وقياس أحداث مسار التحويل الرئيسية في تطبيقك والتي تحدث عبر عروض الويب. ولتحقيق أقصى استفادة من هذا، نقترح أيضًا الاتصال ببرنامج إعلانات Google واستيراد هذه الأحداث كتحويلات.

لقد تعلمت

  • كيفية إرسال أحداث Webview إلى Firebase
  • كيفية إعداد وإنشاء عرض ويب بسيط في Android

المستندات المرجعية