How to get sum of column in SqlLite using where condition? - java

My code is
Button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
int cv;
String getmont="",getyear="";
getmont=year.getText().toString();
getyear= (String) sid.getSelectedItem();
SQLiteDatabase db;
db = openOrCreateDatabase("monthapp", MODE_PRIVATE, null);
curtop = db.rawQuery("SELECT SUM(currentpaid)FROM monthvaluesOrgin WHERE curmonth='" + getmont + "' AND curyear='" + getyear + "'", null);
if (curtop.moveToNext() ) {
cv=curtop.getInt(0);
Toast.makeText(getApplicationContext(),cv,Toast.LENGTH_SHORT).show();
}
}
});
How to print/ toast the sum value?
It always shows error EofException.
My app shows "unfortunately your app has stopped".
Please give me a solution!
Thanks in advance!

You are using the wrong signature for makeText. Because cv is an int the compiler think you are trying to pass a resource id and since your sum is unlikely to be a valid string ID your app crashes because makeText cannot find that that number in the string resources. Try to use valueOf to convert cv to a string like this :
Toast.makeText(getApplicationContext(),String.valueOf(cv),Toast.LENGTH_SHORT).show();

Related

NumberFormatException: null

I am getting this error:NumberFormatException: null when I am trying to add score/points to my app.
I created separated table for this because I need multiple tables .
I have no clue what the problem is so thanks to you all.
if(count==4) {
my_db=new DBHelper(this);
sqdb = my_db.getWritableDatabase();
Cursor c_oldPoints= sqdb.query(DBHelper.TABLE_NAME2,null,DBHelper.NICKNAME+"=?",new String[]{Username},null,null,null);
int col_Points=c_oldPoints.getColumnIndex(DBHelper.POINTS);
c_oldPoints.moveToFirst();
while (!c_oldPoints.isAfterLast())
{
OldPoints=c_oldPoints.getString(col_Points);
c_oldPoints.moveToNext();
}
sqdb.close();
int OldP = Integer.parseInt(OldPoints);
OldP+=countPoints;
String SoldP = Integer.toString(OldP);
my_db=new DBHelper(this);
sqdb = my_db.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(my_db.POINTS,SoldP);
Cursor c = sqdb.query(DBHelper.TABLE_NAME2,null,DBHelper.NICKNAME+"=?",new String[]{Username},null,null,null);
c.moveToFirst();
while (!c.isAfterLast())
{
sqdb.update(DBHelper.TABLE_NAME2,cv, DBHelper.POINTS+"=?",new String[]{OldPoints});
c.moveToNext();
}
sqdb.close();
countPoints=0;
}
This is the logcat :-
2019-05-15 18:18:14.101 8513-8513/com.example.user.soundsequ E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.user.soundsequ, PID: 8513
java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:483)
at java.lang.Integer.parseInt(Integer.java:556)
at com.example.user.soundsequ.Game.onClick(Game.java:353)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
The error appears to be in this line
int OldP = Integer.parseInt(OldPoints);
The error is saying that the value of OldPoints is not a string that can be converted to an integer e.g. if it were A or null;
As such either a value extracted from the POINTS column is not a numeric or the value of Username does not match the column NICKNAME in a row. In which case OldPoints will be whatever value it has been set to before the loop.
As the data itself is not available you need to ascertain which of the two situations is causing the issue.
I'd suggest adding some Logging in to determine which.
e.g. by using something like :-
OldPoints = "my debugging value";
Log.d("MYDEBUGGING","OldPoints, before doing anything is " + OldPoints);
Cursor c_oldPoints= sqdb.query(DBHelper.TABLE_NAME2,null,DBHelper.NICKNAME+"=?",new String[]{Username},null,null,null);
int col_Points=c_oldPoints.getColumnIndex(DBHelper.POINTS);
c_oldPoints.moveToFirst();
while (!c_oldPoints.isAfterLast())
{
OldPoints=c_oldPoints.getString(col_Points);
c_oldPoints.moveToNext();
Log.d("MYDEBUGGING","Extracted the value " + OldPoints + " from position + String.valueOf(c_oldPoints.getPosition());
}
sqdb.close();
Log.d("MYDEBUGGING","Trying to convert the value " + OldPoints + " to an integer");
int OldP = Integer.parseInt(OldPoints);
You could also not make the above changes and add a breakpoint (on the line initially indicated) and then use Run/Debug App and inspect the variables (or use multiple breakpoints at suitable places). You may find this useful in regard to debugging Debug your app.
The following code protects against the exception and also protects against an attempt being made to update a non-existent user :-
if (count == 4) {
SQLiteDatabase sqdb = my_db.getWritableDatabase();
Cursor c_oldPoints= sqdb.query(
DBHelper.TABLE_NAME2,null,
DBHelper.NICKNAME+"=?",
new String[]{Username},
null,null,null
);
int col_Points=c_oldPoints.getColumnIndex(DBHelper.POINTS);
if (c_oldPoints.moveToFirst()) {
Oldpoints = c_oldPoints.getString(col_Points);
//Oldpoints = "oops";
int OldP = 0;
boolean can_convert_to_int = true;
try {
OldP = Integer.parseInt(Oldpoints) + countPoints;
can_convert_to_int = true;
} catch (NumberFormatException e) {
e.printStackTrace(); //TODO not necessary probably remove. just for checking the log
}
if (can_convert_to_int) {
ContentValues cv = new ContentValues();
cv.put(DBHelper.POINTS,OldP);
sqdb.update(DBHelper.TABLE_NAME2,cv, DBHelper.NICKNAME + "=?", new String[]{Username});
}
} else {
Log.d("NICKNAMENOTFOUND","No row was found when attemtping to get the old score for User " + Username);
}
}
However
I would suggest that you add a couple of methods to your DBHelper class, these being :-
public int increasePoints(String user, int points_to_add) {
SQLiteDatabase db = this.getWritableDatabase();
SQLiteStatement sql = db.compileStatement(
"UPDATE " + TABLE_NAME2 +
" SET " + POINTS + "=" + POINTS + " +? " +
"WHERE "+ NICKNAME + "=?"
);
sql.bindLong(1,points_to_add);
sql.bindString(2,user);
return sql.executeUpdateDelete();
}
public int getPoints(String user) {
SQLiteDatabase db = this.getWritableDatabase();
int rv = -1;
String whereclause = NICKNAME + "=?";
String[] whereargs = new String[]{user};
Cursor csr = db.query(TABLE_NAME2,new String[]{POINTS},whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getInt(csr.getColumnIndex(POINTS));
}
csr.close();
return rv;
}
The first method increasePoints performs the change to the points via an UPDATE sql statement and does away for the need to convert the points extracted as a string to an integer. It returns the number of rows that have been updated (1 if the NICKNAME column is always a unique value, 0 if nothing was updated).
The second method getPoints does as it says, it gets the points for the given user, if the user doesn't exist it will return -1.
Your code could then be :-
if (count == 4) {
boolean updated = false; //TODO remove when happy
int old_points = my_db.getPoints(Username); //TODO remove when happy
if (my_db.increasePoints(Username,countPoints) > 0) {
updated = true;
}
int new_points = my_db.getPoints(Username); //TODO remove when happy
//TODO remove following code when happy
String result = "The result of the attempt to update the points for user " + Username;
if (updated) {
result = result + " was successful. ";
} else {
result = result + " was unsuccessful.";
}
Log.d("POINTSINCREASE",result +
" Points were " + String.valueOf(old_points) + " points are now " + String.valueOf(new_points));
}
Note where //TODO remove when happy is coded the lines are just for testing, so the above could be :-
if (count == 4) {
my_db.increasePoints(Username,countPoints);
}

How to integrate search functionality in Android app

I'm trying to create an application to display the call logs based on the call type (incoming calls, outgoing calls, or missing calls). In addition I'm trying to add search and delete functionalities so the user can search for the call (by number) and delete the call. The layout of the app is shown here:
The search functionality works if I hit the 'All' button to display all calls and search by number there, but upon going to other sections to search for a number, such as received or missed, the app crashes.
So far I have managed to run the logcat on Android Studio, and found that the main issue is in my main activity file. I have attached the logcat image here:
There seems to be issues with these pieces of code: my getCalls Method, afterTextChanged Method, and my updateCursor Method.
private Cursor getCalls(int type, String searchString) {
Uri callUri = CallLog.Calls.CONTENT_URI;
ContentResolver contentResolver = getContentResolver();
String[] projection = new String[]{Calls._ID, Calls.NUMBER, Calls.DURATION, Calls.TYPE};
String selection=null;
String[] selectionArgs=null;
if(type != 0){
// filter type calls
selection = Calls.TYPE + "=?";
selectionArgs = new String[]{String.valueOf(type)};
}
if(!TextUtils.isEmpty(searchString)) {
// has some search string
if(TextUtils.isEmpty(selection)) {
// all call types
selection = Calls.NUMBER + " LIKE ?";
selectionArgs = new String[]{"%"+searchString+"%"};
} else {
// some type of call and add search String
selection = selection+" && " + Calls.NUMBER+" LIKE ?";
selectionArgs = new String[]{selectionArgs[0],"'%"+searchString+"%'"};
}
}
String order = Calls.DATE + " DESC ";
//verify permissions to access the user's call log
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
cursor = contentResolver.query(callUri, // URI content provider
projection,
selection,
selectionArgs,
order);
}
return cursor;
}
#Override
public void afterTextChanged(Editable s) {
updateCursor();
}
//updates the search
void updateCursor() {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
cursor = null;
}
cursor = getCalls(currentCallType, searchET.getText().toString());
adapter.swapCursor(cursor);
}
Upon running the app, I expected to be able to go to different sections (for example, I go to the received call section) and search for a number, however upon going to the section and tapping on the search bar, the app crashes. I do not understand how there could be issues with these methods.
SQLException says the error is near the & symbol, so the error should be in this line:
selection = selection+" && " + Calls.NUMBER+" LIKE ?";
Let's replace it with this one, because 'AND' should be used in SQL instead of double &:
selection = selection+" AND " + Calls.NUMBER+" LIKE ?";

