Android: SQLiteDatabase.insert not inserting - android

Summary
SQLiteDatabase.insertOrThrow() executes, does not throw an exception, and returns a positive integer; however, the record is not written to the database.
Details
I am implementing the repository pattern, and have a generic base repository.
public class BaseRepository<T> implements Repository<T> {
private enum Operation {
Add, Update, Delete
}
private final SQLiteOpenHelper openHelper;
private final String tableName;
private final Mapper<T, ContentValues> toContentValues;
private final Mapper<Cursor, T> toTypeMapper;
public BaseRepository(Context context, String tableName, Mapper<T, ContentValues> toContentValues,
Mapper<Cursor, T> toTypeMapper) {
this.openHelper = new DbOpenHelper(context);
this.tableName = tableName;
this.toContentValues = toContentValues;
this.toTypeMapper = toTypeMapper;
}
#Override
public void add(T item) {
transaction(Operation.Add, item, null);
}
#Override
public void update(T item, String filter) {
transaction(Operation.Update, item, filter);
}
#Override
public void delete(String filter) {
transaction(Operation.Delete, null, filter);
}
private void transaction(Operation operation, T item, String filter) {
final SQLiteDatabase database = openHelper.getWritableDatabase();
database.beginTransaction();
try {
switch (operation) {
case Add:
try { // For debugging, to catch any possible exception
ContentValues values = toContentValues.map(item);
long result = database.insertOrThrow(tableName, null, values);
String temp = ""; // For debugging
} catch (Exception e) {
String message = e.getMessage(); // For debugging
}
break;
case Update:
database.update(tableName, toContentValues.map(item), filter, null);
break;
case Delete:
database.delete(tableName, filter, null);
break;
}
} finally {
database.endTransaction();
database.close();
}
}
}
It gets into the transaction() method, and runs the database.insert() method. I have set breakpoints and have examined the table name and the values. The table name is correct and the values is correct. The method runs and returns a positive integer, indicating that the insert was successful. However, when I examine the database, the record is not inserted.
I have methods to get data and they are working correctly. If I manually add a row, the get method works successfully.
Any thoughts on what is going on here? I've been stuck on this for hours.
Thanks!

Figured it out. I forgot to run database.setTransactionSuccessful():
private void transaction(Operation operation, T item, String filter) {
final SQLiteDatabase database = openHelper.getWritableDatabase();
database.beginTransaction();
try {
switch (operation) {
case Add:
try { // For debugging, to catch any possible exception
ContentValues values = toContentValues.map(item);
long result = database.insertOrThrow(tableName, null, values);
String temp = ""; // For debugging
} catch (Exception e) {
String message = e.getMessage(); // For debugging
}
break;
case Update:
database.update(tableName, toContentValues.map(item), filter, null);
break;
case Delete:
database.delete(tableName, filter, null);
break;
}
database.setTransactionSuccessful(); // Added this.
} finally {
database.endTransaction();
database.close();
}
}

Related

App stops whenever I press back button

