Using pre-populated database in Room by copy database file from assert - android-sqlite

I want to use pre-populated database in Android Room. I found a way to make it through using the callback, and filled up the database files.
But something is wrong, I'm sure that the database is copied normally, but it remains empty in the device monitor and android emulator. Can you please help me
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
private static final String DB_NAME = "base.db";
static Context ctx;
public abstract Dao dao();
public static AppDatabase getDatabase(Context context) {
if (INSTANCE == null) {
ctx = context;
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context,
AppDatabase.class, DB_NAME)
.allowMainThreadQueries()
.addCallback(rdc)
.build();
}
}
}
return INSTANCE;
}
private static RoomDatabase.Callback rdc = new RoomDatabase.Callback() {
public void onCreate(SupportSQLiteDatabase db) {
new PopulateDbAsync(INSTANCE, ctx).execute();
Log.d("db create ", "table created when db created first time in onCreate");
}
public void onOpen(#NonNull SupportSQLiteDatabase db) {
ContentValues contentValues = new ContentValues();
}
};
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private Dao dao;
AssetManager assetManager = ctx.getAssets();
PopulateDbAsync(AppDatabase db, Context context) {
Dao = db.Dao();
ctx = context;
}
#Override
protected Void doInBackground(final Void... params) {
String DB_PATH = "/data/data/mypackage/databases/";
String DB_NAME = "base.db";
try {
Log.d("AppDatabase","Trying copy database file");
OutputStream myOutput = new FileOutputStream(DB_PATH + DB_NAME);
byte[] buffer = new byte[1024];
int length;
InputStream myInput = ctx.getAssets().open("base.db");
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myInput.close();
myOutput.flush();
myOutput.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}

I solved after spending 6 hours on researching and R & D .
Context is that : - I want to put already existing finaldb.db(which is present inside assests folder) into room database .
Step 1 :
copy this framework files from here link
Step 2 :
You need to migrate , chill i have code :)
#Database(entities = {Status.class}, version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract DataDao StatusDao();
private static AppDatabase INSTANCE;
public static AppDatabase getDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = createDatabase(context);
}
return (INSTANCE);
}
private static final Migration MIGRATION_2_3 = new Migration(1, 2) {
#Override
public void migrate(#NonNull SupportSQLiteDatabase database) {
Log.d("kkkk","bc");
String SQL_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS 'Status' " +
"( 'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
" 'category' TEXT NOT NULL," +
" 'sub_category' TEXT NOT NULL," +
" 'content' TEXT NOT NULL," +
" 'favourite' INTEGER DEFAULT(0))";
database.execSQL(SQL_CREATE_TABLE);
}
};
private static AppDatabase createDatabase(Context context) {
RoomDatabase.Builder<AppDatabase> builder =
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class,
context.getString(R.string.dbase_name));
return (builder.openHelperFactory(new AssetSQLiteOpenHelperFactory())
.allowMainThreadQueries()
.addMigrations(MIGRATION_2_3)
.build());
}
}
In MIGRATION_2_3 you have to create table exactly same as current database(which is present in assests folder)
want to learn about migration
Step 3 :
Now table is created successfully in room database !
In case of crash see your logcat , in which its written in understandable form .

You cannot, properly, do the copy of the database in the onCreate method.
When the onCreate method is called the database has been created (the created database is passed to the method). You have to do the copy before the onCreate method and before the database is opened.
You could override's the RoomDatabase init method and do the copy from that method or do the copy before invoking the databaseBuilder.

I'm solved it.
Database class:
#Database(entities = {Entity1.class, Entity2.class, Entity3.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract Entity1Dao 1Dao();
public abstract Entity2Dao 2Dao();
public abstract Entity3Dao 3Dao();
public static AppDatabase getDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = createDatabase(context);
}
return (INSTANCE);
}
private static AppDatabase createDatabase(Context context) {
RoomDatabase.Builder<AppDatabase> builder =
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class,
context.getString(R.string.dbase_name));
return (builder.openHelperFactory(new AssetSQLiteOpenHelperFactory())
.allowMainThreadQueries()
.build());
}
}
Also you should get SQL Helpers, link

