org.onepf.opfiab.OPFIab.java Source code

Java tutorial

Introduction

Here is the source code for org.onepf.opfiab.OPFIab.java

Source

/*
 * Copyright 2012-2015 One Platform Foundation
 *
 * 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 org.onepf.opfiab;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;

import org.onepf.opfiab.api.ActivityIabHelper;
import org.onepf.opfiab.api.AdvancedIabHelper;
import org.onepf.opfiab.api.FragmentIabHelper;
import org.onepf.opfiab.api.IabHelper;
import org.onepf.opfiab.api.SimpleIabHelper;
import org.onepf.opfiab.billing.BillingProvider;
import org.onepf.opfiab.model.Configuration;
import org.onepf.opfutils.OPFChecks;
import org.onepf.opfutils.OPFLog;
import org.onepf.opfutils.exception.InitException;

import java.util.Set;
import java.util.concurrent.Executors;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.EventBusException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * This class is OPFIab library entry point.
 * <p>
 * Before anything else, {@link #init(Application, Configuration)} must be called.
 * Multiple init() calls are supported.
 * <p>
 * Before utilizing library billing capabilities {@link BillingProvider} must be picked.
 * This might either be done with direct {@link #setup()} call or through the use of
 * {@link IabHelper} variant featuring lazy setup.
 * <p>
 * To execute billing operations one must interact with {@link IabHelper}.
 *
 * @see #getSimpleHelper()
 * @see #getAdvancedHelper()
 * @see #getFragmentHelper(android.support.v4.app.Fragment)
 * @see #getFragmentHelper(android.app.Fragment)
 * @see #getActivityHelper(android.support.v4.app.FragmentActivity)
 * @see #getActivityHelper(Activity)
 */
@SuppressWarnings("TypeMayBeWeakened")
public final class OPFIab {

    private static final EventBus EVENT_BUS = EventBus.builder()
            // Must use only one background thread
            .executorService(Executors.newSingleThreadExecutor()).throwSubscriberException(true)
            .eventInheritance(true).logSubscriberExceptions(OPFLog.isEnabled()).build();

    private static Context context;
    private static Configuration configuration;

    private static void checkInit() {
        OPFChecks.checkThread(true);
        if (configuration == null) {
            throw new InitException(false);
        }
    }

    static void register(@NonNull final Object subscriber) {
        if (!EVENT_BUS.isRegistered(subscriber)) {
            try {
                EVENT_BUS.register(subscriber);
            } catch (EventBusException exception) {
                OPFLog.d("", exception);
            }
        }
    }

    static void register(@NonNull final Object subscriber, final int priority) {
        if (!EVENT_BUS.isRegistered(subscriber)) {
            EVENT_BUS.register(subscriber, priority);
        }
    }

    static void unregister(@NonNull final Object subscriber) {
        if (EVENT_BUS.isRegistered(subscriber)) {
            EVENT_BUS.unregister(subscriber);
        }
    }

    /**
     * Posts event object for delivery to all subscribers.
     * Intend to be used by {@link BillingProvider} implementations.
     *
     * @param event Event object to deliver.
     *
     * @return True if event was delivered, false if it was skipped due to the lack of subscribers.
     */
    public static boolean post(@NonNull final Object event) {
        final boolean hasSubscriber = EVENT_BUS.hasSubscriberForEvent(event.getClass());
        if (hasSubscriber) {
            EVENT_BUS.post(event);
        } else {
            OPFLog.d("Skipping event delivery: %s", event);
        }
        return hasSubscriber;
    }

    /**
     * @return Simple version of {@link IabHelper}.
     *
     * @see {@link SimpleIabHelper}
     */
    @NonNull
    public static SimpleIabHelper getSimpleHelper() {
        checkInit();
        return new SimpleIabHelperImpl();
    }

    /**
     * @return Feature reach version of {@link SimpleIabHelper}.
     *
     * @see AdvancedIabHelper
     * @see #getSimpleHelper()
     */
    @SuppressWarnings("TypeMayBeWeakened")
    @NonNull
    public static AdvancedIabHelper getAdvancedHelper() {
        checkInit();
        return new AdvancedIabHelperImpl();
    }

    /**
     * Support version of {@link #getActivityHelper(Activity)}.
     */
    @NonNull
    public static ActivityIabHelper getActivityHelper(@NonNull final FragmentActivity fragmentActivity) {
        checkInit();
        return new ActivityIabHelperImpl(fragmentActivity, null);
    }

