Bidirectional Sync Fails after device goes to sleep

5989
25
06-08-2016 04:46 PM
by Anonymous User
Not applicable

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();

  }

}

0 Kudos
25 Replies
by Anonymous User
Not applicable

Hi Alex, Just want to let you know that I have been able to reproduce the issue when device goes to sleep also with the OfflineEditor.  That being said it is kind of tricky to test.  Just going to sleep does not seem to do it.  It appears to be the combination of sleep and the Android system releasing the app resources as a result (it is super variable when this will occur).  The way I confirmed this was merely downloading the feature service  to a local gdb and then waiting about an hour (not using the device during that timeframe) and then collecting a feature on that device and another feature via AGOL on my desktop or by using another device within the same extent.  By following these steps I am also getting the error "File is not a database file" and the download of the data from the other user fails.

I am concerned about this because it is very likely that field staff will allow their devices to sleep for significant amounts of time during the day, for example when they drive back in from the field at the end of the day.  Of course a force stop situation is a concern as well because, who knows when you might need to restart your device.

0 Kudos
by Anonymous User
Not applicable

Hey Alex, Was just curious if you were ever able to re-create this issue with the Offline Editor when the device goes to sleep for a significant amount of time?  Also wondering if we can expect this issue to be fixed with Quartz, or whatever the next build (if any) is of the runtime SDK?

0 Kudos
AlexanderNohe1
Occasional Contributor III

I saw similar behaviors.  I am unsure on whether it will be resolved in the quartz release as I am not part of that team and have yet to test the workflow in Beta.

0 Kudos
by Anonymous User
Not applicable

Just curious if there is anyway to check with the Collector team and see if there is something they did to fix this issue?

It appears that Collector for iOS had this same issue in the past, but they were able to fix it.  They were getting the exact same error which appeared to have something to do with using Web Tier security.  Seems like it could be related..

https://community.esri.com/thread/167025#comments

0 Kudos
AlexanderNohe1
Occasional Contributor III

I do not have access to that team either and would not be able to reach out to them.

0 Kudos
by Anonymous User
Not applicable

Update 2/15/2017 - Esri Case #01778752 - gdbSyncTask Bidirectional Sync Fails when new feature

I am running into a new issue where with internal ArcGIS Server I am getting a different error then I see with hosted services.  What leads to this issue is when trying to sync a feature service when another user has collected in the same extent.  Upload is successful, but download of the new data from the other user fails.  We are using ArcGIS Runtime 10.2.8 because Quartz does not yet have related table functionality.

Hosted Service Error is as follows...
"File opened that is not a database file".
 
Internal ArcGIS Server 10.4.1
"com.esri.core.io.EsriServiceException:"
 
 Only reason I ask is because I was flagging on the original error to attempt to re-download the feature service in the situation where "File opened that is not a database file".  With the more generic error we are seeing with Internal ArcGIS Server this is problmatic because the service could be genuinely down. 
0 Kudos