0

I have an a ListView which fetches the data from JSON and the app saves the downloaded images and texts from the web to the external storage though an ImageLoader class.

I need to make the listview accessible without an internet connection, the app already succesfully saves the cache data into the SD Card.

I found a way to do it by using SQLite. When the app runs for the first time with internet connection, it downloads the JSON data and save them to the sqlite database. When there's no internet connection, instead of downloading the data from the web, the app calls the data from the sqlite database.

But I'm still a newbie and I have difficulties in implementing the SQLite with the codes I have.

Here are my codes:

public class DBAdapter {

       public static String KEY_PROJECTTITLE = "project title";
       public static String KEY_ORGANIZATIONTITLE = "organization title";
       public static String KEY_KEYWORD = "keyword";
       public static String KEY_SHORTCODE = "short code";
       public static String KEY_PROJECTDESCRIPTION = "description";
       public static String KEY_SMALLIMAGE = "smallImageUrl";
       public static String KEY_BIGIMAGE = "bigImageUrl";
       public static String KEY_PRICE= "price";
       public static String KEY_COUNTRY= "country";


       private static final String DATABASE_NAME = "applicationdata";
       private static final String DATABASE_TABLE_PROJECT = "Project";

       private static final int DATABASE_VERSION = 17;


       private static final String DATABASE_CREATE = "CREATE TABLE "+DATABASE_TABLE_PROJECT+" (" +
        KEY_PROJECTTITLE +      " TEXT NOT NULL, " +
        KEY_ORGANIZATIONTITLE +         " TEXT NOT NULL, "+
        KEY_KEYWORD +   " TEXT NOT NULL PRIMARY KEY, " +
        KEY_SHORTCODE +         " TEXT NOT NULL, "+
        KEY_PROJECTDESCRIPTION +    " TEXT NOT NULL, "+
        KEY_SMALLIMAGE +            " TEXT NOT NULL, "+
        KEY_BIGIMAGE +      " TEXT NOT NULL, "+
        KEY_PRICE +         " TEXT NOT NULL, "+
        KEY_COUNTRY +       " TEXT NOT NULL)";

       private final Context context; 

        private DatabaseHelper dbhelper;
        private SQLiteDatabase db;

        public DBAdapter(Context ctx) 
        {
            this.context = ctx;
            dbhelper = new DatabaseHelper(context);
        }

        public static class DatabaseHelper extends SQLiteOpenHelper {


            public DatabaseHelper(Context context) {
                super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }

            @Override
            public void onCreate(SQLiteDatabase db) {
                db.execSQL(DATABASE_CREATE);
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_PROJECT);
                onCreate(db);

            }
        }
        //---opens the database---
        public DBAdapter open() throws SQLException 
        {
            db = dbhelper.getWritableDatabase();
            return this;
        }

        //---closes the database---    
        public void close() 
        {
            dbhelper.close();
        }

        public long insertProject(String project_title, String organization_title, String keyword, String short_code, String project_description,String smallImageUrl,String bigImageUrl,String price, String country) {
            ContentValues initialValues = new ContentValues();
            initialValues.put(KEY_PROJECTTITLE, project_title);
            initialValues.put(KEY_ORGANIZATIONTITLE, organization_title);
            initialValues.put(KEY_KEYWORD, keyword);
            initialValues.put(KEY_SHORTCODE, short_code);
            initialValues.put(KEY_PROJECTDESCRIPTION, project_description);
            initialValues.put(KEY_SMALLIMAGE, smallImageUrl);
            initialValues.put(KEY_BIGIMAGE, bigImageUrl);
            initialValues.put(KEY_PRICE, price);
            initialValues.put(KEY_COUNTRY, country);
            return this.db.insert(DATABASE_TABLE_PROJECT, null, initialValues);
        }
}

ListView Adapter:

public class ProjectAdapter extends ArrayAdapter<Project> {

    int resource;
    String response;
    Context context;
    List<Project> items;
    private ImageLoaderCache imageLoader;
    LayoutInflater mInflater;
    Activity activity;