updating a tuple in a sqlite table in android studio

before voting down please read my question , which I have searched a lot but I couldn't find the answer yet, so I would appreciate if you give me hand to overcome the problem.
Actually I need to update a tuple in a table named "Demographics". But it seems my code does not work correctly, and in fact after running the app , I got the result "0" for updating which means nothing get updated.
12-21 12:34:54.190 2351-2367/? D/Update Result:: =0
I guess my problem is due to not pointing to the right row of the table based on Primary key. Actually when a user Register to my app the following things should happen:
1- Create a tuple in "Demographics" table --> username, password and email will be inserted. An auto increment primary key also constructed and inserted.
2- user logins , then he can complete rest of information in "Demographics" table. --> this MODIFICATION is the "update" process which I', asking.
Would you please tell me if the following codes are wrong or have any implicit error?
DemographicsCRUD.java
public long UpdateDemographics(Demographics_to demoId) {
//SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DataBaseHelper.lastName, demoId.getD_lastName());
values.put(DataBaseHelper.firstName, demoId.getD_firstName());
values.put(DataBaseHelper.dateOfBirth, demoId.getD_dateOfBirth())
long result = database.update(dbHelper.Demographics_Table, values,
WHERE_ID_EQUALS,
new String[]{String.valueOf(demoId.getD_patientID())});
Log.d("Update Result:", "=" + result);
// db.close();
return result;
}
here is where I call the above code:
private void updateDemographicsTable()
{
ep_demoId = new Demographics_to();
String ep_na = ep_name.getText().toString();
String ep_fa = ep_family.getText().toString();
.
.
.
ep_demoId.setD_dateOfBirth(ep_bd);
ep_demoId.setD_firstName(ep_na);
ep_demoId.setD_lastName(ep_fa);
}
#Override
protected Long doInBackground(Void... arg0) {
long result = ep_demoCRUD.UpdateDemographics(ep_demoId);
return result;
}
#Override
protected void onPostExecute(Long result) {
if (activityWeakRef.get() != null
&& !activityWeakRef.get().isFinishing()) {
if (result != -1)
Toast.makeText(activityWeakRef.get(), "Information Updated!",
Toast.LENGTH_LONG).show();
}}
Looks like whatever you are passing in as the patientID does not have a matching record in the database or the dataobject "Demographics_to" has the patient ID set incorrectly.

