I am building a blood bank database app. Where I will take some info along with blood type. I store the blood type as "INTEGER NOT NULL" with 1, 2,....,7 which indicate A+,.....,AB- blood types. But when I try to query a listview according to the user select the blood group from a spinner, I get errors(stack trace is given below). Inserting data in the database doing great without giving an error.
MainActivity relevant code -
private void displayDatabaseInfo(){
String[] projection = {
DonorEntry.COLUMN_DONOR_NAME,
DonorEntry.COLUMN_DONOR_MOBILE,
DonorEntry.COLUMN_BLOOD_GROUP,
DonorEntry.COLUMN_DONATE_DATE };
String selection = DonorEntry.COLUMN_BLOOD_GROUP + "=?";
String [] selectionArgs = new String[] {getString(mBloodType)};
Cursor cursor = getContentResolver().query(DonorEntry.CONTENT_URI,
projection, selection, selectionArgs,null);
ListView listView = (ListView) findViewById(R.id.list);
DonorCursorAdapter adapter = new DonorCursorAdapter(this, cursor);
listView.setAdapter(adapter);
}
DonorCursorAdapter relevant code -
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find individual views that we want to modify in the list item layout
TextView nameTextView = (TextView) view.findViewById(R.id.name);
TextView mobileTextView = (TextView) view.findViewById(R.id.mobileNo);
TextView bloodTypeTextView = (TextView) view.findViewById(R.id.bloodType);
TextView lastDonateTextView = (TextView) view.findViewById(R.id.donateDate);
// Find the columns of donor's attributes that we're interested in
int nameColumnIndex = cursor.getColumnIndex(DonorEntry.COLUMN_DONOR_NAME);
int mobileColumnIndex = cursor.getColumnIndex(DonorEntry.COLUMN_DONOR_MOBILE);
int bloodTypeColumnIndex = cursor.getColumnIndex(DonorEntry.COLUMN_BLOOD_GROUP);
int lastDonateColumnIndex = cursor.getColumnIndex(DonorEntry.COLUMN_DONATE_DATE);
// Read the donor attributes from the Cursor for the current pet
String donorName = cursor.getString(nameColumnIndex);
String donorMobileNo = cursor.getString(mobileColumnIndex);
String donorBloodType = cursor.getString(bloodTypeColumnIndex);
String donorLastDonate = cursor.getString(lastDonateColumnIndex);
// Update the TextViews with the attributes for the current pet
nameTextView.setText(donorName);
mobileTextView.setText(donorMobileNo);
bloodTypeTextView.setText(donorBloodType);
lastDonateTextView.setText(donorLastDonate);
}
Stack trace
<code>
2019-03-02 17:25:37.140 28705-28705/com.sarkerjr.greenBlood E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sarkerjr.greenBlood, PID: 28705
android.content.res.Resources$NotFoundException: String resource ID #0x2
at android.content.res.Resources.getText(Resources.java:339)
at android.content.res.Resources.getString(Resources.java:433)
at android.content.Context.getString(Context.java:556)
at com.sarkerjr.greenBlood.MainActivity.displayDatabaseInfo(MainActivity.java:121)
at com.sarkerjr.greenBlood.MainActivity.access$000(MainActivity.java:21)
at com.sarkerjr.greenBlood.MainActivity$2.onClick(MainActivity.java:56)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
</code>
Here fixed everything for you. There were a few problems.
getString was crashing. This is not the method you want to use to parse any integer, it is used to get a resource and you pass an id of that resource.
CursorAdapter needs _id column inside the cursor and when you passed projection array without _id column, your adapter was crashing. So I removed the projection and now you will get all the columns.
Although this was working somehow but you should not use getString when column value type is INTEGER, so I changed it to getInt.
You were directly assigning the column value to the TextView which was showing integers, so I created a method in MainActivity to get the actual values of blood types.
MainActivity changes -
private void displayDatabaseInfo() {
String selection = DonorEntry.COLUMN_BLOOD_GROUP + "=?";
String[] selectionArgs = new String[]{String.valueOf(mBloodType)};
Cursor cursor = getContentResolver().query(DonorEntry.CONTENT_URI,
null, selection, selectionArgs, null);
ListView listView = findViewById(R.id.list);
DonorCursorAdapter adapter = new DonorCursorAdapter(this, cursor);
listView.setAdapter(adapter);
}
// Get value of readable blood type
public String getBloodTypeString(int bloodType) {
switch (bloodType) {
case A_Positive:
return getResources().getString(R.string.a_positive);
case A_Negative:
return getResources().getString(R.string.a_negative);
case B_Positive:
return getResources().getString(R.string.b_positive);
case B_Negative:
return getResources().getString(R.string.b_negative);
case O_Positive:
return getResources().getString(R.string.o_positive);
case O_Negative:
return getResources().getString(R.string.o_negative);
case AB_Positive:
return getResources().getString(R.string.ab_positive);
case AB_Negative:
return getResources().getString(R.string.ab_negative);
default:
return "UNKNOWN";
}
}
DonorCursorAdapter changes -
int donorBloodType = cursor.getInt(bloodTypeColumnIndex);
String donorBloodTypeString;
try {
donorBloodTypeString = ((MainActivity) context).getBloodTypeString(donorBloodType);
} catch (ClassCastException e) {
throw new ClassCastException("Trying to access MainActivity method from different context");
}
bloodTypeTextView.setText(donorBloodTypeString);
Call
String [] selectionArgs = new String[] {String.valueOf(mBloodType)};
instead of
String [] selectionArgs = new String[] {getString(mBloodType)};
Related
I am creating function for Sqlite database and getting "variable might not initialized" error. I am trying to store sqlite data in string array.
public String[] gettitle()
{
String title[];
String s = "select Title from User_DB;";
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(s,null);
int a = 0;
while(cursor.moveToNext())
{
title[a] = cursor.getString(0);
a++;
}
return title;
}
it says title[] is not initialized but I dont understand why. I clearly initialized it.
You declare title. Allowed C language style is String title[]. In java one keeps the type expression together: String[] title;
String[] title;
This variable is uninitialized, reserves a memory slot for an array object, but the memory is not filled, initialized; it contains garbage. At its first usage of title the compiler issues an error.
In contrast class fields are initialized automatically by a default: here null, but for other types 0, false, 0.0 and so on.
Initialize the variable: give it an initial value.
For arrays that means set an array object. Arrays are fixed length, cannot grow, and thus:
String[] title;
title = new String[10];
Or shorter:
String[] title = new String[10];
Like fields also array elements are initialized with defaults, null.
Note you initialized a: int a = 0;.
Now you can use the array object through the variable:
title[a] = cursor.getString(0);
This was the point where the compiler saw the usage of a variable that still did not have a value.
So the code becomes:
public String[] loadTitles() {
String[] titles = new String[100];
String sql = "select Title from User_DB";
SQLiteDatabase db = getReadableDatabase();
int a = 0;
try (Cursor cursor = db.rawQuery(sql, null)) {
while (a < titles.length && cursor.moveToNext()) {
titles[a] = cursor.getString(0);
a++;
}
} // Calls cursor.close();
return Arrays.copyOf(titles, a);
}
Array.copyOf(array, newLength) make copy of the original array with as new length the number of read titles.
I have added the (weird) try-with-resources syntax which ensures that cursor is closed, even on exception or return happening inside the block.
I am trying to store and retrieve image data in Sqlite Db.
To do so I firstly stored in local device memory an example pic (path: storage/emulated/0/Download/).
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private final String SAMPLE_IMAGE_PATH = "/storage/emulated/0/Download/image.jpg";
Then I set up an insert method to feed the db with these example data:
private void insertProduct() {
// Create a ContentValues object where column names are the keys,
// and sample attributes are the values.
ContentValues values = new ContentValues();
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_NAME, sampleName);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_QTY, sampleQty);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_PRICE, SamplePrice);
values.put(InventoryContract.ProductEntry.COLUMN_EMAIL, sampleMail);
values.put(InventoryContract.ProductEntry.COLUMN_PHONE, samplePhone);
values.put(InventoryContract.ProductEntry.COLUMN_PRODUCT_PIC, SAMPLE_IMAGE_PATH);
//insert a new row
Uri newUri = getContentResolver().insert(InventoryContract.ProductEntry.CONTENT_URI,values);
}
and I define the onCreateLoader method as follows:
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Define a projection that specifies the columns from the table we care about.
String[] projection = {
InventoryContract.ProductEntry._ID,
InventoryContract.ProductEntry.COLUMN_PRODUCT_PIC,
InventoryContract.ProductEntry.COLUMN_PRODUCT_PRICE,
InventoryContract.ProductEntry.COLUMN_PRODUCT_QTY,
InventoryContract.ProductEntry.COLUMN_PRODUCT_NAME};
// This loader will execute the ContentProvider's query method on a background thread
return new CursorLoader(this,
InventoryContract.ProductEntry.CONTENT_URI,
projection,
null,
null,
null);
}
In the CursorAdapter class I updated the listView adding the data from db in bindView() method:
public void bindView(View view, Context context, Cursor cursor) {
// Find individual views that we want to modify in the list item layout
TextView nameTextView = (TextView) view.findViewById(R.id.prod_name);
TextView priceTextView = (TextView) view.findViewById(R.id.prod_price);
TextView qtyTextView = (TextView) view.findViewById(R.id.prod_qty);
ImageView prodImageView = (ImageView) view.findViewById(R.id.prod_img);
// Find the columns of attributes that we're interested in
int nameColumnIndex = cursor.getColumnIndex(InventoryContract.ProductEntry.COLUMN_PRODUCT_NAME);
int priceColumnIndex = cursor.getColumnIndex(InventoryContract.ProductEntry.COLUMN_PRODUCT_PRICE);
int qtyColumnIndex = cursor.getColumnIndex(InventoryContract.ProductEntry.COLUMN_PRODUCT_QTY);
int picColumnIndex = cursor.getColumnIndex(InventoryContract.ProductEntry.COLUMN_PRODUCT_PIC);
// Read the attributes from the Cursor for the current product
String prodName = cursor.getString(nameColumnIndex);
Double prodPrice = cursor.getDouble(priceColumnIndex);
int prodQty = cursor.getInt(qtyColumnIndex);
byte [] prodImg = cursor.getBlob(picColumnIndex);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[1024 * 32];
Bitmap bmp = BitmapFactory.decodeByteArray(prodImg, 0, prodImg.length, options);
//Update Views
nameTextView.setText(String.valueOf(prodName));
priceTextView.setText(prodPrice.toString());
qtyTextView.setText(String.valueOf(prodQty));
prodImageView.setImageBitmap(bmp);
}
}
When I try execute this code everything goes ok, but I see a blank image instead of both the selected pic and placer pic.
So I think that there is some problem with inserting data into db.
I am trying to store and retrieve image data in Sqlite Db
I do not recommend this. Store the images in files. Store data in the rows that identifies the files.
Then I set up an insert method to feed the db with these example data
You are storing a string in COLUMN_PRODUCT_PIC. You are not storing a byte[]. This is good, relative to my recommendation. This is bad relative to your data-retrieval code, where you are attempting to retrieve a byte[].
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
The listview sends an intent to musicplayer Activity. The intent contains integer values used to address songs and it works fine for small number of elements in say a Playlist (a listview) but for large number of songs it crashes (shown in Log below):
Listview:
final int size = lv.getAdapter().getCount();
final String[] F= new String[size];
final int Q[] = new int[size];
// listening to single listitem click
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting listitem index
TextView textView = (TextView) view.findViewById(android.R.id.text1);
String songName = textView.getText().toString();//lv.getItemAtPosition(position).toString();
Queuer(F,Q,size);
//songIndex = manager.getSongIndex(songName, getApplicationContext());
// Starting new intent
Intent i = new Intent(getApplicationContext(), MusicPlayerActivity.class);
Log.d("TAG", "onItemClick");
//// Sending songIndex to PlayerActivity
i.putExtra("size",size);
i.putExtra("queue",Q);
i.putExtra("filtered",true);
// Toast.makeText(getApplicationContext(), "Qi:" + Q[0], Toast.LENGTH_LONG).show();
i.putExtra("start", position);
startActivityForResult(i, 7);
}
});
Queuer method to store the names and indices of songs in arrays
void Queuer(String[] F,int[] Q, int size){
for(int i=0;i<size;i++){
View v = getListView().getChildAt(i);
TextView tv= (TextView) v.findViewById(android.R.id.text1);
F[i] = tv.getText().toString();
Q[i] = manager.getSongIndex(F[i],getApplicationContext());
Toast.makeText(getApplicationContext(), "SongName:" + F[i] , Toast.LENGTH_LONG).show();
}
}
Log:
01-07 00:03:50.293 27292-27292/com.imhotep.musicplayer
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.imhotep.musicplayer, PID: 27292
java.lang.NullPointerException: Attempt to invoke virtual method
'android.view.View android.view.View.findViewById(int)' on a null
object reference
at
com.imhotep.musicplayer.FilteredTracksActivity.Queuer(FilteredTracksActivity.java:307)
at
com.imhotep.musicplayer.FilteredTracksActivity$4.onItemClick(FilteredTracksActivity.java:285)
at android.widget.AdapterView.performItemClick(AdapterView.java:310)
at android.widget.AbsListView.performItemClick(AbsListView.java:1213)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3256)
at android.widget.AbsListView$3.run(AbsListView.java:4190)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5706)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1033)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)
Need help with this.
Adapter code:
String[] columns = {MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.MIME_TYPE};
String where = android.provider.MediaStore.Audio.Media.ARTIST + "=?";
String whereVal[] = { s };
String orderBy = android.provider.MediaStore.Audio.Media.TITLE;
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
columns, where, whereVal, orderBy);
//Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
// new String[]{MediaStore.Audio.Media._ID,MediaStore.Audio.Media.TITLE}, where, whereVal, orderBy);
String[] displayFields = new String[]{MediaStore.Audio.Media.TITLE};
int[] displayViews = new int[]{android.R.id.text1};
ListAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, cursor, displayFields,
displayViews, 0);
setListAdapter(adapter);
It happens because ListView recycles item views to save memory.
So you can access null views still present. For this reason if you want to print all songs in your playlist (that should coincide with your ListView right?) you should get data objects from adapter. From there you can access object data directly, not from views objects.
I am new with android programing and I have a problem with list view
In my app I have to read data from database (name,ID,year) and then add them to listview after that user must select one of
the items and in a new activity again I read data from db and list some of the other Items based on user's selection
Ol at this time In my first activity I read data and add them to listview..To select I must define a listener..right?
I define it like this code
enter code here #Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read_book);
String SDcardPath = Environment.getExternalStorageDirectory().getPath();
String DbPath = SDcardPath + "/Tosca/" + "persian_poem.db";
ListView list = (ListView) findViewById(R.id.list_poet_name);
try {
db = SQLiteDatabase.openDatabase(DbPath,null,SQLiteDatabase.CREATE_IF_NECESSARY);
getData();
db.close();
}
catch (SQLiteException e) {
Toast.makeText(this, e.getMessage(), 1).show();
}
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int position,
long id) {
// TODO Auto-generated method stub
ListView list = (ListView) findViewById(R.id.list_poet_name);
Log.i(TAG, "Listview get Item Pos");
Peot_ID.putString ("Peot_ID", (String) list.getItemAtPosition(position));
Intent Book_list_intent = new Intent (Read.this,Book_list.class);
Book_list_intent.putExtras(Peot_ID);
startActivity(Book_list_intent);
}
});
}
private void getData() {
try {
//txtMsg.append("\n");
// obtain a list of from DB
String TABLE_NAME = "classicpoems__poet_contents";
String COLUMN_ID = "poet_id";
String _ID = "_id";
String COLUMN_NAME = "poet_name";
String COLUMN_CENTURY = "century_start";
String [] columns ={_ID,COLUMN_ID,COLUMN_NAME,COLUMN_CENTURY};
Cursor c = db.query(TABLE_NAME,columns,null, null, null, null, COLUMN_ID);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, c,
new String[] {COLUMN_NAME,COLUMN_CENTURY}, new int[] {android.R.id.text1,android.R.id.text2}, 0);
ListView list = (ListView) findViewById(R.id.list_poet_name);
list.setAdapter(adapter);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), 1).show();
}
}
But here I have a problem..I want to send data of peot_id (Its deffrent from _id column in db) to next activity..Bt I mentioned that
with this code I can get whole row of selected item and I just want part of it(peot_id ) can you help me how to get just Peot_ID from selected
list item?
and I have another question..
As you see in my code I must refer to one spasial listview several times..each time I defined it by this code
enter code hereListView list = (ListView) findViewById(R.id.list_poet_name);
How can I define this listviwe one time and use it in several places in my code?sth like a public variable or sth like that
Thanks for your help.
As you see in my code I must refer to one spasial listview several
times..each time I defined it by this code
No. Just create one global ListView variable list and simply you can access to it from everywhere in your Activity. There is no need to declaring and initialising ListView again in OnItemClick() method.
I want to send data of peot_id (Its deffrent from _id column in db) to
next activity..Bt I mentioned that with this code I can get whole row
of selected item and I just want part of it(peot_id ) can you help me
how to get just Peot_ID from selected list item?
You are using Android's defined basic layout
android.R.layout.simple_list_item_2
I suggest you to create own XML file for row and then simply get whole View from ListView and from View you can get only ID.
Example:
listrow.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
android:background="#drawable/addresses_list_selector"
>
<TextView
android:id="#+id/id_column"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/name_column"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/id_column"
/>
<TextView
android:id="#+id/century_column"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/name_column"
/>
</RelativeLayout>
Then an usage with CursorAdapter:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.listrow, c,
new String[] {COLUMN_ID, COLUMN_NAME, COLUMN_CENTURY},
new int[] {R.id.id_column, R.id.name_column, R.id.century_column}, 0);
And then for getting ID from row:
public void onItemClick(AdapterView<?> parent, View v, int position,
long id) {
TextView id = (TextView) v.findViewById(R.id.id_column);
if (id != null) {
String idString = id.getText().toString();
}
}
Note:
If you still want to use android's predefined layout, you need to pass into String[] from ID_COLUMN and then access to ID from row via row.findViewById(<id>);
String[] from = {ID_COLUMN, NAME_COLUMN};
int[] to = {android.R.id.text1, android.R.id.text2};
TextView id = v.findViewById(android.R.id.android.R.id.text1);
String idString = id.getText().toString();
You do query like this to get a Particular column record alone :
Cursor mCursor = mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
KEY_NAME, KEY_DESIGNATION}, KEY_ROWID + "=" + yourPrimaryKey, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
I personally prefer to use onListItemclick() method like that
//do not forget to override - very important
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
//TODO what you what you have here the vars position - position of the selected item in list
// and also the id so you can easy trace what selection done the user
// you can play with this
}
Cursor curz=mDbHelper.fetchAllRemindersG();
startManagingCursor(curz);
ArrayList<String> mArrayList = new ArrayList<String>();
String name =curz.getString(curz.getColumnIndex(DatabaseIN.KEY_TITLE));
for(curz.moveToFirst(); curz.moveToNext(); curz.isAfterLast())
{ mArrayList.add(name); }
name_Val = (String[]) mArrayList.toArray(new String[mArrayList.size()]);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,name_Val);
txtPhoneName.setAdapter(adapter);
I am filling a autocompletetextview and i get an error at String name =curz.getString(curz.getColumnIndex(DatabaseIN.KEY_TITLE));
it just can't get the correct column index it forcecloses ive tried to wirte mdbHelper.KEY_TITLE or just KEY_TITLE but it was the same error
curz.moveToFirst()
String name =curz.getString(curz.getColumnIndex(DatabaseIN.KEY_TITLE));
do {
mArrayList.add(name);
}while(curz.moveToNext());
First you need to move to first row, then you can get something from it. Because when cursor is created, the pointer points to the -1 index or you can say it points to beforeFirst.
Cursor curz=mDbHelper.fetchAllRemindersG();
startManagingCursor(curz);
// setTheme(android.R.style.Theme_Light);
curz.moveToFirst();
ArrayList<String> mArrayList = new ArrayList<String>();
if (curz.getCount() > 0)
{
do
{
String name = curz.getString(curz.getColumnIndex(DatabaseIN.KEY_TITLE));
if(name!=null)
{
mArrayList.add(name);
}
}while (curz.moveToNext());
}