[Tutorial] Learn to save data with SQLite on Android - Android Software Development

Hello,
I create that thread to present you a tutorial learning you to save data with SQLite on Android. This tutorial is also available in video on Youtube :
Learn to save data with SQLite on Android
On Android, there are several solutions to persist data between users’ sessions. One solution is to use a relational database to persist data and then to be able to query easily these data. In standard, Android SDK comes with a SQLite implementation. Biggest advantage of SQLite integration to Android OS is the fact that there is no need to to setup the database. So, no administration of this database. SQLite is embedded in standard and each application can have its SQLite database.
The only job that developers must make is to define SQL tables and statements for creating and updating data. Access to an SQLite database involves accessing the file system. So, it can be a slow operation. To avoid ANR (Application Not Responding) errors, it’s recommended to perform database operations asynchronously.
When an application creates and uses a SQLite database, it will be saved by default in the directory : DATA/data/APP_PACKAGE/databases/FILENAME .
1. Architecture
All classes needed to manage databases in Android SDK are contained in the package android.database . The package android.database.sqlite contains the SQLite specific classes.
SQLite API is centered around 2 main classes :
SQLiteOpenHelper that is an helper class to extend to manage database operations.
SQLiteDatabase that is the base class for working with a SQLite database in Android.
2. SQLiteOpenHelper
When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
You need also to override the following methods :
onCreate() that is called when database is accessed but not yet created.
onUpgrade() called when you choose to increment the version number of the database. In this method you can manage the migration process between two databases versions.
Both methods get and SQLiteDatabase instance in parameter which is the way to communicate with the database.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
getReadableDatabase() for read mode.
getWriteableDatabase() for write mode.
3. SQLiteDatabase
SQLiteDatabase is the class used to communicate with a SQLite database. It exposes several methods to interact with database like insert(), update() or delete().
In addition, it lets you to make queries via rawQuery() to queries made directly in SQL or via query() method. This last method provides a structured interface for specifying a SQL query.
4. Practice
Now, you know theory about SQLite in Android context. We can put in practice all the concepts. To achieve that, we’re going to make a database with a players table letting us to store NBA players.
To start, we create a simple Player Java POJO :
Code:
public class Player {
private int id;
private String name;
private String position;
private int height;
public Player() {
}
public Player(int id, String name, String position, int height) {
this.id = id;
this.name = name;
this.position = position;
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return name + " - " + position + " - " + height + " cm";
}
}
Then, we must create the SQLiteOpenHelper extended class to manage our application database. Code is here :
Code:
package com.ssaurel.samples.sqlite;
import java.util.LinkedList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteDatabaseHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "PlayersDB";
private static final String TABLE_NAME = "Players";
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_HEIGHT = "height";
private static final String[] COLUMNS = { KEY_ID, KEY_NAME, KEY_POSITION,
KEY_HEIGHT };
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATION_TABLE = "CREATE TABLE Players ( "
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, "
+ "position TEXT, " + "height INTEGER )";
db.execSQL(CREATION_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// you can implement here migration process
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
this.onCreate(db);
}
public void deleteOne(Player player) {
// Get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, "id = ?", new String[] { String.valueOf(player.getId()) });
db.close();
}
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
if (cursor != null)
cursor.moveToFirst();
Player player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
return player;
}
public List<Player> allPlayers() {
List<Player> players = new LinkedList<Player>();
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Player player = null;
if (cursor.moveToFirst()) {
do {
player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
players.add(player);
} while (cursor.moveToNext());
}
return players;
}
public void addPlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
// insert
db.insert(TABLE_NAME,null, values);
db.close();
}
public int updatePlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
int i = db.update(TABLE_NAME, // table
values, // column/value
"id = ?", // selections
new String[] { String.valueOf(player.getId()) });
db.close();
return i;
}
}
Database is created in the constructor of the extended class. Players table is created in the onCreate() method thanks to a SQL statement.
In our class, we add methods to add a new player, to delete an existing one, to update and then a method to get all the players in the table. In this last method, we use a Cursor object to iterate on rows and then build equivalent Player instances.
To use our class to create some players then display on a simple ListView, we can use the following code :
Code:
public class MainActivity extends Activity {
private SQLiteDatabaseHandler db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create our sqlite helper class
db = new SQLiteDatabaseHandler(this);
// create some players
Player player1 = new Player(1, "Lebron James", "F", 203);
Player player2 = new Player(2, "Kevin Durant", "F", 208);
Player player3 = new Player(3, "Rudy Gobert", "C", 214);
// add them
db.addPlayer(player1);
db.addPlayer(player2);
db.addPlayer(player3);
// list all players
List<Player> players = db.allPlayers();
if (players != null) {
String[] itemsNames = new String[players.size()];
for (int i = 0; i < players.size(); i++) {
itemsNames[i] = players.get(i).toString();
}
// display like string instances
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, itemsNames));
}
}
}
Execution result can be seen here :
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
SQLite implementation in Android is simple and really powerful. You can now use it in your Android application to persist data.
Don't hesitate to give it a try and give me your feedbacks about this tutorial.
Thanks.
Sylvain