What is wrong with my ContentProvider in Android 4.3?

My app works just fine with any Android version before 4.3. I mean when I input a word into edWord (EditText field), a list of similarly-spelled words will appear in the list view.
But in Android 4.3, it always returns null, claiming that app_ContentProvider cannot find the supported uri.
I use the following code to show the word list:
public void showWordlist() {
edWord.setEnabled(true);
String word = edWord.getText().toString();
Uri uri = Uri.parse("content://doyle.app_name.app_ContentProvider/dict/" + mDBFile.fileName + "/list/" + word);
edWord.requestFocus();
try
{
Cursor result = getContentResolver().query(uri,null,null,null,null);
Log.i(MAIN_TAG, "Found word = " + result);
//I think the problem lies somewhere here because
//the 'result' is always 'null' (see the above log.i)
if (result != null)
{
int countRow=result.getCount();
Log.i(MAIN_TAG, "countRow = " + countRow);
mLSTCurrentWord.clear();
//mLSTCurrentContent.clear();
mLSTCurrentWordId.clear();
mAdapter.clear();
if (countRow >= 1)
{
int indexWordColumn = result.getColumnIndex("word");
int indexIdColumn = result.getColumnIndex("id");
result.moveToFirst();
String strWord;
int intId;
int i = 0;
do
{
strWord = Utility.decodeContent(result.getString(indexWordColumn));
intId = result.getInt(indexIdColumn);
mLSTCurrentWord.add(i,strWord);
mLSTCurrentWordId.add(i,intId);
//mLSTCurrentContent.add(i,strContent);
mAdapter.add(strWord);
i++;
} while (result.moveToNext());
}
result.close();
}
lstWord.setAdapter(mAdapter);
}
catch (Exception ex)
{
Log.e(MAIN_TAG, "Error = " + ex.toString());
}
edWord.setEnabled(true);
}
And here is my app_ContentProvider.
I have no idea whether there are any changes in Android 4.3 that stop my app from functioning normally.
Regarding my code lines above, can you please tell me what the problem might be? Thanks a lot.
Try set the property android:exported="true" for your content provider in your Manifest. It seems that the default value of this property has changed in android 4.3

