Using the offline editor sample I consistently get the error on download portion of bidirectional sync "File opened that is not a database file". The error presents itself during the following situation.
1. Local runtime GDB created from feature service.
2. Android app is put in background or device goes to sleep.
3. Feature collected on device and another feature is created either on AGOL or on another device in the same extent.
4. GeodatabaseSyncTask is run as per OfflineEditor sample.
5. Upload is successful but features from other device or AGOL do not show up. Error generated "File opened that is not a database file".
This behavior does not occur if device is not allowed to go to sleep and application is kept active in the forefront on device. Error is generated in the syncResponseCallback.
CallbackListener<Map<Integer, GeodatabaseFeatureTableEditErrors>> syncResponseCallback = new CallbackListener<Map<Integer, GeodatabaseFeatureTableEditErrors>>() {
@Override
public void onCallback(Map<Integer, GeodatabaseFeatureTableEditErrors> objs) {
showProgress(activity, false);
if (objs != null) {
if (objs.size() > 0) {
S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
showMessage(activity, "Sync Completed With Errors");
} else {
S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
showMessage(activity, "Sync Completed Without Errors");
}
} else {
showMessage(activity, "Sync Completed Without Errors");
}
}
@Override
public void onError(Throwable e) {
showMessage(activity, e.getMessage());
//showProgress(activity, false);
//e.printStackTrace();
}
};
Here is the full code for this class (very similar to OfflineEditor GDBUtility class)...
package gov.s1.s1mobile;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.View;
import android.widget.Toast;
import com.esri.core.ags.FeatureServiceInfo;
import com.esri.core.geodatabase.GeodatabaseFeatureTableEditErrors;
import com.esri.core.io.UserCredentials;
import com.esri.core.map.CallbackListener;
import com.esri.core.tasks.geodatabase.GeodatabaseStatusCallback;
import com.esri.core.tasks.geodatabase.GeodatabaseStatusInfo;
import com.esri.core.tasks.geodatabase.GeodatabaseSyncTask;
import com.esri.core.tasks.geodatabase.SyncGeodatabaseParameters;
import java.util.Map;
public class SyncUtility {
private static GeodatabaseSyncTask gdbTask;
public static final String TAG = "SyncUtility";
public static UserCredentials creds;
//public static String dirPathHidden;
//public static ProgressBar downloadProgressBar;
public static boolean Completed = false;
// upload and synchronize local geodatabase to the server
static void synchronize(final S1ViewerActivity activity, UserCredentials AgencyCredentials) {
showProgress(activity, true);
String url = S1ViewerActivity.localGDB.getServiceURL();
creds = AgencyCredentials;
gdbTask = new GeodatabaseSyncTask(url, AgencyCredentials);
gdbTask.fetchFeatureServiceInfo(new CallbackListener<FeatureServiceInfo>() {
@Override
public void onError(Throwable e) {
// TODO Auto-generated method stub
showMessage(activity, e.getMessage());
showProgress(activity, false);
String errorMessage = e.getMessage();
if (errorMessage.contains("Error while generating a token")) {
Intent newActivity = new Intent(activity,FeatureServiceLogin.class);
String errorLabel = "error";
newActivity.putExtra("errorLabel",
errorLabel);
newActivity.putExtra("sync", true);
activity.startActivity(newActivity);
}else if (errorMessage.contains("Unauthorized access to a secure service")) {
showMessage(activity, "You are not logged in as the correct user to Sync this database. Please log in as the User who downloaded the database.");
}
}
@Override
public void onCallback(FeatureServiceInfo objs) {
Boolean test = objs.getSyncCapabilities().isRollbackOnFailureSupported();
if (objs.isSyncEnabled()) {
doSyncAllInOne(activity);
}
}
});
}
/**
* All-in-one method used...
*
* @throws Exception
*/
private static void doSyncAllInOne(final S1ViewerActivity activity) {
try {
// get sync parameters from geodatabase
final SyncGeodatabaseParameters syncParams = S1ViewerActivity.localGDB.getSyncParameters();
CallbackListener<Map<Integer, GeodatabaseFeatureTableEditErrors>> syncResponseCallback = new CallbackListener<Map<Integer, GeodatabaseFeatureTableEditErrors>>() {
@Override
public void onCallback(Map<Integer, GeodatabaseFeatureTableEditErrors> objs) {
showProgress(activity, false);
if (objs != null) {
if (objs.size() > 0) {
S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
showMessage(activity, "Sync Completed With Errors");
} else {
S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
showMessage(activity, "Sync Completed Without Errors");
}
} else {
showMessage(activity, "Sync Completed Without Errors");
}
}
@Override
public void onError(Throwable e) {
showMessage(activity, e.getMessage());
//showProgress(activity, false);
//e.printStackTrace();
}
};
GeodatabaseStatusCallback statusCallback = new GeodatabaseStatusCallback() {
@Override
public void statusUpdated(GeodatabaseStatusInfo status) {
S1ViewerActivity.appendLog(status.getStatus().toString());
showMessage(activity, status.getStatus().toString());
String x = "";
/* // TODO Auto-generated method stub
gdbTask.syncGeodatabase(syncParams, S1ViewerActivity.localGDB, statusCallback, syncResponseCallback);
showMessage(activity, "Starting Sync");
} catch (Exception e) {
//S1ViewerActivity.featureServiceError = e.getMessage();
showMessage(activity, e.getMessage());
showProgress(activity, false);
//e.printStackTrace();
}
}
static void showProgress(final S1ViewerActivity activity, final boolean showProgressbar) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!showProgressbar) {
activity.setProgressBarIndeterminateVisibility(showProgressbar);
activity.downloadProgressBar.setVisibility(View.GONE);
}else{
activity.downloadProgressBar.setVisibility(View.VISIBLE);
}
}
});
}
static void showMessage(final S1ViewerActivity activity, final String message) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
//if (message != null || message )
try{
S1ViewerActivity.appendLog(message);
String pMessage = "";
if (message.contains("Sync Completed Without Errors")) {
S1ViewerActivity.AfterSync();
if (S1ViewerActivity.numberPhotos != null) {
pMessage = "Sync has completed. \n\n" + S1ViewerActivity.numFeaturesAddedInteger + " feature(s) have been synchronized. \n\n" + S1ViewerActivity.numberPhotos + " photos have been synchronized.";
}else{
pMessage = "Sync has completed. \n\n" + S1ViewerActivity.numFeaturesAddedInteger + " feature(s) have been synchronized.";
}
showPrompt(pMessage, activity);
}else if (message.contains("Sync Completed With Errors")) {
pMessage = "An error occured. Sync has NOT completed. " + message;
showPrompt(pMessage, activity);
}else if (message.contains("Untrusted server certificate")) {
pMessage = "Security Error Connecting to Feature Service because of Web Application Firewall. Put in help desk ticket.: " + message;
showPrompt(pMessage, activity);
}else if (message.contains("Not Found")) {
pMessage = "Either Internal Feature Service or ArcGIS.com is down. Error details: " + message;
showPrompt(pMessage, activity);
}else if (message.contains("current license level")) {
//S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
pMessage = "Your credentials have expired. You must Log Off of S1 and Log back in. To do this go to Options menu and choose option to Log Off. When prompted type in your username and password.";
showPrompt(pMessage, activity);
}else{
//temp bandaid solution regarding sync issues
//if(message.contains("database file")) {
//pMessage = "Sync Upload Successful, but Download of other new features not possible due to Server Issues.";
//showPrompt(pMessage, activity);
//}else{
Toast.makeText(activity, message, Toast.LENGTH_LONG).show();
//}
}
/* if (message.contains("current license level")) {
Toast.makeText(activity, "Your Login Credentials have expired.", Toast.LENGTH_LONG).show();
}*/
if (pMessage != ""){
S1ViewerActivity.appendLog(pMessage);
}
//S1ViewerActivity.downloadProgressBar.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
static void showPrompt(String message, Context activity ){
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(message).setPositiveButton("OK",dialogClickListener).show();
}
}