Search in sources :

Example 1 with TaskCompletionSource

use of com.parse.boltsinternal.TaskCompletionSource in project Parse-SDK-Android by ParsePlatform.

the class FacebookController method authenticateAsync.

public Task<Map<String, String>> authenticateAsync(Activity activity, Fragment fragment, LoginAuthorizationType authorizationType, Collection<String> permissions) {
    if (callbackManager != null) {
        // This should never happen since FB auth takes over UI and starts an Activity
        return Task.forError(new RuntimeException("Unable to authenticate when another authentication is in process"));
    }
    final TaskCompletionSource<Map<String, String>> tcs = new TaskCompletionSource<>();
    LoginManager manager = facebookSdkDelegate.getLoginManager();
    callbackManager = facebookSdkDelegate.createCallbackManager();
    manager.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {

        @Override
        public void onSuccess(LoginResult loginResult) {
            AccessToken accessToken = loginResult.getAccessToken();
            Map<String, String> authData = getAuthData(accessToken);
            tcs.trySetResult(authData);
        }

        @Override
        public void onCancel() {
            tcs.trySetCancelled();
        }

        @Override
        public void onError(@NonNull FacebookException e) {
            tcs.trySetError(e);
        }
    });
    if (LoginAuthorizationType.PUBLISH.equals(authorizationType)) {
        if (fragment != null) {
            manager.logInWithPublishPermissions(fragment, callbackManager, permissions);
        } else {
            manager.logInWithPublishPermissions(activity, permissions);
        }
    } else {
        if (fragment != null) {
            manager.logInWithReadPermissions(fragment, callbackManager, permissions);
        } else {
            manager.logInWithReadPermissions(activity, permissions);
        }
    }
    return tcs.getTask();
}
Also used : TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) LoginManager(com.facebook.login.LoginManager) AccessToken(com.facebook.AccessToken) FacebookException(com.facebook.FacebookException) LoginResult(com.facebook.login.LoginResult) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with TaskCompletionSource

use of com.parse.boltsinternal.TaskCompletionSource in project Parse-SDK-Android by ParsePlatform.

the class OfflineStore method fetchLocallyAsync.

/**
 * Gets the data for the given object from the offline database. Returns a task that will be
 * completed if data for the object was available. If the object is not in the cache, the task
 * will be faulted, with a CACHE_MISS error.
 *
 * @param object The object to fetch.
 * @param db A database connection to use.
 */
