Skip to content

Commit

Permalink
Merge pull request #823 from Microsoft/feature/event-typed-properties
Browse files Browse the repository at this point in the history
Add typed properties for analytics events
  • Loading branch information
jaeklim authored Oct 11, 2018
2 parents d3bb45b + 65405fb commit e0345f3
Show file tree
Hide file tree
Showing 62 changed files with 4,281 additions and 720 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

### AppCenter

* **[Feature]** Added a `setMaxStorageSize` API which allows setting a maximum size limit on the local SQLite storage. Previously, up to 300 logs were stored of any size. The default value is 10MB.
* **[Feature]** Add a `setMaxStorageSize` API which allows setting a maximum size limit on the local SQLite storage. Previously, up to 300 logs were stored of any size. The default value is 10MB.
* **[Security]** To enforce TLS 1.2 on all HTTPS connections the SDK makes, we are dropping support for API level 15 (which supports only TLS 1.0), the minimum SDK version thus becomes 16. Previous versions of the SDK were already using TLS 1.2 on API level 16+.
* **[Bug fix]** Fix validating and discarding `NaN` and infinite double values when calling `setCustomProperties`.

### AppCenterAnalytics

* **[Feature]** Added `pause`/`resume` APIs which pause/resume sending Analytics logs to App Center.
* **[Feature]** Add `pause`/`resume` APIs which pause/resume sending Analytics logs to App Center.
* **[Feature]** Add support for typed properties. Note that these APIs still convert properties back to strings on the App Center backend. More work is needed to store and display typed properties in the App Center portal. Using the new APIs now will enable future scenarios, but for now the behavior will be the same as it is for current event properties.
* **[Feature]** Preparation work for a future change in transmission protocol and endpoint for Analytics data. There is no impact on your current workflow when using App Center.

## Version 1.8.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package com.microsoft.appcenter.sasquatch.activities;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;

import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.analytics.Analytics;
import com.microsoft.appcenter.analytics.AnalyticsTransmissionTarget;
import com.microsoft.appcenter.sasquatch.R;
import com.microsoft.appcenter.sasquatch.util.EventActivityUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// TODO remove once new APIs available in jCenter.
public class EventActivity extends AppCompatActivity {

private ViewGroup mList;

private LayoutInflater mLayoutInflater;

private Spinner mTransmissionTargetSpinner;

private CheckBox mTransmissionEnabledCheckBox;

private CheckBox mDeviceIdEnabledCheckBox;

private Button mConfigureTargetPropertiesButton;

private Button mOverrideCommonSchemaButton;

private Button mPauseTransmissionButton;

private Button mResumeTransmissionButton;

private List<AnalyticsTransmissionTarget> mTransmissionTargets = new ArrayList<>();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

/* Property view init. */
mList = findViewById(R.id.list);
addProperty();

/* Test start from library. */
AppCenter.startFromLibrary(this, Analytics.class);

/* Transmission target views init. */
mTransmissionTargetSpinner = findViewById(R.id.transmission_target);
ArrayAdapter<String> targetAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.target_id_names));
mTransmissionTargetSpinner.setAdapter(targetAdapter);
mTransmissionTargetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updateButtonStates(getSelectedTarget());
}

@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});

/* Init Configure target properties button. */
mConfigureTargetPropertiesButton = findViewById(R.id.configure_button);
mConfigureTargetPropertiesButton.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Intent intent = new Intent(EventActivity.this, EventPropertiesActivity.class);
intent.putExtra(ActivityConstants.EXTRA_TARGET_SELECTED, mTransmissionTargetSpinner.getSelectedItemPosition() - 1);
startActivity(intent);
}
});

/* Init enabled check boxes. */
mTransmissionEnabledCheckBox = findViewById(R.id.transmission_enabled);
mDeviceIdEnabledCheckBox = findViewById(R.id.device_id_enabled);
mDeviceIdEnabledCheckBox.setVisibility(View.GONE);

/*
* The first element is a placeholder for default transmission.
* The second one is the parent transmission target, the third one is a child,
* the forth is a grandchild, etc...
*/
mTransmissionTargets = EventActivityUtil.getAnalyticTransmissionTargetList(this);

