Hello I have set up a simple listview which is populated by a SQL database hence why I'm using a cursor adapter. I have now added a switch to the custom layout but now I need it to simply function by displaying a toast message with its current row position. Could you please have quick look at my code a guide me in the right direction.
Main Activity............
SimpleCursorAdapter simpleCursorAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_screen);
alarmListView = (ListView)findViewById(R.id.alarmListView);
databaseHandler = new MyDatabaseHandler(this, null, null, 1);
displayProductList();
}
private void displayProductList() {
try
{
Cursor cursor = databaseHandler.getAllProducts();
if (cursor == null)
{
return;
}
if (cursor.getCount() == 0)
{
return;
}
String[] columns = new String[] {
MyDatabaseHandler.COLUMN_AlARMDATE,
MyDatabaseHandler.COLUMN_ALARMTIME,
MyDatabaseHandler.COLUMN_ALARMNAME
};
int[] boundTo = new int[] {
R.id.custom_Date,
R.id.custom_Time,
R.id.custom_Name
};
simpleCursorAdapter = new SimpleCursorAdapter(this,
R.layout.alarm_list,
cursor,
columns,
boundTo,
0);
alarmListView.setAdapter(simpleCursorAdapter);
}
catch (Exception ex)
{
}
}
The other two remaining sections are simply my database and getters and setters.
Thank you
Related
I am trying to edit a group title and Notes,
Editing title works for both system groups and user created groups,
Although notes column only persist if it is a System group(e.g. "Contacts", "Friends", "Family", "Coworkers"),
I assume that it either doesn't save notes for user created groups or some how gets overwritten with title column content in notes column.
How can I use notes column in contact groups? is there any other way to store additional information with groups?
Here is my code snippet:
ArrayList<ContentProviderOperation> ops =new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder op =
ContentProviderOperation.newUpdate(ContactsContract.Groups.CONTENT_URI)
.withSelection(ContactsContract.Groups._ID + "="+group.getId(), null)
.withValue(ContactsContract.Groups.TITLE, group.getTitle());
HashMap<String, String> notes = group.getNotes();
if(notes!=null && notes.size()>0){
op = op.withValue(ContactsContract.Groups.NOTES, new Gson().toJson(group.getNotes()));
}
ops.add(op.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
Hope this solution works for you, seems to be working for me.
I've used ContentResolver.update() method.
I assume that it either doesn't save notes for user created groups or some how gets overwritten with title column content in notes column.
I was able to update the notes for user created groups using below code.
How can I use notes column in contact groups?
You can use notes column to save any TEXT value because it's defined of type TEXT in sqlite. See ContactsContract.Groups.NOTES .
(Tested on Google Pixel XL, Oreo 8.0.0)
public class MainActivity extends AppCompatActivity {
private Cursor mCursor;
private SimpleCursorAdapter adapter;
private ListView lvGroups;
#Override
protected void onDestroy() {
if (mCursor != null)
mCursor.close();
super.onDestroy();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvGroups = findViewById(R.id.lvGroups);
checkAndRequestPermission();
}
private void checkAndRequestPermission() {
if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PermissionChecker.PERMISSION_GRANTED) {
loadGroups();
} else {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS}, 123);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
boolean isGranted = true;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PermissionChecker.PERMISSION_DENIED)
isGranted = false;
}
if (isGranted)
loadGroups();
else
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS},123);
}
private void loadGroups() {
mCursor = getContentResolver().query(ContactsContract.Groups.CONTENT_URI,null,ContactsContract.Groups.GROUP_IS_READ_ONLY + " = 0",null, ContactsContract.Groups.TITLE);
adapter = new SimpleCursorAdapter(this, R.layout.contact_group_item, mCursor, new String[] {
ContactsContract.Groups.TITLE,
ContactsContract.Groups._ID,
ContactsContract.Groups.ACCOUNT_NAME,
ContactsContract.Groups.ACCOUNT_TYPE,
ContactsContract.Groups.AUTO_ADD,
ContactsContract.Groups.GROUP_IS_READ_ONLY,
ContactsContract.Groups.GROUP_VISIBLE,
ContactsContract.Groups.SOURCE_ID,
ContactsContract.Groups.NOTES},
new int[] {
R.id.text1,
R.id.text2,R.id.text3, R.id.text4, R.id.text5, R.id.text6, R.id.text7, R.id.text8, R.id.text9}, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lvGroups.setAdapter(adapter);
lvGroups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cursor = adapter.getCursor();
cursor.moveToPosition(position);
int groupId = cursor.getInt(cursor.getColumnIndex(ContactsContract.Groups._ID));
ContentValues contentValues = new ContentValues();
contentValues.put(ContactsContract.Groups.NOTES,"My test Notes");
getContentResolver().update(ContactsContract.Groups.CONTENT_URI, contentValues, ContactsContract.Groups._ID + " = " + groupId, null);
adapter.notifyDataSetChanged();
}
});
}
}
The NOTES field is a String, it looks like you're trying to set a JSON object to it.
Check if this is working for you:
if (notes!=null && notes.size()>0) {
op = op.withValue(ContactsContract.Groups.NOTES, "TEST STRING!");
}
If so, you'll need to extract the actual string you need from the JSON object, that would depend on the format of your JSON.
i need your help, i did display data in a list view but the problem is that i
want the data to be according to a specific value, that means if the id = 1, only the rows
concerned will be displayed, if you have any suggestions i would be very thankful :
here the code of :
public class MainActivity extends ListActivity {
private static final int FLAG_REGISTER_CONTENT_OBSERVER = 2;
private Cursor cursor;
SimpleCursorAdapter adapter = null;
Cursor c;
DBAdapter db = new DBAdapter(this);
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db.open();
populateListViewFromDB();
} catch (Exception e) {
Log.e("ERROR", "Error occured: " + e.toString());
e.printStackTrace();
}
}
#SuppressWarnings("deprecation")
private void populateListViewFromDB() {
Cursor cursor = db.getAllRecords();
startManagingCursor(cursor);
String[] databaseColumnNames = new String[] { DBAdapter.col_region, };
int[] toViewIDs = new int[] { R.id.text };
SimpleCursorAdapter myCursordapter = new SimpleCursorAdapter(this,R.layout.activity_main, cursor, databaseColumnNames, toViewIDs,FLAG_REGISTER_CONTENT_OBSERVER);
ListView list = (ListView) findViewById(android.R.id.list);
And my DBAdapter is :
private static final String MENAGE = "table_MENAGE";
public static final String _id = "Num_du_Questionnaire";
public Cursor getAllRecords() {
return db.query(MENAGE, new String[] { _id, col_region,
}, null, null, null,
null, null);
}
list.setAdapter(myCursordapter);
} }
As you may check in query documentation, function accepts a selection and selectionArgs parameters, corresponding to SQL WHERE clause.
So, to make a query limited to a specific id, just use:
db.query(MENAGE, new String[] { _id, col_region}, "id = ?", new String[] {_id}, null, null, null);
I have two tables with names disease_table and sysmptoms_table. I retrieved the data from disease_table from the DB and displayed on the listview and when the listitem is clicked, I have to select and display disease category symptoms accordingly and I did that successfully but my code has redundancy, I had to write two methods in the datahelper class to retrieve the symptoms as per the disease in another listview. and I am retrieving the symptom data in list view with the query with the condition of WHERE "disease_id=1" with foreign key reference
the code for the methods is as follows,
//getting pain symptom names in a arraylist and then display in listview
//this.setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1,symptompain));
public List<String> getAllSymptomPain() {
List<String> symptompain = null;
cr = db.query(SYMPTOM_TABLE_NAME, new String[] {"symname"}, "diseaseid=1", null, null, null, null);
if(null != cr){
symptompain = new ArrayList<String>();
if (cr.moveToFirst()) {
do {
symptompain.add(cr.getString(0));
} while (cr.moveToNext());
}
if (cr != null && !cr.isClosed()) {
cr.close();
}
}
return symptompain;
}
//getting colorchange symptom names in a arraylist and then display in listview
//this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,symptomcolorchange));
public List<String> getAllSymptomColorChange() {
List<String> symptomcolorchange = null;
cr = db.query(SYMPTOM_TABLE_NAME, new String[] {"symname"}, "diseaseid=2", null, null, null, null);
if(null != cr){
symptomcolorchange = new ArrayList<String>();
if (cr.moveToFirst()) {
do {
symptomcolorchange.add(cr.getString(0));
} while (cr.moveToNext());
}
if (cr != null && !cr.isClosed()) {
cr.close();
}
}
return symptomcolorchange;
}
How can I write these two in a single method and then call it in class which extends listactivity under onListItemclick method?
And my OnListItemClick() method is as follows :
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
String item=(String)getListAdapter().getItem(position);
if(item.equals("Pain in Teeth")){
// passing the method here
}
else if(item.equals("Pain in Gums")){
// passing the method here
}
else if(item.equals("Pain in Mucosa")){
// passing the method here
}
else if(item.equals("Pain in TMJoint")){
// passing the method here
}
else if(item.equals("Non-Specific Pain")){
// passing the method here
}
}
Try this:
public List<String> getSymptomsByDiseaseId(long diseaseId) {
List<String> symptomsList = new ArrayList<String>();
String selection = "diseaseid=?";
String[] selectionArgs = { String.valueOf(diseaseId) };
Cursor cursor = db.query(false, SYMPTOM_TABLE_NAME, null, selection, selectionArgs, null, null, null, null);
if (cursor.moveToFirst()) {
do {
symptomsList.add(cursor.getString(0));
} while (cursor.moveToNext());
}
cursor.close();
return symptomsList;
}
This question already has an answer here:
attempt to re-open an already-closed object: SQLiteDatabase
(1 answer)
Closed 8 years ago.
I know there are several questions like this one, but all of them seem to have a different approach to solve the problem and none have solved mine.
I have my main activity working just fine, loading the db and populating the listview. Then I call a second activity and the problem shows up when I try to load the listview.
I have tried using start/stop managingcursor(cursor) even though it is deprecated, but it didn't fix the problem. Also I tried cloasing the cursor and db in my main activity before firing the next one but that didn't help either.
Both classes extend from ListActivity and follow the same sequence:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Open db in writing mode
MySQLiteHelper.init(this);
MySQLiteHelper tpdbh =
new MySQLiteHelper(this, "DB", null, 1);
SQLiteDatabase db = tpdbh.getWritableDatabase();
checkLocationAndDownloadData(); //this fires a Asynctask that calls method parseNearbyBranches shown bellow
//I load the data to the ListView in the postExecute method of the asynctask by calling:
/*
Cursor cursor = MysSQLiteHelper.getBranchesNames();
adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
ListView lv = getListView();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the state's capital from this row in the database.
String branch_id = cursor.getString(cursor.getColumnIndexOrThrow("branch_id"));
cursor.close();
openNextActivity(Integer.parseInt(branch_id));
}
});
}
//In another file:
private void parseNearbyBranches(JSONObject jo) throws JSONException
{
if ( jo.has(jsonTitle) &&
jo.has("company_id") &&
jo.has("id")
) {
String branch = jo.getString(jsonTitle);
MySQLiteHelper tpdbh = MySQLiteHelper.instance;
SQLiteDatabase db = tpdbh.getWritableDatabase();
db.execSQL("INSERT INTO Branches (branch_id, name, company_id) " +
"VALUES ('" +jo.getInt("id")+"', '" + branch +"', '" +jo.getInt("company_id")+"' )");
db.close(); //no difference is I comment or uncomment this line
}
}
In MySQLiteHelper.java:
public static Cursor getBranchesNames() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id", "branch_id", "name", "company_id" };
Cursor c = getReadDb().query(branchesTable, columns, null, null, null, null,
null);
return c;
}
My other activity does basically the same:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_branch_surveys);
//Read branch data from DB
int companyID = -1;
MySQLiteHelper.init(this);
String [] columns = new String [] {"company_id"};
String [] args = {Integer.toString(branchID)};
Cursor c = MySQLiteHelper.getReadDb().query(MySQLiteHelper.branchesTable, columns, "branch_id=?", args, null, null, null); //THIS QUERY WORKS JUST FINE
if (c.moveToFirst())
companyID = Integer.parseInt(c.getString(0));
c.close();
if( companyID != -1)
{
new DownloadTask().execute(Integer.toString(companyID) );
//where the Async task calls something just like NearByBranches shown above(but with different objects of course)
//And the postExecute sets the listView:
/* cursor = MySQLiteHelper.getAll();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
setListAdapter(adapter);
*/
}
}
}
In MySQLiteHelper.java:
public static Cursor getAll() {
// TODO Auto-generated method stub
String[] columns = new String[] { "_id","title", "points" };
//********IT IS IN THIS LINE WHERE I GET THE ERROR:********************
Cursor c = getReadDb().query(theTable, columns, null, null, null, null,
null);
return c;
}
public static SQLiteDatabase getReadDb() {
if (null == db) {
db = instance.getReadableDatabase();
}
return db;
}
I hope you can help me out. Thanks!
I just tried commenting the db.close in the similar method of parseNeabyBranches and the problem was solved. Yet I dont get the same error having db.close() in parseNearbyBranches(), can you explain me why?
In parseNearbyBranches() you create a separate SQLiteDatabase object with:
SQLiteDatabase db = tpdbh.getWritableDatabase();
Since this is a different object than the one returned by getReadDb(), you can (and should) close it. The basic rule is each time you call getWritableDatabase() and getReadableDatable() you must have a matching close() statement.
I'm trying to populate a ListView with data from a query using a CursorLoader. I'm new to CursorLoaders and I'm using code I purloined from Beginning Android 4 Application Development. As you can see, I'm getting data from an Intent. The data in the Intent is what I want; I've verified that in the debugger. However, when I query my database, nothing displays in the ListView. Can anyone help?
public class MyList extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String TABLE_BASEPATH = "tbl";
private static final String AUTHORITY = "SQLData";
public static final Uri MY_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_BASEPATH);
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent myData = getIntent();
Bundle info = myData.getExtras();
if (info != null){
Cursor c;
String[] dataColumns = { "mycolumn" };
String selection = "level = '" + info.getString("Level") + "'";
if (android.os.Build.VERSION.SDK_INT < 11)
c = managedQuery(MY_URI, dataColumns, selection, null, "ORDER BY mycolumn");
else
{
CursorLoader cursorloader = new CursorLoader(this, MY_URI, dataColumns, selection, null, "ORDER BY mycolumn");
c = cursorloader.loadInBackground();
}
int[] viewIDs = { R.id.mylist1 };
SimpleCursorAdapter adapter;
if (android.os.Build.VERSION.SDK_INT < 11)
adapter = new SimpleCursorAdapter(this, R.layout.mylist, c, dataColumns, viewIDs);
else
adapter = new SimpleCursorAdapter(this, R.layout.mylist, c, dataColumns, viewIDs, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
this.setListAdapter(adapter);
}
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this, MY_URI,
PROJECTION, null, null, null);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
case LOADER_ID:
mAdapter.swapCursor(cursor);
break;
}
}
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
It doesn't matter if I'm using the cursor or the CursorLoader. If my version is < 11 (cursor), I get no data; if it's > 11 (CursorLoader) I still get no data.
You need to put in the id column in the projection when working with ContentProviders, otherwise they "won't work". Which I think you are doing > api level 11...
String[] dataColumns = { "mycolumn" };
The above code should include the id field. If the id field is "_id" (like Sams answer):
String[] dataColumns = { "mycolumn", "_id" };