I am in a fragment in Android Studio java and want to save and read something there in a SqLite database. To save, I just use this code:
databaseHu = getBaseContext().openOrCreateDatabase(databaseName_Notes, MODE_PRIVATE, null);
databaseHu.execSQL("CREATE TABLE IF NOT EXISTS " + Tabel_Hu_Name + "(subject TEXT, tasks TEXT, dayofyear INT, day INT, month INT, year INT)");
databaseHu.execSQL("INSERT INTO " + Tabel_Hu_Name + " VALUES ('" + subject.getText().toString() + "','" + tasks.getText().toString() + "','" + c.get(Calendar.DAY_OF_YEAR) + "','" + c.get(Calendar.DAY_OF_MONTH) + "','" + c.get(Calendar.MONTH) + "','" + c.get(Calendar.YEAR) + "')");
databaseHu.close();
But because I'm in a fragment, it marks that:
getBaseContext()
as a mistake.
How can I solve this? Thanks in advance!
You can use getActivity() like this,
databaseHu = getActivity().getBaseContext().openOrCreateDatabase(databaseName_Notes, MODE_PRIVATE, null);
but it may invoke nullPtrException. Instead you can override this function and create like this:
Activity activity;
#override
public void onViewCreated(View view, Bundle savedInstanceState) {
if(getActivity()==null){
activity = getActivity;
}
}
Then use it like this,
databaseHu = activity.getBaseContext().openOrCreateDatabase(databaseName_Notes, MODE_PRIVATE, null);
Related
I've been trying for some days to load some data from a SQLite database into a ListView inside a Fragment but I'm having this issue that I can't see the solution neither found help online.
My database consists of two tables, 'user' and 'team', being the former in a one to many relation with the later.
//User Table
public static final String CREATE_TABLE_USER =
"CREATE TABLE " + USER_TABLE + "("
+ USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ USER_NAME + " TEXT NOT NULL,"
+ USER_SURNAME + " TEXT NOT NULL,"
+ USER_EMAIL + " TEXT NOT NULL,"
+ USER_PHONE + " NUMBER,"
+ USER_PASSWORD + " TEXT NOT NULL)";
//Team Table
public static final String CREATE_TABLE_TEAM =
"CREATE TABLE " + TeamColumns.TEAM_TABLE + "("
+ TeamColumns.TEAM_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ TeamColumns.TEAM_NAME + " TEXT NOT NULL,"
+ TeamColumns.TEAM_COUNTRY + " TEXT NOT NULL,"
+ TeamColumns.TEAM_BOSS + " TEXT NOT NULL,"
+ TeamColumns.TEAM_DRIVER1 + " TEXT NOT NULL,"
+ TeamColumns.TEAM_DRIVER2 + " TEXT NOT NULL,"
+ TeamColumns.TEAM_CAR + " TEXT NOT NULL,"
+ TeamColumns.TEAM_POINTS + " NUMBER,"
+ TeamColumns.TEAM_ICON + " TEXT,"
+ TeamColumns.TEAM_USER_ID + " INTEGER,"
+ "CONSTRAINT userID_FK FOREIGN KEY (userID) REFERENCES " + USER_TABLE + "(id))";
So with a database structured this way, I want the ListView to only show the teams associated to the one user logged in. But i can't find how to do it, I don't really select what SQL query is used when loading info, trying to alter the cursor in the overriden bindView method does nothing and the furthest i managed to get showed the wanted rows, but the app crushed the moment i scrolled down to the bottom (I presume i just created a bunch of empty list items where usually are more items). Online search has also been of no help (sorry in advance if this question is already here) so I'm at a stalemate with this part of my app.
My question is:
Is there a way to change the SQL sentence my CustomCursorAdapter uses to load my data?
This is where I load all the data into the ListItem in the CursorAdapter class:
#Override
public void bindView(View view, final Context context, Cursor cursor) {
//Team info placeholders
final ImageView logoView = view.findViewById(R.id.listIcon);
TextView nameText = view.findViewById(R.id.listName);
TextView countryText = view.findViewById(R.id.listCountry);
TextView directorText = view.findViewById(R.id.listDirector);
//Retrieving info
String logoURI = cursor.getString(cursor.getColumnIndexOrThrow(TeamContract.TeamColumns.TEAM_ICON));
String name = cursor.getString(cursor.getColumnIndexOrThrow(TeamContract.TeamColumns.TEAM_NAME));
String country = cursor.getString(cursor.getColumnIndexOrThrow(TeamContract.TeamColumns.TEAM_COUNTRY));
String director = cursor.getString(cursor.getColumnIndexOrThrow(TeamContract.TeamColumns.TEAM_BOSS));
//Seting the image
Glide.with(context).asBitmap()
.load(Uri.parse("file:///android_asset/" + logoURI))
.error(R.drawable.ic_baseline_error_outline_24).centerCrop().into(new BitmapImageViewTarget(logoView) {
#Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);
drawable.setCircular(true);
logoView.setImageDrawable(drawable);
}
});
//Setting the texts
nameText.setText(name);
countryText.setText(country);
directorText.setText(director);
}
And here where I initialize the Adapter from my Fragment class:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_team, container, false);
// Referencias UI
teamList = root.findViewById(R.id.teams_list);
mteamAdapter = new TeamAdapter(getActivity(), null);
// Setup
teamList.setAdapter(mteamAdapter);
// Eventos
teamList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Cursor currentItem = (Cursor) mteamAdapter.getItem(i);
String currentTeamId = currentItem.getString(currentItem.getColumnIndexOrThrow(TeamContract.TeamColumns.TEAM_ID));
launchTeamView(currentTeamId);
}
});
mTeamDbHelper = new DatabaseHelper(getActivity());
loadLawyers();
return root;
}
So i am trying to insert some data in the internal sqlite database but after i run the insert no data has been added. There are, as far as i can see no errors in the logs and every debug log i put into it is shown. If i try to run the query that is returned in the log in sqlitestudio it works without a problem so i haven't got a clue as to what is going wrong.
#Override
public void onCreate(SQLiteDatabase db) {
String SQL = pictureTable();
db.execSQL(SQL);
}
private String pictureTable() {
return "CREATE TABLE geophoto_db_pictures ( picid integer,"
+ "name varying character(50),"
+ "city varying character(20) NOT NULL,"
+ "zipcode varying character(20) NOT NULL,"
+ "country varying character(20) NOT NULL,"
+ "picdate datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,"
+ "tags varying character(200),"
+ "image varying character(200) NOT NULL,"
+ "uploaded integer NOT NULL DEFAULT 0, PRIMARY KEY (picid))";
}
#Override
public void savePicture(Picture pic) {
Log.d(LOG_TAG, "saving picture started. Data: " + pic.getName());
// clean the inputs
String name = pic.getName();
String city = pic.getCity();
if (city != null) {
city = "'" + city + "'";
}
String country = pic.getCountry();
if (country != null) {
country = "'" + country + "'";
}
String zip = pic.getZipcode();
if (zip != null) {
zip = "'" + zip + "'";
}
String tags = tagsToString(pic.getTags());
String image = pic.getImage();
// Insert Query, all possible null values on "not null" rows will be
// replaced by a default value.
String SQL = "INSERT INTO geophoto_db_pictures(name, city, zipcode, country, tags, image)"
+ "VALUES('"
+ name
+ "',"
+ "IFNULL("
+ city
+ ", 'Unknown')"
+ ","
+ "IFNULL("
+ zip
+ ", 'Unknown')"
+ ","
+ "IFNULL("
+ country + ",'Unknown')" + ",'" + tags + "','" + image + "')";
Log.d(LOG_TAG, SQL);
executeWriteQuery(SQL);
ArrayList<Picture> list = getAllPictures();
Log.d(LOG_TAG, "Size :"+list.size());
}
private Cursor executeWriteQuery(String query){
Log.d(LOG_TAG, "execute write query");
SQLiteDatabase db = getWritableDatabase();
Cursor response = db.rawQuery(query, null);
Log.d(LOG_TAG, "write query executed");
return response;
}
All tips/help greatly appreciated!
Thomas
Try to put a semicolon at the end of table creation query. In your case as show below
private String pictureTable() {
return "CREATE TABLE geophoto_db_pictures ( picid integer,"
+ "name varying character(50),"
+ "city varying character(20) NOT NULL,"
+ "zipcode varying character(20) NOT NULL,"
+ "country varying character(20) NOT NULL,"
+ "picdate datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,"
+ "tags varying character(200),"
+ "image varying character(200) NOT NULL,"
+ "uploaded integer NOT NULL DEFAULT 0, PRIMARY KEY (picid));";
}
While providing a query through an external String, you will need to provide SQL query with an end of statement ;. Using the primitive SQLite does not require ; as it just takes arguments and create function query itself. I have experienced both cases and I ended up understanding the way I have put it here.
The problem you are facing is that you are trying to use rawQuery() to insert a record, when you should be using execSQL() instead (see this answer).
So, the correct code for executeWriteQuery would be as follows:
private void executeWrite(String command){
Log.d(LOG_TAG, "execute write");
SQLiteDatabase db = getWritableDatabase();
db.execSQL(command);
Log.d(LOG_TAG, "write executed");
}
Also, consider using insert() instead as that will allow you to get a return value to determine whether or not the data was inserted successfully.
I want perform a search operation.I am using CursorAdapter to show data from database.Here is my code
DBHelper
public Cursor fetchDataByName(String string) {
// TODO Auto-generated method stub
Cursor cursor = database.rawQuery("select ABSTRACTS_ITEM._id,ABSTRACTS_ITEM.TITLE,ABSTRACTS_ITEM.TOPIC, "
+ "ABSTRACTS_ITEM.TYPE,ABSTRACTS_ITEM.TEXT"
+ "ABSTRACT_KEY_WORDS.KEYWORDS "
+ "from ABSTRACTS_ITEM,ABSTRACT_KEY_WORDS "
+ "where ABSTRACTS_ITEM._id = ABSTRACT_KEY_WORDS._id "
+ "and ABSTRACT_KEY_WORDS.KEYWORDS like '%" + string + "%'"
+ "or ABSTRACTS_ITEM.TITLE like '%" + string + "%'", null);
return cursor;
}
Inside Activity
cursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchDataByName(constraint.toString());
}
});
Previously, I can search data only with Title. Now, I want search data according to Title or keyword. As you can see my query, tried with that. But, it's not working.Because, it shows nothing.
You're missing a , comma and you need to group your OR condition in brackets because AND has a higher precedence.
Cursor cursor = database.rawQuery("select ABSTRACTS_ITEM._id, "
+ "ABSTRACTS_ITEM.TITLE, ABSTRACTS_ITEM.TOPIC, "
+ "ABSTRACTS_ITEM.TYPE, ABSTRACTS_ITEM.TEXT, " // <-- Comma needed
+ "ABSTRACT_KEY_WORDS.KEYWORDS "
+ "from ABSTRACTS_ITEM,ABSTRACT_KEY_WORDS "
+ "where ABSTRACTS_ITEM._id = ABSTRACT_KEY_WORDS._id "
// Group the OR condition with "()"; AND has higher precedence
+ "and (ABSTRACT_KEY_WORDS.KEYWORDS like '%" + string + "%' "
+ "or ABSTRACTS_ITEM.TITLE like '%" + string + "%')", null);
I think you have a simple precedence problem, AND in SQL has a higher precedence than OR. I think you want your SQL to look more like this:
where ABSTRACTS_ITEM._id = ABSTRACT_KEY_WORDS._id
and (
ABSTRACT_KEY_WORDS.KEYWORDS like '%' || ? || '%'
or ABSTRACTS_ITEM.TITLE like '%' || ? || '%'
)
I've also switched to placeholders since using string concatenation to build SQL is far too 1999 for me. This means that you'll want to use the rawQuery(String sql, String\[\] selectionArgs) version of rawQuery.
I'm having an issue inputting information into a Sqlite database on the app I'm creating. I was using the help of the Cursor before. I am used to MySQL although clearly not 'used to' that well.
I am trying to add to the database from a file. I had this working before but it would be added with the Cursor. I was then told that in order to make it so I could add new information to the file and have the app ONLY add the new information into the database I should use INSERT OR IGNORE.
Is this the correct syntax? I currently am not having any information inserted for whatever reason...
ourDatabase.rawQuery("INSERT OR IGNORE INTO " + DATABASE_TABLE + " ("+KEY_CLASS+",
" + KEY_QUESTION+ ") VALUES ('" + qclass + "', '" + question + "');", null);
This is my database:
"CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_CLASS + " TEXT NOT NULL, " +
KEY_QUESTION + " TEXT NOT NULL UNIQUE);
Thanks for the help in advance!
Your query seems right but try the one below anyway
ContentValues insertValues = new ContentValues();
insertValues.put(KEY_CLASS, qclass);
insertValues.put(KEY_QUESTION, question);
yourDbName.insertWithOnConflict(DATABASE_TABLE, null, insertValues, SQLiteDatabase.CONFLICT_IGNORE);
KEY_QUESTION + " TEXT NOT NULL UNIQUE);";
I'm really struggling to sort some issues inserting time and dates into a table in my database that dosent seem to excist!.
I asked a question on the 'no such table' issue but didn't get an answer that sorted this issue and circumstances have changed.
Really hoping someone can help me as i cant go forward until i solve this.
Edit:
Does the logcat show im trying to insert before creating the table?
Heres my Logcat error:
01-20 23:38:24.128: E/Database(287): Error inserting app_time=00114200T000000Europe/Dublin(0,0,0,-1,0) app_alarm=false app_date=2013-01-24 app_name=gggg app_comments=a app_type=Business
01-20 23:38:24.128: E/Database(287): android.database.sqlite.SQLiteException: no such table: appointmentsTable: , while compiling: INSERT INTO appointmentsTable(app_time, app_alarm, app_date, app_name, app_comments, app_type) VALUES(?, ?, ?, ?, ?, ?);
Is it a case of this data cannot be inserted as there is no table? I have no idea why I cannot create a table. Im also confused as to why the values passed are '?'
Again here is my OnCreate method:
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_NAME + " TEXT NOT NULL, " +
KEY_TEL + " TEXT NOT NULL, " +
KEY_EMAIL + " TEXT NOT NULL, " +
KEY_COMMENTS + " TEXT NOT NULL);"
);
db.execSQL("CREATE TABLE " + DATABASE_TABLEAPP + " (" +
KEY_ROWAPPID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_NAMEAPP + " TEXT NOT NULL, " +
KEY_TYPEAPP + " TEXT NOT NULL, " +
KEY_TIMEAPP + " TEXT NOT NULL, " +
KEY_DATEAPP + " TEXT NOT NULL, " +
KEY_COMMENTAPP + " TEXT NOT NULL, " +
KEY_ALARM + " BOOLEAN NOT NULL);"
);
}
My insertion method:
public void createAppointmentEntry(String nameApp, String typeApp, Time timeApp, Date dateApp ,String commentApp, Boolean onOrOff) {
ContentValues cv = new ContentValues();
cv.put(KEY_NAMEAPP, nameApp);
cv.put(KEY_TYPEAPP, typeApp);
cv.put(KEY_TIMEAPP, timeApp.toString());
cv.put(KEY_DATEAPP, dateApp.toString());
cv.put(KEY_COMMENTAPP, commentApp);
cv.put(KEY_ALARM, onOrOff);
ourDatabase.insert(DATABASE_TABLEAPP, null, cv);
}
Do you see how you have your data types as " TEXT NOT NULL "? Try changing the "app_time" column to just " TEXT, " and increase the database version. Also, try downloading SQLite Viewer so that you can get a visual idea of what your db actually looks like and if the column exists.