Search in sources :

Example 11 with Continuation

use of bolts.Continuation in project facebook-android-sdk by facebook.

the class FacebookAppLinkResolverTests method executeResolverOnBlockerThread.

public void executeResolverOnBlockerThread(final FacebookAppLinkResolver resolver, final Uri testUrl) {
    final TestBlocker blocker = getTestBlocker();
    Runnable runnable = new Runnable() {

        public void run() {
            try {
                resolveTask = resolver.getAppLinkFromUrlInBackground(testUrl);
                resolveTask.continueWith(new Continuation() {

                    @Override
                    public Object then(Task task) throws Exception {
                        // Once the task is complete, unblock the test thread, so it can inspect for errors/results.
                        blocker.signal();
                        return null;
                    }
                });
            } catch (Exception e) {
                // Get back to the test case if there was an uncaught exception
                blocker.signal();
            }
        }
    };
    Handler handler = new Handler(blocker.getLooper());
    handler.post(runnable);
}
Also used : Continuation(bolts.Continuation) Task(bolts.Task) Handler(android.os.Handler)

Example 12 with Continuation

use of bolts.Continuation in project Parse-SDK-Android by ParsePlatform.

the class ParseCommandCache method maybeRunAllCommandsNow.

/**
   * Attempts to run every command in the disk queue in order, synchronously. If there is no network
   * connection, returns immediately without doing anything. If there is supposedly a connection,
   * but parse can't be reached, waits timeoutRetryWaitSeconds before retrying up to
   * retriesRemaining times. Blocks until either there's a connection, or the retries are exhausted.
   * If any command fails, just deletes it and moves on to the next one.
   */
