Bug 1380850 - Track when Focus or Klar get installed; r?mcomella
Added a static broadcast receiver that will inform us as soon as possible of any installed packages.
Because mma methods are static, if LeanPlum is enabled, the event will be tracked even if the app was not running when the new package was installed
and as per LeanPlum's internal workings the event will be reported to the dashboard when the application resumes.
MozReview-Commit-ID: AGNsQn7LuCz
***
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -391,16 +391,25 @@
<!-- DON'T EXPORT THIS, please! An attacker could delete arbitrary files. -->
<service
android:exported="false"
android:name="org.mozilla.gecko.cleanup.FileCleanupService">
</service>
<receiver
+ android:name="org.mozilla.gecko.mma.PackageAddedReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.intent.action.PACKAGE_ADDED"/>
+ <data android:scheme="package"/>
+ </intent-filter>
+ </receiver>
+
+ <receiver
android:name="org.mozilla.gecko.PackageReplacedReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"></action>
</intent-filter>
</receiver>
<service
--- a/mobile/android/base/java/org/mozilla/gecko/mma/MmaDelegate.java
+++ b/mobile/android/base/java/org/mozilla/gecko/mma/MmaDelegate.java
@@ -39,33 +39,36 @@ public class MmaDelegate {
public static final String READER_AVAILABLE = "E_Reader_Available";
public static final String DOWNLOAD_MEDIA_SAVED_IMAGE = "E_Download_Media_Saved_Image";
public static final String CLEARED_PRIVATE_DATA = "E_Cleared_Private_Data";
public static final String SAVED_BOOKMARK = "E_Saved_Bookmark";
public static final String OPENED_BOOKMARK = "E_Opened_Bookmark";
public static final String INTERACT_WITH_SEARCH_URL_AREA = "E_Interact_With_Search_URL_Area";
public static final String SCREENSHOT = "E_Screenshot";
public static final String SAVED_LOGIN_AND_PASSWORD = "E_Saved_Login_And_Password";
- public static final String LAUNCH_BUT_NOT_DEFAULT_BROWSER = "E_Launch_But_Not_Default_Browser";
- public static final String LAUNCH_BROWSER = "E_Launch_Browser";
public static final String RESUMED_FROM_BACKGROUND = "E_Resumed_From_Background";
public static final String NEW_TAB = "E_Opened_New_Tab";
public static final String DISMISS_ONBOARDING = "E_Dismiss_Onboarding";
- public static final String CHANGED_DEFAULT_TO_FENNEC = "E_Changed_Default_To_Fennec";
+
+ private static final String LAUNCH_BUT_NOT_DEFAULT_BROWSER = "E_Launch_But_Not_Default_Browser";
+ private static final String LAUNCH_BROWSER = "E_Launch_Browser";
+ private static final String CHANGED_DEFAULT_TO_FENNEC = "E_Changed_Default_To_Fennec";
+ private static final String INSTALLED_FOCUS = "E_Just_Installed_Focus";
+ private static final String INSTALLED_KLAR = "E_Just_Installed_Klar";
- public static final String USER_ATT_FOCUS_INSTALLED = "Focus Installed";
- public static final String USER_ATT_KLAR_INSTALLED = "Klar Installed";
- public static final String USER_ATT_POCKET_INSTALLED = "Pocket Installed";
- public static final String USER_ATT_DEFAULT_BROWSER = "Default Browser";
- public static final String USER_ATT_SIGNED_IN = "Signed In Sync";
- public static final String USER_ATT_POCKET_TOP_SITES = "Pocket in Top Sites";
+ private static final String USER_ATT_FOCUS_INSTALLED = "Focus Installed";
+ private static final String USER_ATT_KLAR_INSTALLED = "Klar Installed";
+ private static final String USER_ATT_POCKET_INSTALLED = "Pocket Installed";
+ private static final String USER_ATT_DEFAULT_BROWSER = "Default Browser";
+ private static final String USER_ATT_SIGNED_IN = "Signed In Sync";
+ private static final String USER_ATT_POCKET_TOP_SITES = "Pocket in Top Sites";
- public static final String PACKAGE_NAME_KLAR = "org.mozilla.klar";
- public static final String PACKAGE_NAME_FOCUS = "org.mozilla.focus";
- public static final String PACKAGE_NAME_POCKET = "com.ideashower.readitlater.pro";
+ private static final String PACKAGE_NAME_KLAR = "org.mozilla.klar";
+ private static final String PACKAGE_NAME_FOCUS = "org.mozilla.focus";
+ private static final String PACKAGE_NAME_POCKET = "com.ideashower.readitlater.pro";
private static final String TAG = "MmaDelegate";
public static final String KEY_ANDROID_PREF_STRING_LEANPLUM_DEVICE_ID = "android.not_a_preference.leanplum.device_id";
private static final String KEY_ANDROID_PREF_BOOLEAN_FENNEC_IS_DEFAULT = "android.not_a_preference.fennec.default.browser.status";
private static final String DEBUG_LEANPLUM_DEVICE_ID = "8effda84-99df-11e7-abc4-cec278b6b50a";
@@ -126,16 +129,30 @@ public class MmaDelegate {
if (!sharedPreferences.getBoolean(KEY_ANDROID_PREF_BOOLEAN_FENNEC_IS_DEFAULT, true) && isFennecDefaultBrowser) {
track(CHANGED_DEFAULT_TO_FENNEC);
}
}
sharedPreferences.edit().putBoolean(KEY_ANDROID_PREF_BOOLEAN_FENNEC_IS_DEFAULT, isFennecDefaultBrowser).apply();
}
+ static void trackJustInstalledPackage(@NonNull final Context context, @NonNull final String packageName,
+ final boolean firstTimeInstall) {
+ if (!isMmaEnabled(context)) {
+ return;
+ }
+
+ if (packageName.equals(PACKAGE_NAME_FOCUS) && firstTimeInstall) {
+ // Already know Mma is enabled, safe to call directly and avoid a superfluous check
+ mmaHelper.event(INSTALLED_FOCUS);
+ } else if (packageName.equals(PACKAGE_NAME_KLAR) && firstTimeInstall) {
+ mmaHelper.event(INSTALLED_KLAR);
+ }
+ }
+
public static void track(String event) {
if (applicationContext != null && isMmaEnabled(applicationContext)) {
mmaHelper.event(event);
}
}
public static void track(String event, long value) {
@@ -157,17 +174,16 @@ public class MmaDelegate {
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
// if selected tab is private, mma should be disabled.
final boolean isInPrivateBrowsing = selectedTab != null && selectedTab.isPrivate();
// only check Gecko Pref when Gecko is running
return inExperiment && healthReport && !isInPrivateBrowsing;
}
-
public static boolean isDefaultBrowser(Context context) {
final Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mozilla.org"));
final ResolveInfo info = context.getPackageManager().resolveActivity(viewIntent, PackageManager.MATCH_DEFAULT_ONLY);
if (info == null) {
// No default is set
return false;
}
final String packageName = info.activityInfo.packageName;
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/mma/PackageAddedReceiver.java
@@ -0,0 +1,43 @@
+package org.mozilla.gecko.mma;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+
+
+/**
+ * Used to inform as soon as possible of any applications being installed.
+ */
+public class PackageAddedReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() != null && intent.getData() != null) {
+ final String updatedPackage = getInstalledPackageName(intent.getData());
+ try {
+ MmaDelegate.trackJustInstalledPackage(context, updatedPackage,
+ getIfFirstTimeInstall(context, updatedPackage));
+ } catch (PackageManager.NameNotFoundException e) {
+ /* Nothing to do */
+ }
+ }
+ }
+
+ // Our intent filter uses the "package" scheme
+ // So the intent we receive would be in the form package:org.mozilla.klar
+ private String getInstalledPackageName(@NonNull Uri intentData) {
+ return intentData.getSchemeSpecificPart();
+ }
+
+ private boolean getIfFirstTimeInstall(@NonNull Context context, @NonNull final String packageName)
+ throws PackageManager.NameNotFoundException {
+
+ // The situation of an invalid package name(very unlikely) will be handled by the caller
+ final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
+ return packageInfo.firstInstallTime == packageInfo.lastUpdateTime;
+ }
+}
--- a/mobile/android/docs/mma.rst
+++ b/mobile/android/docs/mma.rst
@@ -159,16 +159,24 @@ List of current Events related data that
* The user just resumed the app from background
{
"event" : "E_Resumed_From_Background"
}
* User set Fennec as default browser and resumed the app
{
"event" : "E_Changed_Default_To_Fennec"
}
+* User installed the Focus app
+{
+ "event" : "E_Just_Installed_Focus"
+}
+* User installed the Klar app
+{
+ "event" : "E_Just_Installed_Klar"
+}
Deep Links:
Deep links are actions that can point Fennec to open certain pages or load features such as `show bookmark list` or
`open a SUMO page`. When users see a prompt Leanplum message, they can click the button(s) on it. These buttons can
trigger the following deep links
* Link to Set Default Browser settings (firefox://default_browser)
* Link to specific Add-on page (http://link_to_the_add_on_page)
* Link to sync signup/sign in (firefox://sign_up)