com.alchemiasoft.book.service.BookActionService.java Source code

Java tutorial

Introduction

Here is the source code for com.alchemiasoft.book.service.BookActionService.java

Source

/*
 * Copyright 2015 Simone Casagranda.
 *
 * 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.alchemiasoft.book.service;

import android.annotation.TargetApi;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;
import android.text.TextUtils;
import android.util.Log;

import com.alchemiasoft.book.R;
import com.alchemiasoft.book.activity.HomeActivity;
import com.alchemiasoft.common.content.BookDB;
import com.alchemiasoft.common.model.Book;

/**
 * Service that allows to buy
 * <p/>
 * Created by Simone Casagranda on 28/12/14.
 */
public class BookActionService extends IntentService {

    /**
     * Tag used for logging purposes.
     */
    private static final String TAG_LOG = BookActionService.class.getSimpleName();

    private static final int NOTIFICATION_ID = 37;

    /**
     * Available params.
     */
    private static final String EXTRA_BOOK_ID = "com.alchemiasoft.book.service.BOOK_ID";
    private static final String EXTRA_NOTIFICATION_ID = "com.alchemiasoft.book.service.NOTIFICATION_ID";
    private static final String EXTRA_WEARABLE_INPUT = "com.alchemiasoft.book.service.WEARABLE_INPUT";
    private static final String EXTRA_ADD_NOTE = "com.alchemiasoft.book.service.ADD_NOTE";

    /**
     * Not valid id for book.
     */
    private static final long NOT_VALID_BOOK = -1L;

    /**
     * Not valid id for notifications.
     */
    private static final int NOT_VALID_NOTIFICATION = -1;

    /**
     * Available actions.
     */
    private static enum Action {
        BUY, SELL, ADD_NOTE
    }

    public static final class IntentBuilder {

        private final Intent mIntent;

        private IntentBuilder(Context context, Book book, Action action) {
            mIntent = new Intent(context, BookActionService.class);
            mIntent.putExtra(EXTRA_BOOK_ID, book.getId());
            mIntent.setAction(action.name());
        }

        public static IntentBuilder buy(@NonNull Context context, @NonNull Book book) {
            return new IntentBuilder(context, book, Action.BUY);
        }

        public static IntentBuilder sell(@NonNull Context context, @NonNull Book book) {
            return new IntentBuilder(context, book, Action.SELL);
        }

        public static IntentBuilder addNote(@NonNull Context context, @NonNull Book book) {
            return new IntentBuilder(context, book, Action.ADD_NOTE);
        }

        public IntentBuilder notificationId(int id) {
            mIntent.putExtra(EXTRA_NOTIFICATION_ID, id);
            return this;
        }

        public IntentBuilder wearableInput() {
            mIntent.putExtra(EXTRA_WEARABLE_INPUT, true);
            return this;
        }

        public Intent build() {
            return mIntent;
        }
    }

    public static final class RemoteInputBuilder {

        private final Context mContext;
        private final RemoteInput.Builder mBuilder;

        private RemoteInputBuilder(@NonNull Context context, @NonNull String label) {
            mContext = context.getApplicationContext();
            mBuilder = new RemoteInput.Builder(EXTRA_ADD_NOTE).setLabel(label);
        }

        public static RemoteInputBuilder create(Context context) {
            return new RemoteInputBuilder(context, context.getString(R.string.add_notes));
        }

        public RemoteInputBuilder options(int options) {
            mBuilder.setChoices(mContext.getResources().getStringArray(options));
            return this;
        }

        public RemoteInput build() {
            return mBuilder.build();
        }

    }

    public BookActionService() {
        super(TAG_LOG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, NOT_VALID_NOTIFICATION);
        // Cancelling any shown notification
        if (notificationId != NOT_VALID_NOTIFICATION) {
            Log.d(TAG_LOG, "Dismissing notification with id=" + notificationId);
            NotificationManagerCompat.from(this).cancel(notificationId);
        }
        final long bookId = intent.getLongExtra(EXTRA_BOOK_ID, NOT_VALID_BOOK);
        if (bookId != NOT_VALID_BOOK) {
            final ContentResolver cr = getContentResolver();
            final Action action = Action.valueOf(intent.getAction());
            Log.d(TAG_LOG, "Performing action=" + action + " on book with id=" + bookId);
            final ContentValues cv = new ContentValues();
            switch (action) {
            case BUY:
                cv.put(BookDB.Book.OWNED, 1);
                if (cr.update(BookDB.Book.create(bookId), cv, null, null) == 1
                        && intent.getBooleanExtra(EXTRA_WEARABLE_INPUT, false)) {
                    final Book book = getBook(bookId);
                    if (book != null) {
                        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
                        builder.setSmallIcon(R.drawable.ic_launcher).setAutoCancel(true)
                                .setContentTitle(getString(R.string.book_purchased))
                                .setContentText(book.getTitle());
                        builder.setContentIntent(PendingIntent.getActivity(this, 0,
                                HomeActivity.createFor(this, book), PendingIntent.FLAG_UPDATE_CURRENT));

                        // ONLY 4 WEARABLE(s)
                        final NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender();
                        wearableExtender
                                .setBackground(BitmapFactory.decodeResource(getResources(), R.drawable.background));
                        // ACTION TO SELL A BOOK FROM A WEARABLE
                        final PendingIntent sellIntent = PendingIntent.getService(
                                this, 0, BookActionService.IntentBuilder.sell(this, book)
                                        .notificationId(NOTIFICATION_ID).wearableInput().build(),
                                PendingIntent.FLAG_UPDATE_CURRENT);
                        wearableExtender.addAction(new NotificationCompat.Action.Builder(R.drawable.ic_action_sell,
                                getString(R.string.action_sell), sellIntent).build());
                        // Finally extending the notification
                        builder.extend(wearableExtender);

                        NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, builder.build());
                    }
                }
                break;
            case SELL:
                cv.put(BookDB.Book.OWNED, 0);
                if (cr.update(BookDB.Book.create(bookId), cv, null, null) == 1
                        && intent.getBooleanExtra(EXTRA_WEARABLE_INPUT, false)) {
                    final Book book = getBook(bookId);
                    if (book != null) {
                        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
                        builder.setSmallIcon(R.drawable.ic_launcher).setAutoCancel(true)
                                .setContentTitle(getString(R.string.book_sold)).setContentText(book.getTitle());
                        builder.setContentIntent(PendingIntent.getActivity(this, 0,
                                HomeActivity.createFor(this, book), PendingIntent.FLAG_UPDATE_CURRENT));

                        NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, builder.build());
                    }
                }
                break;
            case ADD_NOTE:
                final CharSequence notes = getExtraNotes(intent);
                if (!TextUtils.isEmpty(notes)) {
                    cv.put(BookDB.Book.NOTES, notes.toString());
                    cr.update(BookDB.Book.create(bookId), cv, null, null);
                }
                break;
            default:
                break;
            }
        }
    }

    private Book getBook(long bookId) {
        final Cursor c = getContentResolver().query(BookDB.Book.create(bookId), null, null, null, null);
        try {
            if (c.moveToNext()) {
                return Book.oneFrom(c);
            }
        } finally {
            c.close();
        }
        return null;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
    private CharSequence getExtraNotes(Intent intent) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            final Bundle result = RemoteInput.getResultsFromIntent(intent);
            if (result != null) {
                return result.getCharSequence(EXTRA_ADD_NOTE);
            }
        }
        return null;
    }
}