Code Monkey home page Code Monkey logo

blackbooks's Introduction

BlackBooks

This repository contains the source code for the Black Books Android app.

Get it on Google Play

App features

Black Books helps you make an inventory of your books and manage them!

  • Make a list of your books: add them manually or simply scan their ISBN (Pic2Shop required).
  • Automatically get book details (including thumbnails) from Amazon, Google Books and Open Library.
  • Bulk add books: scan or enter a list of ISBNs while offline and start a background search when you are connected to the Internet.
  • Edit your books: thumbnail, authors, categories, series, language, page count, etc.
  • Have a quick overview of your library directly from the home screen.
  • Browse your books by author, category, series, language.
  • Search your library using the simple full-text search feature.
  • Keep track of the books to read.
  • Mark your favourite books.
  • Don't lose your books anymore by indicating their location.
  • Manage your loans: to whom and when?
  • Export your library as a Spreadsheet compatible text file.
  • Import or update books from a Spreadsheet compatible text file.

Privacy policy

This application DOES NOT collect any data from your device.

Permissions

Black Books requires the following permissions:

  • Camera: this feature allows you to take pictures of your book covers and import them directly into the app.
  • Internet: this is necessary in order to retrieve the book details.
  • Read contacts: when loaning a book, you can pick one of your contacts as the loanee. Only the name of the contact is stored in the app as long as the book is marked as loaned. The app does not send the contacts to any other party.
  • Read logs: if an unexpected error occurs, the app offers the possibility to send us the log file, which will help us figure out what went wrong.
  • Write external storage: the app needs to write the external storage when:
    • Exporting the library as a Spreadsheet compatible text file.
    • Saving a backup of the app database.

Implementation

Data storage

Black Books creates a SQLite database on the user's device to store all the information about the books (including thumbnails).

  • The app manipulates books, authors, categories and other entities using the Java classes defined in package com.blackbooks.model.persistent.
  • These classes are decorated with the annotations located in package com.blackbooks.model.metadata to define a mapping between them and the SQLite tables where they will be persisted.
  • The basic database operations (insert, update, select, delete) are performed using the Broker class, located in package com.blackbooks.sql.

Caching

The book thumbnails are Bitmap images stored in the SQLite database as BLOBs (Binary Large Objects).

When displaying the list of all the books in the user's library, the app executes a select from table BOOK. The column where the thumbnails are stored is excluded from the select because the thumbnails are loaded separately using the class ThumbnailManager

The ThumbnailManager class loads the thumbnails asyncronously and stores them in a LruCache, providing a safer memory management. When the thumbnail of a book must be displayed, ThumbnailManager first checks if it is not already in the LruCache. If it is, the Bitmap is immediately returned (avoiding a select in the database), otherwise the thumbnail is loaded in an AsyncTask and stored in the LruCache.

ISBN lookup

When the device is connected to the Internet, Black Books can perform ISBN lookups by making calls to the following services:

All the classes implementing the ISBN lookup are defined in package com.blackbooks.services.search. The entry point is the method search(String isbn) in class BookSearcher which calls each service and merges their results into a single instance of BookInfo.

The call to each service is implemented by a corresponding Java class that sends a HTTP request and parses the response before returning the result.

blackbooks's People

Stargazers

 avatar

Watchers

 avatar  avatar

blackbooks's Issues

Create a "Manage database" activity

This activity displays:

  • The size of the database on the device.

The activity provides the features to:

  • Backup the database
  • Restore the database from a file stored on the device

Update README.md

Update the app description because:

  • The app organization has changed.
  • When adding a single book using its ISBN, the app checks if there are books corresponding to it.
  • New feature: bulk add books.

Crash when picking an image from the gallery (OutOfMemoryError)

01-31 15:18:03.484 E/com.blackbooks(15623): Uncaught exception.
01-31 15:18:03.484 E/com.blackbooks(15623): java.lang.OutOfMemoryError
01-31 15:18:03.484 E/com.blackbooks(15623): at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:603)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:626)
01-31 15:18:03.484 E/com.blackbooks(15623): at com.blackbooks.utils.BitmapUtils.compress(BitmapUtils.java:43)
01-31 15:18:03.484 E/com.blackbooks(15623): at com.blackbooks.fragments.BookEditGeneralFragment.onActivityResult(BookEditGeneralFragment.java:198)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:167)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.Activity.dispatchActivityResult(Activity.java:5650)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.ActivityThread.deliverResults(ActivityThread.java:3676)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3723)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.ActivityThread.access$1400(ActivityThread.java:174)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1355)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.os.Handler.dispatchMessage(Handler.java:102)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.os.Looper.loop(Looper.java:146)
01-31 15:18:03.484 E/com.blackbooks(15623): at android.app.ActivityThread.main(ActivityThread.java:5593)
01-31 15:18:03.484 E/com.blackbooks(15623): at java.lang.reflect.Method.invokeNative(Native Method)
01-31 15:18:03.484 E/com.blackbooks(15623): at java.lang.reflect.Method.invoke(Method.java:515)
01-31 15:18:03.484 E/com.blackbooks(15623): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
01-31 15:18:03.484 E/com.blackbooks(15623): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
01-31 15:18:03.484 E/com.blackbooks(15623): at dalvik.system.NativeStart.main(Native Method)