/* Init common schema properties button. */
mOverrideCommonSchemaButton = findViewById(R.id.override_cs_button);

/* Init override common schema properties button. */
mOverrideCommonSchemaButton.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Intent intent = new Intent(EventActivity.this, CommonSchemaPropertiesActivity.class);
intent.putExtra(ActivityConstants.EXTRA_TARGET_SELECTED, mTransmissionTargetSpinner.getSelectedItemPosition());
startActivity(intent);
}
});

/* Init pause/resume buttons. */
mPauseTransmissionButton = findViewById(R.id.pause_transmission_button);
mPauseTransmissionButton.setVisibility(View.GONE);
mResumeTransmissionButton = findViewById(R.id.resume_transmission_button);
mResumeTransmissionButton.setVisibility(View.GONE);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.add, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
addProperty();
break;
}
return true;
}

private void addProperty() {
mList.addView(mLayoutInflater.inflate(R.layout.property, mList, false));
}

@SuppressWarnings("unused")
public void send(@SuppressWarnings("UnusedParameters") View view) {
String name = ((TextView) findViewById(R.id.name)).getText().toString();
Map<String, String> properties = null;
for (int i = 0; i < mList.getChildCount(); i++) {
View childAt = mList.getChildAt(i);
CharSequence key = ((TextView) childAt.findViewById(R.id.key)).getText();
CharSequence value = ((TextView) childAt.findViewById(R.id.value)).getText();
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
if (properties == null) {
properties = new HashMap<>();
}
properties.put(key.toString(), value.toString());
}
}

/* First item is always empty as it's default value which means either appcenter, one collector or both. */
AnalyticsTransmissionTarget target = getSelectedTarget();
if (target == null) {
Analytics.trackEvent(name, properties);
} else {
target.trackEvent(name, properties);
}
}

private AnalyticsTransmissionTarget getSelectedTarget() {
return mTransmissionTargets.get(mTransmissionTargetSpinner.getSelectedItemPosition());
}

public void toggleTransmissionEnabled(View view) {
boolean checked = mTransmissionEnabledCheckBox.isChecked();
final AnalyticsTransmissionTarget target = getSelectedTarget();
if (target != null) {
target.setEnabledAsync(checked);
updateButtonStates(target);
}
}

public void toggleDeviceIdEnabled(View view) {
}

private void updateButtonStates(AnalyticsTransmissionTarget target) {
if (target == null) {
mTransmissionEnabledCheckBox.setVisibility(View.GONE);
mConfigureTargetPropertiesButton.setVisibility(View.GONE);
mOverrideCommonSchemaButton.setVisibility(View.GONE);
mDeviceIdEnabledCheckBox.setVisibility(View.GONE);
mPauseTransmissionButton.setVisibility(View.GONE);
mResumeTransmissionButton.setVisibility(View.GONE);
} else {
mTransmissionEnabledCheckBox.setVisibility(View.VISIBLE);
mConfigureTargetPropertiesButton.setVisibility(View.VISIBLE);
mOverrideCommonSchemaButton.setVisibility(View.VISIBLE);
boolean enabled = target.isEnabledAsync().get();
mTransmissionEnabledCheckBox.setChecked(enabled);
mTransmissionEnabledCheckBox.setText(enabled ? R.string.transmission_enabled : R.string.transmission_disabled);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import static com.microsoft.appcenter.sasquatch.activities.ActivityConstants.EXTRA_TARGET_SELECTED;

// TODO remove once new APIs available in jCenter.
public class EventPropertiesActivity extends AppCompatActivity {

private Spinner mTransmissionTargetSpinner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
android:orientation="vertical"
android:visibility="gone">

<!-- TODO replace this file by project version after SDK available in jCenter. -->
<include layout="@layout/property" />

<LinearLayout
Expand All @@ -36,15 +37,15 @@
android:orientation="horizontal">

<Button
style="?android:attr/buttonBarButtonStyle"
android:id="@+id/cancel_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />

<Button
style="?android:attr/buttonBarButtonStyle"
android:id="@+id/add_button"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add" />
Expand Down
Loading

0 comments on commit e0345f3

Please sign in to comment.