Hey, I have made a preview for SQLite database earlier this month for my friend.
If anyone's interested then it's there at https://www.GitHub.com/Fifa2151/SQLiteTest
Thanks,
Raj.
Sent from my Pixel using Tapatalk

sylsau said:
Hello,
I create that thread to present you a tutorial learning you to save data with SQLite on Android. This tutorial is also available in video on Youtube :
Learn to save data with SQLite on Android
On Android, there are several solutions to persist data between users’ sessions. One solution is to use a relational database to persist data and then to be able to query easily these data. In standard, Android SDK comes with a SQLite implementation. Biggest advantage of SQLite integration to Android OS is the fact that there is no need to to setup the database. So, no administration of this database. SQLite is embedded in standard and each application can have its SQLite database.
The only job that developers must make is to define SQL tables and statements for creating and updating data. Access to an SQLite database involves accessing the file system. So, it can be a slow operation. To avoid ANR (Application Not Responding) errors, it’s recommended to perform database operations asynchronously.
When an application creates and uses a SQLite database, it will be saved by default in the directory : DATA/data/APP_PACKAGE/databases/FILENAME .
1. Architecture
All classes needed to manage databases in Android SDK are contained in the package android.database . The package android.database.sqlite contains the SQLite specific classes.
SQLite API is centered around 2 main classes :
SQLiteOpenHelper that is an helper class to extend to manage database operations.
SQLiteDatabase that is the base class for working with a SQLite database in Android.
2. SQLiteOpenHelper
When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
You need also to override the following methods :
onCreate() that is called when database is accessed but not yet created.
onUpgrade() called when you choose to increment the version number of the database. In this method you can manage the migration process between two databases versions.
Both methods get and SQLiteDatabase instance in parameter which is the way to communicate with the database.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
getReadableDatabase() for read mode.
getWriteableDatabase() for write mode.
3. SQLiteDatabase
SQLiteDatabase is the class used to communicate with a SQLite database. It exposes several methods to interact with database like insert(), update() or delete().
In addition, it lets you to make queries via rawQuery() to queries made directly in SQL or via query() method. This last method provides a structured interface for specifying a SQL query.
4. Practice
Now, you know theory about SQLite in Android context. We can put in practice all the concepts. To achieve that, we’re going to make a database with a players table letting us to store NBA players.
To start, we create a simple Player Java POJO :
Code:
public class Player {
private int id;
private String name;
private String position;
private int height;
public Player() {
}
public Player(int id, String name, String position, int height) {
this.id = id;
this.name = name;
this.position = position;
this.height = height;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return name + " - " + position + " - " + height + " cm";
}
}
Then, we must create the SQLiteOpenHelper extended class to manage our application database. Code is here :
Code:
package com.ssaurel.samples.sqlite;
import java.util.LinkedList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteDatabaseHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "PlayersDB";
private static final String TABLE_NAME = "Players";
private static final String KEY_ID = "id";
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_HEIGHT = "height";
private static final String[] COLUMNS = { KEY_ID, KEY_NAME, KEY_POSITION,
KEY_HEIGHT };
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATION_TABLE = "CREATE TABLE Players ( "
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, "
+ "position TEXT, " + "height INTEGER )";
db.execSQL(CREATION_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// you can implement here migration process
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
this.onCreate(db);
}
public void deleteOne(Player player) {
// Get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, "id = ?", new String[] { String.valueOf(player.getId()) });
db.close();
}
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
if (cursor != null)
cursor.moveToFirst();
Player player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
return player;
}
public List<Player> allPlayers() {
List<Player> players = new LinkedList<Player>();
String query = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Player player = null;
if (cursor.moveToFirst()) {
do {
player = new Player();
player.setId(Integer.parseInt(cursor.getString(0)));
player.setName(cursor.getString(1));
player.setPosition(cursor.getString(2));
player.setHeight(Integer.parseInt(cursor.getString(3)));
players.add(player);
} while (cursor.moveToNext());
}
return players;
}
public void addPlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
// insert
db.insert(TABLE_NAME,null, values);
db.close();
}
public int updatePlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, player.getName());
values.put(KEY_POSITION, player.getPosition());
values.put(KEY_HEIGHT, player.getHeight());
int i = db.update(TABLE_NAME, // table
values, // column/value
"id = ?", // selections
new String[] { String.valueOf(player.getId()) });
db.close();
return i;
}
}
Database is created in the constructor of the extended class. Players table is created in the onCreate() method thanks to a SQL statement.
In our class, we add methods to add a new player, to delete an existing one, to update and then a method to get all the players in the table. In this last method, we use a Cursor object to iterate on rows and then build equivalent Player instances.
To use our class to create some players then display on a simple ListView, we can use the following code :
Code:
public class MainActivity extends Activity {
private SQLiteDatabaseHandler db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create our sqlite helper class
db = new SQLiteDatabaseHandler(this);
// create some players
Player player1 = new Player(1, "Lebron James", "F", 203);
Player player2 = new Player(2, "Kevin Durant", "F", 208);
Player player3 = new Player(3, "Rudy Gobert", "C", 214);
// add them
db.addPlayer(player1);
db.addPlayer(player2);
db.addPlayer(player3);
// list all players
List<Player> players = db.allPlayers();
if (players != null) {
String[] itemsNames = new String[players.size()];
for (int i = 0; i < players.size(); i++) {
itemsNames[i] = players.get(i).toString();
}
// display like string instances
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, itemsNames));
}
}
}
Execution result can be seen here :
SQLite implementation in Android is simple and really powerful. You can now use it in your Android application to persist data.
Don't hesitate to give it a try and give me your feedbacks about this tutorial.
Thanks.
Sylvain
Click to expand...
Click to collapse
Awesome guide @sylsau...
Also, do you know how to make a flashify type app but only for a specific zip?

