How can I encrypt my data?
As far as the solutions I study there are two ways:
Encrypt data using an algorithm provided by android. I use "Cipher" is provided by android to encrypt my data. But I'm having problems retrieving data with large number of records, making the app's performance significantly reduced.
I coded the whole database and then every session I decoded and saved in the cache but no algorithm was found to solve this.
I use the following for encrypting/decrypting at a column level, i.e. it is only applied to the sensitive data.
class EncryptDecrypt {
private Cipher cipher;
private static SecretKeySpec secretKeySpec;
private static IvParameterSpec ivParameterSpec;
private boolean do_encrypt = true;
/**
* Construct EncryptDecrypt instance that checks the current logged-in
* user status; basically if the user is the special NOUSER, where
* the user does not use a password, then encryption decryption is
* skipped, the alternative constructor does not undergo this check and
* thus will always encrypt (see alternative)
* #param context The context, required for database usage (user)
* #param skey The secret key to be used to encrypt/decrypt
* #param userid The userid (so that the salt can be obtained)
*/
EncryptDecrypt(Context context, String skey, long userid) {
DBUsersMethods users = new DBUsersMethods(context);
if (MainActivity.mLoginMode == LoginActivity.LOGINMODE_NONE) {
do_encrypt = false;
return;
}
String saltasString = users.getUserSalt(userid);
String paddedskey = (skey + saltasString).substring(0,16);
secretKeySpec = new SecretKeySpec(paddedskey.getBytes(),"AES/CBC/PKCS5Padding");
ivParameterSpec = new IvParameterSpec((saltasString.substring(0,16)).getBytes());
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (Exception e){
}
}
/**
* Construct EncryptDecrypt instance that does not check user login-in
* mode, thus the assumption is that this user is NOT the special user
* NOUSER that doesn't require a password to login; this constructor
* is designed to ONLY be used when a user has been added by NOUSER,
* and to then encrypt the data using the enccryptForced method solely
* to encrypt any existing card data for the new user that has a password.
*
* #param context The context, required for database usage (user)
* #param skey The secret key to be used to encrypt/decrypt
* #param userid The userid (so that the salt can be obtained)
* #Param mode Not used other than to distinguish constructor
*/
EncryptDecrypt(Context context, String skey, long userid, boolean mode) {
DBUsersMethods users = new DBUsersMethods(context);
String saltasString = users.getUserSalt(userid);
String paddedskey = (skey + saltasString).substring(0,16);
secretKeySpec = new SecretKeySpec(paddedskey.getBytes(),"AES/CBC/PKCS5Padding");
ivParameterSpec = new IvParameterSpec((saltasString.substring(0,16)).getBytes());
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (Exception e){
//e.printStackTrace();
}
}
/**
* Normal encryption routine that will not encrypt data if the user is
* the special case NOUSER (i.e LOGIN mode is NOUSER), otherwise data
* is encrypted.
*
* #Param toEncrypt The string to be encrypted
* #return The encryted (or not if NOUSER) data as a string
*/
String encrypt(String toEncrypt) {
if (!do_encrypt) {
return toEncrypt;
}
byte[] encrypted;
try {
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
encrypted = cipher.doFinal(toEncrypt.getBytes());
} catch (Exception e) {
//e.printStackTrace();
return null;
}
return Base64.encodeToString(encrypted,Base64.DEFAULT);
}
/**
* Encryption, irrespective of the USER type, noting that this should
* only be used in conjunction with an EncryptDecrypt instance created
* using the 2nd/extended constructor
*
* #param toEncrypt The string to be encrypted
* #return The encrypted data as a string
*/
String encryptForced(String toEncrypt) {
byte[] encrypted;
try {
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
encrypted = cipher.doFinal(toEncrypt.getBytes());
} catch (Exception e) {
//e.printStackTrace();
return null;
}
return Base64.encodeToString(encrypted,Base64.DEFAULT);
}
/**
* Decrypt an encrypted string
* #param toDecrypt The encrypted string to be decrypted
* #return The decrypted string
*/
String decrypt(String toDecrypt) {
if (!do_encrypt) {
return toDecrypt;
}
byte[] decrypted;
try {
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec);
decrypted = cipher.doFinal(Base64.decode(toDecrypt,Base64.DEFAULT));
} catch (Exception e) {
//e.printStackTrace();
return null;
}
return new String(decrypted);
}
}
Example usage (encryption) :-
........
db.beginTransaction();
........
newed = new EncryptDecrypt(mContext,newPassword,newUserId,true);
// Process the MatrixCursor created above
while (mxc.moveToNext()) {
// Generate the whereclause to determine which row is to be updated
whereclause = DBCardsTableConstants.CARDID.getDBColumnName() + "=?";
// Set the value to replace the ? plcaeholder with the current CARDID
whereargs = new String[]{
Long.toString(
mxc.getLong(
mxc.getColumnIndex(
DBCardsTableConstants.CARDID.getDBColumnName()
)
)
)
};
String mxc_nameoncard = mxc.getString(mxc.getColumnIndex(DBCardsTableConstants.CARDNAMEONCARD.getDBColumnName()));
String mxc_number = mxc.getString(mxc.getColumnIndex(DBCardsTableConstants.CARDNUMBER.getDBColumnName()));
String mxc_cvv = mxc.getString(mxc.getColumnIndex(DBCardsTableConstants.CARDCVVCODE.getDBColumnName()));
String mxc_pin = mxc.getString(mxc.getColumnIndex(DBCardsTableConstants.CARDPIN.getDBColumnName()));
String mxc_exp = mxc.getString(mxc.getColumnIndex(DBCardsTableConstants.CARDEXPIRYDATE.getDBColumnName()));
String enc_nameoncard = newed.encryptForced(mxc_nameoncard);
String enc_number = newed.encryptForced(mxc_number);
String enc_cvv = newed.encryptForced(mxc_cvv);
String enc_pin = newed.encryptForced(mxc_pin);
String enc_exp = newed.encryptForced(mxc_exp);
// Prepare the data to be updated.
ContentValues cv = new ContentValues();
cv.put(DBCardsTableConstants.CARDOWNER.getDBColumnName(),
newUserId
);
cv.put(DBCardsTableConstants.CARDNAMEONCARD.getDBColumnName(),enc_nameoncard);
cv.put(DBCardsTableConstants.CARDNUMBER.getDBColumnName(),enc_number);
cv.put(DBCardsTableConstants.CARDCVVCODE.getDBColumnName(),enc_cvv);
cv.put(DBCardsTableConstants.CARDPIN.getDBColumnName(),enc_pin);
cv.put(DBCardsTableConstants.CARDEXPIRYDATE.getDBColumnName(),enc_exp);
// Perform the update
db.update(DBCardsTableConstants.CARDS.getDBTableName(),
cv,
whereclause,
whereargs
);
}
// Done with the MatrixCursor so close it
mxc.close();
// Done updating so apply all the changes
db.setTransactionSuccessful();
// Done with the transaction
db.endTransaction();
Example Usage (decryption)
Cursor getDecyrptedCard(long cardid) {
EncryptDecrypt ed = new EncryptDecrypt(mContext,
LoginActivity.getCurrentUserPassWord(),
MainActivity.mCurrentUserid);
MatrixCursor cnvcsr = new MatrixCursor(mCardsTableColumns,10);
String whereclause = DBCardsTableConstants.CARDID.getDBColumnName() +
"=? AND " +
DBCardsTableConstants.CARDOWNER.getDBColumnName() +
"=?";
String[] whereargs = {Long.toString(cardid), Long.toString(MainActivity.mCurrentUserid)};
Cursor basecsr = db.query(DBCardsTableConstants.CARDS.getDBTableName(),
null,
whereclause,
whereargs,
null,null,null,null);
// Check to see of card exists (always should)
if (!basecsr.moveToFirst()) {
cnvcsr.addRow(new Object[]{0L,0L,"NOTACARD","NOTACARD","","","","",""});
return cnvcsr;
}
// If Card is for NOUSER then no decryption requires so return
// base cursor after repositioning to before first.
if (MainActivity.getLoginMode() == LoginActivity.LOGINMODE_NONE) {
basecsr.moveToPosition(-1);
return basecsr;
}
// Get data to decrypt
String extracted_cardnameoncard = basecsr.getString(basecsr.getColumnIndex(
DBCardsTableConstants.CARDNAMEONCARD.getDBColumnName()
));
String extracted_cardnumber = basecsr.getString(basecsr.getColumnIndex(
DBCardsTableConstants.CARDNUMBER.getDBColumnName()
));
String extracted_cardcvv = basecsr.getString(basecsr.getColumnIndex(
DBCardsTableConstants.CARDCVVCODE.getDBColumnName()
));
String extracted_cardpin = basecsr.getString(basecsr.getColumnIndex(
DBCardsTableConstants.CARDPIN.getDBColumnName()
));
String extracted_cardexpiry = basecsr.getString(basecsr.getColumnIndex(
DBCardsTableConstants.CARDEXPIRYDATE.getDBColumnName()
));
// Decrypt data
String decrypted_nameoncard = ed.decrypt(extracted_cardnameoncard);
String decrypted_cardnumber = ed.decrypt(extracted_cardnumber);
String deccrypted_cardcvv = ed.decrypt(extracted_cardcvv);
String decrypted_expiry = ed.decrypt(extracted_cardexpiry);
String decrypted_cardpin = ed.decrypt(extracted_cardpin);
// Store decrypted data
cnvcsr.addRow(new Object[]{
basecsr.getLong(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDID.getDBColumnName()
)),
basecsr.getLong(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDTYPEREF.getDBColumnName()
)
),
basecsr.getLong(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDOWNER.getDBColumnName()
)
),
basecsr.getString(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDNAME.getDBColumnName()
)
),
decrypted_nameoncard,
decrypted_cardnumber,
deccrypted_cardcvv,
decrypted_cardpin,
decrypted_expiry,
basecsr.getString(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDNOTES.getDBColumnName()
)
),
basecsr.getInt(
basecsr.getColumnIndex(
DBCardsTableConstants.CARDCOLOUR.getDBColumnName()
)
)
});
basecsr.close();
return cnvcsr;
}
Note! NOUSER is when a single user of the App decides to not use a password/login.
Related
can you please help me.
I have created a table and now I want to generate the Update command with SQLiteCommandBuilder.
But the Commandbuilder fails with
Dynamic SQL generation is not supported against a SelectCommand that does not return any base table information.
Im at a loss here, The Table has a primary key, and the Fill is working, giving me a Table with the 2 Fields. Its just the Commandbuilder thats failing me.
string extStorage = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
string ProjectPath = Path.Combine(extStorage, "DBTEST");
string dbFile = Path.Combine(ProjectPath, "TEST.DB");
if (!Directory.Exists(ProjectPath)) {
Directory.CreateDirectory(ProjectPath);
}
if (File.Exists(dbFile)) {
File.Delete(dbFile);
}
SqliteConnection.CreateFile(dbFile);
string my_Connection = string.Format("Data Source={0};Version=3;", dbFile);
try {
SqliteConnection my_DB_Con = new SqliteConnection(my_Connection);
my_DB_Con.Open();
SqliteCommand cmdCreate = new SqliteCommand("Create Table [T_RESULT] ( [LFDNR] int PRIMARY KEY not null, [TTT1] text);", my_DB_Con);
cmdCreate.ExecuteNonQuery();
SqliteCommand cmd = new SqliteCommand("select * from [T_RESULT]", my_DB_Con);
SqliteDataAdapter my_adapter = new SqliteDataAdapter(cmd);
DataSet ds = new DataSet();
my_adapter.Fill(ds, "T_RESULT");
SqliteCommandBuilder bld = new SqliteCommandBuilder(my_adapter);
my_adapter.Fill(ds);
my_adapter.UpdateCommand = bld.GetUpdateCommand(true);
string text = my_adapter.UpdateCommand.CommandText;
} catch (Exception exc) {
string t = exc.Message;
}
The Code throws at GetUpdateCommand.
The same Code works on Windows.
Can anyone help me here please.
I am developing a mobile application in android.The application gets data from a database(in SQL Server) using a soap web service(in java). Now i have been stuck into a problem and it is as follows- the android application retrieves a row (all the columns) from the database and sets the column values to the respective text fields but i don't know what to do in the web service. Please help me
My Code for the web method is-
#WebMethod(operationName = "DiseaseInfoGC")
public String DiseaseInfo4( #WebParam(name = "crop_name") String crop,
#WebParam(name = "spread_mode") String spread_mode,
#WebParam(name = "path_cong_env") String path_cong_env) {
query_disease = new String();
try {
DBConnect.databaseconnect();
Statement stmt_disease = DBConnect.connect.createStatement();
query_disease = "Select * from Disease where crop_name='" + crop + "' and Disease_SpreadMode='"+spread_mode+"' "
+ "and Disease_PathCongEnv='" + path_cong_env + "'";
System.out.println(query_disease);
ResultSet rslt_disease = stmt_disease.executeQuery(query_disease);
System.out.println(query_disease);
executemyquery(rslt_disease);
System.out.println(query_disease);
} catch (ClassNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (SQLException ex) {
System.out.println(ex.getMessage());;
} catch (NullPointerException ex) {
System.out.println(ex.getMessage());
}
return disease_name;
}
And the executequery() is-
private void executemyquery(ResultSet rslt_disease) throws SQLException {
while (rslt_disease.next()) {
disease_name = rslt_disease.getString("Disease_EngName");
System.out.println("Name Of the Disease: "+disease_name);
path_name = rslt_disease.getString("Disease_PathScName");
System.out.println("Name of the Pathogen: "+path_name);
path_geo_dis = rslt_disease.getString("Disease_PathGeoDist");
System.out.println("Pathogen Scientific name: "+path_geo_dis);
path_life_cycle = rslt_disease.getString("Disease_PathLCycle");
System.out.println("Life Cycle of the Pathogen: "+path_life_cycle);
disease_symptoms = rslt_disease.getString("Disease_Symptom");
System.out.println("Disease Symptoms: "+disease_symptoms);
disease_controls = rslt_disease.getString("Disease_Control");
System.out.println("Disease control mechanism: "+disease_controls);
prevention = rslt_disease.getString("Disease_Prevention");
System.out.println("Disease prevention Mechanism: "+prevention);
spread_mode = rslt_disease.getString("Disease_SpreadMode");
System.out.println("Spread mode of the disease: "+spread_mode);
primary_source = rslt_disease.getString("Disease_PSource");
System.out.println("Primary Source: "+primary_source);
secondary_source = rslt_disease.getString("Disease_SSource");
System.out.println("Secondary Source: "+secondary_source);
path_a_host = rslt_disease.getString("Disease_PathAHost");
System.out.println("Pathogen host"+path_a_host);
path_cong_env = rslt_disease.getString("Disease_PathCongEnv");
System.out.println("Pathogen Congenial Envoronment"+path_cong_env);
occur_period = rslt_disease.getString("Disease_OccurancePd");
System.out.println("Disease occuring period: "+occur_period);
}
I have just stored the column values in the string. I know that it is useless use string here. But i have no idea how to store the column values from the database in the web method so that i can use them in the android application.Hope you can understand my question. Please guide me..
I have an android application that display data from my external Database so from several tables. Everything work fine while internet connection is available (all data come from URL link and they are been parsed with volley). But how can I save and load lastest data when internet is not available.
What is the best way to do that. Im new in android....
Please help.
Normally Volley and also HttpStack it uses allows you to seamlessly cache responses. This however depends on your responses and requests. Those cache strategies obeys http cache definition. If You want to have different behavior for Volley you can just override this part. basically when you create a request you can override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
and instead of
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
you do
long now = System.currentTimeMillis();
Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
entry.ttl = now + 30l * 24 * 60 * 60 * 1000; //kepps cache for 30 days
//entry.softTtl = now + 30l * 24 * 60 * 60 * 1000; //will not refresh for 30 days
return Response.success(parsed, entry);
Which basically will refresh the cache every time the server specifies so but will always return the cache for 30 days unless changes .
Note that here you may receive 2 callbacks in response or in one response and 1 error(in case of no network). the first one will be the cache.
UPDATE:
if you add (which is commented in the example above):
entry.softTtl = now + 30l * 24 * 60 * 60 * 1000; //will not refresh for 30 days
this will affect the refresh of the cache. in this case it wont event try to refresh the cache for 30 days. In that case you will return 1 response.
Note that I never would recommend solution like this because cache needs to be updated, especially if you want to fake cache on POST requests as in your case.
Receiving 2 callbacks is not really an issue as you can handle this seamlesly for the user and update UI when needed. also if you want to have more control you can know which one is from the cache and which one form the network by implementing your
ResponseDelivery
or extend
ExecutorDelivery
and then check for the param
mResponse.intermediate
and decide what to do then. ResponseDelivery is the one which calls the callbacks.
Update
similar question and examples here
if you have to store only small chunk of data then use SharedPreferences
If you have large data then use SQLite
Use below code to create and update SQLite DB
public class SqlMangaeMenu
{
SQLiteDatabase db1 = null;
private static String DBNAME = "YourLocal.db";
Context gcntxt;
public SqlMangaeMenu(Context cntxt)
{
// TODO Auto-generated constructor stub
gcntxt=cntxt;
db1 = cntxt.openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE,null);
db1.execSQL("CREATE TABLE IF NOT EXISTS mytbl(appid varchar PRIMARY KEY,appname varchar,iconcode varchar,msgidentfier varchar,scode varchar,image blob,imagehdr blobhdr); ");
}//EOF Constructor
public void insertContent(String appid,String appname,String iconcode,String msgidentifier,String scode,Bitmap bmp,Bitmap bmphdr)
{
ContentValues contentValues = new ContentValues();
contentValues.put("appid", appid);
contentValues.put("appname", appname);
contentValues.put("iconcode", iconcode);
contentValues.put("msgidentfier", msgidentifier);
contentValues.put("scode", scode);
byte[] blob = null,blobhdr=null;
if(bmp!=null)
{
ByteArrayOutputStream outStr = new ByteArrayOutputStream();
bmp.compress(CompressFormat.PNG, 100, outStr);
blob = outStr.toByteArray();
}
contentValues.put("image", blob);
if(bmphdr!=null)
{
ByteArrayOutputStream outStr1 = new ByteArrayOutputStream();
bmphdr.compress(CompressFormat.PNG, 100, outStr1);
blobhdr = outStr1.toByteArray();
}
contentValues.put("imagehdr", blobhdr);
Log.d("db", "SQL Writing"+appid+appname+iconcode+msgidentifier+scode);
try {
// db1.insert("mytbl",null,contentValues);
db1.insertWithOnConflict("mytbl", null, contentValues,SQLiteDatabase.CONFLICT_IGNORE);
} catch (Exception e)
{
// TODO: handle exception
}
db1.close();
}//EOF insertContent
// Deleting single contact
public void Delete_appid(String id)
{
db1.delete("mytbl", "appid" + "=" + id, null);
db1.close();
}//EOF Delete_appid
public void readAppId()
{
MyApplication.dbappid=new ArrayList<String>();
String appid;
try
{
Cursor c = db1.rawQuery("SELECT * FROM mytbl", null);
//Cursor c = db1.rawQuery("SELECT MAX(ID) FROM mytbl", null);
if(c!= null)
{
if (c.moveToFirst())
{
do {
appid=c.getString(c.getColumnIndex("appid"));
MyApplication.dbappid.add(appid);
}while(c.moveToNext());
}
}
Log.d("db", "SQL Reading");
db1.close();
}
catch(Exception e)
{
System.out.println(e);
}
}//EOF readAppId
public void readDataandImage()
{
Bitmap image=null,imagehdr = null;
//Bitmap images
MyApplication.dbimg=new ArrayList<Bitmap>();
MyApplication.dbhdrimage=new ArrayList<Bitmap>();
//String
MyApplication.dbappname=new ArrayList<String>();
MyApplication.dbappid=new ArrayList<String>();
MyApplication.dbiconcode=new ArrayList<String>();
String appname,appid,iconcode;
try
{
Cursor c = db1.rawQuery("SELECT * FROM mytbl", null);
if(c!= null)
{
if (c.moveToFirst())
{
do {
image=null;imagehdr=null;
byte[] blob = c.getBlob(c.getColumnIndex("image"));
byte[] blobhdr = c.getBlob(c.getColumnIndex("imagehdr"));
appid=c.getString(c.getColumnIndex("appid"));
appname=c.getString(c.getColumnIndex("appname"));
iconcode=c.getString(c.getColumnIndex("iconcode"));
if(blob!=null)
{
image = BitmapFactory.decodeByteArray(blob, 0, blob.length);
}
if(blobhdr!=null)
{
imagehdr = BitmapFactory.decodeByteArray(blobhdr, 0, blobhdr.length);
}
//Images
MyApplication.dbimg.add(image);
MyApplication.dbappid.add(appid);
//String
MyApplication.dbappname.add(appname);
MyApplication.dbiconcode.add(iconcode);
MyApplication.dbhdrimage.add(imagehdr);
}while(c.moveToNext());
}
}
Log.d("db", "SQL Reading");
db1.close();
}
catch(Exception e)
{
System.out.println(e);
}
}//EOF readDataandImage
public int dbRowCount()
{
int rowcnt=0;
String countQuery = "SELECT * FROM mytbl";
//SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db1.rawQuery(countQuery, null);
rowcnt = cursor.getCount();
cursor.close();
db1.close();
Log.d("db", "Numrecs"+rowcnt);
return rowcnt;
}//EOFdbRowCount
}
where MyApplication is a static class to hold the read values.
I've seen apps doing this, but I don't have a clue where to start. Any hints? Some code snippets will be appreciated.
/**
* Add a bookmark to the database.
*
* #param context
* Context of the calling Activity. This is used to make Toast confirming that the bookmark has been added. If the caller provides null, the Toast will not be shown.
* #param cr
* The ContentResolver being used to add the bookmark to the db.
* #param url
* URL of the website to be bookmarked.
* #param name
* Provided name for the bookmark.
* #param thumbnail
* A thumbnail for the bookmark.
* #param retainIcon
* Whether to retain the page's icon in the icon database. This will usually be <code>true</code> except when bookmarks are added by a settings restore agent.
*/
static void addBookmark(Context context, ContentResolver cr, String url, String name, Bitmap thumbnail, boolean retainIcon) {
final String WHERE_CLAUSE = "url = ? OR url = ? OR url = ? OR url = ?";
final String WHERE_CLAUSE_SECURE = "url = ? OR url = ?";
String[] SELECTION_ARGS;
// Want to append to the beginning of the list
long creationTime = new Date().getTime();
// First we check to see if the user has already visited this
// site. They may have bookmarked it in a different way from
// how it's stored in the database, so allow different combos
// to map to the same url.
boolean secure = false;
String compareString = url;
if (compareString.startsWith("http://")) {
compareString = compareString.substring(7);
} else if (compareString.startsWith("https://")) {
compareString = compareString.substring(8);
secure = true;
}
if (compareString.startsWith("www.")) {
compareString = compareString.substring(4);
}
if (secure) {
SELECTION_ARGS = new String[2];
SELECTION_ARGS[0] = "https://" + compareString;
SELECTION_ARGS[1] = "https://www." + compareString;
} else {
SELECTION_ARGS = new String[4];
SELECTION_ARGS[0] = compareString;
SELECTION_ARGS[1] = "www." + compareString;
SELECTION_ARGS[2] = "http://" + compareString;
SELECTION_ARGS[3] = "http://" + SELECTION_ARGS[1];
}
Cursor cursor = cr.query(Browser.BOOKMARKS_URI, Browser.HISTORY_PROJECTION, secure ? WHERE_CLAUSE_SECURE : WHERE_CLAUSE, SELECTION_ARGS, null);
ContentValues map = new ContentValues();
if (cursor.moveToFirst() && cursor.getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
// This means we have been to this site but not bookmarked
// it, so convert the history item to a bookmark
map.put(Browser.BookmarkColumns.CREATED, creationTime);
map.put(Browser.BookmarkColumns.TITLE, name);
map.put(Browser.BookmarkColumns.BOOKMARK, 1);
// map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
cr.update(Browser.BOOKMARKS_URI, map, "_id = " + cursor.getInt(0), null);
} else {
int count = cursor.getCount();
boolean matchedTitle = false;
for (int i = 0; i < count; i++) {
// One or more bookmarks already exist for this site.
// Check the names of each
cursor.moveToPosition(i);
if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX).equals(name)) {
// The old bookmark has the same name.
// Update its creation time.
map.put(Browser.BookmarkColumns.CREATED, creationTime);
cr.update(Browser.BOOKMARKS_URI, map, "_id = " + cursor.getInt(0), null);
matchedTitle = true;
break;
}
}
if (!matchedTitle) {
// Adding a bookmark for a site the user has visited,
// or a new bookmark (with a different name) for a site
// the user has visited
map.put(Browser.BookmarkColumns.TITLE, name);
map.put(Browser.BookmarkColumns.URL, url);
map.put(Browser.BookmarkColumns.CREATED, creationTime);
map.put(Browser.BookmarkColumns.BOOKMARK, 1);
map.put(Browser.BookmarkColumns.DATE, 0);
// map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
int visits = 0;
if (count > 0) {
// The user has already bookmarked, and possibly
// visited this site. However, they are creating
// a new bookmark with the same url but a different
// name. The new bookmark should have the same
// number of visits as the already created bookmark.
visits = cursor.getInt(Browser.HISTORY_PROJECTION_VISITS_INDEX);
}
// Bookmark starts with 3 extra visits so that it will
// bubble up in the most visited and goto search box
map.put(Browser.BookmarkColumns.VISITS, visits + 3);
cr.insert(Browser.BOOKMARKS_URI, map);
}
}
if (retainIcon) {
WebIconDatabase.getInstance().retainIconForPageUrl(url);
}
cursor.close();
}
You can see the OS code here
public GenericRawResults<Object[]> getCountByStatus(Date date,int status){
Log.info("CallDayPlanningDao",date.toString());
GenericRawResults<Object[]> rawResults=null;
Dao callDayPlanningDao = getDao(CallDayPlanning.class);
QueryBuilder query = callDayPlanningDao.queryBuilder();
int year = date.getYear();
int month = date.getMonth();
Date date1 = new Date(year, month,1);
Date date2 = new Date(year, month+1,1);
Date startDate = new Date(date1.getTime()-5);
Date endDate = new Date(date2.getTime()-5);
try {
**query.where().between("calldate", startDate, endDate);**//This line is not working
if(status==Constant.cnStatus){
query.where().in("callstatus", status,Constant.ccStatus);
}else{
query.where().eq("callstatus", status);
}
query.groupBy("calldate");
query.selectRaw("calldate,count(*)");
rawResults = callDayPlanningDao.queryRaw(query.prepareStatementString(), new DataType[] {
DataType.DATE_STRING, DataType.INTEGER });
// page through the results
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return rawResults;
}
Well, I want to get the count of the object, but the condition of date is invalid, I get all the data from my database.Somebody could help me?Thanks.
I am new to ORMLite and faced the same problem when accessed SQLite database.
It took me a whole day today to figure it out, here is the summary:
I found format "yyyy-M-d H:m:s" works fine in ORMLite for dealing with SQLite DateTime data type, not ORMLite's default format "yyyy-MM-dd HH:mm:ss.SSSSS".
For ORMLite to translate between "Java Date" and "SQLite DateTime", a persister class will be needed.
Here shows the code of the persister class I use, which override the public functions of DateStringType and use "dateFormatConfig" instead of defaultDateFormatConfig" :
`
public class DateStringSQLiteType extends DateStringType {
protected static final DateStringFormatConfig dateFormatConfig = new DateStringFormatConfig(
"yyyy-M-d H:m:s");
private static final DateStringSQLiteType singleTon = new DateStringSQLiteType();
public static DateStringSQLiteType getSingleton() {
return singleTon;
}
private DateStringSQLiteType() {
super(SqlType.STRING, new Class<?>[0]);
}
/**
* Convert a default string object and return the appropriate argument to a
* SQL insert or update statement.
*/
#Override
public Object parseDefaultString(FieldType fieldType, String defaultStr)
throws SQLException {
DateStringFormatConfig formatConfig = convertDateStringConfig(
fieldType, dateFormatConfig);
try {
// we parse to make sure it works and then format it again
return normalizeDateString(formatConfig, defaultStr);
} catch (ParseException e) {
throw SqlExceptionUtil.create("Problems with field " + fieldType
+ " parsing default date-string '" + defaultStr
+ "' using '" + formatConfig + "'", e);
}
}
/**
* Return the SQL argument object extracted from the results associated with
* column in position columnPos. For example, if the type is a date-long
* then this will return a long value or null.
*
* #throws SQLException
* If there is a problem accessing the results data.
* #param fieldType
* Associated FieldType which may be null.
*/
#Override
public Object resultToSqlArg(FieldType fieldType, DatabaseResults results,
int columnPos) throws SQLException {
return results.getString(columnPos);
}
/**
* Return the object converted from the SQL arg to java. This takes the
* database representation and converts it into a Java object. For example,
* if the type is a date-long then this will take a long which is stored in
* the database and return a Date.
*
* #param fieldType
* Associated FieldType which may be null.
* #param sqlArg
* SQL argument converted with
* {#link #resultToSqlArg(FieldType, DatabaseResults, int)} which
* will not be null.
*/
#Override
public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos)
throws SQLException {
String value = (String) sqlArg;
DateStringFormatConfig formatConfig = convertDateStringConfig(
fieldType, dateFormatConfig);
try {
return parseDateString(formatConfig, value);
} catch (ParseException e) {
throw SqlExceptionUtil.create("Problems with column " + columnPos
+ " parsing date-string '" + value + "' using '"
+ formatConfig + "'", e);
}
}
/**
* Convert a Java object and return the appropriate argument to a SQL insert
* or update statement.
*/
#Override
public Object javaToSqlArg(FieldType fieldType, Object obj) {
DateFormat dateFormat = convertDateStringConfig(fieldType,
dateFormatConfig).getDateFormat();
return dateFormat.format((Date) obj);
}
/**
* #throws SQLException
* If there are problems creating the config object. Needed for
* subclasses.
*/
#Override
public Object makeConfigObject(FieldType fieldType) {
String format = fieldType.getFormat();
if (format == null) {
return dateFormatConfig;
} else {
return new DateStringFormatConfig(format);
}
}
}
`
Define you data class with notation:
#DatabaseField(..., persisterClass = DateStringSQLiteType.class)
private Date date;
It worked fine for me, can do "Between" query like:
list = foo.getDao().queryBuilder().where().between(HistoryStandardView.DATE_FIELD_NAME, new Date(98,1,1), new Date(115,1,1)).query();
ORMLite's logger shows the resulting statement:
[DEBUG] StatementExecutor query of 'SELECT * FROM `HistoryStandardView` WHERE `date` BETWEEN '1998-2-1 0:0:0' AND '2015-2-1 0:0:0' ' returned 2 results
Correct me if am wrong is your calldate column's type is DataType.DATE_STRING ? If that's the case it means that the persisted data type is VARCHAR so when you execute your query your doing a String comparison and not a Date comparison. So to solve your problem you can either :
Change your calldate column's type to DataType.DATE which is represented as a TIMESTAMP.
Change your calldate column's type to DataType.DATE_LONG.
Find a way to do a String comparison that matches what your need (for instance calling the sql date(calldate) fonction if your calldate values matches a Time Strings format see http://www.sqlite.org/lang_datefunc.html).
Here is what i did, it's not pretty but works like wanted to:
QueryBuilder<OffreEntity, Integer> qb = this.daoOffre.queryBuilder();
//Need to format the date i want to compare so it can actually be compare with what i have on db
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyMMdd");
String correctFormat = dateFormatter.format(dateLimite);
//In db the date is represented as a VARCHAR with format dd/MM/yy so i need to reformat so it matches yyMMdd
String rawQuery = String.format("substr(%1$s,7)||substr(%1$s,4,2)||substr(%1$s,1,2) > '%2$s'", OffreEntity.COLUMN_NAME_DATE, correctFormat);
qb.where().raw(rawQuery);
offresDept = qb.query();
Hope it helps!
Ps: Thanks to Jack Douglas for the date format query