@Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_scrollview);

    // Create new PullToRefreshAttacher
    mPullToRefreshAttacher = PullToRefreshAttacher.get(this);

    // Retrieve the PullToRefreshLayout from the content view
    PullToRefreshLayout ptrLayout = (PullToRefreshLayout) findViewById(R.id.ptr_layout);

    // Give the PullToRefreshAttacher to the PullToRefreshLayout, along with the refresh
    // listener (this).
    ptrLayout.setPullToRefreshAttacher(mPullToRefreshAttacher, this);

    // As we haven't set an explicit HeaderTransformer, we can safely cast the result of
    // getHeaderTransformer() to DefaultHeaderTransformer
    DefaultHeaderTransformer ht =
        (DefaultHeaderTransformer) mPullToRefreshAttacher.getHeaderTransformer();

    // As we're using a DefaultHeaderTransformer we can change the text which is displayed.
    // You should load these values from localised resources, but we'll just use static strings.
    ht.setPullText("Swipe Me!!!");
    ht.setRefreshingText("Refreshing :)");
  }
 private void checkIfUptodate() {
   if (rs3 != null && rs1 != null && rs3.length() == 0 && rs1.length() == 0) {
     Log.i(TAG, "Facebook Sync Completed with no changes");
     if (ptrl != null) {
       ptrl.setRefreshComplete();
     }
   } else if (rs3 == null && rs1 != null && rs1.length() == 0
       || rs1 == null && rs3 != null && rs3.length() == 0) {
     Log.i(TAG, "Facebook Sync Completed with no changes");
     if (ptrl != null) {
       ptrl.setRefreshComplete();
     }
   }
 }
 public int onStartCommand(Intent intent, int flags, int startId) {
   sp = PreferenceManager.getDefaultSharedPreferences(this);
   ptrl = AgendaNOW.getPtr_reference();
   if (ptrl != null) {
     ptrl.setRefreshing(true);
   }
   if (sp.getBoolean("fb_enable", false)) {
     res = getResources();
     syncFB();
   } else {
     if (ptrl != null) {
       ptrl.setRefreshComplete();
     }
   }
   return Service.START_REDELIVER_INTENT;
 }
 @Override
 public View onCreateView(
     LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   mPullToRefreshLayout =
       (PullToRefreshLayout) inflater.inflate(R.layout.fragment_user, container, false);
   mListView = (ListView) mPullToRefreshLayout.findViewById(R.id.list_fragment_user);
   mHeader = mPullToRefreshLayout.findViewById(R.id.header_fragment_user);
   mHeaderLogo = (ImageView) mPullToRefreshLayout.findViewById(R.id.header_logo_fragment_user);
   mName = (TextView) mPullToRefreshLayout.findViewById(R.id.txt_fragment_user_name);
   mDescription = (TextView) mPullToRefreshLayout.findViewById(R.id.txt_fragment_user_description);
   mPlaceHolderView =
       getActivity()
           .getLayoutInflater()
           .inflate(R.layout.view_header_placeholder, mListView, false);
   mListView.addHeaderView(mPlaceHolderView, null, false);
   mListView.setOnItemClickListener(this);
   return mPullToRefreshLayout;
 }
 private void checkIfFinished() {
   if (uChecksCounter == 0
       && iChecksCounter == 0
       && deletionCounter == 0
       && insertionCounter == 0
       && updateCounter == 0) {
     if (ptrl != null) {
       Log.i(TAG, "Facebook Sync Completed.");
       ptrl.setRefreshComplete();
     }
   }
 }
 @Override
 public void gDriveConnected(final boolean connected, final boolean canceled) {
   mPullToRefreshLayout.setRefreshing(false);
   if (connected) {
     statusText.setText(R.string.gDriveConnected);
     gDrive.getListOfBackups(GDriveBackupsAdapter);
   } else if (gDrive.isError()) {
     GDriveBackupsAdapter.clear();
     statusText.setText(gDrive.getErrorMessage());
   } else {
     GDriveBackupsAdapter.clear();
     statusText.setText(R.string.gDriveDisconnected);
   }
   getActivity().invalidateOptionsMenu();
 }
 @Override
 public void onDeleteComplete(int token, Object cookie, int result) {
   switch (token) {
     case DELETE_CANCELED_EV:
       Log.i("SyncService", "Canceled event deleted");
       deletionCounter--;
       if (deletionCounter == 0 && insertionCounter == 0 && updateCounter == 0) {
         Log.i(TAG, "Facebook Sync Completed");
         if (ptrl != null) {
           ptrl.setRefreshComplete();
         }
       }
       break;
   }
 }
 @Override
 public void onUpdateComplete(int token, Object cookie, int result) {
   switch (token) {
     case UPDATE_STORED_EV:
     case UPDATE_STORED_BD:
       Log.i(TAG, "Stored event updated");
       updateCounter--;
       if (deletionCounter == 0 && insertionCounter == 0 && updateCounter == 0) {
         Log.i(TAG, "Facebook Sync Completed");
         if (ptrl != null) {
           ptrl.setRefreshComplete();
         }
       }
       break;
   }
 }
 @Override
 public void onInsertComplete(int token, Object cookie, Uri uri) {
   switch (token) {
     case INSERT_NEW_EV:
     case INSERT_NEW_BD:
       Log.i(TAG, "New event inserted");
       insertionCounter--;
       if (deletionCounter == 0 && insertionCounter == 0 && updateCounter == 0) {
         Log.i(TAG, "Facebook Sync Completed");
         if (ptrl != null) {
           ptrl.setRefreshComplete();
         }
       }
       break;
   }
 }
 @Override
 public void showProgress(boolean inProgress, String text) {
   statusText.setText(text);
   mPullToRefreshLayout.setRefreshing(inProgress);
 }
 /*
  * Handling actions to execute on the completion of queries, updates, deletions, insertions.
  * Order of the operations:
  * 1) Querying for future FB events stored;
  * 2) Deletion of canceled FB events;
  * 3) For each event got from the JSON, check if there is a row to update
  *    or if there is no row: in the latter case, create it.
  *
  * NB: on completion of queries, updates, deletes, insertions the operation counters
  * are checked; if they are all set to 0, then sync process has been completed.
  * In this case, if there is a PTR layout active, then its animation is stopped.
  */
 @Override
 public void onQueryComplete(int token, Object cookie, Cursor cursor) {
   switch (token) {
     case QUERY_FUTURE_STORED_EVS:
       deleteCanceledEvents(cursor);
       for (int i = 0; i < rs1.length(); i++) {
         try {
           JSONObject ev = rs1.getJSONObject(i);
           queryEventToUpdate(ev);
           queryEventToInsert(ev);
         } catch (JSONException e1) {
           e1.printStackTrace();
         }
       }
       checkIfUptodate();
       break;
     case QUERY_FUTURE_STORED_BDS:
       deleteCanceledBdays(cursor);
       for (int i = 0; i < rs3.length(); i++) {
         try {
           JSONObject bd = rs3.getJSONObject(i);
           queryBdayToUpdate(bd);
           queryBdayToInsert(bd);
         } catch (JSONException e1) {
           e1.printStackTrace();
         }
       }
       checkIfUptodate();
       break;
     case QUERY_EV_TO_UPDATE:
       CustomAsyncHandler updateHandler = new CustomAsyncHandler(getContentResolver(), this);
       if (cursor.getCount() > 0) {
         cursor.moveToFirst();
         if (ptrl != null) {
           if (!ptrl.isRefreshing()) ptrl.setRefreshing(true);
         }
         updateCounter++;
         JSONObject ev = (JSONObject) cookie;
         String selection = null;
         try {
           selection =
               EventTable.COLUMN_PLATFORM
                   + " = \""
                   + EventTable.PLATFORM_FACEBOOK
                   + "\" AND "
                   + EventTable.COLUMN_BEGIN
                   + " >= "
                   + today_begin.getTimeInMillis()
                   + " AND "
                   + EventTable.COLUMN_OID
                   + " = "
                   + ev.getString("eid")
                   + " AND "
                   + EventTable.COLUMN_UPDATED_TIME
                   + " <> "
                   + ev.getString("update_time");
           if (isAppLaunchStage) {
             selection += " AND " + EventTable.COLUMN_BEGIN + "<=" + today_end.getTimeInMillis();
           }
           updateHandler.startUpdate(
               UPDATE_STORED_EV,
               null,
               AgendaNowProvider.CONTENT_URI_EV,
               setContentValues(
                   ev,
                   UPDATE_STORED_EV,
                   cursor.getString(cursor.getColumnIndex(EventTable.COLUMN_PIC_URL))),
               selection,
               null);
         } catch (JSONException e) {
           e.printStackTrace();
         }
       }
       cursor.close();
       uChecksCounter--;
       checkIfFinished();
       break;
     case QUERY_BD_TO_UPDATE:
       CustomAsyncHandler updateHandler2 = new CustomAsyncHandler(getContentResolver(), this);
       if (cursor.getCount() > 0) {
         cursor.moveToFirst();
         if (ptrl != null) {
           if (!ptrl.isRefreshing()) ptrl.setRefreshing(true);
         }
         updateCounter++;
         JSONObject bd = (JSONObject) cookie;
         String selection = null;
         try {
           selection =
               EventTable.COLUMN_CALENDAR_ID
                   + " = \""
                   + EventTable.CALENDAR_ID_FB_BIRTHDAYS
                   + "\" AND "
                   + EventTable.COLUMN_OID
                   + " = "
                   + bd.getString("uid");
           updateHandler2.startUpdate(
               UPDATE_STORED_BD,
               null,
               AgendaNowProvider.CONTENT_URI_EV,
               setContentValues(
                   bd,
                   UPDATE_STORED_BD,
                   cursor.getString(cursor.getColumnIndex(EventTable.COLUMN_PIC_URL))),
               selection,
               null);
         } catch (JSONException e) {
           e.printStackTrace();
         }
       }
       cursor.close();
       uChecksCounter--;
       checkIfFinished();
       break;
     case QUERY_EV_TO_INSERT:
       CustomAsyncHandler insertHandler = new CustomAsyncHandler(getContentResolver(), this);
       if (cursor.getCount() < 1) {
         if (ptrl != null) {
           if (!ptrl.isRefreshing()) ptrl.setRefreshing(true);
         }
         insertionCounter++;
         JSONObject ev = (JSONObject) cookie;
         try {
           insertHandler.startInsert(
               INSERT_NEW_EV,
               null,
               AgendaNowProvider.CONTENT_URI_EV,
               setContentValues(ev, INSERT_NEW_EV, null));
         } catch (JSONException e) {
           e.printStackTrace();
         }
       }
       cursor.close();
       iChecksCounter--;
       checkIfFinished();
       break;
     case 101:
       CustomAsyncHandler insertHandler2 = new CustomAsyncHandler(getContentResolver(), this);
       if (cursor.getCount() < 1) {
         if (ptrl != null) {
           if (!ptrl.isRefreshing()) ptrl.setRefreshing(true);
         }
         insertionCounter++;
         JSONObject bd = (JSONObject) cookie;
         try {
           insertHandler2.startInsert(
               INSERT_NEW_BD,
               null,
               AgendaNowProvider.CONTENT_URI_EV,
               setContentValues(bd, INSERT_NEW_BD, null));
         } catch (JSONException e) {
           e.printStackTrace();
         }
       }
       cursor.close();
       iChecksCounter--;
       checkIfFinished();
       break;
   }
 }
 @Override
 public void onCompleted(Response response) {
   /*
    * Check on FB session: if active one is null,
    * then die and optionally show a Toast (if FB sync is enabled).
    */
   if (Session.openActiveSessionFromCache(getApplication()) == null) {
     Toast.makeText(getApplicationContext(), R.string.fb_login_missing, Toast.LENGTH_LONG)
         .show();
     if (ptrl != null) {
       ptrl.setRefreshComplete();
     }
     return;
   }
   json = null;
   /*
    * Extracting JSON object embedded to the returned graph object.
    * Dying on null response, and, if running in foreground, showing a Toast.
    */
   if (response == null
       || response.getGraphObject() == null
       || response.getGraphObject().getInnerJSONObject() == null) {
     if (ptrl != null) {
       ptrl.setRefreshComplete();
       Toast.makeText(getApplicationContext(), R.string.network_error, Toast.LENGTH_SHORT)
           .show();
     }
     return;
   }
   // At this point, JSON object can be retrieved and split in two result sets (one per
   // query).
   json = response.getGraphObject().getInnerJSONObject();
   JSONArray jArray;
   try {
     jArray = json.getJSONArray("data");
     //					Log.i(TAG, jArray.toString());
     JSONObject o1 = jArray.getJSONObject(0);
     if (jArray.length() == 1) { // then  only birthdays are being imported
       rs3 = o1.getJSONArray("fql_result_set");
     } else {
       if (o1.getString("name").equals("birthdays")) {
         rs3 = o1.getJSONArray("fql_result_set");
       } else {
         if (o1.getString("name").equals("events")) {
           rs1 = o1.getJSONArray("fql_result_set");
         } else {
           rs2 = o1.getJSONArray("fql_result_set");
         }
       }
       JSONObject o2 = jArray.getJSONObject(1);
       if (o2.getString("name").equals("events")) {
         rs1 = o2.getJSONArray("fql_result_set");
       } else {
         if (o2.getString("name").equals("eventcreators")) {
           rs2 = o2.getJSONArray("fql_result_set");
         } else {
           rs3 = o2.getJSONArray("fql_result_set");
         }
       }
       if (jArray.length() > 2) {
         JSONObject o3 = jArray.getJSONObject(2);
         if (o3.getString("name").equals("eventcreators")) {
           rs2 = o3.getJSONArray("fql_result_set");
         } else {
           if (o3.getString("name").equals("birthdays")) {
             rs3 = o3.getJSONArray("fql_result_set");
           } else {
             rs1 = o3.getJSONArray("fql_result_set");
           }
         }
       }
     }
   } catch (JSONException e) {
     Log.wtf(TAG, "Something is wrong with JSON response");
   }
   // Now we can start CRUD operations on provider.
   //				Log.i("rs1", rs1.toString());
   //				Log.i("rs2", rs2.toString());
   Log.i("rs3", rs3.toString());
   if (rs1 != null) queryFutureStoredEvents();
   if (rs3 != null) queryFutureStoredBDays();
 }