Android Open Source - android-memento Content Provider Operation Service






From Project

Back to project page android-memento.

License

The source code is released under:

Apache License

If you think the Android project android-memento listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * android-memento-lib https://github.com/twofortyfouram/android-memento
 * Copyright 2014 two forty four a.m. LLC
 */*from  w  w  w. j  a  v  a 2s .  co m*/
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.twofortyfouram.memento.provider;

import com.twofortyfouram.log.Lumberjack;
import com.twofortyfouram.spackle.util.bundle.BundleScrubber;

import net.jcip.annotations.ThreadSafe;

import android.app.IntentService;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.os.RemoteException;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import java.util.ArrayList;

/**
 * Perform a series of {@link ContentProviderOperation}s in a background thread.
 * The primary use case is to simplify improving UI performance. For example,
 * when the user hits the back button in an Activity that wants to save some
 * data. Rather than blocking the Activity (which is necessary to ensure the
 * process has enough priority to complete the save to disk), this service
 * provides an alternative way to raise the process's priority without blocking
 * the main thread for the disk write.
 * <p>
 * To use, call either
 * {@link #applyBatchWithAlternativeAsynchronous(Context, String, ArrayList, ArrayList)}
 * or
 * {@link #applyBatchWithAlternativeSynchronous(Context, String, ArrayList, ArrayList)}
 * .
 */
@ThreadSafe
public final class ContentProviderOperationService extends IntentService {

    /**
     * Type: {@code String}.
     * <p>
     * Authority for the operations to write.
     */
    @NonNull
    private static final String EXTRA_STRING_AUTHORITY = ContentProviderOperationService.class
            .getName() + ".extra.STRING_AUTHORITY"; //$NON-NLS-1$

    /**
     * Type: {@code ArrayList<ContentProviderOperation>}.
     * <p>
     * Set of Content Provider operations to apply.
     */
    @NonNull
    private static final String EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_PRIMARY =
            ContentProviderOperationService.class
                    .getName() + ".extra.PARCELABLE_ARRAY_LIST_OPERATIONS_PRIMARY"; //$NON-NLS-1$

    /**
     * Type: {@code ArrayList<ContentProviderOperation>}.
     * <p>
     * Set of optional alternative Content Provider operations to apply if
     * {@link #EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_PRIMARY} fail.
     */
    @NonNull
    private static final String EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_ALTERNATIVE =
            ContentProviderOperationService.class
                    .getName() + ".extra.PARCELABLE_ARRAY_LIST_OPERATIONS_ALTERNATIVE"; //$NON-NLS-1$


    /**
     * Construct a new ContentProviderService.
     */
    public ContentProviderOperationService() {
        super(ContentProviderOperationService.class.getName());

        /*
         * Redelivery is not desired, as that could cause duplicate
         * transactions.
         */
        setIntentRedelivery(false);
    }

    @Override
    protected void onHandleIntent(@Nullable final Intent intent) {
        BundleScrubber.scrub(intent);
        Lumberjack.v("Received %s", intent); //$NON-NLS-1$

        if (null != intent) {
            final String authority = intent.getStringExtra(EXTRA_STRING_AUTHORITY);
            final ArrayList<ContentProviderOperation> primaryOperations = intent
                    .getParcelableArrayListExtra(EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_PRIMARY);
            final ArrayList<ContentProviderOperation> alternativeOperations = intent
                    .getParcelableArrayListExtra(
                            EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_ALTERNATIVE);

            applyBatchWithAlternativeSynchronous(getApplicationContext(), authority,
                    primaryOperations, alternativeOperations);
        }
    }

    /**
     * Performs
     * {@link #applyBatchWithAlternativeSynchronous(Context, String, ArrayList, ArrayList)}
     * asynchronously. Operations are queued, so multiple calls to this method
     * are applied in the order that they were queued.
     *
     * @param context               Application context.
     * @param authority             Content Provider authority to use for all operations.
     * @param primaryOperations     A set of operations to perform.
     * @param alternativeOperations A set of operations to perform if
     *                              {@code primaryOperations} fail.
     */
    public static void applyBatchWithAlternativeAsynchronous(@NonNull final Context context,
            @NonNull final String authority,
            @NonNull final ArrayList<ContentProviderOperation> primaryOperations,
            @Nullable final ArrayList<ContentProviderOperation> alternativeOperations) {
        final Intent i = new Intent(context, ContentProviderOperationService.class);
        i.putExtra(EXTRA_STRING_AUTHORITY, authority);
        i.putExtra(EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_PRIMARY, primaryOperations);
        i.putExtra(EXTRA_PARCELABLE_ARRAY_LIST_OPERATIONS_ALTERNATIVE, alternativeOperations);

        context.startService(i);
    }

