How to fix Android Wear MessageClient instability issues
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I'm developing an application which sends heart-rate data from an Android Wear watch (TicWatch Pro) to a connected phone. This works well, until the watch goes into Ambient mode. Messages do no longer come through, until the screen of the watch is touched, and the watch goes out of Ambient mode.
I'm using a TicWatch Pro running Android Wear 2. I tried to implement the service as much along the lines of the Developer guide. I've done some research online, and could not find similar issues. Am I doing something wrong, or could it be the watch performing differently to other watches?
MeasuringService.java
...
public class MeasuringService extends Service implements MessageClient.OnMessageReceivedListener, SensorEventListener {
...
private String nodeId = null;
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
...
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
@Override
public void onCreate() {
super.onCreate();
Wearable.getMessageClient(this).addListener(this);
openNotification();
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
findNodeId();
startMeasurement();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Wearable.getMessageClient(this).removeListener(this);
stopMeasurement();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onMessageReceived(@NonNull MessageEvent messageEvent) {
Log.d(
TAG,
"onMessageReceived() A message from phone was received:"
+ messageEvent.getRequestId()
+ " "
+ messageEvent.getPath());
}
private void sendHeartRate(HeartRateModel heartRateModel) {
Log.d(TAG, "sendHeartRate(): timestamp: " + Long.toString(heartRateModel.getTimestamp()));
sendMessageToPhone(ClientPaths.HR_UPDATE, heartRateModel.toByteArray());
}
private void sendMessageToPhone(String path, byte payload) {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
if (nodeId != null) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(context).sendMessage(nodeId, path, payload);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
Log.d(TAG, "Message sent: " + result);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
} else {
Log.e(TAG, "No node to send message to");
}
}
}).start();
}
private void findNodeId() {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
try {
CapabilityInfo capabilityInfo = Tasks.await(
Wearable.getCapabilityClient(context).getCapability(
Constants.CAPABILITY_PHONE_APP, CapabilityClient.FILTER_REACHABLE));
updateNodeId(capabilityInfo);
} catch (ExecutionException | InterruptedException e) {
Log.d(TAG, "Could not find node: " + e);
}
capabilityListener =
capabilityInfo -> {
updateNodeId(capabilityInfo);
};
Wearable.getCapabilityClient(context).addListener(
capabilityListener,
Constants.CAPABILITY_PHONE_APP);
}
}).start();
}
private void updateNodeId(CapabilityInfo capabilityInfo) {
nodeId = pickBestNodeId(capabilityInfo.getNodes());
}
private String pickBestNodeId(Set<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
private void openNotification() {
String title = "";
String text = "";
showNotification(RUNNING_NOTIFICATION_CHANNEL, RUNNING_NOTIFICATION_ID, title, text, true);
}
...
private void startMeasurement() {
Log.w(TAG, "startMeasurement()");
mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
if (mSensorManager != null) {
Sensor mHeartrateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
if (mHeartrateSensor != null) {
mSensorManager.registerListener(this, mHeartrateSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
...
}
private void stopMeasurement() {
if (mSensorManager != null)
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// send heartrate data and create new intent
if (event.sensor.getType() == Sensor.TYPE_HEART_RATE && event.values.length > 0 && event.accuracy > 0) {
int newValue = Math.round(event.values[0]);
if(newValue!=0) {
// HeartRateModel is a data class cointaining the time of measurement, heart-rate and sensor accuracy
HeartRateModel heartRateModel = new HeartRateModel(System.currentTimeMillis(), event.values[0], event.accuracy);
sendHeartRate(heartRateModel);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
I'd expect the messages to be sent, even when the watch goes into Ambient mode.
If more information is needed, I'd be happy to oblige.
java android wear-os android-wear-data-api
add a comment |
I'm developing an application which sends heart-rate data from an Android Wear watch (TicWatch Pro) to a connected phone. This works well, until the watch goes into Ambient mode. Messages do no longer come through, until the screen of the watch is touched, and the watch goes out of Ambient mode.
I'm using a TicWatch Pro running Android Wear 2. I tried to implement the service as much along the lines of the Developer guide. I've done some research online, and could not find similar issues. Am I doing something wrong, or could it be the watch performing differently to other watches?
MeasuringService.java
...
public class MeasuringService extends Service implements MessageClient.OnMessageReceivedListener, SensorEventListener {
...
private String nodeId = null;
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
...
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
@Override
public void onCreate() {
super.onCreate();
Wearable.getMessageClient(this).addListener(this);
openNotification();
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
findNodeId();
startMeasurement();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Wearable.getMessageClient(this).removeListener(this);
stopMeasurement();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onMessageReceived(@NonNull MessageEvent messageEvent) {
Log.d(
TAG,
"onMessageReceived() A message from phone was received:"
+ messageEvent.getRequestId()
+ " "
+ messageEvent.getPath());
}
private void sendHeartRate(HeartRateModel heartRateModel) {
Log.d(TAG, "sendHeartRate(): timestamp: " + Long.toString(heartRateModel.getTimestamp()));
sendMessageToPhone(ClientPaths.HR_UPDATE, heartRateModel.toByteArray());
}
private void sendMessageToPhone(String path, byte payload) {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
if (nodeId != null) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(context).sendMessage(nodeId, path, payload);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
Log.d(TAG, "Message sent: " + result);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
} else {
Log.e(TAG, "No node to send message to");
}
}
}).start();
}
private void findNodeId() {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
try {
CapabilityInfo capabilityInfo = Tasks.await(
Wearable.getCapabilityClient(context).getCapability(
Constants.CAPABILITY_PHONE_APP, CapabilityClient.FILTER_REACHABLE));
updateNodeId(capabilityInfo);
} catch (ExecutionException | InterruptedException e) {
Log.d(TAG, "Could not find node: " + e);
}
capabilityListener =
capabilityInfo -> {
updateNodeId(capabilityInfo);
};
Wearable.getCapabilityClient(context).addListener(
capabilityListener,
Constants.CAPABILITY_PHONE_APP);
}
}).start();
}
private void updateNodeId(CapabilityInfo capabilityInfo) {
nodeId = pickBestNodeId(capabilityInfo.getNodes());
}
private String pickBestNodeId(Set<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
private void openNotification() {
String title = "";
String text = "";
showNotification(RUNNING_NOTIFICATION_CHANNEL, RUNNING_NOTIFICATION_ID, title, text, true);
}
...
private void startMeasurement() {
Log.w(TAG, "startMeasurement()");
mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
if (mSensorManager != null) {
Sensor mHeartrateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
if (mHeartrateSensor != null) {
mSensorManager.registerListener(this, mHeartrateSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
...
}
private void stopMeasurement() {
if (mSensorManager != null)
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// send heartrate data and create new intent
if (event.sensor.getType() == Sensor.TYPE_HEART_RATE && event.values.length > 0 && event.accuracy > 0) {
int newValue = Math.round(event.values[0]);
if(newValue!=0) {
// HeartRateModel is a data class cointaining the time of measurement, heart-rate and sensor accuracy
HeartRateModel heartRateModel = new HeartRateModel(System.currentTimeMillis(), event.values[0], event.accuracy);
sendHeartRate(heartRateModel);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
I'd expect the messages to be sent, even when the watch goes into Ambient mode.
If more information is needed, I'd be happy to oblige.
java android wear-os android-wear-data-api
add a comment |
I'm developing an application which sends heart-rate data from an Android Wear watch (TicWatch Pro) to a connected phone. This works well, until the watch goes into Ambient mode. Messages do no longer come through, until the screen of the watch is touched, and the watch goes out of Ambient mode.
I'm using a TicWatch Pro running Android Wear 2. I tried to implement the service as much along the lines of the Developer guide. I've done some research online, and could not find similar issues. Am I doing something wrong, or could it be the watch performing differently to other watches?
MeasuringService.java
...
public class MeasuringService extends Service implements MessageClient.OnMessageReceivedListener, SensorEventListener {
...
private String nodeId = null;
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
...
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
@Override
public void onCreate() {
super.onCreate();
Wearable.getMessageClient(this).addListener(this);
openNotification();
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
findNodeId();
startMeasurement();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Wearable.getMessageClient(this).removeListener(this);
stopMeasurement();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onMessageReceived(@NonNull MessageEvent messageEvent) {
Log.d(
TAG,
"onMessageReceived() A message from phone was received:"
+ messageEvent.getRequestId()
+ " "
+ messageEvent.getPath());
}
private void sendHeartRate(HeartRateModel heartRateModel) {
Log.d(TAG, "sendHeartRate(): timestamp: " + Long.toString(heartRateModel.getTimestamp()));
sendMessageToPhone(ClientPaths.HR_UPDATE, heartRateModel.toByteArray());
}
private void sendMessageToPhone(String path, byte payload) {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
if (nodeId != null) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(context).sendMessage(nodeId, path, payload);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
Log.d(TAG, "Message sent: " + result);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
} else {
Log.e(TAG, "No node to send message to");
}
}
}).start();
}
private void findNodeId() {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
try {
CapabilityInfo capabilityInfo = Tasks.await(
Wearable.getCapabilityClient(context).getCapability(
Constants.CAPABILITY_PHONE_APP, CapabilityClient.FILTER_REACHABLE));
updateNodeId(capabilityInfo);
} catch (ExecutionException | InterruptedException e) {
Log.d(TAG, "Could not find node: " + e);
}
capabilityListener =
capabilityInfo -> {
updateNodeId(capabilityInfo);
};
Wearable.getCapabilityClient(context).addListener(
capabilityListener,
Constants.CAPABILITY_PHONE_APP);
}
}).start();
}
private void updateNodeId(CapabilityInfo capabilityInfo) {
nodeId = pickBestNodeId(capabilityInfo.getNodes());
}
private String pickBestNodeId(Set<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
private void openNotification() {
String title = "";
String text = "";
showNotification(RUNNING_NOTIFICATION_CHANNEL, RUNNING_NOTIFICATION_ID, title, text, true);
}
...
private void startMeasurement() {
Log.w(TAG, "startMeasurement()");
mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
if (mSensorManager != null) {
Sensor mHeartrateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
if (mHeartrateSensor != null) {
mSensorManager.registerListener(this, mHeartrateSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
...
}
private void stopMeasurement() {
if (mSensorManager != null)
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// send heartrate data and create new intent
if (event.sensor.getType() == Sensor.TYPE_HEART_RATE && event.values.length > 0 && event.accuracy > 0) {
int newValue = Math.round(event.values[0]);
if(newValue!=0) {
// HeartRateModel is a data class cointaining the time of measurement, heart-rate and sensor accuracy
HeartRateModel heartRateModel = new HeartRateModel(System.currentTimeMillis(), event.values[0], event.accuracy);
sendHeartRate(heartRateModel);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
I'd expect the messages to be sent, even when the watch goes into Ambient mode.
If more information is needed, I'd be happy to oblige.
java android wear-os android-wear-data-api
I'm developing an application which sends heart-rate data from an Android Wear watch (TicWatch Pro) to a connected phone. This works well, until the watch goes into Ambient mode. Messages do no longer come through, until the screen of the watch is touched, and the watch goes out of Ambient mode.
I'm using a TicWatch Pro running Android Wear 2. I tried to implement the service as much along the lines of the Developer guide. I've done some research online, and could not find similar issues. Am I doing something wrong, or could it be the watch performing differently to other watches?
MeasuringService.java
...
public class MeasuringService extends Service implements MessageClient.OnMessageReceivedListener, SensorEventListener {
...
private String nodeId = null;
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
...
private CapabilityClient.OnCapabilityChangedListener capabilityListener = null;
@Override
public void onCreate() {
super.onCreate();
Wearable.getMessageClient(this).addListener(this);
openNotification();
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
findNodeId();
startMeasurement();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Wearable.getMessageClient(this).removeListener(this);
stopMeasurement();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onMessageReceived(@NonNull MessageEvent messageEvent) {
Log.d(
TAG,
"onMessageReceived() A message from phone was received:"
+ messageEvent.getRequestId()
+ " "
+ messageEvent.getPath());
}
private void sendHeartRate(HeartRateModel heartRateModel) {
Log.d(TAG, "sendHeartRate(): timestamp: " + Long.toString(heartRateModel.getTimestamp()));
sendMessageToPhone(ClientPaths.HR_UPDATE, heartRateModel.toByteArray());
}
private void sendMessageToPhone(String path, byte payload) {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
if (nodeId != null) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(context).sendMessage(nodeId, path, payload);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
Log.d(TAG, "Message sent: " + result);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
} else {
Log.e(TAG, "No node to send message to");
}
}
}).start();
}
private void findNodeId() {
Context context = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
try {
CapabilityInfo capabilityInfo = Tasks.await(
Wearable.getCapabilityClient(context).getCapability(
Constants.CAPABILITY_PHONE_APP, CapabilityClient.FILTER_REACHABLE));
updateNodeId(capabilityInfo);
} catch (ExecutionException | InterruptedException e) {
Log.d(TAG, "Could not find node: " + e);
}
capabilityListener =
capabilityInfo -> {
updateNodeId(capabilityInfo);
};
Wearable.getCapabilityClient(context).addListener(
capabilityListener,
Constants.CAPABILITY_PHONE_APP);
}
}).start();
}
private void updateNodeId(CapabilityInfo capabilityInfo) {
nodeId = pickBestNodeId(capabilityInfo.getNodes());
}
private String pickBestNodeId(Set<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
private void openNotification() {
String title = "";
String text = "";
showNotification(RUNNING_NOTIFICATION_CHANNEL, RUNNING_NOTIFICATION_ID, title, text, true);
}
...
private void startMeasurement() {
Log.w(TAG, "startMeasurement()");
mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE));
if (mSensorManager != null) {
Sensor mHeartrateSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
if (mHeartrateSensor != null) {
mSensorManager.registerListener(this, mHeartrateSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
...
}
private void stopMeasurement() {
if (mSensorManager != null)
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// send heartrate data and create new intent
if (event.sensor.getType() == Sensor.TYPE_HEART_RATE && event.values.length > 0 && event.accuracy > 0) {
int newValue = Math.round(event.values[0]);
if(newValue!=0) {
// HeartRateModel is a data class cointaining the time of measurement, heart-rate and sensor accuracy
HeartRateModel heartRateModel = new HeartRateModel(System.currentTimeMillis(), event.values[0], event.accuracy);
sendHeartRate(heartRateModel);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
I'd expect the messages to be sent, even when the watch goes into Ambient mode.
If more information is needed, I'd be happy to oblige.
java android wear-os android-wear-data-api
java android wear-os android-wear-data-api
asked Jan 3 at 16:17
Ties BoldingTies Bolding
11
11
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54026056%2fhow-to-fix-android-wear-messageclient-instability-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54026056%2fhow-to-fix-android-wear-messageclient-instability-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown