Skip to content

Commit 51b31e5

Browse files
authored
Merge pull request #422 from Microsoft/push
Merge push to develop
2 parents 51fdb90 + 2c8344e commit 51b31e5

File tree

46 files changed

+2584
-60
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2584
-60
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ The Mobile Center SDK uses a modular architecture so you can use any or all of t
1717

1818
3. **Mobile Center Distribute**: Mobile Center Distribute will let your users install a new version of the app when you distribute it via the Mobile Center. With a new version of the app available, the SDK will present an update dialog to the users to either download or postpone the new version. Once they choose to update, the SDK will start to update your application. This feature will NOT work if your app is deployed to the app store.
1919

20+
4. **Mobile Center Push**: Mobile Center Push enables you to send push notifications to users of your app from the Mobile Center portal. To do that the Mobile Center SDK and portal integrate with [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/).
21+
2022
## 1. Get started
2123
It is super easy to use Mobile Center. Have a look at our [get started documentation](https://docs.microsoft.com/en-us/mobile-center/sdk/getting-started/android) and onboard your app within minutes. Our [detailed documentation](https://docs.microsoft.com/en-us/mobile-center/sdk/) is available as well.
2224

apps/sasquatch/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/build
2+
google-services.json

apps/sasquatch/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
projectDependencyCompile project(':sdk:mobile-center-analytics')
2828
projectDependencyCompile project(':sdk:mobile-center-crashes')
2929
projectDependencyCompile project(':sdk:mobile-center-distribute')
30+
projectDependencyCompile project(':sdk:mobile-center-push')
3031
jcenterDependencyCompile "com.microsoft.azure.mobile:mobile-center-analytics:${version}"
3132
jcenterDependencyCompile "com.microsoft.azure.mobile:mobile-center-crashes:${version}"
3233
jcenterDependencyCompile "com.microsoft.azure.mobile:mobile-center-distribute:${version}"
@@ -35,4 +36,6 @@ dependencies {
3536
androidTestCompile "com.android.support:support-annotations:${rootProject.ext.supportLibVersion}"
3637
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
3738
compile 'com.android.support.test.espresso:espresso-idling-resource:2.2.2'
38-
}
39+
}
40+
41+
apply plugin: 'com.google.gms.google-services'

apps/sasquatch/lint.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<lint>
3+
4+
<!-- Ignore the UnusedResources issue for the given ids -->
5+
<issue id="UnusedResources">
6+
<ignore regexp="google_crash_reporting_api_key" />
7+
</issue>
8+
</lint>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.microsoft.azure.mobile.sasquatch.features;
2+
3+
public class PushListenerHelper {
4+
5+
public static void setup() {
6+
7+
/* Not available in jCenter yet. See project build flavour class file. */
8+
}
9+
}

apps/sasquatch/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<activity
4242
android:name=".activities.ManagedErrorActivity"
4343
android:label="@string/title_error"/>
44+
<activity android:name=".activities.CustomPropertiesActivity"></activity>
4445
</application>
4546

