4

I want a simple bookmarks and/or history for my app, and I'm wondering what the most appropriate storage would be? A text in a text file or preference, or perhaps a database? Which would be most flexible across updates, and efficient for space and lookup time?

For the display, I'm thinking this would be a good starting point, but would it be easy to add an icon to some items?

Edit:

I finally set up a Bookmark activity that should connect to a database:

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.bookmarkview);
    Cursor cursor = managedQuery(getIntent().getData(), new String[] {Bookmark.TITLE, Bookmark.URL},
            null, null, Bookmark.DEFAULT_SORT_ORDER);

    setListAdapter(new SimpleCursorAdapter(this, R.layout.bookmarkitem, cursor,
            new String[] { Bookmark.TITLE }, new int[] { android.R.id.text1 }));
    findViewById(R.id.addBookmark).setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            ContentValues values = new ContentValues();
            values.put("url", _url);
            values.put("title", _title);

            // When the update completes,
            // the content provider will notify the cursor of the change, which will
            // cause the UI to be updated.
            getContentResolver().update(_myuri, values, null, null);
        }
    });
}

Bookmark.java:

package com.tunes.viewer.Bookmarks;

import android.net.Uri;
import android.provider.BaseColumns;

/*
 * Database will have:
 * pk - primary key
 * title - the name of the bookmark.
 * url - the url.
 */
public class Bookmark implements BaseColumns{

    public static final String AUTHORITY = "com.tunes.viewer";

    /**
     * The content:// style URL for this table
     */
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/Bookmarks");

    /**
     * The MIME type of {@link #CONTENT_URI} providing a directory of notes.
     */
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";

    /**
     * The MIME type of a {@link #CONTENT_URI} sub-directory of a single note.
     */
    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";

    /**
     * The default sort order for this table
     */
    public static final String DEFAULT_SORT_ORDER = "title";

    /**
     * The title of the note
     * <P>Type: TEXT</P>
     */
    public static final String TITLE = "title";

    /**
     * The url
     * <P>Type: TEXT</P>
     */
    public static final String URL = "url";

}

I seem to have fixed most of the problems I was having, but unfortunately it doesn't add to the database when I click the Add button (calling the onclick above). Furthermore, I added data to the database, but it doesn't show up in the view. What's wrong with the cursor/adapter here? Full source is here.

NoBugs
  • 9,310
  • 13
  • 80
  • 146
  • my answer was intended for your earlier question. Now after edit its completely new question on "HOW to implement database" or "whats the problem with the implementation of my database". you can put an another question on SO anyway. – N-JOY May 25 '12 at 05:19

3 Answers3

4

i would suggest, you go with database. It will be easy and efficient solution for your requirement.

A single table in sqlite will suffice to your requirements. as you will need to maintain a list of url you visited. this table will also serve your requirement of storing bookmark.

your table format could be something like this.

_____________________________________________________________________________________
Id(Auto-increment) | Title of page | Url of Page |name of icon(if needed) |isBookmark |
_____________________________________________________________________________________

This could be a good structure to achieve you requirement. set isBookmark to 0/1 to set specific link as bookmark or unbookmark it.

EDIT

  • I did not suggest you to use SharedPreferences and i wont (though it is straight forword and easy to implement) and reason lies in very definition of SharedPreferences which says:
    "The SharedPreferences class provides a general framework that allows you to save and retrieve persistent key-value pairs of primitive data types. You can use SharedPreferences to save any primitive data: booleans, floats, ints, longs, and strings."
    Now i can not imagine a single way to store ArrayList<String>(Urls) in one of these primitive datatypes.

  • There is one more work around.and it is Object Serialization. you can save your complete arraylist instance to a file and next time when you need this object, deseralize it similarly.. Here is the sample code for Serialization.

.

public void serializeMap(ArrayList<String> list) {
    try {
        FileOutputStream fStream = openFileOutput(namefile.bin, Context.MODE_PRIVATE) ;
        ObjectOutputStream oStream = new ObjectOutputStream(fStream);
        oStream.writeObject(list);        
        oStream.flush();
        oStream.close();
        Log.v("Serialization success", "Success");
    } catch (Exception e) {
        Log.v("IO Exception", e.getMessage());
    }
}  

But this approach is not much recommended though.

