In my Android application i use a conflictHandler class inorder to detect conflicts between the records of the mobile device's DB and the Server's DB. When a conflict is detected,i want to display an Alert Dialog so that the user can choose which record version will "win"(Server's or Mobile Device's). I have put the code of the Alert Dialog in the class of the conflictHandler, so when a conflict is detected the Alert Dialog pops up. The problem is that the code execution doesn't stop when the Alert Dialog pops up, so that the user can select which action will be done. It always returns the serverItem.
private class ConflictResolvingSyncHandler implements MobileServiceSyncHandler {
@Override
public JsonObject executeTableOperation(
final RemoteTableOperationProcessor processor, final TableOperation operation)
throws MobileServiceSyncHandlerException {
final JsonObject clientItem = processor.getItem().getAsJsonObject();
MobileServicePreconditionFailedExceptionBase ex = null;
final JsonObject[] result = {null};
try {
result[0] = operation.accept(processor);
} catch (MobileServicePreconditionFailedExceptionBase e) {
ex = e;
} catch (Throwable e) {
ex = (MobileServicePreconditionFailedExceptionBase) e.getCause();
}
if (ex != null) {
// A conflict was detected; let's force the server to "win"
// by discarding the client version of the item
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set title
alertDialogBuilder.setTitle("Conflict Detected");
// set dialog message
final MobileServicePreconditionFailedExceptionBase finalEx = ex;
alertDialogBuilder
.setMessage("Choose winner")
.setCancelable(false)
.setPositiveButton("Server",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Server wins
JsonObject serverItem = finalEx.getValue();
if (serverItem == null) {
// Item not returned in the exception, retrieving it from the server
try {
serverItem = mClient.getTable(operation.getTableName()).lookUp(operation.getItemId()).get();
} catch (Exception e) {
try {
throw new MobileServiceSyncHandlerException(e);
} catch (MobileServiceSyncHandlerException e1) {
e1.printStackTrace();
}
}
}
result[0] = serverItem;
}
})
.setNegativeButton("Client",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Client wins
result[0]=clientItem;
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
return result[0];
}
@Override
public void onPushComplete(MobileServicePushCompletionResult result)
throws MobileServiceSyncHandlerException {
}
}
You need to block the thread which is executing the executeTableOperation
until the user clicks something in the dialog. For example, using a CountDownLatch
, as in the code below:
private class ConflictResolvingSyncHandler implements MobileServiceSyncHandler {
@Override
public JsonObject executeTableOperation(
final RemoteTableOperationProcessor processor, final TableOperation operation)
throws MobileServiceSyncHandlerException {
final JsonObject clientItem = processor.getItem().getAsJsonObject();
MobileServicePreconditionFailedExceptionBase ex = null;
final JsonObject[] result = {null};
try {
result[0] = operation.accept(processor);
} catch (MobileServicePreconditionFailedExceptionBase e) {
ex = e;
} catch (Throwable e) {
ex = (MobileServicePreconditionFailedExceptionBase) e.getCause();
}
if (ex != null) {
// A conflict was detected; let's make the client choose who "wins"
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
final CountDownLatch latch = new CountDownLatch(1);
// set title
alertDialogBuilder.setTitle("Conflict Detected");
// set dialog message
final MobileServicePreconditionFailedExceptionBase finalEx = ex;
alertDialogBuilder
.setMessage("Choose winner")
.setCancelable(false)
.setPositiveButton("Server",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Server wins
JsonObject serverItem = finalEx.getValue();
if (serverItem == null) {
// Item not returned in the exception, retrieving it from the server
try {
serverItem = mClient.getTable(operation.getTableName()).lookUp(operation.getItemId()).get();
} catch (Exception e) {
try {
throw new MobileServiceSyncHandlerException(e);
} catch (MobileServiceSyncHandlerException e1) {
e1.printStackTrace();
}
}
}
result[0] = serverItem;
latch.countDown();
}
})
.setNegativeButton("Client",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, Client wins
result[0] = clientItem;
latch.countDown();
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result[0];
}
@Override
public void onPushComplete(MobileServicePushCompletionResult result)
throws MobileServiceSyncHandlerException {
}
}