When you want to work with a SQLite database in Android, you must extend SQLiteOpenHelper class. In the constructor of your subclass you call the super() method of SQLiteOpenHelper, specifying the database name and the current database version.
Click to expand...
Click to collapse
You don't actually need to use a subclass of SQLiteOpenHelper you can use the SQliteDatabase's open????? methods.
Furthermore, SQLiteOpenHelper provides 2 methods to get access to an SQLiteDatabase instance object respectively in read and in write modes :
Click to expand...
Click to collapse
Actually, in either case, except if the database cannot be opened, for write, both getReadableDatabase and getWritableDatabase will open a database that can be written to. As per :-
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future.
Click to expand...
Click to collapse
as per developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper#getReadableDatabase()​
On occasions people new to SQLite sometimes wonder why no database exists after they have instantiated the subclass of SQLiteOpenHelper (aka the DatabaseHelper). This is because the database is only created when either getWritableDatabase or getReadableDatabase is called. With a single line added to the constructor, the constructor will create the database (and thus invoke the onCreate method) e.g.
Code:
public SQLiteDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.getWritableDatabse();
}
AUTOINCREMENT is perhaps the most commonly misused keyword (perhaps wrongly named). It does not make the column automatically generate a unique ID. It is INTEGER PRIMARY KEY that does this, as it make the column an alias of the **rowid**.
Rather AUTOINCREMENT compliments INTEGER PRIMARY KEY adding a constraint that the generated ID must be larger that any ID that exists or have existed. However, this is a moot point as it's only when the largest possible ID has been assigned (9223372036854775807) that it comes into play (other than without AUTOINCREMENT a deleted highest ID will be resused). At this point a table with AUTOINCREMENT will then fail with an SQLITE_FULL exception (without AUTOINCREMENT will attempt to assign a free lower ID rather than fail). However, AUTOINCREMENT has overheads (using a limited test I came up with an 8-12% degradation in performance when inserting). This is due to a changed algorithm being used that utilises another table sqlite_sequence that stores the highest allocated ID.
The SQLite documentation states :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and disk I/O overhead and should be avoided if not strictly needed. It is usually not needed.
Click to expand...
Click to collapse
sqlite.org/autoinc.html
There are a few issues with the code, such as :-
You should always close Cursors when finished with them (not doing so may result in too many databases /database objects open exception ).
Checking a Cursor for null after a Cursor is returned from a call to an SQLiteDatabase method that returns a Cursor serves no purpose. A valid Cursor will always be returned. If there is no data then using a Cursor moveTo????? method will return false is the move cannot be made, alternately the getCount() method will return the number of rows in the Cursor.
If there were now rows in the Players table, the the code would fail with an error when an attempt is made to retrieve data at
Code:
player.setId(Integer.parseInt(cursor.getString(0)));
Issues regarding mis-calculated column offsets can be reduced by taking advantage of the Cursor's **getColumnIndex** method.
As such, as an example, the getPlayer method would be improved if changed to :-
Code:
public Player getPlayer(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, // a. table
COLUMNS, // b. column names
" id = ?", // c. selections
new String[] { String.valueOf(id) }, // d. selections args
null, // e. group by
null, // f. having
null, // g. order by
null); // h. limit
Player player = new Player(); //<<<<<<<<<< Always have a Player to return (should check for default player to indicated )
if (cursor.moveToFirst()) {
player.setId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_ID))));
player.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
player.setPosition(cursor.getString(cursor.getColumnIndex(KEY_POSITION)));
player.setHeight(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_HEIGHT))));
}
cursor.close(); //<<<<<<<<<< Important to close a Cursor
return player;
}