/* package for OfflineQueryLogic */
<T extends ParseObject> Task<T> fetchLocallyAsync(final T object, final ParseSQLiteDatabase db) {
    final TaskCompletionSource<T> tcs = new TaskCompletionSource<>();
    Task<String> uuidTask;
    synchronized (lock) {
        if (fetchedObjects.containsKey(object)) {
            // noinspection unchecked
            return (Task<T>) fetchedObjects.get(object);
        }
        /*
             * Put a placeholder so that anyone else who attempts to fetch this object will just wait for
             * this call to finish doing it.
             */
        // noinspection unchecked
        fetchedObjects.put(object, (Task<ParseObject>) tcs.getTask());
        uuidTask = objectToUuidMap.get(object);
    }
    String className = object.getClassName();
    String objectId = object.getObjectId();
    /*
         * If this gets set, then it will contain data from the offline store that needs to be merged
         * into the existing object in memory.
         */
    Task<String> jsonStringTask = Task.forResult(null);
    if (objectId == null) {
        // This Object has never been saved to Parse.
        if (uuidTask == null) {
        /*
                 * This object was not pulled from the data store or previously saved to it, so there's
                 * nothing that can be fetched from it. This isn't an error, because it's really convenient
                 * to try to fetch objects from the offline store just to make sure they are up-to-date, and
                 * we shouldn't force developers to specially handle this case.
                 */
        } else {
            /*
                 * This object is a new ParseObject that is known to the data store, but hasn't been
                 * fetched. The only way this could happen is if the object had previously been stored in
                 * the offline store, then the object was removed from memory (maybe by rebooting), and then
                 * a object with a pointer to it was fetched, so we only created the pointer. We need to
                 * pull the data out of the database using the UUID.
                 */
            final String[] select = { OfflineSQLiteOpenHelper.KEY_JSON };
            final String where = OfflineSQLiteOpenHelper.KEY_UUID + " = ?";
            final Capture<String> uuid = new Capture<>();
            jsonStringTask = uuidTask.onSuccessTask(task -> {
                uuid.set(task.getResult());
                String[] args = { uuid.get() };
                return db.queryAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, select, where, args);
            }).onSuccess(task -> {
                Cursor cursor = task.getResult();
                cursor.moveToFirst();
                if (cursor.isAfterLast()) {
                    cursor.close();
                    throw new IllegalStateException("Attempted to find non-existent uuid " + uuid.get());
                }
                String json = cursor.getString(0);
                cursor.close();
                return json;
            });
        }
    } else {
        if (uuidTask != null) {
            /*
                 * This object is an existing ParseObject, and we must've already pulled its data out of the
                 * offline store, or else we wouldn't know its UUID. This should never happen.
                 */
            tcs.setError(new IllegalStateException("This object must have already been " + "fetched from the local datastore, but isn't marked as fetched."));
            synchronized (lock) {
                // Forget we even tried to fetch this object, so that retries will actually...
                // retry.
                fetchedObjects.remove(object);
            }
            return tcs.getTask();
        }
        /*
             * We've got a pointer to an existing ParseObject, but we've never pulled its data out of the
             * offline store. Since fetching from the server forces a fetch from the offline store, that
             * means this is a pointer. We need to try to find any existing entry for this object in the
             * database.
             */
        String[] select = { OfflineSQLiteOpenHelper.KEY_JSON, OfflineSQLiteOpenHelper.KEY_UUID };
        String where = String.format("%s = ? AND %s = ?", OfflineSQLiteOpenHelper.KEY_CLASS_NAME, OfflineSQLiteOpenHelper.KEY_OBJECT_ID);
        String[] args = { className, objectId };
        jsonStringTask = db.queryAsync(OfflineSQLiteOpenHelper.TABLE_OBJECTS, select, where, args).onSuccess(task -> {
            Cursor cursor = task.getResult();
            cursor.moveToFirst();
            if (cursor.isAfterLast()) {
                /*
                                             * This is a pointer that came from Parse that references an object that has
                                             * never been saved in the offline store before. This just means there's no data
                                             * in the store that needs to be merged into the object.
                                             */
                cursor.close();
                throw new ParseException(ParseException.CACHE_MISS, "This object is not available in the offline cache.");
            }
            // we should fetch its data and record its UUID for future
            // reference.
            String jsonString = cursor.getString(0);
            String newUUID = cursor.getString(1);
            cursor.close();
            synchronized (lock) {
                /*
                                             * It's okay to put this object into the uuid map. No one will try to fetch
                                             * it, because it's already in the fetchedObjects map. And no one will try to
                                             * save to it without fetching it first, so everything should be just fine.
                                             */
                objectToUuidMap.put(object, Task.forResult(newUUID));
                uuidToObjectMap.put(newUUID, object);
            }
            return jsonString;
        });
    }
    return jsonStringTask.onSuccessTask((Continuation<String, Task<Void>>) task -> {
        String jsonString = task.getResult();
        if (jsonString == null) {
            return Task.forError(new ParseException(ParseException.CACHE_MISS, "Attempted to fetch an object offline which was never saved to the offline cache."));
        }
        final JSONObject json;
        try {
            json = new JSONObject(jsonString);
        } catch (JSONException e) {
            return Task.forError(e);
        }
        final Map<String, Task<ParseObject>> offlineObjects = new HashMap<>();
        (new ParseTraverser() {

            @Override
            protected boolean visit(Object object1) {
                if (object1 instanceof JSONObject && ((JSONObject) object1).optString("__type").equals("OfflineObject")) {
                    String uuid = ((JSONObject) object1).optString("uuid");
                    offlineObjects.put(uuid, getPointerAsync(uuid, db));
                }
                return true;
            }
        }).setTraverseParseObjects(false).setYieldRoot(false).traverse(json);
        return Task.whenAll(offlineObjects.values()).onSuccess(task1 -> {
            object.mergeREST(object.getState(), json, new OfflineDecoder(offlineObjects));
            return null;
        });
    }).continueWithTask(task -> {
        if (task.isCancelled()) {
            tcs.setCancelled();
        } else if (task.isFaulted()) {
            tcs.setError(task.getError());
        } else {
            tcs.setResult(object);
        }
        return tcs.getTask();
    });
}
Also used : Context(android.content.Context) Arrays(java.util.Arrays) ConstraintMatcher(com.parse.OfflineQueryLogic.ConstraintMatcher) Pair(android.util.Pair) TextUtils(android.text.TextUtils) HashMap(java.util.HashMap) UUID(java.util.UUID) ArrayList(java.util.ArrayList) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) List(java.util.List) JSONException(org.json.JSONException) Capture(com.parse.boltsinternal.Capture) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Map(java.util.Map) ContentValues(android.content.ContentValues) LinkedList(java.util.LinkedList) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) WeakHashMap(java.util.WeakHashMap) Cursor(android.database.Cursor) Task(com.parse.boltsinternal.Task) Continuation(com.parse.boltsinternal.Continuation) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) JSONException(org.json.JSONException) Cursor(android.database.Cursor) Capture(com.parse.boltsinternal.Capture) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) JSONObject(org.json.JSONObject) JSONObject(org.json.JSONObject)

