Bidirectional Sync Fails after device goes to sleep

6026
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, The issue is that the features from other users do not even get added to the local GDB on device after sync.  Features upload and you can see them on AGOL, but no new features from other users are downloaded back to device (and this is when they are collected in the same extent).  At the point when it tries to insert I get an error saying "File is not a database file".

0 Kudos
AlexanderNohe1
Occasional Contributor III

I think I must be confused on what processes you are doing here.  Are you doing a sync and the device goes to sleep or is the device awake while you sync?

0 Kudos
by Anonymous User
Not applicable

Hi Alex, the device is always awake when I sync.  Here is the behavior.

1.  If I download a GDB and right away do a sync (device never goes to sleep) I am always successful  If there are other features in the same extent from other users in this situation they come in correctly.

2.  If I download the GDB and then allow my device to go to sleep, any sync I do after this point in time will upload and be visible on AGOL, but any new data from new users will not insert properly (I see no errors on the ArcGIS Server end).  In this case I get the error "File is not a database file" and I do not see any new features from other users.  In this case I was not actually syncing when when the device went to sleep.  It is just the act of the device going to sleep or application running in the background that causes the issue.

0 Kudos
AlexanderNohe1
Occasional Contributor III

Aaron Dick

Since I cannot reproduce in-house, can you try doing this:

Can you log the path to the geodatabase when you sync.

This would look something like this:

Log.e("FORESRI",S1ViewerActivity.localGDB.getPath());

This will show us the path the the GDB that you are syncing to has.

Does this show the correct path that you expect?

0 Kudos
by Anonymous User
Not applicable

Alex, I am noticing that when I use your simple example that I have no

problems with our application...

http://services.arcgis.com/Wl7Y1m92PbjtJs5n/arcgis/rest/services/SyncData/FeatureServer

I went ahead and posted a more robust sample for you guys to test out. It

appears to not sync properly with the offlineeditor although how on earth

do you enter in attributes with the offlineeditor? That might be why it

does not work. Anyways try out this service and see if you can get it to

sync.

https://services3.arcgis.com/cLHDcAMZcbfKAqyY/arcgis/rest/services/R6_RO_Park_Features/FeatureServer

Aaron Dick

Service First Mobile GIS Lead

Oregon Washington BLM

USFS Region 6 Data Resources Management

Tel: 503.808.6601

Cell: 503.382.7355

Mobile GIS and GPS Info:

https://partnerteamspace.blm.doi.net/sites-or/orwamobile/default.aspx (BLM

only)

https://ems-team.usda.gov/sites/fs-r06-s1gis/mobile-gis/default.aspx (USFS

only)

0 Kudos
AlexanderNohe1
Occasional Contributor III

Hey Aaron Dick

Just wanted to confirm.  You wanted me to test out:

https://services3.arcgis.com/cLHDcAMZcbfKAqyY/ArcGIS/rest/services/R6_RO_Park_Features/FeatureServer

In the ArcGIS Runtime Sample?

0 Kudos
by Anonymous User
Not applicable

Yes try that out with the runtime sample. It is an exact copy of what we

had in our internal organization.

Aaron Dick

Service First Mobile GIS Lead

Oregon Washington BLM

USFS Region 6 Data Resources Management

Tel: 503.808.6601

Cell: 503.382.7355

Mobile GIS and GPS Info:

https://partnerteamspace.blm.doi.net/sites-or/orwamobile/default.aspx (BLM

only)

https://ems-team.usda.gov/sites/fs-r06-s1gis/mobile-gis/default.aspx (USFS

only)

0 Kudos
AlexanderNohe1
Occasional Contributor III

I cannot reproduce with your service and the runtime sample.  I was adding and deleting points both online and locally while opening and closing the app.

0 Kudos
by Anonymous User
Not applicable

Alex,

*I have been able to re-create the issue using the Offline Editor so am

certain the problem is not specific to our code.* Note that I did have to

add UserCredentials in several locations in the OfflineEditor sample to

make it work within an organization. Here is how I am able to trigger the

problem.

1) I setup a feature service and add it to my trial test organization.

2)* I share the feature service only in the organization to a group I am a

member of. This is very critical. What I am finding is that the error

never happens when a feature service is shared with everyone.*

3) I download the feature service using the Offline Editor application on

my phone. Samsung S5 running Android L.

4) I create a feature on device and in AGOL. I sync. This sync is

successful.

5. I Run the application from Android Studio or use Task Manager on the

device to force close the application (this causes the same behavior as

device going to sleep but much quicker).

6. I reopen Offline Editor either manually or Android Studio Run. I now

collect a feature on the device and on AGOL in the same extent. Now when I

sync I get the error "File is not a dabatase file".

Please try this and see if you can replicate. Again not sharing to

everyone appears to be the critical thing here. I am able to re-create

this on many interations when I follow the steps above. I am able to

recreate this across many different feature services. I even took your

points feature service, exported to gdb and then published that to my test

organization. Same behavior. Works when published to everyone, errors out

when following steps above and sharing only to a group in the organization.

Aaron Dick

Service First Mobile GIS Lead

Oregon Washington BLM

USFS Region 6 Data Resources Management

Tel: 503.808.6601

Cell: 503.382.7355

Mobile GIS and GPS Info:

https://partnerteamspace.blm.doi.net/sites-or/orwamobile/default.aspx (BLM

only)

https://ems-team.usda.gov/sites/fs-r06-s1gis/mobile-gis/default.aspx (USFS

only)

0 Kudos
AlexanderNohe1
Occasional Contributor III

I see what you are doing.  I am going to work with my colleagues on addressing this.

0 Kudos