My issue is a little bit different than the OP.
I was copying the database file from internal storage which I downloaded from the internet, not from assets. And java.lang.RuntimeException: Unable to copy database file is raised because I didn't grant READ_EXTERNAL_STORAGE before this, or in general granting WRITE_EXTERNAL_STORAGE as READ_EXTERNAL_STORAGE is included in WRITE_EXTERNAL_STORAGE and already need the write permission for downloading the file.

Related

SpringBatch - How to track whether Update is happening successfully or not

I have 2 ItemWriters, one for DB Insert and one for DB Update.
With use of ClassifierCustomItemWriter which I am calling the respective ItemWriter for new record and update the existing records.
Here i have concern. How to know the update has been happened or not ? For Example, if the "Application ID" not exists in the DB , the ItemWriter will not throw any error, but i want to know that update has not happened for this record and log it.
How can i track that ?
#Bean
public ClassifierCompositeItemWriter<TRSBatchEntryFormRequest> classifierCompositeItemWriter(ItemWriter<TRSBatchEntryFormRequest> databaseTableItemWriter, ItemWriter<TRSBatchEntryFormRequest> databaseTableUpdateItemWriter) {
ClassifierCompositeItemWriter<TRSBatchEntryFormRequest> classifierCompositeItemWriter = new ClassifierCompositeItemWriter<>();
classifierCompositeItemWriter.setClassifier((Classifier<TRSBatchEntryFormRequest, ItemWriter<? super TRSBatchEntryFormRequest>>) trsBatchEntryFormRequest -> {
if (trsBatchEntryFormRequest.getForm_status().equals("New")) {
return databaseTableItemWriter;
} else {
return databaseTableUpdateItemWriter;
}
});
return classifierCompositeItemWriter;
}
// Writer for DB
#Bean
public ItemWriter<TRSBatchEntryFormRequest> databaseTableItemWriter(DataSource springBatchDatasource) {
JdbcBatchItemWriter<TRSBatchEntryFormRequest> databaseItemWriter = new JdbcBatchItemWriter<TRSBatchEntryFormRequest>();
databaseItemWriter.setDataSource(springBatchDatasource);
logger.info("INSERT QUERY....: " + QUERY_INSERT_TRSEntryForms);
databaseItemWriter.setSql(QUERY_INSERT_TRSEntryForms);
databaseItemWriter.setItemSqlParameterSourceProvider(new TRSDBInputProvider());
return databaseItemWriter;
}
//Update Writer for DB
#Bean
public ItemWriter<TRSBatchEntryFormRequest> databaseTableUpdateItemWriter(DataSource springBatchDatasource) {
JdbcBatchItemWriter<TRSBatchEntryFormRequest> databaseItemWriter = new JdbcBatchItemWriter<TRSBatchEntryFormRequest>();
databaseItemWriter.setDataSource(springBatchDatasource);
logger.info("UPDATE QUERY....: " + QUERY_UPDATE_TRSEntryForms);
databaseItemWriter.setSql(QUERY_UPDATE_TRSEntryForms);
databaseItemWriter.setItemSqlParameterSourceProvider(new TRSDBInputProvider());
return databaseItemWriter;
}
​
Thanks
You can't track that with a CompositeItemWriter. What you can do is use a custom item writer like the following:
import java.util.List;
import org.springframework.batch.item.ItemWriter;
import org.springframework.jdbc.core.JdbcTemplate;
public class TRSBatchEntryFormRequestItemWriter implements ItemWriter<TRSBatchEntryFormRequest> {
private static final String INSERT_ITEM = "insert into item...";
private static final String UPDATE_ITEM = "update item set...";
private JdbcTemplate jdbcTemplate;
public TRSBatchEntryFormRequestItemWriter(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Override
public void write(List<? extends TRSBatchEntryFormRequest> items) throws Exception {
for (TRSBatchEntryFormRequest item : items) {
int updated = jdbcTemplate.update(UPDATE_ITEM);
if (updated == 0) {
jdbcTemplate.update(INSERT_ITEM);
}
}
}
}
The idea is to try to issue an update. If the operation returns 0, this means no rows have been updated and the item does not exist in the database, and you can issue an insert in that case.
Hope this helps.

Getting NullPointerException with AndroidAnnotations & ORMLite

I am using AndroidAnnotations and SQLite with ORMLite and am trying to get the database up and running. I was able to create the table and make a test-insert of a Contact object a few days ago.
However, I did some changes and then it stopped working - unfortunately I was not able to revert my changes and now I'm stuck and can't get it working anymore.
Whenever I start the app I get this error:
02-12 23:09:39.931 11766-11766/net.gazeapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: net.gazeapp, PID: 11766
java.lang.RuntimeException: Unable to start activity ComponentInfo{net.gazeapp/net.gazeapp.MainActivity_}: java.lang.NullPointerException: Attempt to invoke virtual method 'int net.gazeapp.data.ContactDao.create(java.lang.Object)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int net.gazeapp.data.ContactDao.create(java.lang.Object)' on a null object reference
at net.gazeapp.service.ContactService.addContact(ContactService.java:55)
at net.gazeapp.MainActivity.testNewORM(MainActivity.java:171)
at net.gazeapp.MainActivity.createView(MainActivity.java:148)
at net.gazeapp.MainActivity_.onViewChanged(MainActivity_.java:111)
at org.androidannotations.api.view.OnViewChangedNotifier.notifyViewChanged(OnViewChangedNotifier.java:41)
at net.gazeapp.MainActivity_.setContentView(MainActivity_.java:57)
at net.gazeapp.MainActivity_.onCreate(MainActivity_.java:45)
at android.app.Activity.performCreate(Activity.java:6251)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
So here is my MainActivity in which I do the ORM-testing (in the testNewORM() method):
#EActivity(R.layout.activity_main_viewpagertab)
#OptionsMenu(R.menu.menu_main)
public class MainActivity extends BaseActivity implements ObservableScrollViewCallbacks {
private final String TAG = getClass().getSimpleName();
private int mBaseTranslationY;
private NavigationAdapter mPagerAdapter;
private Contact mContact;
private static String[] tabTitles = null;
#App
GazeApplication application;
#ViewById(R.id.header)
View mHeaderView;
#ViewById(R.id.toolbar)
View mToolbarView;
#ViewById(R.id.pager)
ViewPager mPager;
#ViewById(R.id.fab)
FloatingActionButton fab;
#ViewById(R.id.adview)
MoPubView mAdView;
#Bean
ContactService contactService;
#AfterViews
void createView() {
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
Tools.readJsonFile(this, "fetishes.json");
// TAB TITLES: RECENT, ALL, MY MEDIA
tabTitles = new String[]{getString(R.string.recent), getString(R.string.all), getString(R.string.my_media)};
ViewCompat.setElevation(mHeaderView, getResources().getDimension(R.dimen.toolbar_elevation));
mPagerAdapter = new NavigationAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
slidingTabLayout.setCustomTabView(R.layout.tab_indicator, android.R.id.text1);
slidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.colorAccent));
slidingTabLayout.setDistributeEvenly(true);
slidingTabLayout.setViewPager(mPager);
// When the page is selected, other fragments' scrollY should be adjusted
// according to the toolbar status(shown/hidden)
slidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i2) {
}
#Override
public void onPageSelected(int i) {
propagateToolbarState(toolbarIsShown());
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
propagateToolbarState(toolbarIsShown());
displayAdBanner();
// TESTING ORMAPPER
// TESTING ORMAPPER
testNewORM();
}
void testNewORM() {
java.util.Date date = new java.util.Date();
Timestamp timeNow = new Timestamp(date.getTime());
Timestamp birthdateTimestamp = new Timestamp(date.getTime());
Date birthdate = new Date();
try {
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
birthdate = dateFormat.parse("04/07/1980");
long time = birthdate.getTime();
birthdateTimestamp = new Timestamp(time);
} catch (ParseException e) {
e.printStackTrace();
}
Contact contact = new Contact("Dominik Erbsland");
contact.setBirthdate(birthdate);
try {
mContact = contactService.addContact(contact);
} catch (ItemNotFoundException | SQLException e) {
Log.e(TAG, e.getLocalizedMessage());
e.printStackTrace();
}
}
...
}
And here the other used classes:
#EBean(scope = EBean.Scope.Singleton)
public class ContactService {
private static final String TAG = ContactService.class.getSimpleName();
#RootContext
Context ctx;
#OrmLiteDao(helper = DatabaseHelper.class)
ContactDao mContactDao;
public Contact getContact(int contactId) throws ItemNotFoundException, SQLException {
Contact contact = mContactDao.queryForId(contactId);
if (contact == null) {
Log.e(TAG, "Contact not found in database");
throw new ItemNotFoundException();
}
return contact;
}
public List<Contact> getContacts() throws ItemNotFoundException, SQLException {
List<Contact> contact = mContactDao.queryForAll();
if (contact == null) {
Log.e(TAG, "Contacts not found in database");
throw new ItemNotFoundException();
}
return contact;
}
public Contact addContact(Contact contact) throws SQLException {
int rowsAffected = 0;
try {
rowsAffected = mContactDao.create(contact);
} catch (SQLException e) {
Log.e(TAG, e.getLocalizedMessage());
e.printStackTrace();
}
Log.d(TAG, "New Contact ID: " + contact.getId());
return contact;
}
public void testOutput() {
Log.d(TAG, "THIS IS A TEST OUTPUT");
}
}
here my database helper:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "Gaze.db";
private static final int DATABASE_VERSION = 1;
private final Context context;
// the DAO object we use to access the Person table
private Dao<Contact, Integer> contactDao = null;
private Dao<MyPreferences, Integer> preferencesDao = null;
private Dao<SecurityQuestion, Integer> securityQuestionDao = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(DatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, Contact.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, Contact.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our Person class. It will create it or just give the cached
* value.
*/
public Dao<Contact, Integer> getContactDao() throws SQLException {
if (contactDao == null) {
contactDao = getDao(Contact.class);
}
return contactDao;
}
public Dao<MyPreferences, Integer> getPreferencesDao() throws SQLException {
if (preferencesDao == null) {
preferencesDao = getDao(MyPreferences.class);
}
return preferencesDao;
}
public Dao<SecurityQuestion, Integer> getSecurityQuestionDao() throws SQLException {
if (securityQuestionDao == null) {
securityQuestionDao = getDao(SecurityQuestion.class);
}
return securityQuestionDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
#Override
public void close() {
super.close();
contactDao = null;
preferencesDao = null;
securityQuestionDao = null;
}
}
and the data class:
#DatabaseTable(tableName = "Contact", daoClass = ContactDao.class)
public class Contact implements Serializable {
#DatabaseField(generatedId = true, columnName = PersistentObject.ID)
int id;
#DatabaseField(index = true)
String contactName;
#DatabaseField
String mainPic;
#DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S")
Date birthdate;
#DatabaseField
boolean knowPersonally;
#DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S")
Timestamp created;
#DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss.S")
Timestamp lastMod;
public Contact() {
// needed by ormlite
}
...
}
and the ContactDao:
public class ContactDao extends BaseDaoImpl<Contact, Integer> {
public ContactDao(Class<Contact> dataClass) throws SQLException {
super(dataClass);
}
public ContactDao(ConnectionSource connectionSource, Class<Contact> dataClass) throws SQLException {
super(connectionSource, dataClass);
}
public ContactDao(ConnectionSource connectionSource, DatabaseTableConfig<Contact> tableConfig) throws SQLException {
super(connectionSource, tableConfig);
}
public List<Contact> getContacts() throws SQLException {
return queryForAll();
}
}
So in the ContactService class at "mContactDao.create(contact);" it crashed with the Exception. This is the part I don't understand because ContactService is annotated with #EBean and is being accessed in MainActivity with "#Bean
ContactService contactService;" and shouldn't be null there...
Thanks for any help or hints in advance.
The problem is the following:
The code is trying to access the mContactDao field, but it is indeed null, altough it should be injected by AndroidAnnotations. But the field cannot be injected, because the dao creation fails with an exception. This is logged by AndroidAnnotations, you can check it in LogCat.
The cause of the problem lies in the Contact class. You are using List<Something> fields, but ORMLite does not know how to persist the java.util.List object. You can either use a custom persister, or you can use foreign fields:
Contact.java:
#ForeignCollectionField
private ForeignCollection<Address> adresses;
Update:
Applying the ForestCollectionField changes and debugging again showed another problem. The DataType.DATE_STRING persister cannot be used with the java.sql.Timestamp class. But you can use DataType.TIME_STAMP instead:
#DatabaseField(dataType = DataType.TIME_STAMP, format = "yyyy-MM-dd HH:mm:ss.S")
Timestamp created;
#DatabaseField(dataType = DataType.TIME_STAMP, format = "yyyy-MM-dd HH:mm:ss.S")
Timestamp lastMod;

best way to manage a history from both activity and service?

Short version: what is the best practice way to access maintain a history for certain messages from both an activity and from a service?
Long version:
I have an activity and a service, which both may be running or not. I want to keep a message log (history) in an object an persist it in a file and be able to e.g. delete entries.
When I have such history in the service and one in the activity I run into sync problems. So, any advice, what the best solution would be?
ideally I could use the methods from the history class in both the service and activity. Probably not possible.
I could write and read the file in each action. Probably not very efficient in the long run.
do I really need to setup a service for the history and handle all actions with it via intents?
It is a bit similiar to "proper way to access DB from both Activity and a started Service?", but with just an own class instead of a SQLite DB.
Any advice?
Conclusion: Use a ContentProvider with a SQLite-DB. Short version of the code:
package com.example.history;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
public class HistoryContentProvider extends ContentProvider {
static final String PROVIDER_NAME = "com.example.HistoryContentProvider";
static final String URL = "content://" + PROVIDER_NAME + "/history";
static final Uri CONTENT_URI = Uri.parse(URL);
static final String id = "id";
static final String normalized_number = "normalized_number";
static final String display_name = "display_name";
static final int uriCode = 1;
static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "history", uriCode);
}
#Override
public boolean onCreate() {
Context context = getContext();
DatabaseHelper dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
if (db != null) {
return true;
}
return false;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(TABLE_NAME);
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
#Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case uriCode:
return "vnd.android.cursor.dir/history";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
} }
#Override
public Uri insert(Uri uri, ContentValues values) {
long rowID = db.insert(TABLE_NAME, "", values);
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to add a record into " + uri);
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.delete(TABLE_NAME, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return count;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.update(TABLE_NAME, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return count;
}
private SQLiteDatabase db;
static final String DATABASE_NAME = "historyDb";
static final String TABLE_NAME = "history";
static final int DATABASE_VERSION = 3;
static final String CREATE_DB_TABLE = " CREATE TABLE " + TABLE_NAME
+ " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ normalized_number + " TEXT NOT NULL, "
+ display_name + " TEXT NOT NULL, ";
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
}
I have an activity and a service, which both may be running or not. I
want to keep a message log (history) in an object an persist it in a
file and be able to e.g. delete entries.
What you are describing there sounds exactly like a ContentProvider! Link to documentation.
You can use a ContentResolver instance to access data in the ContentProvider from anywhere, be it Activity or Service. The ContentProvider and ContentResolver already handle most of the work for you and basically you just need to implement how you want to save the data in the ContentProvider. The rest is already taken care of! The ContentProvider may have been designed to be used with a SQLiteDatabase - and I would recommend that you use a database - but there is nothing preventing you from saving the data in another way.
If you are not looking for DB style persistence, then maybe a Queue with File backed persistence is what you are looking for:
This maybe of use
https://github.com/square/tape/blob/master/tape/src/main/java/com/squareup/tape/QueueFile.java
Tip: Create a QueueFile singleton in your App class, and access it from your Activities or services.

call component from form to class and save data back to table

i am working on ado.net project,, i used to have separate classes for codes ,,,
now i am trying to learn more about local databases but i am stock when i tried to call class that contain SQL commands ,,, please
have a look to my code i commented where i stock
namespace Maintenance
{
public partial class registerReports : Form
{
private void btnSave_Click(object sender, EventArgs e)
{
//the code works if it exists here
/**
conn.Open();
com.Parameters.AddWithValue("#reportID",
tbReportIDox.Text);
com.ExecuteNonQuery();
conn.Close();
**/
}
}
}
class reportTableSQL
{
public void reportTable()
{
string connectionString = connectionString = "Data Source=
..//..//maintenanceDB.sdf";
SqlCeConnection conn = new SqlCeConnection(connectionString);
using (SqlCeCommand com = new SqlCeCommand("INSERT INTO
ReportForm VALUES(#reportID)", conn))
{
// if i call this method from class registerReports : Form
// it doesn't recognise tbReportIDox.Text as
//it isn't exist in this class
/**
conn.Open();
com.Parameters.AddWithValue("#reportID",
tbReportIDox.Text);
com.ExecuteNonQuery();
conn.Close();
**/
}
}
}
thank you
What you can do is to pull tbReportIDox.Text up as a parameters to the method, that is
public void reportTable(string reportName)
{
...
com.Parameters.AddWithValue("#reportID", reportName);
...
}
And then on a button click
private void btnSave_Click(object sender, EventArgs e)
{
// resolve instance of reportTableSQL class
// for example through: new reportTableSQL();
var reportGenerator = new reportTableSQL();
reportGenerator.reportTable(tbReportIDox.Text);
}

spring data mongodb converter

I am using spring data mongo-db 1.4.1.RELEASE.
My entity 'Event' has a getter method which is calculated based on other properties:
public int getStatus() {
return (getMainEventId() == null) ? (elapseTimeInMin() < MINIMUM_TIME ? CANDIDATE :
VALID) : POINTER;
}
I wanted the property 'status' to be persisted only through the getter ,so I wrote converters:
#WritingConverter
public class EventWriteConverter implements Converter<Event ,BasicDBObject > {
static final Logger logger = LoggerFactory.getLogger(EventWriteConverter.class.getCanonicalName());
public BasicDBObject convert(Event event) {
logger.info("converting " +event );
if (event.getMainEventId() != null)
return new BasicDBObject("mainEventId", event.getMainEventId() );
BasicDBObject doc = new BasicDBObject("status",event.getStatus()).
append("updated_date",new Date()).
append("start",event.getS0()).
append("end",event.getS1()).
append("location",event.getLocation()).
;
BasicDBList list = new BasicDBList();
doc.append("access_points",event.getHotPoints());
return doc;
}
#ReadingConverter
public class EventReadConverter implements Converter<BasicDBObject, Event> {
#Inject
HotPointRepositry hotRepositry;
static final Logger logger = LoggerFactory.getLogger(EventReadConverter.class.getCanonicalName());
public Event convert(BasicDBObject doc) {
logger.info(" converting ");
Event event = new Event();
event.setId(doc.getObjectId("_id"));
event.setS0(doc.getDate("start"));
event.setS1(doc.getDate("end"));
BasicDBList dblist = (BasicDBList) doc.get("hot_points");
if (dblist != null) {
for (Object obj : dblist) {
ObjectId hotspotId = ((BasicDBObject) obj).getObjectId("_id");
event.addHot(hotRepositry.findOne(hotId));
}
}
dblist = (BasicDBList) doc.get("devices");
if (dblist != null) {
for (Object obj : dblist)
event.addDevice(obj.toString());
}
event.setMainEventId(doc.getObjectId("mainEventId"));
return event;
}
}
My test mongo configuration is
#Profile("test")
#Configuration
#EnableMongoRepositories(basePackages = "com.echo.spring.data.mongo")
#ComponentScan(basePackages = "com.echo.spring.data.mongo" )
public class MongoDbTestConfig extends AbstractMongoConfiguration {
static final Logger logger = LoggerFactory.getLogger(MongoDbTestConfig.class.getCanonicalName());
#Override
protected String getDatabaseName() {
return "echo";
}
#Override
public Mongo mongo() {
return new Fongo("echo-test").getMongo();
}
#Override
protected String getMappingBasePackage() {
return "com.echo.spring.data.mongo";
}
#Bean
#Override
public CustomConversions customConversions() {
logger.info("loading custom converters");
List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
converterList.add(new EventReadConverter());
converterList.add(new EventWriteConverter());
CustomConversions cus = new CustomConversions(converterList);
return new CustomConversions(converterList);
}
}
And my test (using fongo) is
ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = MongoDbTestConfig.class )
public class SampleMongoApplicationTests {
#Test
#ShouldMatchDataSet(location = "/MongoJsonData/events.json")
public void shouldSaveEvent() throws IOException {
URL url = Resources.getResource("MongoJsonData/events.json");
List<String> lines = Resources.readLines(url,Charsets.UTF_8);
for (String line : lines) {
Event event = objectMapper.readValue(line.getBytes(),Event.class);
eventRepository.save(event);
}
}
I can see the converters are loaded when the configuration customConversions() is called
I added logging and breakpoints in the convert methods but they do not seems to be
called when I run or debug, though they are loaded .
What am I doing wrong ?
I had a similar situation, I followed Spring -Mongodb storing/retrieving enums as int not string
and I need both the converter AND converterFactory wired to get it working.