Example 3 with TaskCompletionSource

use of com.parse.boltsinternal.TaskCompletionSource in project Parse-SDK-Android by ParsePlatform.

the class LocationNotifier method getCurrentLocationAsync.

/**
 * Asynchronously gets the current location of the device.
 *
 * <p>This will request location updates from the best provider that match the given criteria
 * and return the first location received.
 *
 * <p>You can customize the criteria to meet your specific needs. * For higher accuracy, you can
 * set {@link Criteria#setAccuracy(int)}, however result in longer times for a fix. * For better
 * battery efficiency and faster location fixes, you can set {@link
 * Criteria#setPowerRequirement(int)}, however, this will result in lower accuracy.
 *
 * @param context The context used to request location updates.
 * @param timeout The number of milliseconds to allow before timing out.
 * @param criteria The application criteria for selecting a location provider.
 * @see android.location.LocationManager#getBestProvider(android.location.Criteria, boolean)
 * @see android.location.LocationManager#requestLocationUpdates(String, long, float,
 *     android.location.LocationListener)
 */
/* package */
static Task<Location> getCurrentLocationAsync(Context context, long timeout, Criteria criteria) {
    final TaskCompletionSource<Location> tcs = new TaskCompletionSource<>();
    final Capture<ScheduledFuture<?>> timeoutFuture = new Capture<>();
    final LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    final LocationListener listener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            if (location == null) {
                return;
            }
            timeoutFuture.get().cancel(true);
            tcs.trySetResult(location);
            manager.removeUpdates(this);
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };
    timeoutFuture.set(ParseExecutors.scheduled().schedule(() -> {
        tcs.trySetError(new ParseException(ParseException.TIMEOUT, "Location fetch timed out."));
        manager.removeUpdates(listener);
    }, timeout, TimeUnit.MILLISECONDS));
    String provider = manager.getBestProvider(criteria, true);
    if (provider != null) {
        manager.requestLocationUpdates(provider, /* minTime */
        0, /* minDistance */
        0.0f, listener);
    }
    if (fakeLocation != null) {
        listener.onLocationChanged(fakeLocation);
    }
    return tcs.getTask();
}
Also used : LocationManager(android.location.LocationManager) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) Bundle(android.os.Bundle) LocationListener(android.location.LocationListener) ScheduledFuture(java.util.concurrent.ScheduledFuture) Capture(com.parse.boltsinternal.Capture) Location(android.location.Location)