Related

[Q] My App use API of Google Maps but the map is slow

Hello Boys,
I am a new Android developer and I'm developing an app with the API of Google Maps.
Into an area of the map I place many markers.
The application works correctly, but the map scroolling and the map zoom isn't quick, everything goes slow.
The marker that I have included in the map is in the "png" format image, and his weighs is approximately 600 bytes.
it is possible that many marker object cause low map scrool?
this is the code of my APP:
Code:
plublic class IDC extends MapActivity {
private LocationManager locationManager;
private LocationListener locationListener;
private MapController mc;
private MapView mapView;
private String myPosition;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String errore="";
myPosition="";
try{
mapView = (MapView) findViewById(R.id.mapview);
mc = mapView.getController();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new GPSLocationListener();
//getMyLocation();
MyDBHelper myDB = new MyDBHelper(IDS.this);
Cursor cursor= myDB.query(new String[] { "x", "y", "y2", "w", "k", "latitude", "longitude"});
//Log.i("NOMI", "TOT. NOMI"+cursor.getCount());
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.mm_20_blue);
MyItemizedOverlay itemizedoverlay = new MyItemizedOverlay(drawable,IDS.this);
List<Address> address = new ArrayList<Address>();
Log.i("TOT TUPLE", " = "+cursor.getCount());
while(cursor.moveToNext()){
String s= cursor.getString(0);
errore=s;
String nome[]=s.split("-");
// Log.i("Pos Colonna NOME", ""+cursor.getColumnIndex("nome"));
// Log.i("Pos. in Colonna", ""+cursor.getString(0));
//address.addAll(gc.getFromLocationName(nome[1], 1));
//Address a= address.get(address.size()-1);
String la=cursor.getString(5);
String lo=cursor.getString(6);
double latitude= Double.parseDouble(la);
double longitude= Double.parseDouble(lo);
int lan= (int)(latitude*1E6);
int lon= (int)(longitude*1E6);
GeoPoint point = new GeoPoint(lan, lon);
String tel1=cursor.getString(1);
String tel2=cursor.getString(2);
String mail=cursor.getString(4);
String web=cursor.getString(3);
String info[]= {tel1,tel2,nome[1],web,mail};
MyOverlayItem overlayitem = new MyOverlayItem(point, "Hello", nome[0], info);
//mc.animateTo(point);
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
}
mapView.setBuiltInZoomControls(true);
mc.setZoom(6);
}catch (Exception e) {
e.printStackTrace();
}
}
}
Code:
public class MyItemizedOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private Context mContext;
private CustomizeDialog customizeDialog;
public MyItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
public MyItemizedOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
mContext = context;
}
protected boolean onTap(int index)
MyOverlayItem item = (MyOverlayItem) mOverlays.get(index);
customizeDialog = new CustomizeDialog(mContext);
customizeDialog.setPersonalText(item.getSnippet());
String []info= item.getInfo();
customizeDialog.setT1(info[0]);
customizeDialog.setT2(info[1]);
customizeDialog.setA(info[2]);
customizeDialog.setW(info[3]);
customizeDialog.setM(info[4]);
customizeDialog.show();
return true;
}
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
public int size() {
return mOverlays.size();
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
}
what is the problem??....PLEASE, HELP ME!!

[Q] Making selected spinner items into array references