4647
</manifest>
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
package com.microsoft.azure.mobile.sasquatch.activities;
2+
3+
import android.app.DatePickerDialog;
4+
import android.app.Dialog;
5+
import android.app.TimePickerDialog;
6+
import android.os.Bundle;
7+
import android.support.annotation.NonNull;
8+
import android.support.v4.app.DialogFragment;
9+
import android.support.v4.app.Fragment;
10+
import android.support.v4.app.FragmentTransaction;
11+
import android.support.v7.app.AppCompatActivity;
12+
import android.view.LayoutInflater;
13+
import android.view.Menu;
14+
import android.view.MenuItem;
15+
import android.view.View;
16+
import android.view.ViewGroup;
17+
import android.widget.AdapterView;
18+
import android.widget.CheckBox;
19+
import android.widget.DatePicker;
20+
import android.widget.EditText;
21+
import android.widget.Spinner;
22+
import android.widget.TimePicker;
23+
24+
import com.microsoft.azure.mobile.MobileCenter;
25+
import com.microsoft.azure.mobile.sasquatch.R;
26+
27+
import java.lang.reflect.Method;
28+
import java.text.DateFormat;
29+
import java.util.ArrayList;
30+
import java.util.Calendar;
31+
import java.util.Date;
32+
import java.util.List;
33+
34+
public class CustomPropertiesActivity extends AppCompatActivity {
35+
36+
private final List<CustomPropertyFragment> mProperties = new ArrayList<>();
37+
38+
private CustomPropertyFragment mCurrentProperty = null;
39+
40+
@Override
41+
protected void onCreate(Bundle savedInstanceState) {
42+
super.onCreate(savedInstanceState);
43+
setContentView(R.layout.activity_custom_properties);
44+
addProperty();
45+
}
46+
47+
@Override
48+
public boolean onCreateOptionsMenu(Menu menu) {
49+
getMenuInflater().inflate(R.menu.add, menu);
50+
return true;
51+
}
52+
53+
@Override
54+
public boolean onOptionsItemSelected(MenuItem item) {
55+
switch (item.getItemId()) {
56+
case R.id.action_add:
57+
addProperty();
58+
break;
59+
}
60+
return true;
61+
}
62+
63+
private void addProperty() {
64+
CustomPropertyFragment fragment = new CustomPropertyFragment();
65+
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
66+
transaction.add(R.id.list, fragment).commit();
67+
mProperties.add(fragment);
68+
}
69+
70+
@SuppressWarnings({"unused", "unchecked"})
71+
public void send(@SuppressWarnings("UnusedParameters") View view) {
72+
try {
73+
Class classCustomProperties = Class.forName("com.microsoft.azure.mobile.CustomProperties");
74+
Object customProperties = classCustomProperties.getConstructor().newInstance();
75+
for (CustomPropertyFragment property : mProperties) {
76+
property.set(customProperties);
77+
}
78+
Method method = MobileCenter.class.getDeclaredMethod("setCustomProperties",classCustomProperties);
79+
method.setAccessible(true);
80+
method.invoke(null, customProperties);
81+
} catch (Throwable throwable) {
82+
throwable.printStackTrace();
83+
}
84+
}
85+
86+
public static class CustomPropertyFragment extends Fragment
87+
implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener {
88+
89+
private static final int TYPE_CLEAR = 0;
90+
private static final int TYPE_BOOLEAN = 1;
91+
private static final int TYPE_NUMBER = 2;
92+
private static final int TYPE_DATETIME = 3;
93+
private static final int TYPE_STRING = 4;
94+
95+
private EditText mEditKey;
96+
private Spinner mEditType;
97+
private EditText mEditString;
98+
private EditText mEditNumber;
99+
private EditText mEditDate;
100+
private EditText mEditTime;
101+
private CheckBox mEditBool;
102+
private View mDateTime;
103+
104+
private Date mDate;
105+
106+
@Override
107+
public View onCreateView(LayoutInflater inflater, ViewGroup container,
108+
Bundle savedInstanceState) {
109+
View view = inflater.inflate(R.layout.custom_property, container, false);
110+
111+
mEditKey = (EditText) view.findViewById(R.id.key);
112+
mEditType = (Spinner) view.findViewById(R.id.type);
113+
mEditString = (EditText) view.findViewById(R.id.string);
114+
mEditNumber = (EditText) view.findViewById(R.id.number);
115+
mEditDate = (EditText) view.findViewById(R.id.date);
116+
mEditTime = (EditText) view.findViewById(R.id.time);
117+
mEditBool = (CheckBox) view.findViewById(R.id.bool);
118+
mDateTime = view.findViewById(R.id.datetime);
119+
120+
mEditType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
121+
122+
@Override
123+
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
124+
updateValueType();
125+
}
126+
127+
@Override
128+
public void onNothingSelected(AdapterView<?> parent) {
129+
}
130+
});
131+
mEditDate.setOnClickListener(new View.OnClickListener() {
132+
133+
@Override
134+
public void onClick(View view) {
135+
showDate();
136+
}
137+
});
138+
mEditTime.setOnClickListener(new View.OnClickListener() {
139+
140+
@Override
141+
public void onClick(View view) {
142+
showTime();
143+
}
144+
});
145+
146+
setDate(new Date());
147+
148+
return view;
149+
}
150+
151+
private void showDate() {
152+
CustomPropertiesActivity activity = (CustomPropertiesActivity) getActivity();
153+
activity.mCurrentProperty = this;
154+
new DatePickerFragment().show(activity.getSupportFragmentManager(), "datePicker");
155+
}
156+
157+
private void showTime() {
158+
CustomPropertiesActivity activity = (CustomPropertiesActivity) getActivity();
159+
activity.mCurrentProperty = this;
160+
new TimePickerFragment().show(activity.getSupportFragmentManager(), "timePicker");
161+
}
162+
163+
private void updateValueType() {
164+
int type = mEditType.getSelectedItemPosition();
165+
mEditString.setVisibility(type == TYPE_STRING ? View.VISIBLE : View.GONE);
166+
mEditNumber.setVisibility(type == TYPE_NUMBER ? View.VISIBLE : View.GONE);
167+
mEditBool.setVisibility(type == TYPE_BOOLEAN ? View.VISIBLE : View.GONE);
168+
mDateTime.setVisibility(type == TYPE_DATETIME ? View.VISIBLE : View.GONE);
169+
}
170+
171+
private void setDate(Date date) {
172+
mDate = date;
173+
mEditDate.setText(DateFormat.getDateInstance().format(mDate));
174+
mEditTime.setText(DateFormat.getTimeInstance().format(mDate));
175+
}
176+
177+
public void onDateSet(DatePicker view, int year, int month, int day) {
178+
Calendar calendar = Calendar.getInstance();
179+
calendar.setTime(mDate);
180+
calendar.set(Calendar.YEAR, year);
181+
calendar.set(Calendar.MONTH, month);
182+
calendar.set(Calendar.DAY_OF_MONTH, day);
183+
setDate(calendar.getTime());
184+
}
185+
186+
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
187+
Calendar calendar = Calendar.getInstance();
188+
calendar.setTime(mDate);
189+
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
190+
calendar.set(Calendar.MINUTE, minute);
191+
calendar.set(Calendar.SECOND, 0);
192+
calendar.set(Calendar.MILLISECOND, 0);
193+
setDate(calendar.getTime());
194+
}
195+
196+
public void set(Object customProperties) throws Throwable {
197+
int type = mEditType.getSelectedItemPosition();
198+
String key = mEditKey.getText().toString();
199+
switch (type) {
200+
case TYPE_CLEAR:
201+
customProperties.getClass().getMethod("clear", String.class).invoke(customProperties, key);
202+
break;
203+
case TYPE_BOOLEAN:
204+
customProperties.getClass().getMethod("set", String.class, boolean.class).invoke(customProperties, key, mEditBool.isChecked());
205+
break;
206+
case TYPE_NUMBER:
207+
String stringValue = mEditNumber.getText().toString();
208+
Number value;
209+
try {
210+
value = Integer.parseInt(stringValue);
211+
} catch (NumberFormatException ignored) {
212+
value = Double.parseDouble(stringValue);
213+
}
214+
customProperties.getClass().getMethod("set", String.class, Number.class).invoke(customProperties, key, value);
215+
break;
216+
case TYPE_DATETIME:
217+
customProperties.getClass().getMethod("set", String.class, Date.class).invoke(customProperties, key, mDate);
218+
break;
219+
case TYPE_STRING:
220+
customProperties.getClass().getMethod("set", String.class, String.class).invoke(customProperties, key, mEditString.getText().toString());
221+
break;
222+
}
223+
}
224+
}
225+
226+
public static class DatePickerFragment extends DialogFragment {
227+
228+
@NonNull
229+
@Override
230+
public Dialog onCreateDialog(Bundle savedInstanceState) {
231+
CustomPropertiesActivity activity = (CustomPropertiesActivity) getActivity();
232+
CustomPropertyFragment property = activity.mCurrentProperty;
233+
Calendar calendar = Calendar.getInstance();
234+
if (property != null) {
235+
calendar.setTime(property.mDate);
236+
}
237+
int year = calendar.get(Calendar.YEAR);
238+
int month = calendar.get(Calendar.MONTH);
239+
int day = calendar.get(Calendar.DAY_OF_MONTH);
240+
return new DatePickerDialog(activity, property, year, month, day);
241+
}
242+
}
243+
244+
public static class TimePickerFragment extends DialogFragment {
245+
246+
@NonNull
247+
@Override
248+
public Dialog onCreateDialog(Bundle savedInstanceState) {
249+
CustomPropertiesActivity activity = (CustomPropertiesActivity) getActivity();
250+
CustomPropertyFragment property = activity.mCurrentProperty;
251+
Calendar calendar = Calendar.getInstance();
252+
if (property != null) {
253+
calendar.setTime(property.mDate);
254+
}
255+
int hour = calendar.get(Calendar.HOUR_OF_DAY);
256+
int minute = calendar.get(Calendar.MINUTE);
257+
return new TimePickerDialog(activity, property, hour, minute, true);
258+
}
259+
}
260+
}
Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.microsoft.azure.mobile.sasquatch.activities;
22

