I have created one listview where I want to retrieve the items from sqlite database. So I have created one method as a List named as getrequestitems where I will map the details and add to a arraylist.
public List<Map<String, String>> getrequestitems() {
List<Map<String, String>> data = null;
data = new ArrayList<Map<String, String>>();
try {
SQLiteDatabase db = dbHandler.getReadableDatabase();
String sql = "SELECT * from request WHERE time > date('now','-1 day')";
Cursor rs = db.rawQuery(sql,null);
if(rs.moveToFirst()) {
do {
Map<String, String> dtname = new HashMap<String, String>();
dtname.put("bloodgrp", rs.getString(rs.getColumnIndex("bloodgrp")));
dtname.put("date", "Date:- " + rs.getString(rs.getColumnIndex("Datetime1")));
dtname.put("time", "Time:- " + rs.getString(rs.getColumnIndex("time")));
dtname.put("name", "Name:- " + rs.getString(rs.getColumnIndex("Name")));
dtname.put("Username", rs.getString(rs.getColumnIndex("Username")));
data.add(dtname);
}
while (rs.moveToNext());
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
return data;
}
But When I open that activity It doesn't displayed any records. I have debug the code but can't any exception. I have written wrong query? as "SELECT * from request WHERE time > date('now','-1 day')";
Here is my complete code.
public class request extends AppCompatActivity {
SimpleAdapter ad;
TextView list3;
private SlidrInterface slidr;
private DBHandler dbHandler;
private static ArrayList<String> arrayList = new ArrayList<>();
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request);
slidr = Slidr.attach(this);
slidr.unlock();
dbHandler = new DBHandler(this);
list3 = findViewById(R.id.list3);
TextView txt = findViewById(R.id.list4);
ListView lst1 = (ListView) findViewById(R.id.list2);
List<Map<String, String>> MyDataList = null;
MyDataList = getrequestitems();
String[] from = {"bloodgrp", "date", "time", "name", "Username"};
int[] to = {R.id.listt, R.id.date, R.id.time1, R.id.name3, R.id.user};
ad = new SimpleAdapter(request.this, MyDataList, R.layout.listrequest, from, to);
lst1.setAdapter(ad);
lst1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
List<Map<String, String>> MyDataList1 = null;
MyDataList1 = getrequestitems();
String[] from = {"Username"};
int[] to = {R.id.user};
Toast.makeText(getApplicationContext(), MyDataList1.toString(), Toast.LENGTH_SHORT).show();
ad = new SimpleAdapter(request.this, MyDataList1, R.layout.listrequest, from, to);
if(ad.getCount()==0){
Toast.makeText(getApplicationContext(), "No requests are currently visible", Toast.LENGTH_SHORT).show();
}
HashMap<String, String> obj = (HashMap<String, String>) ad.getItem(i);
String name = (String) obj.get("Username");
try {
SQLiteDatabase db = dbHandler.getReadableDatabase();
String sql = "select * from request where Username = '" + name + "'";
Cursor rs = db.rawQuery(sql,null);
if (rs.moveToFirst()) {
do {
runOnUiThread(new Runnable() {
#SuppressLint("Range")
#Override
public void run() {
try {
final AlertDialog.Builder alert = new AlertDialog.Builder(request.this);
View mView = getLayoutInflater().inflate(R.layout.custom_dialog3, null);
final TextView txt_inputText = (TextView) mView.findViewById(R.id.name1);
txt_inputText.setText(rs.getString(rs.getColumnIndex("Name")));
final TextView txt_inputText2 = (TextView) mView.findViewById(R.id.contactno1);
txt_inputText2.setText(rs.getString(rs.getColumnIndex("contactNo")));
final TextView txt_inputText3 = (TextView) mView.findViewById(R.id.message1);
txt_inputText3.setText(rs.getString(rs.getColumnIndex("message")));
Button btn_cancel = (Button) mView.findViewById(R.id.btn_cancel);
Button btn_okay = (Button) mView.findViewById(R.id.btn_okay);
alert.setView(mView);
final AlertDialog alertDialog = alert.create();
alertDialog.setCanceledOnTouchOutside(false);
btn_cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
btn_okay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String number = txt_inputText2.getText().toString();
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + number));// Initiates the Intent
startActivity(intent);
alertDialog.dismiss();
}
});
alertDialog.show();
alertDialog.getWindow().setLayout(730, 850); //Controlling width and height.
} catch (Exception e) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
});
}while (rs.moveToNext());
}
} catch (Exception e) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();
}
});
}
}
});
}
#SuppressLint("Range")
public List<Map<String, String>> getrequestitems() {
List<Map<String, String>> data = null;
data = new ArrayList<Map<String, String>>();
try {
SQLiteDatabase db = dbHandler.getReadableDatabase();
String sql = "SELECT * from request WHERE time > date('now','-1 day')";
Cursor rs = db.rawQuery(sql,null);
if(rs.moveToFirst()) {
do {
Map<String, String> dtname = new HashMap<String, String>();
dtname.put("bloodgrp", rs.getString(rs.getColumnIndex("bloodgrp")));
dtname.put("date", "Date:- " + rs.getString(rs.getColumnIndex("Datetime1")));
dtname.put("time", "Time:- " + rs.getString(rs.getColumnIndex("time")));
dtname.put("name", "Name:- " + rs.getString(rs.getColumnIndex("Name")));
dtname.put("Username", rs.getString(rs.getColumnIndex("Username")));
data.add(dtname);
}
while (rs.moveToNext());
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
return data;
}
}
But When I open that activity It doesn't displayed any records. I have debug the code but can't any exception. I have written wrong query?
probably as it appears that you are very likely comparing the anecdotal oranges and apples (see explanation/example) that is, at a guess you are comparing the time and a date (see Possible fix below BUT this very much depends upon what you are actually storing in the time column, see Possible debug action below that would allow you to see a) if you are extracting any data and if applying the get all (no WHERE clause) to see the actual underlying data)
format is yyyy-MM-dd –
That seems unlikely or if not a waste seeing that you have a column for the date and a column for the time.
If the time contains just the time hh:mm or even hh:mm:ss, as an example then extracting the date is going to result in unintended results.
Consider the following that highlights the issues that you may encounter:-
DROP TABLE IF EXISTS request;
CREATE TABLE IF NOT EXISTS request (booldgrp TEXT, Datetime1 TEXT, time TEXT, Name TEXT, Username TEXT);
INSERT INTO request VALUES
('O','2023-01-01 10:10','2023-01-01 10:10','FRED','USER001')
,('O','2023-01-01 10:10','10:10','FRED','USER002')
,('O','2023-01-01 10:10','2023-01-01 23:11','FRED','USER003')
,('O','2023-01-01 10:10','23:59','FRED','USER004')
,('O','2023-01-01 10:10','21:59','FRED','USER005')
,('O','2023-01-01 10:10','22:00','FRED','USER006')
,('O','2023-01-01 10:10','20:00','FRED','USER007')
,('O','2023-01-01 10:10','20:01','FRED','USER008')
,('O','2023-01-01 10:10','19:59:59','FRED','USER009')
;
SELECT *, date('now','-1 day') AS comparedate, time > date('now','-1 day') AS comparison FROM request;
SELECT *, date('now','-1 day') AS comparedate, datetime1 > date('now','-1 day') AS comparison FROM request;
DROP table IF EXISTS request;
that you can run in your favourite SQLite tool (Navicat was used)
The resultant output (what would be in the Cursor) is :-
As can be seen if the time is actually stored as hh:mm or hh:mm:ss (or similar where you just have the time and not the date) then the first 2 characters are significant, so if the year of the current date - 1 day is in the 21st century that only times that are 8 pm (20:00) or greater would be selected.
Possible fix (if date column has the date only or the date and time and the time column has the time)
Perhaps you want "SELECT * from request WHERE datetime1 > date('now','-1 day')"
Possible debug action
If the above is not the fix for your situation then consider changing your code to :-
SQLiteDatabase db = dbHandler.getReadableDatabase();
String sql = "SELECT * from request /* WHERE time > date('now','-1 day') */"; // <<<<<<<<<< WHERE clause commented out to get ALL data, try also with WHERE clause */
Cursor rs = db.rawQuery(sql,null);
DatabaseUtils.dumpCursor(rs); /* ADDED FOR DEBUG, run and check the LOG */
if(rs.moveToFirst()) {
see comments
The log would include either something like (where data is extracted ):-
2022-07-19 13:21:50.995 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#31816bf
2022-07-19 13:21:50.996 I/System.out: 0 {
2022-07-19 13:21:50.996 I/System.out: bloodgrp=O
2022-07-19 13:21:50.996 I/System.out: Datetime1=2023-01-01
2022-07-19 13:21:50.996 I/System.out: time=10:30
2022-07-19 13:21:50.996 I/System.out: Name=FRED
2022-07-19 13:21:50.996 I/System.out: Username=USER001
2022-07-19 13:21:50.996 I/System.out: }
2022-07-19 13:21:50.996 I/System.out: <<<<<
or (where no data has been extracted) :-
2022-07-19 13:24:12.216 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#30380ea
2022-07-19 13:24:12.217 I/System.out: <<<<<
Note
The getColumnIndex index method is case sensitive (or at least was) and as such if any of the column names mismatch, even if only due to the case, then the trapped exception row 0 column -1 will also result in no result (only a short while to notice this with a Toast). I would suggest:-
using Constants for column names and ALWAYS using those Constants to refer to column names i.e. only ever hard code each column name once. Incorrect variables names will not compile. Coded incorrect column names will happily compile and may not be noticed.
consider using e.printStackTrace() as well as or even instead of the Toast
trapping and catching SQLite errors can so easily mask issues
Example
based upon your code, but with :-
DBhandler and layouts composed from what can be gleaned from your code AND
with it inserting a row when the database is created as per :-
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
REQUEST_COLUMN_BLOODGROUP + " TEXT" +
"," + REQUEST_COLUMN_DATE + " TEXT" +
"," + REQUEST_COLUMN_TIME + " TEXT" +
"," + REQUEST_COLUMN_NAME + " TEXT " +
"," + REQUEST_COLUMN_USERNAME + " TEXT" +
"," + REQUEST_COLUMN_CONTACTNo + " TEXT" +
"," + REQUEST_COLUMN_MESSAGE + " TEXT" +
")");
ContentValues cv = new ContentValues();
cv.put(REQUEST_COLUMN_BLOODGROUP,"O");
cv.put(REQUEST_COLUMN_DATE,"2023-01-01");
cv.put(REQUEST_COLUMN_TIME,"10:30");
cv.put(REQUEST_COLUMN_NAME,"FRED");
cv.put(REQUEST_COLUMN_USERNAME,"USER001");
cv.put(REQUEST_COLUMN_CONTACTNo,"0000000000");
cv.put(REQUEST_COLUMN_MESSAGE,"MESSAGE X");
db.insert(TABLE_NAME,null,cv);
}
with the Request (changed to capitalise) Activity started directly from the MainActivity
and with the possible fix applied to the WHERE clause (i.e. Datetime column used for the comparison rather than the time column)
The ListView with a Teal background (to distinguish it)
Then when run :-
and then when the item is clicked:-
and if OK is clicked :-
so I'm having some trouble with SQLLite/Android studio, I have an activity that lets me update a user's password through an SQLLite function but it doesn't seem to be working, when I press the update password button, nothing happens, and the database doesn't update.
SQLLITE Update:
public int updateShopper(Shopper shopper)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL_SPPASS, shopper.getShopperPS());
String[] l = {shopper.getShopperID()+""};
return db.update(TABLE_NAME, values, COL_SPID + " =? ",l);
}
Get all shoppers :
public ArrayList<Shopper> getAllShoppers()
{
ArrayList splist = new ArrayList();
String selectQuery = "SELECT * FROM " + TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery(selectQuery, null);
if(c.moveToFirst())
{
do {
Shopper shopper = new Shopper();
shopper.setShopperUN(c.getString((c.getColumnIndex(COL_SPNAME))));
shopper.setShopperPS(c.getString(c.getColumnIndex(COL_SPPASS)));
splist.add(shopper);
} while(c.moveToNext());
}
return splist;
}
}
Activity Button :
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String username = ed1.getText().toString();
String password = ed2.getText().toString();
SQLShop sqlsp2 = new SQLShop(getApplicationContext());
ArrayList splist=sqlsp2.getAllShoppers();
for(int i=0;i<splist.size();i++)
{
Shopper sp=(Shopper) splist.get(i);
if(username.equalsIgnoreCase(sp.getShopperUN()))
{
Shopper shopper = new Shopper();
shopper.setShopperUN(username);
shopper.setShopperPS(password);
shopper.setShopperID(shopper.getShopperID());
sqlsp2.updateShopper(shopper);
break;
}
}
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
}
});
In your getAllShoppers() you're not setting the shopper id and it remains as 0. Trying to update a row with id 0 matches no rows, so no rows are updated.
After adding reading the shopper id from the database, fix this part too:
shopper.setShopperID(shopper.getShopperID());
Here you're assigning the id of a new Shopper back to itself so it stays as 0 default value. Change shopper.getShopperID() to sp.getShopperID().
I an trying to fetch data from my SQLite database on Android. However, when I run the code and see the Android Monitor, I get this message:
04-14 15:27:27.737 11177-11177/com.example.daniel.toto E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 6 rows, 5 columns.
This is the method in the database helper class I use to get the data from the database:
public ArrayList<String> getAllSales() {
ArrayList<String> array_list = new ArrayList<String>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res;
res = db.rawQuery( "select * from sales", null );
if (res != null) {
res.moveToFirst();
while (res.isAfterLast() == false) {
array_list.add(res.getString(res.getColumnIndex(SALES_TABLE_NAME)));
res.moveToNext();
}
return array_list;
} else {
array_list = null;
}
return array_list;
}
This is where I call it in onCreate method the activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sales);
mydb = new SalesDBHelper(this.getBaseContext());
array_list = mydb.getAllSales();
}
Thank you for deciphering the error message. Indeed the part of the error message column -1means: there is no such column.
Thank you a lot for pointing it out, it finally solved my problem!
new to Java here :)
The problem I'm facing is that I am unable to display the database from the Main Activity with a click of a button. The data in the database is being passed from another activity, would like to know if I'm missing anything or how would I go about fixing this. Thanks :)
(Method being used in the Main Activity after the onCreate)
MainActivity
public void displayDataInTable() {
roomDatabase myOpenHelper;
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String status = bundle.getString("status");
String roomValue =bundle.getString("roomValue");
//List for the name of the players and their scores
List<String> roomNumber = new ArrayList<String>();
List<String> roomStatus = new ArrayList<String>();
//The data being read from the database
myOpenHelper = new roomDatabase(this, DATABASE_NAME, null, VERSION_NUMBER);
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
Cursor cursor = db.query(roomDatabase.TABLE_NAME, null, null, null, null, null,null,null);
//The name and the score is printed on the row of the list
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("_id"));
String roomValueA = cursor.getString(cursor.getColumnIndex("roomValue"));
String statusA = cursor.getString(cursor.getColumnIndex("status"));
roomNumber.add(roomValueA);
roomStatus.add(" Recipe Ordered " + statusA);
}
//The items to de displayed are sent to the AdapterB
if ((roomNumber != null) && (roomStatus != null)) {
AdapterB adapter = new AdapterB(this, roomNumber, roomStatus);
setListAdapter(adapter);
}
}
LogsActivity
public class LogsActivity extends ListActivity{
roomDatabase myOpenHelper;
final String DATABASE_NAME = "roomstatus.db";
final int VERSION_NUMBER = 1;
ContentValues values1 = new ContentValues();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//variables are extracted from the bundle
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String status = bundle.getString("status");
String roomValue = bundle.getString("roomValue");
myOpenHelper = new roomDatabase(this, DATABASE_NAME, null, VERSION_NUMBER);
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
values1.put("status", status);
values1.put("roomValue", roomValue);
Toast.makeText(LogsActivity.this, status, Toast.LENGTH_LONG).show();
//Data is entered into the table
db.insert(roomDatabase.TABLE_NAME, null, values1);
Intent newIntentBundle = new Intent(LogsActivity.this, MainActivity.class);
Bundle bundleA = new Bundle();
bundle.putString("status", status);
bundle.putString("roomValue", roomValue);
newIntentBundle.putExtras(bundle);
startActivity(newIntentBundle);
}
}
NOTE - I am aware this may not be right way to do as it would mean creating a new database in the Main Activity and trouble with the adapter, so any help would be appreciated. :)
These are the methods to save and fetch in RoomDatabase class:-
public boolean addDetails(String status,String roomValue){
SQLiteDatabase db=this.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(KEY_STATUS,status);
values.put(KEY_ROOMVALUE,roomValue);
db.insert(TABLE_NAME,null,values);
db.close();
return true;
}
public List<String> getAllDetail(){
List<String> detailList=new ArrayList<>();
SQLiteDatabase db=this.getReadableDatabase();
Cursor cursor=db.rawQuery("select * from "+TABLE_NAME,null);
String status,roomValue;
if(cursor.moveToFirst()){
do{
status=cursor.getString(cursor.getColumnIndex(KEY_STATUS));
roomValue=cursor.getString(cursor.getColumnIndex(KEY_ROOMVALUE));
detailList.add(status);
detailList.add(roomValue);
}while (cursor.moveToNext());
}
return detailList;
}
In your activity where you have to save in db:
RoomDatabase roomDatabase=new RoomDatabase(getContext());
roomDatabase.addDetails(status,roomValue);
In your activity where you have to retrieve from db:
RoomDatabase roomDatabase=new RoomDatabase(getContext());
List<String> detailList=db.getAllDetail();
in detailList you can get the values.
Create a separate class for Database. Here are some links to how to create SQLite database in android.
http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
https://developer.android.com/training/basics/data-storage/databases.html
I am trying to get contacts from call log. I can get the contact numbers from main contacts using this code :
public void getContacts(View view) {
Intent intentContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intentContact, 0);
}
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
if (requestCode == 0)
{
try {
to.setText(getContactInfo(intent));
} catch(NullPointerException e) {
// Do nothing ;)
}
}
}
protected String getContactInfo(Intent intent)
{
String phoneNumber = to.getText().toString();
Cursor cursor = managedQuery(intent.getData(), null, null, null, null);
while (cursor.moveToNext())
{
String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
if(phoneNumber.endsWith(">"))
phoneNumber += ", "+name;
else
phoneNumber += name;
String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if ( hasPhone.equalsIgnoreCase("1"))
hasPhone = "true";
else
hasPhone = "false" ;
if (Boolean.parseBoolean(hasPhone))
{
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);
while (phones.moveToNext())
{ phoneNumber = phoneNumber + " <" + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))+">";
}
phones.close();
}
}
cursor.close();
return phoneNumber;
}
What this does is when we click a "Contact" button it open a list with all the contacts, the user can select any contact and that selected contact will be added in the "To" field. I want to do the exactly same thing, but instead of displaying all the contacts i want to display only those who were recently used (call log) for selection.
Also it would be nice if you can tell how to do this with groups also.
I got this going using my own version. i used a dialog and handed it the cursor to the call log. Here is the function:
public void getCallLog() {
String[] callLogFields = { android.provider.CallLog.Calls._ID,
android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.CACHED_NAME /* im not using the name but you can*/};
String viaOrder = android.provider.CallLog.Calls.DATE + " DESC";
String WHERE = android.provider.CallLog.Calls.NUMBER + " >0"; /*filter out private/unknown numbers */
final Cursor callLog_cursor = getActivity().getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, callLogFields,
WHERE, null, viaOrder);
AlertDialog.Builder myversionOfCallLog = new AlertDialog.Builder(
getActivity());
android.content.DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int item) {
callLog_cursor.moveToPosition(item);
Log.v("number", callLog_cursor.getString(callLog_cursor
.getColumnIndex(android.provider.CallLog.Calls.NUMBER)));
callLog_cursor.close();
}
};
myversionOfCallLog.setCursor(callLog_cursor, listener,
android.provider.CallLog.Calls.NUMBER);
myversionOfCallLog.setTitle("Choose from Call Log");
myversionOfCallLog.create().show();
}
You can use ContactsContract.Contacts.CONTENT_STREQUENT_URI which will give you both Frequently called and Starred contacts.
From API 21 is possible to use this: https://developer.android.com/reference/kotlin/android/provider/CallLog.Calls#CACHED_LOOKUP_URI
CACHED_LOOKUP_URI added in API level 21 static val CACHED_LOOKUP_URI:
String The cached URI to look up the contact associated with the phone
number, if it exists.
This value is typically filled in by the dialer app for the caching
purpose, so it's not guaranteed to be present, and may not be current
if the contact information associated with this number has changed.