private void maybeRunAllCommandsNow(int retriesRemaining) {
    synchronized (lock) {
        unprocessedCommandsExist = false;
        if (!isConnected()) {
            // There's no way to do work when there's no network connection.
            return;
        }
        String[] fileNames = cachePath.list();
        if (fileNames == null || fileNames.length == 0) {
            return;
        }
        Arrays.sort(fileNames);
        for (String fileName : fileNames) {
            final File file = new File(cachePath, fileName);
            // Read one command from the cache.
            JSONObject json;
            try {
                json = ParseFileUtils.readFileToJSONObject(file);
            } catch (FileNotFoundException e) {
                // This shouldn't really be possible.
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "File disappeared from cache while being read.", e);
                }
                continue;
            } catch (IOException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Unable to read contents of file in cache.", e);
                }
                removeFile(file);
                continue;
            } catch (JSONException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Error parsing JSON found in cache.", e);
                }
                removeFile(file);
                continue;
            }
            // Convert the command from a string.
            final ParseRESTCommand command;
            final TaskCompletionSource<JSONObject> tcs = pendingTasks.containsKey(file) ? pendingTasks.get(file) : null;
            try {
                command = commandFromJSON(json);
            } catch (JSONException e) {
                if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                    log.log(Level.SEVERE, "Unable to create ParseCommand from JSON.", e);
                }
                removeFile(file);
                continue;
            }
            try {
                Task<JSONObject> commandTask;
                if (command == null) {
                    commandTask = Task.forResult(null);
                    if (tcs != null) {
                        tcs.setResult(null);
                    }
                    notifyTestHelper(TestHelper.COMMAND_OLD_FORMAT_DISCARDED);
                } else {
                    commandTask = command.executeAsync(httpClient).continueWithTask(new Continuation<JSONObject, Task<JSONObject>>() {

                        @Override
                        public Task<JSONObject> then(Task<JSONObject> task) throws Exception {
                            String localId = command.getLocalId();
                            Exception error = task.getError();
                            if (error != null) {
                                if (error instanceof ParseException && ((ParseException) error).getCode() == ParseException.CONNECTION_FAILED) {
                                // do nothing
                                } else {
                                    if (tcs != null) {
                                        tcs.setError(error);
                                    }
                                }
                                return task;
                            }
                            JSONObject json = task.getResult();
                            if (tcs != null) {
                                tcs.setResult(json);
                            } else if (localId != null) {
                                // If this command created a new objectId, add it to the map.
                                String objectId = json.optString("objectId", null);
                                if (objectId != null) {
                                    ParseCorePlugins.getInstance().getLocalIdManager().setObjectId(localId, objectId);
                                }
                            }
                            return task;
                        }
                    });
                }
                waitForTaskWithoutLock(commandTask);
                if (tcs != null) {
                    waitForTaskWithoutLock(tcs.getTask());
                }
                // The command succeeded. Remove it from the cache.
                removeFile(file);
                notifyTestHelper(TestHelper.COMMAND_SUCCESSFUL);
            } catch (ParseException e) {
                if (e.getCode() == ParseException.CONNECTION_FAILED) {
                    if (retriesRemaining > 0) {
                        // Parse. Wait N minutes, or until we get signaled again before doing anything else.
                        if (Parse.LOG_LEVEL_INFO >= Parse.getLogLevel()) {
                            log.info("Network timeout in command cache. Waiting for " + timeoutRetryWaitSeconds + " seconds and then retrying " + retriesRemaining + " times.");
                        }
                        long currentTime = System.currentTimeMillis();
                        long waitUntil = currentTime + (long) (timeoutRetryWaitSeconds * 1000);
                        while (currentTime < waitUntil) {
                            // or should stop, just quit.
                            if (!isConnected() || shouldStop) {
                                if (Parse.LOG_LEVEL_INFO >= Parse.getLogLevel()) {
                                    log.info("Aborting wait because runEventually thread should stop.");
                                }
                                return;
                            }
                            try {
                                lock.wait(waitUntil - currentTime);
                            } catch (InterruptedException ie) {
                                shouldStop = true;
                            }
                            currentTime = System.currentTimeMillis();
                            if (currentTime < (waitUntil - (long) (timeoutRetryWaitSeconds * 1000))) {
                                // This situation should be impossible, so it must mean the clock changed.
                                currentTime = (waitUntil - (long) (timeoutRetryWaitSeconds * 1000));
                            }
                        }
                        maybeRunAllCommandsNow(retriesRemaining - 1);
                    } else {
                        setConnected(false);
                        notifyTestHelper(TestHelper.NETWORK_DOWN);
                    }
                } else {
                    if (Parse.LOG_LEVEL_ERROR >= Parse.getLogLevel()) {
                        log.log(Level.SEVERE, "Failed to run command.", e);
                    }
                    // Delete the command from the cache, even though it failed.
                    // Otherwise, we'll just keep trying it forever.
                    removeFile(file);
                    notifyTestHelper(TestHelper.COMMAND_FAILED, e);
                }
            }
        }
    }
}
Also used : Continuation(bolts.Continuation) Task(bolts.Task) FileNotFoundException(java.io.FileNotFoundException) JSONException(org.json.JSONException) IOException(java.io.IOException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) JSONException(org.json.JSONException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JSONObject(org.json.JSONObject) File(java.io.File)

Example 13 with Continuation

use of bolts.Continuation in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method saveLocallyAsync.

/**
   * Stores a single object in the local database. If the object is a pointer, isn't dirty, and has
   * an objectId already, it may not be saved, since it would provide no useful data.
   *
   * @param object
   *          The object to save.
   * @param db
   *          A database connection to use.
   */
private Task<Void> saveLocallyAsync(final String key, final ParseObject object, final ParseSQLiteDatabase db) {
    // If this is just a clean, unfetched pointer known to Parse, then there is nothing to save.
    if (object.getObjectId() != null && !object.isDataAvailable() && !object.hasChanges() && !object.hasOutstandingOperations()) {
        return Task.forResult(null);
    }
    final Capture<String> uuidCapture = new Capture<>();
    // Make sure we have a UUID for the object to be saved.
    return getOrCreateUUIDAsync(object, db).onSuccessTask(new Continuation<String, Task<Void>>() {

        @Override
        public Task<Void> then(Task<String> task) throws Exception {
            String uuid = task.getResult();
            uuidCapture.set(uuid);
            return updateDataForObjectAsync(uuid, object, db);
        }
    }).onSuccessTask(new Continuation<Void, Task<Void>>() {

        @Override
        public Task<Void> then(Task<Void> task) throws Exception {
            final ContentValues values = new ContentValues();
            values.put(OfflineSQLiteOpenHelper.KEY_KEY, key);
            values.put(OfflineSQLiteOpenHelper.KEY_UUID, uuidCapture.get());
            return db.insertWithOnConflict(OfflineSQLiteOpenHelper.TABLE_DEPENDENCIES, values, SQLiteDatabase.CONFLICT_IGNORE);
        }
    });
}
Also used : ContentValues(android.content.ContentValues) Continuation(bolts.Continuation) Task(bolts.Task) Capture(bolts.Capture) JSONException(org.json.JSONException)

Example 14 with Continuation

use of bolts.Continuation in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method getOrCreateUUIDAsync.

/**
   * Gets the UUID for the given object, if it has one. Otherwise, creates a new UUID for the object
   * and adds a new row to the database for the object with no data.
   */
private Task<String> getOrCreateUUIDAsync(final ParseObject object, ParseSQLiteDatabase db) {
    final String newUUID = UUID.randomUUID().toString();
    final TaskCompletionSource<String> tcs = new TaskCompletionSource<>();
    synchronized (lock) {
        Task<String> uuidTask = objectToUuidMap.get(object);
        if (uuidTask != null) {
            return uuidTask;
        }
        // The object doesn't have a UUID yet, so we're gonna have to make one.
        objectToUuidMap.put(object, tcs.getTask());
        uuidToObjectMap.put(newUUID, object);
        fetchedObjects.put(object, tcs.getTask().onSuccess(new Continuation<String, ParseObject>() {

            @Override
            public ParseObject then(Task<String> task) throws Exception {
                return object;
            }
        }));
    }
    /*
     * We need to put a placeholder row in the database so that later on, the save can just be an
     * update. This could be a pointer to an object that itself never gets saved offline, in which
     * case the consumer will just have to deal with that.
     */
    ContentValues values = new ContentValues();
    values.put(OfflineSQLiteOpenHelper.KEY_UUID, newUUID);
    values.put(OfflineSQLiteOpenHelper.KEY_CLASS_NAME, object.getClassName());
    db.insertOrThrowAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, values).continueWith(new Continuation<Void, Void>() {

        @Override
        public Void then(Task<Void> task) throws Exception {
            // This will signal that the UUID does represent a row in the database.
            tcs.setResult(newUUID);
            return null;
        }
    });
    return tcs.getTask();
}
Also used : ContentValues(android.content.ContentValues) TaskCompletionSource(bolts.TaskCompletionSource) Continuation(bolts.Continuation) Task(bolts.Task) JSONException(org.json.JSONException)