Problem: This only happening on some pages. when I press back app stops. I get this error. I am not able to figure it out the exact problem. I am new to android. and this is happening at many pages.Any help would be highly appreciated.
logcat error:
InputEventSender:Exception dispatching finished signal.E/MessageQueue-JNI:Exception in MessageQueue callback:handleReceiveCallbackE/MessageQueue-JNI:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.database.sqlite.SQLiteDatabase.close()' on a null object reference at twik.in.DBHelper.close(DBHelper.java:102)at twik.in.ActivityMenuDetail.onBackPressed(ActivityMenuDetail.java:285)at android.app.Activity.onKeyUp(Activity.java:2477)at android.view.KeyEvent.dispatch(KeyEvent.java:2664)at android.app.Activity.dispatchKeyEvent(Activity.java:2730)
In error these two classes are mentioned so I am posting its code here
public class ActivityMenuDetail extends Activity {
ImageView imgPreview;
TextView txtText, txtSubText;
WebView txtDescription;
Button btnAdd;
ScrollView sclDetail;
ProgressBar prgLoading;
TextView txtAlert;
// declare dbhelper object
static DBHelper dbhelper;
// declare ImageLoader object
ImageLoader imageLoader;
// declare variables to store menu data
String Menu_image, Menu_name, Menu_serve, Menu_description;
double Menu_price;
int Menu_quantity;
long Menu_ID;
String MenuDetailAPI;
int IOConnect = 0;
// create price format
DecimalFormat formatData = new DecimalFormat("#.##");
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu_detail);
ActionBar bar = getActionBar();
bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.header)));
bar.setTitle("Service Centre Detail");
bar.setDisplayHomeAsUpEnabled(true);
bar.setHomeButtonEnabled(true);
imgPreview = (ImageView) findViewById(R.id.imgPreview);
txtText = (TextView) findViewById(R.id.txtText);
txtSubText = (TextView) findViewById(R.id.txtSubText);
txtDescription = (WebView) findViewById(R.id.txtDescription);
btnAdd = (Button) findViewById(R.id.btnAdd);
//btnShare = (Button) findViewById(R.id.btnShare);
sclDetail = (ScrollView) findViewById(R.id.sclDetail);
prgLoading = (ProgressBar) findViewById(R.id.prgLoading);
txtAlert = (TextView) findViewById(R.id.txtAlert);
// get screen device width and height
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int wPix = dm.widthPixels;
int hPix = wPix / 2 + 50;
// change menu image width and height
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(wPix, hPix);
imgPreview.setLayoutParams(lp);
imageLoader = new ImageLoader(ActivityMenuDetail.this);
dbhelper = new DBHelper(this);
// get menu id that sent from previous page
Intent iGet = getIntent();
Menu_ID = iGet.getLongExtra("menu_id", 0);
// Menu detail API url
MenuDetailAPI = Constant.MenuDetailAPI+"?accesskey="+Constant.AccessKey+"&menu_id="+Menu_ID;
// call asynctask class to request data from server
new getDataTask().execute();
// event listener to handle add button when clicked
btnAdd.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
// show input dialog
addtoCart();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_detail, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case R.id.cart:
// refresh action
Intent iMyOrder = new Intent(ActivityMenuDetail.this, ActivityCart.class);
startActivity(iMyOrder);
overridePendingTransition (R.anim.open_next, R.anim.close_next);
return true;
case android.R.id.home:
// app icon in action bar clicked; go home
this.finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// method to show number of order form
void addtoCart(){
// open database first
try{
dbhelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
if(dbhelper.isDataExist(Menu_ID)){
dbhelper.updateData(Menu_ID, 1, (Menu_price));
}else{
dbhelper.addData(Menu_ID, Menu_name, 1, (Menu_price));
}
startActivity(new Intent(ActivityMenuDetail.this,ActivityCart.class));
};
// asynctask class to handle parsing json in background
public class getDataTask extends AsyncTask<Void, Void, Void>{
// show progressbar first
getDataTask(){
if(!prgLoading.isShown()){
prgLoading.setVisibility(0);
txtAlert.setVisibility(8);
}
}
#Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
// parse json data from server in background
parseJSONData();
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
// when finish parsing, hide progressbar
prgLoading.setVisibility(8);
// if internet connection and data available show data
// otherwise, show alert text
if((Menu_name != null) && IOConnect == 0){
sclDetail.setVisibility(0);
imageLoader.DisplayImage(Constant.AdminPageURL+Menu_image, imgPreview);
txtText.setText(Menu_name);
txtSubText.setText("Price : " +Menu_price+" "+ActivityMenuList.Currency+"\n"+"Status : "+Menu_serve+"\n"+"Empty Slots : "+Menu_quantity);
txtDescription.loadDataWithBaseURL("", Menu_description, "text/html", "UTF-8", "");
txtDescription.setBackgroundColor(Color.parseColor("#e7e7e7"));
}else{
txtAlert.setVisibility(0);
}
}
}
// method to parse json data from server
public void parseJSONData(){
try {
// request data from menu detail API
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 15000);
HttpConnectionParams.setSoTimeout(client.getParams(), 15000);
HttpUriRequest request = new HttpGet(MenuDetailAPI);
HttpResponse response = client.execute(request);
InputStream atomInputStream = response.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(atomInputStream));
String line;
String str = "";
while ((line = in.readLine()) != null){
str += line;
}
// parse json data and store into tax and currency variables
JSONObject json = new JSONObject(str);
JSONArray data = json.getJSONArray("data"); // this is the "items: [ ] part
for (int i = 0; i < data.length(); i++) {
JSONObject object = data.getJSONObject(i);
JSONObject menu = object.getJSONObject("Menu_detail");
Menu_image = menu.getString("Menu_image");
Menu_name = menu.getString("Menu_name");
Menu_price = Double.valueOf(formatData.format(menu.getDouble("Price")));
Menu_serve = menu.getString("Serve_for");
Menu_description = menu.getString("Description");
Menu_quantity = menu.getInt("Quantity");
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
IOConnect = 1;
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// close database before back to previous page
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
//imageLoader.clearCache();
super.onDestroy();
}
#Override
public void onConfigurationChanged(final Configuration newConfig)
{
// Ignore orientation change to keep activity from restarting
super.onConfigurationChanged(newConfig);
}
}
and debhelper class here
public class DBHelper extends SQLiteOpenHelper{
String DB_PATH;
private final static String DB_NAME = "db_order";
public final static int DB_VERSION = 1;
public static SQLiteDatabase db;
private final Context context;
private final String TABLE_NAME = "tbl_order";
private final String ID = "id";
private final String MENU_NAME = "Menu_name";
private final String QUANTITY = "Quantity";
private final String TOTAL_PRICE = "Total_price";
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
DB_PATH = Constant.DBPath;
}
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
SQLiteDatabase db_Read = null;
if(dbExist){
//do nothing - database already exist
}else{
db_Read = this.getReadableDatabase();
db_Read.close();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase(){
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
private void copyDataBase() throws IOException{
InputStream myInput = context.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
String myPath = DB_PATH + DB_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
#Override
public void close() {
db.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
/** this code is used to get all data from database */
public ArrayList<ArrayList<Object>> getAllData(){
ArrayList<ArrayList<Object>> dataArrays = new ArrayList<ArrayList<Object>>();
Cursor cursor = null;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID, MENU_NAME, QUANTITY, TOTAL_PRICE},
null,null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast()){
do{
ArrayList<Object> dataList = new ArrayList<Object>();
dataList.add(cursor.getLong(0));
dataList.add(cursor.getString(1));
dataList.add(cursor.getString(2));
dataList.add(cursor.getString(3));
dataArrays.add(dataList);
}
while (cursor.moveToNext());
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return dataArrays;
}
/** this code is used to get all data from database */
public boolean isDataExist(long id){
boolean exist = false;
Cursor cursor = null;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID},
ID +"="+id,
null, null, null, null);
if(cursor.getCount() > 0){
exist = true;
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return exist;
}
/** this code is used to get all data from database */
public boolean isPreviousDataExist(){
boolean exist = false;
Cursor cursor = null;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID},
null,null, null, null, null);
if(cursor.getCount() > 0){
exist = true;
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return exist;
}
public void addData(long id, String menu_name, int quantity, double total_price){
// this is a key value pair holder used by android's SQLite functions
ContentValues values = new ContentValues();
values.put(ID, id);
values.put(MENU_NAME, menu_name);
values.put(QUANTITY, quantity);
values.put(TOTAL_PRICE, total_price);
// ask the database object to insert the new data
try{db.insert(TABLE_NAME, null, values);}
catch(Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void deleteData(long id){
// ask the database manager to delete the row of given id
try {db.delete(TABLE_NAME, ID + "=" + id, null);}
catch (Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void deleteAllData(){
// ask the database manager to delete the row of given id
try {db.delete(TABLE_NAME, null, null);}
catch (Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void updateData(long id, int quantity, double total_price){
// this is a key value pair holder used by android's SQLite functions
ContentValues values = new ContentValues();
values.put(QUANTITY, quantity);
values.put(TOTAL_PRICE, total_price);
// ask the database object to update the database row of given rowID
try {db.update(TABLE_NAME, values, ID + "=" + id, null);}
catch (Exception e)
{
Log.e("DB Error", e.toString());
e.printStackTrace();
}
}}
The logcat says your dbhelper object is null when preforming close()
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
if (dbhelper != null)
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
}
That should fix the problem
From the error trace that you have provided, it seems that "db" instance in DBHelper is null. Therefore in your onBackPressed() when you try to close db by called dbHelper.close(), it's throwing the NullPointerException. Adding a null check will help.
// close database before back to previous page
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
}
The above function will eventually call the function below:
#Override
public void close() {
db.close();
}
Add a null check for "db"
#Override
public void close() {
if (db != null) {
db.close();
}
}
In a quick glance of your code, it seems that you are opening DB only on action like "add to cart".
void addtoCart(){
// open database first
try{
dbhelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
if(dbhelper.isDataExist(Menu_ID)){
dbhelper.updateData(Menu_ID, 1, (Menu_price));
}else{
dbhelper.addData(Menu_ID, Menu_name, 1, (Menu_price));
}
startActivity(new Intent(ActivityMenuDetail.this,ActivityCart.class));
};
If you try to close the screen without performing such action DB object would not be available.
This is because it may getting null object reference of dbhelper and also it doesn't need to use finish(); as when onBackPressed() called activity finished automatically.
if (dbhelper != null)
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
super.onBackPressed();
According to logcat you dbhelper is null, so its giving a NULL POINTER EXCEPTION.
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
}
In the above method, super.onBackPressed(); is called first before closing the database, which is not a good practice.
Change it to,
#Override
public void onBackPressed() {
if (dbhelper != null)
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
super.onBackPressed();
}
Also change,
public void close() {
db.close();
}
to
public void close() {
if(db!=null)
db.close();
}
in Dbhelper.class

null pointer exception when passing strin value from one class to another and initializing db there

//packages
//imports
public class MainActivity extends Activity
{
// some string declarations;
// object creations etc etc
DatabaseManipulation dbManage = new DatabaseManipulation();//whereDatabaseManipulation is a class bdManage -->object
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//creating contentViews;
}
public void methods()
{
//works
}
public void methods2(String name)
{
try{
dbManage.functioncall(name);
}
catch(Exception e)
{
System.out.println(e);// value of e is NullPointerException
}
}
}
And the Second class is DatabaseManipulation.class Which is given below
public class DatabaseManipulation extends Activity
{
public void functioncall(String name)
{
System.out.println(bookName+ " bookname in addBookmark");
SQLiteDatabase db;
db = openOrCreateDatabase("epub.db", SQLiteDatabase.CREATE_IF_NECESSARY,null);// error occurs here
db.setLocale(Locale.getDefault());
db.setLockingEnabled(true);
db.setVersion(1);
String temp_address="nothing";
try
{
String selectQuery = "SELECT lastchapter FROM Bookdetails WHERE bookpath=?";
Cursor c = db.rawQuery(selectQuery, new String[] { name });
if (c.moveToFirst()) {
temp_address = c.getString(c.getColumnIndex("lastchapter")); // assigning value in lastchapter to temp_address
}
System.out.println(temp_address+" result of select Query"); //
}
catch(Exception e)
{
System.out.println(e);
}
try
{
System.out.println("BLOW FILE111");
System.out.println("BLOW FILE222");
final String createtabBook="CREATE TABLE IF NOT EXISTS BookMark(lid INTEGER UNIQUE AUTOINCREMENT, bookpath TEXT , lastchapter TEXT, PRIMARY KEY(bookpath,lastchapter));";
db.execSQL(createtabBook);
ContentValues val=new ContentValues();
val.put("bookpath",name );
val.put("lastchapter", temp_address);
db.insert("Bookdetails", val, "bookpath="+name, null);
System.out.println("BLOW FILE333");
}
catch(Exception e)
{
System.out.println(e+" errors happens");
}
finally
{
db.close();
}
}
}
i just want to call this function from main activity to DatabaseManipulation.java, what am i doing wrong?
in log cat Null pointer exception is shown as the error, because i called it in try catch
can we actually do this type of function call? please help
You can't instantiate an activity like this:
DatabaseManipulation dbManage = new DatabaseManipulation();
You need to use an Intent. Something like this:
Intent intent = new Intent(this, DatabaseManipulation.class);
startActivity(intent);
You can't initialize your database class before your
super.onCreate(savedInstanceState);
method. Make global variable for your Database class
DatabaseManipulation dbManage;
and initiailize it after on onCreate() method after
setContentView(R.layout.urlayout)
method.
dbManage = new DatabaseManipulation();

ResultSet to Android Cursor

I my connecting to a MySQL database that is on PC from my android application.
I am using java.sql.jdb for that. Now I want my result set to get in android.database.cursor??
How can I do that..??
Thats my code I am using in android application its getting the results for database but can't cast to Cursor:
Connection connect = null;
ResultSet resultSet = null;
Statement statement = null;
try {
connect = DriverManager.getConnection("jdbc:mysql://"+DbHelper.DB_Path+"/"+DbHelper.DB_Name+"?"
+ "user="+ DbHelper.DB_UserName+ "&password="+ DbHelper.DB_Pass);
statement = connect.createStatement();
// Result set get the result of the SQL query
resultSet = statement
.executeQuery("Select * from btag_store "+
"Where "+
"guid='"+filterArgs+"'");
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Cursor cc;
cc = (Cursor) resultSet; // error in type casr
I know that type casting will give me error, but is there any other way for that..??
Thanks
To put it simply, you cannot. Unless you are willing to do all the work to define an object that implements the Cursor interface and uses a ResultSet to fulfil Cursor's implementation details. That would be somewhat silly, though, as the ResultSet object is already designed to iterate over results returned from the database. The cleanest approach is to use the ResultSet object as it was intended.
What Dave said is correct. My database items were constructed upon Cursor (Sqlite) but I need the same entrypoint wiht MySQL. So I tried this:
I created a base class
AbstractCursorGen.java:
import android.database.Cursor;
import java.sql.ResultSet;
public abstract class AbstractCursorGen {
protected Cursor c;
protected ResultSet rs;
public abstract int getColumnIndex(String iName);
public abstract String getString(String iName);
public abstract int getInt(String iName);
public abstract long getLong(String iName);
public abstract boolean moveToNext();
public abstract void close();
}
Then the one using Cursor will hold the instance of cursor. There is an additional benefit by getting result giving directly the column string. My code uses this for SQLite.
CursonGen.Java:
import android.database.Cursor;
public class CursorGen extends AbstractCursorGen{
public CursorGen(Cursor c)
{
this.c = c;
}
public int getColumnIndex(String iName)
{
return c.getColumnIndex(iName);
}
public String getString(String iName){
return c.getString(getColumnIndex(iName));
}
public int getInt(String iName){
return c.getInt(getColumnIndex(iName));
}
public long getLong(String iName){
return c.getLong(getColumnIndex(iName));
}
public boolean moveToNext()
{
return c.moveToNext();
}
public void close()
{
c.close();
}
}
And one built upon the resultset. This is used for MySQL results
ResultSetGen.java
import android.util.Log;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ResultSetGen extends AbstractCursorGen{
public ResultSetGen(ResultSet rs)
{
this.rs = rs;
}
public int getColumnIndex(String iName)
{
try {
return rs.findColumn(iName);
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
return -1;
}
}
public String getString(String iName){
try {
return rs.getString(getColumnIndex(iName));
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
return null;
}
}
public int getInt(String iName){
try {
return rs.getInt(getColumnIndex(iName));
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
return -1;
}
}
public long getLong(String iName){
try {
return rs.getLong(getColumnIndex(iName));
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
return -1;
}
}
public boolean moveToNext()
{
try {
return rs.next();
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
return false;
}
}
public void close()
{
try {
rs.close();
} catch (SQLException ex)
{
Log.e("PROX","Column not found");
}
}
}
The trick is providing implementation only for the methods I'm actually using.
This is finally called by (one example)
public Person(AbstractCursorGen cursor)
{
setFromCursor(cursor);
}
protected void setFromCursor(AbstractCursorGen cursor)
{
PersonID = cursor.getLong ( COLUMN_PERSON_ID);
ClusterID = cursor.getInt ( COLUMN_CLUSTER_ID);
Name = cursor.getString ( COLUMN_NAME);
.....
}
Hope this helps.

Getting 2 SQLite records for every email received

I'm very new to android, and programming in general. I've got an email receiver using the K9 email client. I'm checking the email for proper formatting and taking the contents of the email and entering it into an SQLite database on the phone. The receiver is working properly. The problem is that when I send a properly formatted message, it makes 2 records from the first email. If I send another message without deleting the first one, it makes 4 records of the second. The third makes 6 records, etc. I know there is probably something obvious that I'm missing but I can't find the problem.
Here is the code:
public class EmailReceiver extends BroadcastReceiver{
private JobsData jobs;
public static final Uri k9uri = Uri.parse("content://com.fsck.k9.messageprovider/inbox_messages/");
static String[] messages_projection = new String[] {"subject", "preview", "unread"};
#Override
public void onReceive(Context context, Intent intent) {
try {
Context mContext = context;
Cursor curSt = mContext.getContentResolver().query(k9uri, messages_projection, "unread='true'", null, null);
curSt.moveToFirst();
String preview = null;
String subject = null;
jobs = new JobsData(context);
int i = 0;
while (!curSt.isAfterLast()) {
subject = curSt.getString(0);
boolean test = subject.startsWith("JOB# ");
if (test) {
boolean check = true;
try {
for (int k = 5; k < subject.length(); k++) {
if (!Character.isDigit(subject.charAt(k))) {
check = false;
break;
}
}
} catch (Exception e) {
} finally {
}
if (check) {
preview = curSt.getString(1);
compareDb(subject.substring(7), preview, context);
}
}
curSt.moveToNext();
}
curSt.close();
} catch (Exception e) {
Toast toast = Toast.makeText(context, e.toString(), Toast.LENGTH_LONG);
toast.show();
}
if (emails != null) {
}
}
private void compareDb (String jobNo, String preview, Context context) {
try {
String[] dbJobs = new String[] {"JobNo"};
SQLiteDatabase db = jobs.getReadableDatabase();
Cursor dbCur = db.query(tableName, dbJobs, null, null, null, null, null);
dbCur.moveToFirst();
while (!dbCur.isAfterLast()) {
if (!jobNo.equals(dbCur.getString(0))) {
jobExtractor(preview, jobNo, context);
}
dbCur.moveToNext();
}
dbCur.close();
} catch (Exception e){
Toast toast = Toast.makeText(context, e.toString(), Toast.LENGTH_LONG);
toast.show();
}
}
private void addJobs(Job job){
SQLiteDatabase db = jobs.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(custName, job.getCustName());
values.put(jobNumber, job.getJobNumber());
values.put(jobType, job.getJobType());
values.put(address, job.getAddress());
values.put(zip, job.getZip());
values.put(contact, job.getContact());
values.put(contactNumber, job.getContactNumber());
values.put(problem, job.getProblem());
db.insertOrThrow(tableName, null, values);
db.close();
}
The "jobextractor" method works fine so I didn't include it. If someone can please help me I would appreciate it.
Thanks
Just a side note. I also want it to only look at unread email but that's not working either. Not a major problem at this point but if you have an answer to that I would be very grateful.
I foundthe problem.
while (!dbCur.isAfterLast()) {
if (!jobNo.equals(dbCur.getString(0))) {
jobExtractor(preview, jobNo, context);
}
dbCur.moveToNext();
}
The problem was here. I was checking to see if the job number matched existing records in the database. It went through each record in the table and added a new job for every record that didn't match. I replaced the jobExctractor line with a boolean check and if the check returned true after the loop I didn't add the job.

I have problems when using sqlite inside AsyncTask in android?

I face two main problems when using a sqlite command inside an AsncTask in android.
When I execute a select command on the first try I get no results but on the second try (loading a activity that has this Asynctask) I do get results.
Sometimes I get an error that the database is not closed despite that it is already closed/
What is the problem with this?
UPDATE:
This is the code that retrive data from database (db.getAllMessage)
private ArrayList<FriendMessagesResulted> getMessagesFromCach(Context c){
FriendMessagesResulted messagesResulted1 = new FriendMessagesResulted();
DBAdapter db = new DBAdapter(c);
Cursor c1;
db.open();
c1 = db.getAllMessage(Settings.getCurrentUserId(c),Integer.parseInt(fId));
Log.d("***Database count",c1.getCount()+" from: "+Settings.getCurrentUserId(c)+" to:"+Integer.parseInt(fId));
c1.moveToFirst();
if(c1.getCount()>0)
status=true;
if (messagesResultedList == null) {
messagesResultedList = new ArrayList<FriendMessagesResulted>();
}
else
messagesResultedList.clear();
while (c1.isAfterLast() == false) {
if(Integer.parseInt(c1.getString(0))>maxId)
maxId=Integer.parseInt(c1.getString(0));
messagesResulted1.set_mId(Integer.parseInt(c1.getString(0)));
messagesResulted1.set_msgTxt("MD:"+c1.getString(3));
messagesResulted1.set_MessageTime(c1.getString(4));
messagesResulted1.set_dir(c1.getString(5));
messagesResultedList.add(messagesResulted1);
c1.moveToNext();
}
db.close();
c1.close();
return messagesResultedList;
}
and this the code for AsyncTask, where I call get getMessagesFromCach method
private void getMessages(final Context c)
{
handler = new Handler();
r=new Runnable() {
public void run() {
class RecentMessageLoader extends AsyncTask<Void, Void, ArrayList<FriendMessagesResulted>>{
ArrayList<FriendMessagesResulted> messagesResultedList=null;
#Override
protected ArrayList<FriendMessagesResulted> doInBackground(Void... params) {
if(!finishLoadingPastMessages)
{
messagesResultedList=getMessagesFromCach(c);
if(!status){
Log.d("Where are you","I'm in JSON");
messagesResultedList=getMessagesFromJSON(c);
}
}
else{
Log.d("Where are you","I'm in Recent messages");
messagesResultedList=getRecentMessages(c,Settings.getCurrentUserId(c),Integer.parseInt(fId));
}
return messagesResultedList;
}
protected void onPostExecute( ArrayList<FriendMessagesResulted> FMRList ) {
// to disappear loading message
d.dismiss();
finishLoadingPastMessages=true;
if(FMRList!=null){
for(int i=FMRList.size()-1;i>=0;i--)
addMessage(FMRList.get(i),c);
}
handler.postDelayed(r, 2000);
}
}
new RecentMessageLoader().execute();
}
};
handler.post(r);
}
UPDATE 2 : Cach class ..
public class Cach {
static DBAdapter db;
public Cach(Context c)
{
}
public static void AddMessages(Context c,
int id,
int fromId,
int toId,
String message,
String dir,
String MessageTime)
{
db = new DBAdapter(c);
db.open();
long id2;
id2 = db.insertMessage(id, fromId, toId, message, dir,MessageTime);
db.close();
}
}
It seems the problem is with the type of variables you are using.. there must be Static variables of instance variables which are getting set from many sources... try not to use static variables and use local variables I mean in the methods implicitly.

Categories

Resources