33
import android.content.Context;
4+
import android.content.Intent;
45
import android.os.Bundle;
56
import android.support.v7.app.AppCompatActivity;
67
import android.text.Editable;
78
import android.text.TextUtils;
89
import android.text.TextWatcher;
910
import android.view.LayoutInflater;
11+
import android.view.Menu;
12+
import android.view.MenuItem;
1013
import android.view.View;
1114
import android.view.ViewGroup;
1215
import android.widget.TextView;
@@ -16,9 +19,7 @@
1619
import java.util.HashMap;
1720
import java.util.Map;
1821

19-
public abstract class LogActivity extends AppCompatActivity implements TextWatcher {
20-
21-
private TextView mLastInput;
22+
public abstract class LogActivity extends AppCompatActivity {
2223

2324
private ViewGroup mList;
2425

@@ -33,13 +34,24 @@ public void onCreate(Bundle savedInstanceState) {
3334
addProperty();
3435
}
3536

37+
@Override
38+
public boolean onCreateOptionsMenu(Menu menu) {
39+
getMenuInflater().inflate(R.menu.add, menu);
40+
return true;
41+
}
42+
43+
@Override
44+
public boolean onOptionsItemSelected(MenuItem item) {
45+
switch (item.getItemId()) {
46+
case R.id.action_add:
47+
addProperty();
48+
break;
49+
}
50+
return true;
51+
}
52+
3653
private void addProperty() {
37-
if (mLastInput != null)
38-
mLastInput.removeTextChangedListener(this);
39-
View view = mLayoutInflater.inflate(R.layout.property, mList, false);
40-
mList.addView(view);
41-
mLastInput = (TextView) view.findViewById(R.id.value);
42-
mLastInput.addTextChangedListener(this);
54+
mList.addView(mLayoutInflater.inflate(R.layout.property, mList, false));
4355
}
4456

4557
@SuppressWarnings("unused")
@@ -60,18 +72,4 @@ public void send(@SuppressWarnings("UnusedParameters") View view) {
6072
}
6173

6274
protected abstract void trackLog(String name, Map<String, String> properties);
63-
64-
@Override
65-
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
66-
}
67-
68-
@Override
69-
public void onTextChanged(CharSequence s, int start, int before, int count) {
70-
if (s.length() > 0)
71-
addProperty();
72-
}
73-
74-
@Override
75-
public void afterTextChanged(Editable s) {
76-
}
7775
}

0 commit comments

Comments
 (0)