Example 4 with TaskCompletionSource

use of com.parse.boltsinternal.TaskCompletionSource in project Parse-SDK-Android by ParsePlatform.

the class ParseRequest method executeAsync.

private Task<Response> executeAsync(final ParseHttpClient client, final ParseHttpRequest request, final int attemptsMade, final long delay, final ProgressCallback downloadProgressCallback, final Task<Void> cancellationToken) {
    if (cancellationToken != null && cancellationToken.isCancelled()) {
        return Task.cancelled();
    }
    return sendOneRequestAsync(client, request, downloadProgressCallback).continueWithTask(task -> {
        Exception e = task.getError();
        if (task.isFaulted() && e instanceof ParseException) {
            if (cancellationToken != null && cancellationToken.isCancelled()) {
                return Task.cancelled();
            }
            if (e instanceof ParseRequestException && ((ParseRequestException) e).isPermanentFailure) {
                return task;
            }
            if (attemptsMade < maxRetries()) {
                PLog.i("com.parse.ParseRequest", "Request failed. Waiting " + delay + " milliseconds before attempt #" + (attemptsMade + 1));
                final TaskCompletionSource<Response> retryTask = new TaskCompletionSource<>();
                ParseExecutors.scheduled().schedule(() -> {
                    executeAsync(client, request, attemptsMade + 1, delay * 2, downloadProgressCallback, cancellationToken).continueWithTask((Continuation<Response, Task<Void>>) task1 -> {
                        if (task1.isCancelled()) {
                            retryTask.setCancelled();
                        } else if (task1.isFaulted()) {
                            retryTask.setError(task1.getError());
                        } else {
                            retryTask.setResult(task1.getResult());
                        }
                        return null;
                    });
                }, delay, TimeUnit.MILLISECONDS);
                return retryTask.getTask();
            }
        }
        return task;
    });
}
Also used : ParseHttpResponse(com.parse.http.ParseHttpResponse) ParseHttpRequest(com.parse.http.ParseHttpRequest) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) NonNull(androidx.annotation.NonNull) IOException(java.io.IOException) BlockingQueue(java.util.concurrent.BlockingQueue) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) TimeUnit(java.util.concurrent.TimeUnit) ParseHttpBody(com.parse.http.ParseHttpBody) Continuation(com.parse.boltsinternal.Continuation) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ThreadFactory(java.util.concurrent.ThreadFactory) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) ParseHttpResponse(com.parse.http.ParseHttpResponse) ExecutorService(java.util.concurrent.ExecutorService) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) Task(com.parse.boltsinternal.Task) IOException(java.io.IOException)

Example 5 with TaskCompletionSource

use of com.parse.boltsinternal.TaskCompletionSource in project Parse-SDK-Android by ParsePlatform.

the class ParseRESTObjectBatchCommand method executeBatch.