    /**
     * Instantiates {@link IabHelper} associated with supplied activity.
     * <p>
     * This call will attach invisible fragment which monitors activity lifecycle.
     * <p>
     * Supplied activity <b>must</b> delegate {@link Activity#onActivityResult(int, int, Intent)}
     * to {@link ActivityIabHelper#onActivityResult(Activity, int, int, Intent)}.
     *
     * @param activity Activity object to associate helper with.
     *
     * @return Version of {@link IabHelper} designed to be used from activity.
     *
     * @see ActivityIabHelper
     */
    @NonNull
    public static ActivityIabHelper getActivityHelper(@NonNull final Activity activity) {
        checkInit();
        return new ActivityIabHelperImpl(null, activity);
    }

    /**
     * Support version of {@link #getFragmentHelper(android.app.Fragment)}.
     */
    @NonNull
    public static FragmentIabHelper getFragmentHelper(@NonNull final android.support.v4.app.Fragment fragment) {
        checkInit();
        return new FragmentIabHelperImpl(fragment, null);
    }

    /**
     * Instantiates {@link IabHelper} associated with supplied fragment.
     * <p>
     * This call will attach invisible child fragment which monitors parent lifecycle.
     * <p>
     * If parent activity delegates {@link Activity#onActivityResult(int, int, Intent)}
     * to {@link ActivityIabHelper#onActivityResult(Activity, int, int, Intent)}, consider using
     * {@link SimpleIabHelper}.
     * <p>
     * Nested fragments were introduced in Android API 17, use
     * {@link #getFragmentHelper(android.support.v4.app.Fragment)} for earlier versions.
     *
     * @param fragment Fragment object to associate helper with.
     *
     * @return Version of {@link IabHelper} designed to be used from fragment.
     */
    @NonNull
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public static FragmentIabHelper getFragmentHelper(@NonNull final android.app.Fragment fragment) {
        checkInit();
        return new FragmentIabHelperImpl(null, fragment);
    }

    @NonNull
    public static Configuration getConfiguration() {
        checkInit();
        return configuration;
    }

    /**
     * Initialize OPFIab library with supplied configuration.
     * <p>
     * It's strongly recommended to call this method from {@link Application#onCreate()}.
     * <p>
     * Subsequent calls are supported but will reset any previous setup state.
     *
     * @param application   Application object to add {@link Application.ActivityLifecycleCallbacks}
     *                      to and to use as {@link Context}.
     * @param configuration Configuration object to use.
     */
    @SuppressFBWarnings({ "LI_LAZY_INIT_UPDATE_STATIC", "LI_LAZY_INIT_STATIC" })
    public static void init(@NonNull final Application application, @NonNull final Configuration configuration) {
        OPFLog.logMethod(configuration);
        OPFChecks.checkThread(true);
        OPFIab.context = application.getApplicationContext();

        final BillingBase billingBase = BillingBase.getInstance();
        final BillingRequestScheduler scheduler = BillingRequestScheduler.getInstance();
        final Set<BillingProvider> providers = configuration.getProviders();
        if (OPFIab.configuration == null) {
            // first init
            final ActivityMonitor activityMonitor = ActivityMonitor.getInstance(context);
            application.registerActivityLifecycleCallbacks(activityMonitor);
            register(billingBase, Integer.MAX_VALUE);
            register(SetupManager.getInstance(application));
            register(scheduler);
            register(activityMonitor);
            register(BillingEventDispatcher.getInstance());
        } else {
            for (final BillingProvider provider : OPFIab.configuration.getProviders()) {
                unregister(provider);
            }
        }
        OPFIab.configuration = configuration;

        for (final BillingProvider provider : providers) {
            provider.checkManifest();
            register(provider);
        }

        scheduler.dropQueue();
        billingBase.setConfiguration(configuration);
    }

    /**
     * Tries to pick one of the {@link BillingProvider}s supplied in {@link Configuration}.
     * <p>
     * {@link #init(Application, Configuration)} must be called prior to this method.
     * <p>
     * Subsequent calls are supported.
     */
    public static void setup() {
        checkInit();
        SetupManager.getInstance(context).startSetup(configuration);
    }

    private OPFIab() {
        throw new UnsupportedOperationException();
    }
}