How to sort results on android from SQLite?

i need to display multiple database tables to seperate textviews.
So i need to pull all 'appointments' from a table and sort them to display in separate textviews on the mainActivity such as txtMonday, txtTuesday, txtWednesday
The database is designed to store the day along with the other details:
private static final String DATABASE_CREATE =
"create table " + TABLE_AP + "(" + COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_DAY + " text not null, "
+ COLUMN_TIME + " text not null, "
+ COLUMN_DURATION + " text not null, "
+ COLUMN_DESCRIPTION + " text not null);";
This is how i attempt to call it through MainActivity:
(I also will be calling it with onCreate)
public void onResume (){
APData = new AppointmentDataSource(this);
APData.open();
List<Appointment> appointments = APData.retrieveAllAppointments();
APData.close();
AppointmentDataSource:
public List<Appointment> retrieveAllAppointments () {
List<Appointment> appointments = new ArrayList<Appointment>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_AP, , null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Appointment ap = cursorToBk(cursor);
appointments.add(ap);
cursor.moveToNext();
}
cursor.close();
return appointments;
}
Also for the days, i used radio buttons to choose between monday / tue / wed / thur / fri
so i store the day with :
createButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
findRadioGroup = (RadioGroup) findViewById(R.id.radioDay);
int selectedId = findRadioGroup.getCheckedRadioButtonId();
radioButton = (RadioButton) findViewById(selectedId);
String day=radioButton.getText().toString();
String time=txtTime.getText().toString();
String duration=txtDuration.getText().toString();
String description=txtDescription.getText().toString();
APData.insert(day, time, duration, description);
APData.close();
finish();
}
});
and the XML/strings for them:
<string name="RadioMon">Mon</string>
<string name="RadioTue">Tue</string>
<string name="RadioWed">Wed</string>
<string name="RadioThu">Thur</string>
<string name="RadioFri">Fri</string>
In your datamodel you should have a class that manipulates the Appointments, so when you retrieve all your appointments from the database just filter them by appointments[i].Day, or something like that, based on how your Appointment class is created. You don't need to explicitly create different DB selects for each of them.
public void onResume (){
APData = new AppointmentDataSource(this);
APData.open();
List<Appointment> appointments = APData.retrieveAllAppointments();
APData.close();
TextView tvMonday = (TextView)findViewById(R.id.tvMonday);
TextView tvTuesday = (TextView)findViewById(R.id.tvTuesday);
... (all your days textViews).
for(Iterator<Appointment> i = appointments.iterator(); i.hasNext();){
Appointment item = i.next();
if(item.Day.equals("Monday") tvMonday.append(item.ToString());
//same for the rest of your textViews
}
Should be something like this.

Categories

Resources