Hello, i'm making an app, and i need for the app to populate a list view, i've got this to work, the listview is populated by arrays in the values resources folder. the name for this array is defined by the selected items of two spinners combined with a "_" in the middle. How do i set this custom array ID?
here is my current main activity code: (i've used a existing array id to test that it works "tener_future")
Code:
package org.townsend.spanish.donate;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
public class Main extends Activity implements OnClickListener {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
View conjugateButton = findViewById(R.id.conjugate_button);
conjugateButton.setOnClickListener(this);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void verbAndTense() {
Resources res = getResources();
String[] listItems = res.getStringArray(R.array.tener_conditional);
Spinner verbs = (Spinner) findViewById(R.id.verbs);
Spinner verb_tenses = (Spinner) findViewById(R.id.verb_tenses);
ListView conjugated = (ListView) findViewById(R.id.ListView01);
conjugated.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listItems));;
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.conjugate_button:
verbAndTense();
break;
}
}
}
If I understand your question correctly, you are trying to get a reference to an Id stored in the R class, but which reference you need changes at runtime?
If that is the case, I think you may want to program a custom utility/method that can return the correct R reference for you. R is just a static generated class of ints, so it cannot evaluate something like R.id.dynamicterm1_dynamicterm2 where dynamicterm1 and dynamicterm2 change at runtime.
One way to do this might be a static util class like this:
Code:
package org.townsend.spanish.donate.util;
import org.townsend.spanish.donate.R;
public class ReferenceFinder
{
public static int find(String prefixName, String suffixName)
{
int returnValue = -1; // -1 indicates an error
if ( prefixName.equals("verb") && suffixName.equals("tense") )
{
returnValue = R.id.verb_tense;
}
else if( prefixName.equals("adj") && suffixName.equals("tense") )
{
returnValue = R.id.adjective_tense;
}
return returnValue;
}
Then you would call it like so:
Code:
Resources res = getResources();
int resourceID = ReferenceFinder.find("verb", "tense") ;
String[] listItems = res.getStringArray( resourceID );
I'm sure there are other ways to do this, but this is the first that came to mind. Hope that helps
would that mean that in the resource finder class that i'd have to define every possible outcome? because i'll have hundreds of outcomes once i have loaded the full list's and their outcome array's
and i think you have understood me correctly, basically it's and app (for spanish) where in one spinner you input a verb, in another you input a tense, and when you press a button it fills a list view with the 6 conjugations.
also it seems like in the second snippet of code i would have to actually set the "verb" and "tense" or could i put something dynamic like
Code:
verbs.getSelectedItem() + "_" + verb_tenses.getSelectedItem
Thanks for the help
hmm.... you might be able to do it via reflection actually, so that you wouldnt have to define each one.
I'm not 100% sure what the code would be but it would probably looks something like this:
Code:
String className= "com.example.myapp.R.id";
Class cl = Class.forName( className );
String fieldName = verbs.getSelectedItem() + "_" + tenses.getSelectedItem();
Field f = cl.getDeclaredField ( fieldName );
//since field is static, the "object" is ignored
int resourceID = f.getInt ( new Object() );
ok thanks i'm trying to get it to fit in, and i believe i have:
Code:
@SuppressWarnings({ "unchecked", "rawtypes" })
private void verbAndTense() {
Spinner verbs = (Spinner) findViewById(R.id.verbs);
Spinner verb_tenses = (Spinner) findViewById(R.id.verb_tenses);
verb_tenses.getSelectedItem();
String className= "org.townsend.spanish.donate.R.array";
Class cl = Class.forName( className );
String fieldName = verbs.getSelectedItem() + "_" + verb_tenses.getSelectedItem();
Field f = cl.getDeclaredField ( fieldName );
//since field is static, the "object" is ignored
int resourceID = f.getInt ( new Object() );
String[] listItems = f.getStringArray( resourceID );
ListView conjugated = (ListView) findViewById(R.id.ListView01);
conjugated.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listItems));
}
where it says :
Code:
String[] listItems = f.getStringArray( resourceID );
is it correct to put the "f" in there? and second is asks to define "Field" what should i import it as? or do i need to declare it in another format?
should be something like
String[] listItems = getResources.getStringArray( resourceID );
resourceID is an int just like R.id.something_something
i changed getResources to res, since it was defined as:
Code:
Resources res = getResources();
however my problem with "Field" in the line:
Code:
Field f = cl.getDeclaredField ( fieldName );
still exists, it says "Field cannot be resolved to a type" and gives me a load of options including imports, making a new class, interface, enum or adding a parameter. what should i do? I've tried several of the imports but then other segments suchs as:
Code:
cl.getDeclaredField ( fieldName );
become errored.
Thank you for all your guys' help so far
If you're using the Field class and don't IMPORT it, well, that's a problem
You're best friend --> http://developer.android.com/reference/java/lang/reflect/Field.html
thank you yes my porblem was i was unsure which to import it as, although i was more confident about it being that one (i had about 8 options from eclipse)
previous code however has now given me errors, :
Code:
Class cl = [U]Class.forName( className )[/U];
this section saying : "Unhandled exception type ClassNotFoundException"
Code:
Field f = [U]cl.getDeclaredField ( fieldName )[/U];
this with: "Unhandled exception type NoSuchFieldException"
and
Code:
int resourceID = [U]f.getInt ( new Object() )[/U];
with: "Unhandled exception type IllegalAccessException"
I looked through the field resource page and the last one where it says this error occurs when the field is not accesible....:/
I then checked the Class resources page and the first one said that type ClassNotFoundException is thrown when requested class cannot be found, and i thought i had declarred it in the previous
Code:
String className= "org.townsend.spanish.donate.R.array";
I know that in the example you provided me you put R.id, howeve this is a value array so it should be array right?
and the second says its thrown when the field cannot be found.
Im guessing that means that the first one is affecting the rest? how could i correct this,
if you wish to see the entire void it is here
Code:
@SuppressWarnings({ "rawtypes", "unchecked" })
private void verbAndTense() {
Spinner verbs = (Spinner) findViewById(R.id.verbs);
Spinner verb_tenses = (Spinner) findViewById(R.id.verb_tenses);
verb_tenses.getSelectedItem();
String className= "org.townsend.spanish.donate.R.array";
Class cl = Class.forName( className );
String fieldName = verbs.getSelectedItem() + "_" + verb_tenses.getSelectedItem();
Field f = cl.getDeclaredField ( fieldName );
//since field is static, the "object" is ignored
Resources res = getResources();
int resourceID = f.getInt ( new Object() );
String[] listItems = res.getStringArray( resourceID );
ListView conjugated = (ListView) findViewById(R.id.ListView01);
conjugated.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, listItems));
}
Thank you
Yes, sorry it should be R.array or whatever
As for the "unhandled exceptions", if you use eclipse, just do the "recommended fix" and it will add a try/catch for you.
You may have to define some fields outside the try catch block and move some stuff around a bit after eclipse adds the try/catch.
Also, just as an aside, you may want to read a tutorial or two on reflection in Java so what I am saying doesnt sound as new/strange. Not required but it always helps to know a bit of reflection I think