    /**
     * Synchronously applies a batch operation, with an alternative batch
     * operation if the first operation fails.
     *
     * @param context               Application context.
     * @param authority             Content Provider authority to use for all operations.
     * @param primaryOperations     A set of operations to perform.
     * @param alternativeOperations A set of operations to perform if
     *                              {@code primaryOperations} fail.
     */
    public static void applyBatchWithAlternativeSynchronous(@NonNull final Context context,
            @NonNull final String authority,
            @NonNull final ArrayList<ContentProviderOperation> primaryOperations,
            @Nullable final ArrayList<ContentProviderOperation> alternativeOperations) {
        final ContentResolver resolver = context.getContentResolver();

        try {
            resolver.applyBatch(authority, primaryOperations);
        } catch (final OperationApplicationException e) {
            if (null != alternativeOperations) {
                /*
                 * TODO: Ideally the primary and alternative operations would both occur in the same
                 * transaction, rather than two separate transactions.  This is impossible for
                 * standard Android ContentProvider objects which do not guarantee applyBatch() is
                 * atomic, but it might be possible if the provider is a local instance of
                 * AbstractSqliteContentProvider.
                 */
                try {
                    resolver.applyBatch(authority, alternativeOperations);
                } catch (final OperationApplicationException e2) {
                    Lumberjack.e("Error occurred during ContentProviderOperation%s",
                            e2); //$NON-NLS-1$
                } catch (final RemoteException e2) {
                    Lumberjack.e("Error occurred during ContentProviderOperation%s",
                            e2); //$NON-NLS-1$
                }
            }
        } catch (final RemoteException e) {
            Lumberjack.e("Error occurred during ContentProviderOperation%s", e); //$NON-NLS-1$
        }
    }
}




Java Source Code List

com.twofortyfouram.memento.debug.provider.SqliteContentProviderImpl.java
com.twofortyfouram.memento.debug.provider.SqliteOpenHelperImpl.java
com.twofortyfouram.memento.debug.provider.SqliteUriMatcherImpl.java
com.twofortyfouram.memento.debug.provider.TableOneContract.java
com.twofortyfouram.memento.provider.ContentChangeNotificationQueueTest.java
com.twofortyfouram.memento.provider.ContentChangeNotificationQueue.java
com.twofortyfouram.memento.provider.ContentProviderOperationServiceTest.java
com.twofortyfouram.memento.provider.ContentProviderOperationService.java
com.twofortyfouram.memento.provider.ContentProviderUtilTest.java
com.twofortyfouram.memento.provider.ContentProviderUtil.java
com.twofortyfouram.memento.provider.ImmutableUriMatcherTest.java
com.twofortyfouram.memento.provider.ImmutableUriMatcher.java
com.twofortyfouram.memento.provider.sqlite.AbstractSqliteContentProviderIntegrationTest.java
com.twofortyfouram.memento.provider.sqlite.AbstractSqliteContentProviderTest.java
com.twofortyfouram.memento.provider.sqlite.AbstractSqliteContentProvider.java
com.twofortyfouram.memento.provider.sqlite.SqliteColumnBuilderTest.java
com.twofortyfouram.memento.provider.sqlite.SqliteColumnBuilder.java
com.twofortyfouram.memento.provider.sqlite.SqliteIndexBuilderTest.java
com.twofortyfouram.memento.provider.sqlite.SqliteIndexBuilder.java
com.twofortyfouram.memento.provider.sqlite.SqliteOpenHelperCompat.java
com.twofortyfouram.memento.provider.sqlite.SqliteStorageClass.java
com.twofortyfouram.memento.provider.sqlite.SqliteTableBuilderTest.java
com.twofortyfouram.memento.provider.sqlite.SqliteTableBuilder.java
com.twofortyfouram.memento.provider.sqlite.SqliteUriMatchTest.java
com.twofortyfouram.memento.provider.sqlite.SqliteUriMatch.java
com.twofortyfouram.memento.provider.sqlite.SqliteUriMatcher.java