N-JOY
  • 10,344
  • 7
  • 51
  • 69
  • Wouldn't a list of strings be just right for a list of urls (strings), especially if used with JSON or XML? Or does sharedpreference have limits with size or efficiency? – NoBugs May 23 '12 at 18:23
  • yes ArrayList will be fine. how would you store list in shared prefs if its possible? if it is, do you have any scope in it to mark a particular link as bookmark? then there is one more question how many no. of urls can be there in history list. if it is predefined? – N-JOY May 24 '12 at 05:31
  • Why not store with something like Mybookmark\nURL\nAnotherbookmark\nanotherurl or similar? – NoBugs May 24 '12 at 16:03
  • I tried the database method, but it fails without error message - see updated question. – NoBugs May 25 '12 at 03:36
  • i responded to your earlier question. now after edit its completely new question about HOW to implement database or whats the problem with the implementation of my database. you can put an another question on SO. but it seems you have implemented it using ContentProvider, which i think is not at all required asfar as your needs are concerned. – N-JOY May 25 '12 at 05:17
  • Thanks N-JOY, it's a bit of a continuation of the question but.. do you know what would be the appropriate adapter to the list in that circumstance? – NoBugs May 25 '12 at 06:11
  • use BaseAdapter, i would suggest. you can iterate cursor on by one in getView – N-JOY May 25 '12 at 06:15
  • BaseAdapter is good for minimal database connection to list? Can you link an example please? – NoBugs May 25 '12 at 06:22
  • you can access database and prepare an arrayList. now use this arraylist to populate your listView – N-JOY May 25 '12 at 06:28
  • Ok, but I assumed the best way to do that was a cursor? Maybe something like this? http://joesapps.blogspot.com/2011/02/customized-listview-data-display-in.html – NoBugs May 25 '12 at 06:29
  • ya may be i never used SimpleCursorAdapter, i prefer BaseAdapter it is lot more customizable. – N-JOY May 25 '12 at 06:31
  • Can you give example of a customized BaseAdapter? – NoBugs May 25 '12 at 06:33
  • can you come in chatRoom http://chat.stackoverflow.com/rooms/522/android-for-life – N-JOY May 25 '12 at 06:35
2

I agree with WareNinja- the SharedPreferences data areas would be sufficient for simple, non-relational data. This SO answer is very comprehensive in describing the nuances of implementing Activity and/or application-wide SharedPreferences.

The SharedPreferences framework will take care of all the data persistence minimising the amount of code you will need to write and your exposure to db-like 'update' transactions. However be aware, in terms of expanding your application this medium is powerful but inflexible. The minute you feel the need to expand the type of data being stored move to SQLite or similar.

Community
  • 1
  • 1
BrantApps
  • 6,362
  • 2
  • 27
  • 60
  • In other words, "select url from table" would work for a table with any number of "columns", but to make a backward/forward-compatible app with sharedpreference strings would be harder, correct? – NoBugs May 22 '12 at 02:31
  • Yes. ````SharedPreferences```` is ideal for one off simple storage such as a line of text (bookmark URL) or boolean. Even more so if the data being stored is of a known size, i.e. 10 bookmarks only. However, if you are wanting to add in support for 'any number' of bookmarks perhaps linking to a history table of when this bookmark was last visited then the data is now relational and DB tooling should be used. If you don't need that link and you want just a limited bookmark and history facility then ````SharedPreferences```` would work. Expanding your app would require you to move to a proper DB – BrantApps May 22 '12 at 07:53
  • What's the best way to connect a database to the list? – NoBugs May 23 '12 at 18:25
  • Hey NoBugs. Apologies for the delay. When I first started working with SQLite and Android I followed the NotePad tutorial. It's quick. The entry point for the Android documentation surrounding persisting data locally is [here](http://developer.android.com/guide/topics/data/data-storage.html#db) – BrantApps May 24 '12 at 19:55
  • Thanks OceanLife, I have modified the NotePad tutorial earlier, and it seems to work (no errors), but doesn't save or view from database. – NoBugs May 24 '12 at 19:58
  • See updated question, I linked the source if you could take a look – NoBugs May 24 '12 at 20:46
1

I suggest using SharedPreferences and/or memdiskcache, both works fast and seamlessly. p.s. nothing against using sqlite, however i always try to avoid using db for client apps.

example lib to abstract local storage (no db!); https://github.com/wareninja/generic-store-for-android

you can store and retrieve any type of data in key-value form,
sample code for loading java object from memdiskcache;

String keyPrefix = "blabla1";
if (GenericStore.isCustomKeyExist(GenericStore.TYPE_MEMDISKCACHE, keyPrefix, this)) {

                mNewPoiDataList = (NewPoiDataList)GenericStore.getObject(GenericStore.TYPE_MEMDISKCACHE
                        , keyPrefix, this);
            }
Yilmaz Guleryuz
  • 9,313
  • 3
  • 32
  • 43