Add an import from CSV feature

Add the possibility to import data from a CSV file. After selecting the CSV file to import on the local storage of the device, a fragment should allow the user to map the detected columns of the file to the actual properties of the book.

Add an "About" activity

In this "About" activity, display:

  • The version of the app
  • A link to the GitHub repository
  • The contact email address

Crash when trying to take a picture of the cover

Android version: 19
Device: samsung GT-I9195
App version: 1
--------- beginning of /dev/log/main
01-22 22:46:11.522 W/dalvikvm( 1748): threadid=1: thread exiting with uncaught exception (group=0x4193cda0)
01-22 22:46:11.552 E/com.blackbooks( 1748): Uncaught exception.
01-22 22:46:11.552 E/com.blackbooks( 1748): java.lang.NullPointerException
01-22 22:46:11.552 E/com.blackbooks( 1748): at com.blackbooks.fragments.BookEditGeneralFragment$4.onItemSelected(BookEditGeneralFragment.java:266)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.AdapterView.fireOnSelected(AdapterView.java:964)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.AdapterView.selectionChanged(AdapterView.java:947)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.AdapterView.checkSelectionChanged(AdapterView.java:1114)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.AdapterView.handleDataChanged(AdapterView.java:1094)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:180)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.Spinner.onMeasure(Spinner.java:503)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1781)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.ScrollView.onMeasure(ScrollView.java:477)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1456)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:412)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5376)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-22 22:46:11.552 E/com.blackbooks( 1748): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2548)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.View.measure(View.java:17482)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2287)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2009)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1256)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6635)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.Choreographer.doCallbacks(Choreographer.java:613)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.Choreographer.doFrame(Choreographer.java:583)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.os.Handler.handleCallback(Handler.java:733)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.os.Handler.dispatchMessage(Handler.java:95)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.os.Looper.loop(Looper.java:146)
01-22 22:46:11.552 E/com.blackbooks( 1748): at android.app.ActivityThread.main(ActivityThread.java:5593)
01-22 22:46:11.552 E/com.blackbooks( 1748): at java.lang.reflect.Method.invokeNative(Native Method)
01-22 22:46:11.552 E/com.blackbooks( 1748): at java.lang.reflect.Method.invoke(Method.java:515)
01-22 22:46:11.552 E/com.blackbooks( 1748): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
01-22 22:46:11.552 E/com.blackbooks( 1748): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
01-22 22:46:11.552 E/com.blackbooks( 1748): at dalvik.system.NativeStart.main(Native Method)

Crash in the AutoCompleteAdapter

01-23 20:06:30.442 W/dalvikvm(27692): threadid=1: thread exiting with uncaught exception (group=0x4193cda0)
01-23 20:06:30.462 E/com.blackbooks(27692): Uncaught exception.
01-23 20:06:30.462 E/com.blackbooks(27692): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(-1, class android.widget.ListPopupWindow$DropDownListView) with Adapter(class com.blackbooks.adapters.AutoCompleteAdapter)]
01-23 20:06:30.462 E/com.blackbooks(27692): at android.widget.ListView.layoutChildren(ListView.java:1566)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.widget.AbsListView.onLayout(AbsListView.java:2564)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.View.layout(View.java:15749)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewGroup.layout(ViewGroup.java:4880)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.View.layout(View.java:15749)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewGroup.layout(ViewGroup.java:4880)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2358)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2071)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1256)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6635)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.Choreographer.doCallbacks(Choreographer.java:613)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.Choreographer.doFrame(Choreographer.java:583)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.os.Handler.handleCallback(Handler.java:733)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.os.Handler.dispatchMessage(Handler.java:95)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.os.Looper.loop(Looper.java:146)
01-23 20:06:30.462 E/com.blackbooks(27692): at android.app.ActivityThread.main(ActivityThread.java:5593)
01-23 20:06:30.462 E/com.blackbooks(27692): at java.lang.reflect.Method.invokeNative(Native Method)
01-23 20:06:30.462 E/com.blackbooks(27692): at java.lang.reflect.Method.invoke(Method.java:515)
01-23 20:06:30.462 E/com.blackbooks(27692): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
01-23 20:06:30.462 E/com.blackbooks(27692): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
01-23 20:06:30.462 E/com.blackbooks(27692): at dalvik.system.NativeStart.main(Native Method)

Improve the language selection

Instead of the spinner used in the class BookEditGeneralFragment, create a new dialog fragment that allows the user to search for languages by typing the first letters of their names.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.