    private DBAdapter mDBHelper;
    // Initialize adapter
    public ProjectAdapter(Context context, int resource, List<Project> items,
            Activity activity) {
        super(context, resource, items);
        this.resource = resource;
        imageLoader = new ImageLoaderCache(context);
        this.items = items;
        mInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.activity = activity;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        // Inflate the view
        if (convertView == null) {

            convertView = mInflater.inflate(resource, null);
            holder = new ViewHolder();
            holder.image = (ImageView) convertView.findViewById(R.id.image);
            holder.textTitle = (TextView) convertView
                    .findViewById(R.id.txt_title);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Project project = items.get(position);

        holder.textTitle.setText(project.project_title);

        String imageurl = project.smallImageUrl;
        holder.image.setTag(imageurl);
        imageLoader.displayImage(imageurl, activity, holder.image);
        return convertView;

    }

    static class ViewHolder {

        TextView textTitle;

        ImageView image;
    }
}

the class where the JSON data is populated to the ListView

public class ProjectsList extends Activity {
    /** Called when the activity is first created. */
    //ListView that will hold our items references back to main.xml
    ListView lstTest;

    //Array Adapter that will hold our ArrayList and display the items on the ListView
    ProjectAdapter arrayAdapter;


    //List that will  host our items and allow us to modify that array adapter
    ArrayList<Project> prjcts=null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.projects_list);

        //Initialize ListView
        lstTest= (ListView)findViewById(R.id.lstText);

         //Initialize our ArrayList
        prjcts = new ArrayList<Project>();
        //Initialize our array adapter notice how it references the listitems.xml layout

        arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);

        //Set the above adapter as the adapter of choice for our list
            lstTest.setAdapter(arrayAdapter);
            if (isOnline())
            {
        //Instantiate the Web Service Class with he URL of the web service not that you must pass
        WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");


        //Pass the parameters if needed , if not then pass dummy one as follows
        Map<String, String> params = new HashMap<String, String>();
        params.put("var", "");

        //Get JSON response from server the "" are where the method name would normally go if needed example
        // webService.webGet("getMoreAllerts", params);
        String response = webService.webGet("", params);

        try
        {
            //Parse Response into our object
            Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();

            //JSON expects an list so can't use our ArrayList from the lstart
            List<Project> lst= new Gson().fromJson(response, collectionType);


            //Now that we have that list lets add it to the ArrayList which will hold our items.
            for(Project l : lst)
            {
                prjcts.add(l);
                ConstantData.projectsList.add(l);
            }

            //Since we've modified the arrayList we now need to notify the adapter that
            //its data has changed so that it updates the UI
            arrayAdapter.notifyDataSetChanged();
        }
        catch(Exception e)
        {
            Log.d("Error: ", e.getMessage());
        }
       }


        lstTest.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {              

                Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
                care.putExtra("spendino.de.ProjectDetail.position",position);
                startActivity(care);
            }
        });

    }


    protected boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            return true;
        } else {
             AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
             alertbox.setTitle("spendino Helfomat");
             alertbox.setMessage ("Please check your internet connection");
             alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                      //Main.this.finish();
                 }
             });
             alertbox.show();
            return false;
        }
    }   
}

I'm open to any kind of solution.

3
  • What is the exact problem you're having? Reading or writing to the db? Commented May 19, 2011 at 10:39
  • both, since I fetch the data from the web, can't find an exact example Commented May 19, 2011 at 10:45
  • hehe it takes me 2h to made this app just take a look at 2nd edit of my answer :) Commented May 20, 2011 at 8:16

2 Answers 2

1

asuming that

public static String KEY_PROJECTTITLE = "project title";

is a Column name in db it should be without spaces ot within []

EDIT: and for FSM's sake if you're using SQLite dont use ArrayAdapter use (Simple)CursorAdapter instead