public static List<Task<JSONObject>> executeBatch(ParseHttpClient client, List<ParseRESTObjectCommand> commands, String sessionToken) {
    final int batchSize = commands.size();
    List<Task<JSONObject>> tasks = new ArrayList<>(batchSize);
    if (batchSize == 1) {
        // There's only one, just execute it
        tasks.add(commands.get(0).executeAsync(client));
        return tasks;
    }
    if (batchSize > COMMAND_OBJECT_BATCH_MAX_SIZE) {
        // There's more than the max, split it up into batches
        List<List<ParseRESTObjectCommand>> batches = Lists.partition(commands, COMMAND_OBJECT_BATCH_MAX_SIZE);
        for (int i = 0, size = batches.size(); i < size; i++) {
            List<ParseRESTObjectCommand> batch = batches.get(i);
            tasks.addAll(executeBatch(client, batch, sessionToken));
        }
        return tasks;
    }
    final List<TaskCompletionSource<JSONObject>> tcss = new ArrayList<>(batchSize);
    for (int i = 0; i < batchSize; i++) {
        TaskCompletionSource<JSONObject> tcs = new TaskCompletionSource<>();
        tcss.add(tcs);
        tasks.add(tcs.getTask());
    }
    JSONObject parameters = new JSONObject();
    JSONArray requests = new JSONArray();
    try {
        for (ParseRESTObjectCommand command : commands) {
            JSONObject requestParameters = new JSONObject();
            requestParameters.put("method", command.method.toString());
            requestParameters.put("path", new URL(server, command.httpPath).getPath());
            JSONObject body = command.jsonParameters;
            if (body != null) {
                requestParameters.put("body", body);
            }
            requests.put(requestParameters);
        }
        parameters.put("requests", requests);
    } catch (JSONException | MalformedURLException e) {
        throw new RuntimeException(e);
    }
    ParseRESTCommand command = new ParseRESTObjectBatchCommand("batch", ParseHttpRequest.Method.POST, parameters, sessionToken);
    command.executeAsync(client).continueWith((Continuation<JSONObject, Void>) task -> {
        TaskCompletionSource<JSONObject> tcs;
        if (task.isFaulted() || task.isCancelled()) {
            for (int i = 0; i < batchSize; i++) {
                tcs = tcss.get(i);
                if (task.isFaulted()) {
                    tcs.setError(task.getError());
                } else {
                    tcs.setCancelled();
                }
            }
        }
        JSONObject json = task.getResult();
        JSONArray results = json.getJSONArray(KEY_RESULTS);
        int resultLength = results.length();
        if (resultLength != batchSize) {
            for (int i = 0; i < batchSize; i++) {
                tcs = tcss.get(i);
                tcs.setError(new IllegalStateException("Batch command result count expected: " + batchSize + " but was: " + resultLength));
            }
        }
        for (int i = 0; i < batchSize; i++) {
            JSONObject result = results.getJSONObject(i);
            tcs = tcss.get(i);
            if (result.has("success")) {
                JSONObject success = result.getJSONObject("success");
                tcs.setResult(success);
            } else if (result.has("error")) {
                JSONObject error = result.getJSONObject("error");
                tcs.setError(new ParseException(error.getInt("code"), error.getString("error")));
            }
        }
        return null;
    });
    return tasks;
}
Also used : ParseHttpRequest(com.parse.http.ParseHttpRequest) MalformedURLException(java.net.MalformedURLException) URL(java.net.URL) IOException(java.io.IOException) ArrayList(java.util.ArrayList) List(java.util.List) JSONException(org.json.JSONException) Continuation(com.parse.boltsinternal.Continuation) JSONObject(org.json.JSONObject) Task(com.parse.boltsinternal.Task) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) ParseHttpResponse(com.parse.http.ParseHttpResponse) JSONArray(org.json.JSONArray) InputStream(java.io.InputStream) Task(com.parse.boltsinternal.Task) MalformedURLException(java.net.MalformedURLException) ArrayList(java.util.ArrayList) JSONArray(org.json.JSONArray) JSONException(org.json.JSONException) URL(java.net.URL) TaskCompletionSource(com.parse.boltsinternal.TaskCompletionSource) JSONObject(org.json.JSONObject) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

TaskCompletionSource (com.parse.boltsinternal.TaskCompletionSource)9 Continuation (com.parse.boltsinternal.Continuation)6 Task (com.parse.boltsinternal.Task)6 IOException (java.io.IOException)5 JSONObject (org.json.JSONObject)5 Capture (com.parse.boltsinternal.Capture)4 HashMap (java.util.HashMap)4 JSONException (org.json.JSONException)4 Context (android.content.Context)3 File (java.io.File)3 ArrayList (java.util.ArrayList)3 Arrays (java.util.Arrays)3 List (java.util.List)3 Map (java.util.Map)3 ContentValues (android.content.ContentValues)2 Cursor (android.database.Cursor)2 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)2 TextUtils (android.text.TextUtils)2 Pair (android.util.Pair)2 ConstraintMatcher (com.parse.OfflineQueryLogic.ConstraintMatcher)2