Example 15 with Continuation

use of bolts.Continuation in project Parse-SDK-Android by ParsePlatform.

the class Parse method initialize.

public static void initialize(Configuration configuration) {
    // NOTE (richardross): We will need this here, as ParsePlugins uses the return value of
    // isLocalDataStoreEnabled() to perform additional behavior.
    isLocalDatastoreEnabled = configuration.localDataStoreEnabled;
    ParsePlugins.Android.initialize(configuration.context, configuration.applicationId, configuration.clientKey);
    try {
        ParseRESTCommand.server = new URL(configuration.server);
    } catch (MalformedURLException ex) {
        throw new RuntimeException(ex);
    }
    Context applicationContext = configuration.context.getApplicationContext();
    ParseHttpClient.setKeepAlive(true);
    ParseHttpClient.setMaxConnections(20);
    // If we have interceptors in list, we have to initialize all http clients and add interceptors
    if (configuration.interceptors != null && configuration.interceptors.size() > 0) {
        initializeParseHttpClientsWithParseNetworkInterceptors(configuration.interceptors);
    }
    ParseObject.registerParseSubclasses();
    if (configuration.localDataStoreEnabled) {
        offlineStore = new OfflineStore(configuration.context);
    } else {
        ParseKeyValueCache.initialize(configuration.context);
    }
    // Make sure the data on disk for Parse is for the current
    // application.
    checkCacheApplicationId();
    final Context context = configuration.context;
    Task.callInBackground(new Callable<Void>() {

        @Override
        public Void call() throws Exception {
            getEventuallyQueue(context);
            return null;
        }
    });
    ParseFieldOperations.registerDefaultDecoders();
    if (!allParsePushIntentReceiversInternal()) {
        throw new SecurityException("To prevent external tampering to your app's notifications, " + "all receivers registered to handle the following actions must have " + "their exported attributes set to false: com.parse.push.intent.RECEIVE, " + "com.parse.push.intent.OPEN, com.parse.push.intent.DELETE");
    }
    // May need to update GCM registration ID if app version has changed.
    // This also primes current installation.
    GcmRegistrar.getInstance().registerAsync().continueWithTask(new Continuation<Void, Task<Void>>() {

        @Override
        public Task<Void> then(Task<Void> task) throws Exception {
            // Prime current user in the background
            return ParseUser.getCurrentUserAsync().makeVoid();
        }
    }).continueWith(new Continuation<Void, Void>() {

        @Override
        public Void then(Task<Void> task) throws Exception {
            // Prime config in the background
            ParseConfig.getCurrentConfig();
            return null;
        }
    }, Task.BACKGROUND_EXECUTOR);
    if (ManifestInfo.getPushType() == PushType.PPNS) {
        PushService.startServiceIfRequired(applicationContext);
    }
    dispatchOnParseInitialized();
    // FYI we probably don't want to do this if we ever add other callbacks.
    synchronized (MUTEX_CALLBACKS) {
        Parse.callbacks = null;
    }
}
Also used : Context(android.content.Context) MalformedURLException(java.net.MalformedURLException) Continuation(bolts.Continuation) Task(bolts.Task) URL(java.net.URL) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Aggregations

Continuation (bolts.Continuation)22 Task (bolts.Task)22 JSONException (org.json.JSONException)9 ArrayList (java.util.ArrayList)8 JSONObject (org.json.JSONObject)8 CancellationException (java.util.concurrent.CancellationException)6 AggregateException (bolts.AggregateException)4 Capture (bolts.Capture)4 IOException (java.io.IOException)4 TaskCompletionSource (bolts.TaskCompletionSource)3 File (java.io.File)3 Callable (java.util.concurrent.Callable)3 ContentValues (android.content.ContentValues)2 Cursor (android.database.Cursor)2 QueryConstraints (com.parse.ParseQuery.QueryConstraints)2 FileNotFoundException (java.io.FileNotFoundException)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 HashMap (java.util.HashMap)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2