to avoid your next question C:\android\android-sdk-windows\samples\android-8\ApiDemos\src\com\example\android\apis\view\List7.java <- (Simple)CursorAdapter sample

2nd EDIT:

here is working sample of your program it takes 2h to made it ... and yeah i am new in android too (1 month or so)

LooserSample.zip

Sign up to request clarification or add additional context in comments.

6 Comments

download sample again to know how to open details activity
Hi Selvin, I'm wondering why the ListView isn't updated when I add or delete an entry on the JSON file? I got the question here: stackoverflow.com/questions/6137416/… this is very crucial. Thx
Hi Selvin, I got a question.. so I have an activitiy which shows 3 random image from the json entries, and the image leads to the detailsactivity. But again I'm a bit clueless to integrate this activity with the sql thingie.. shall I send you an email or I give you a link of my question?
so you're getting money for making this app and i do it for you for free ... hmmm this makes no sens for me
managedQuery(uri, new String[] { BaseColumns._ID, Database.Project.C_PROJECTTITLE, Database.Project.C_PROJECTDESCRIPTION, Database.Project.C_BIGIMAGE }, null, null, null); with uri = Uri.withAppendedPath(Uri.withAppendedPath( LooserProvider.CONTENT_URI, Database.Project.NAME), Long .toString(id)); so it looks like "content://just.sample.forloosers/Project/1" this returns Cursor with 1 row from Project table where _id = 1 change new String[].. to support more columns or replace it with null to get all columns developer.android.com/guide/topics/fundamentals/activities.html
|
0

Try not to use spaces in column names e.g. use "short_code" instead of "short code".

To insert data into the database use the SQLiteStatement First compile a query:

private static final String INSERT_ITEM_TYPE = "insert into " + ITEM_TYPE_TABLE_NAME + "(recordGUID, code, item_type) values (?, ?, ?)";

than create an insert statement:

public long insertItemType(int code, String itemName) {
      UUID guid = UUID.randomUUID();
      this.insertStmt = this.db.compileStatement(INSERT_ITEM_TYPE);
      this.insertStmt.bindString(1, guid.toString());
      this.insertStmt.bindLong(2, code);
      this.insertStmt.bindString(3, itemName);
      return this.insertStmt.executeInsert();
   }

To select, just use the Cursor and the query like so:

public String[] getItemType(int code){
       Cursor cursor = db.query(ITEM_TYPE_TABLE_NAME, new String [] {"item_type, recordGUID"}, "code = " + code, null, null, null, null);
       String[] list = new String[2];
       if (cursor.moveToFirst()) {
             list[0] = cursor.getString(0);
             list[1] = cursor.getString(1);
          }
          if (cursor != null && !cursor.isClosed()) {
             cursor.close();
          }
          return list;
   }

The return value could also be a List<List<String>> depending on how many rows you expect back.

public List<List<String>> getItemAction(String itemGUID){
       List<List<String>> list = new ArrayList<List<String>>();
          Cursor cursor = this.db.query(ITEM_ACTION_TABLE_NAME, new String[] { "action, recordGUID" }, "ref_item = '" + itemGUID + "'", null, null, null, null);
          if (cursor.moveToFirst()) {
             do {
                 List<String> temp = new ArrayList<String>();
                 temp.add(cursor.getString(0));
                 temp.add(cursor.getString(1));
                 list.add(temp);
             } while (cursor.moveToNext());
          }
          if (cursor != null && !cursor.isClosed()) {
             cursor.close();
          }
          return list;
   }

I hope this helps you in the right direction.

4 Comments

Declare all in your DBAdapter. In the activity create an instance of DBAdapter. Then call the methods DBadapter db = new DBadapter db.getItemAction(GUID);
Sorry, that is the SQLiteStatement
no problem, I got it right. As far as I know, what I have to modify according to my project is this = ITEM_ACTION_TABLE_NAME right? And what else?
I used this site ( screaming-penguin.com/node/7742 ) as a model for my database. All fields in caps should be renamed according to your own database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.