[Q] Code not bringing desired results

good day,
i'm trying to create an app that will create options in a listview on an an activity based on the option a user selects in the previous activity
below is the code i came up with but it doesn't work.
please what am i doing wrong?
thanks in advance
package com.inveniotech.moneyventure;
/**
* Created by BolorunduroWB on 9/3/13.
*/
import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.widget.*;
import java.util.*;
import android.content.Intent;
public class menu_options extends Activity {
SimpleAdapter simpleAdpt;
Intent intent = getIntent();
public String message = intent.getStringExtra(football.EXTRA_MESSAGE);
String[] menuList;
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menuoptionsview);
initList();
// We get the ListView component from the layout
ListView lv = (ListView) findViewById(R.id.listView);
// This is a simple adapter that accepts as parameter
// Context
// Data list
// The row layout that is used during the row creation
// The keys used to retrieve the data
// The View id used to show the data. The key number and the view id must match
simpleAdpt = new SimpleAdapter(this, optionList, android.R.layout.simple_list_item_1, new String[] {"options"}, new int[] {android.R.id.text1});
lv.setAdapter(simpleAdpt);
// React to user clicks on item
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id) {
// We know the View is a TextView so we can cast it
TextView clickedView = (TextView) view;
Toast.makeText(menu_options.this, "Item with id ["+id+"] - Position ["+position+"] - Planet ["+clickedView.getText()+"]", Toast.LENGTH_SHORT).show();
}
});
}
@override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
// The data to show
List<Map<String, String>> optionList = new ArrayList<Map<String,String>>();
private void initList() {
// We populate the planets
if (message.equals("5")){
menuList = new String[]{"News", "Fixtures","Results","Standings"," "};
}
else if (message.equals("6")){
menuList = new String[]{"News", "Tables"," "," "," "};
}
else if (message.equals("7")){
menuList = new String[]{"Done Deals", "Rumours","Latest News","Live","Transfer Centre"};
}
else {
menuList = new String[] {"News","Teams","Fixtures","Results","Table"};
}
optionList.add(createOptions("options", menuList[0]));
optionList.add(createOptions("options", menuList[1]));
optionList.add(createOptions("options", menuList[2]));
optionList.add(createOptions("options", menuList[3]));
optionList.add(createOptions("options", menuList[4]));
}
private HashMap<String, String> createOptions(String key, String name) {
HashMap<String, String> options = new HashMap<String, String>();
options.put(key, name);
return options;
}
}
Read This guide first, then it's easier to help you.
What I'm seeing is that you should set your message=getIntent ().... ; in the onCreate since the Intent data is probably not available before.
SimplicityApks said:
Read This guide first, then it's easier to help you.
What I'm seeing is that you should set your message=getIntent ().... ; in the onCreate since the Intent data is probably not available before.
Click to expand...
Click to collapse
Thank you. Wanted to post the link, too. :laugh:

[Q] app slow down when using sqlite database

I am trying to create a circular buffer using sqlite. For some reason every time I instantiate my db access class, the os start skipping frames (I am using the emulator to run my code).
02-22 20:22:03.172: I/Choreographer(860): Skipped 628 frames! The application may be doing too much work on its main thread.
I do not understand what I am doing wrong. I am calling the database class from an intentService (I assume this should not slow down the main thread at all) as follows:
Code:
private SqliteLog mSqliteLog;
mSqliteLog = new SqliteLog(context);
mSqliteLog.writelogInformation("sleepMode", "ON");
I added my code at the end of this message
Code:
/**
* SqliteLog
*
*
* Base class for sqliteLog control
*
*
*/
public class SqliteLog {
// Debug log tag
private static final String tag = "SqliteLog";
// Version of database
private static final int DATABASE_VERSION = 1;
// Name of database
private static final String DATABASE_NAME = "log";
// Table of database
private static final String TABLE_NAME = "log";
public static final String ROWID_NAME = "id";
public static final String PREFERENCE_NAME = tag + "Pref";
public static final String COLUMN_LOGNUMBER = "logNumber";
public static final String COLUMN_TIME = "time";
public static final String COLUMN_FUNCTION = "function";
public static final String COLUMN_DESCRIPTION = "description";
public static final int TABLE_SIZE = 20;
private static final String DATABASE_CREATE ="create table " + TABLE_NAME + " (" + ROWID_NAME + " integer primary key autoincrement, " +
COLUMN_LOGNUMBER + " INTEGER NOT NULL, " +
COLUMN_TIME + " TEXT NOT NULL, " +
COLUMN_FUNCTION + " TEXT NOT NULL, " +
COLUMN_DESCRIPTION + " TEXT NOT NULL " +
");";
//The context of the calling class;
private Context thisContext;
/**
* <p>Constructor for SqliteLog
* @param context :- Context of calling class
*
*/
public SqliteLog(Context context) {
Log.d(tag,"SqliteLog constructor called");
thisContext = context;
}
/**
* writelogInformation :- Writes a row into the log table
*
*/
public void writelogInformation(String functionName, String descriptionInfo) {
// Retrieve preferences
SharedPreferences SqliteLogPref = thisContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
int logNumber = SqliteLogPref.getInt("logNumber", 1);
// Open database for writing
DatabaseHelper databaseHelper = new DatabaseHelper(thisContext);
SQLiteDatabase sQLiteDatabase = databaseHelper.getWritableDatabase();
// Define the column name and data
ContentValues values = new ContentValues();
values.put(COLUMN_LOGNUMBER, logNumber);
values.put(COLUMN_TIME, getTime());
values.put(COLUMN_FUNCTION, functionName);
values.put(COLUMN_DESCRIPTION, descriptionInfo);
// Update database
sQLiteDatabase.update(TABLE_NAME, values, null, null);
// Close database
databaseHelper.close();
// Test if next database update will need to be wrapped around
logNumber = (logNumber % TABLE_SIZE) + 1;
// Store preferences
SharedPreferences.Editor editor = SqliteLogPref.edit();
editor.putInt("logNumber", logNumber);
editor.commit();
}
/**
* clearLog :- Erase all information from table
*
*/
public void clearLog() {
// Retrieve preferences
SharedPreferences SqliteLogPref = thisContext.getSharedPreferences(PREFERENCE_NAME, 0);
// Store preferences
SharedPreferences.Editor editor = SqliteLogPref.edit();
editor.putInt("logNumber", 1);
editor.commit();
// Delete all rows
DatabaseHelper databaseHelper = new DatabaseHelper(thisContext);
SQLiteDatabase sQLiteDatabase = databaseHelper.getReadableDatabase();
sQLiteDatabase.delete (TABLE_NAME, null, null);
}
/**
* readlogInformation :- Read the whole table
*
*/
public String[] readlogInformation() {
// Create string array of appropriate length
String[] returnArray;
// Retrieve preferences
SharedPreferences SqliteLogPref = thisContext.getSharedPreferences(PREFERENCE_NAME, 0);
int logNumber = SqliteLogPref.getInt("logNumber", 0);
// Open database for reading
DatabaseHelper databaseHelper = new DatabaseHelper(thisContext);
try {
SQLiteDatabase sQLiteDatabase = databaseHelper.getReadableDatabase();
// Get a cursor to the correct cell
Cursor cursor = sQLiteDatabase.query(TABLE_NAME, null, null, null, null, null, null);
// Get number of rows in table
int lengthOfTable = 0;
// Move cursor to where it needs to be
if (cursor != null) {
lengthOfTable = cursor.getCount();
// If count is less than max, then we have not wrapped around yet
if(lengthOfTable < TABLE_SIZE) {
cursor.moveToFirst();
}
// Position cursor appropriately
else {
cursor.moveToPosition(logNumber-1);
}
// Create string array of appropriate length
returnArray = new String[lengthOfTable];
for(int i=1; i<=lengthOfTable; i++) {
returnArray[i] = cursor.getString(1) + "; " + cursor.getString(2) + "; " + cursor.getString(3);
}
}
else {
Log.e(tag,"Cursor null");
// Create string array of appropriate length
returnArray = new String[0];
}
} catch(SQLiteException e) {
Log.d(tag,"SQLiteException when using getReadableDatabase");
// Create string array of appropriate length
returnArray = new String[0];
}
// Close database
databaseHelper.close();
return returnArray;
}
/**
* readlogInformation :- Read the whole table
*
*/
public String getTime() {
// Create a new time object
Time currentTime = new Time(Time.getCurrentTimezone());
// Get current time
currentTime.setToNow();
return currentTime.toString();
}
/**
* DatabaseHelper
*
*
* Class to help control database
*
*
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
/**
* <p>Constructor for DatabaseHelper
* @param context :- Context of calling class<p>
*
*/
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
Log.d(tag,"DatabaseHelper constructor called");
}
/**
* <p>onCreate
* @param db :- Pass an sqlite object
*
*/
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(tag,"onCreate called");
// Create database
db.execSQL(DATABASE_CREATE);
// Insert a new row
ContentValues values = new ContentValues();
// Create a certain number of rows
for(int i=1; i<=TABLE_SIZE; i++) {
values.clear();
values.put(COLUMN_LOGNUMBER, i);
values.put(COLUMN_FUNCTION, "empty");
values.put(COLUMN_DESCRIPTION, "empty");
db.insert(TABLE_NAME, "null", values);
}
Log.d(tag,"database created");
}
/**
* <p>onUpgrade
* @param db :- Pass an sqlite object
* @param oldVersion :- Old version of table
* @param newVersion :- New version of table
*
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(tag,"onUpgrade called");
// Not used, but you could upgrade the database with ALTER
// Scripts
}
}
}
I have been trying to figure this out for a while now. I would appreciate any insight, Amish

adding an image column to an existing tabe in sqlite database

I wanted to add a column which will be able to store images, to an existing sqlite table which has two columns, What datatype column do i create so that i can be able to store images in my database?
My code looks like this
public class Sqlite extends SQLiteOpenHelper {
public static final String DB_NAME = "vault";
public static final int DB_VERSION = 1;
public static final String DB_CREATE = "CREATE TABLE data(key VARCHAR(32) PRIMARY KEY NOT NULL, value VARCHAR(100) NOT NULL)";
public SQLiteDatabase db;
public Context context;
public Sqlite(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
}
@override
public void onCreate(SQLiteDatabase db) {
this.db = db;
this.db.execSQL(DB_CREATE);
}
@override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@override
public synchronized void close() {
if(this.db != null) {
this.db.close();
super.close();
}
}
public List<VaultItem> getAll() throws Exception {
// load items
List<VaultItem> items = new ArrayList<VaultItem>();
// query db
Cursor c = db.query("data", new String[]{"key", "value"}, null, null, null, null, null);
c.moveToFirst();
while(!c.isAfterLast()) {
items.add(new VaultItem(c.getString(0), SimpleCrypto.decrypt(c.getString(1))));
c.moveToNext();
}
return items;
}
public VaultItem getOne(String key) throws Exception {
Cursor c = db.query("data", new String[]{"key", "value"}, "key = '"+key+"'", null, null, null, null);
c.moveToFirst();
VaultItem item=null;
while(!c.isAfterLast()) {
item = new VaultItem(c.getString(0), SimpleCrypto.decrypt(c.getString(1)));
c.moveToNext();
}
return item;
}
}
This table only stores, .txt documents, with their name and content. I want it to to be able to store .doc documents and .jpg files. Please help me...
A Blob data type is what you would want to store in a database for images. http://developer.android.com/reference/java/sql/Blob.html has good info on it.
Basically take your image (bitmap) and convert to byte[] to store in db. Retrieve it by converting byte array to bitmap.
Do not forget to update your DB version to update db with new fields.
Noted to self thrice via tapatalk

Categories

Resources