force close while adding to array - java

I want to get one column from my SQLite database and add that information in an array.
I use from array and cursor and two java classes.
My sqlite database doesn't have a problem as in another page I was able to get information.
My Android application force closes while I'm expecting to see the information displayed.
My method (displayrooidad):
public String displayrooidad(int row) {
Cursor cu = db.query(DB_TBL_ROOIDAD, null, null, null, null, null, null, null);
cu.moveToPosition(row);
String content = cu.getString(1);
return content;
}
my java class
SQLiteHelper: is a javaclass for connect to database.
open and close methods Working properly.
public class Rooidad extends AppCompatActivity {
Spinner sp;
TextView txt;
SQLiteHelper sq;
String[] myarray;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rooidad);
// sp=(Spinner)findViewById(R.id.sp);
txt = (TextView)findViewById(R.id.test);
sq=new SQLiteHelper(getBaseContext());
sq.open();
int row =sq.countofrow();
myarray=new String[row];
for(int teller=0;teller<=row;teller++){
String tittle = sq.displayrooidad(teller);
myarray[teller]=tittle.toString();
}
sq.close();
txt.setText(myarray[4].toString());
}
}

I think you need to put teller < row because your tab has only row elements not row+1.

Related

Error querying sqlite database in android studio

I have a problem in my application, to see if there is someone who can help me.
It turns out that in my application I have made a database with SQLite that has two tables, one for players and one for results.
#Override
public void onCreate(SQLiteDatabase BaseDeDades) {
BaseDeDades.execSQL("create table jugadors(codi int primary key, nom text, cognoms text, data date, club text, categoria text)");
BaseDeDades.execSQL("create table resultats(codipuntuacio int primary key, codijugador int,codiexercici text, puntuacio text, temps long, data date)");
}
To consult the first of the tables (players) that shows a list of all the players entered in the database, I did it as follows.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_llistajug);
Llistajugadors();
}
public void Llistajugadors(){
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this,"administracio",null,1);
SQLiteDatabase BaseDeDades = admin.getWritableDatabase();
if(BaseDeDades!=null){
Cursor c= BaseDeDades.rawQuery("select * from jugadors",null);
int quantitat = c.getCount();
int i=0;
String[] array = new String[quantitat];
if (c.moveToFirst()){
do{
String linia = c.getInt(0)+"-"+c.getString(1);
array[i] = linia;
i++;
}while(c.moveToNext());
}
ArrayAdapter<String>adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
final ListView llista = (ListView)findViewById(R.id.llista);
llista.setAdapter(adapter);
llista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = getIntent();
intent.putExtra("dato2", llista.getItemAtPosition(position).toString());
setResult(RESULT_OK,intent);
finish();
}
});
}
}
}
The problem has arisen when trying to consult the data of the other table (results) since I have tried to do it the same way
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_llistajug);
jugador = getIntent().getStringExtra("name");
exercici = getIntent().getStringExtra("exercise");
nom = jugador.split("-")[1];
codi = Integer.parseInt(jugador.split("-")[0]);
Resultats();
}
public void Resultats() {
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this, "administracio", null, 1);
SQLiteDatabase BaseDeDades = admin.getWritableDatabase();
if (BaseDeDades != null) {
Cursor c2 = BaseDeDades.rawQuery("select * from resultats",null);
int quantitat2 = c2.getCount();
int i2 = 0;
String[] array2 = new String[quantitat2];
if (c2.moveToFirst()) {
do {
String linia2 = c2.getInt(0) + "-" + c2.getString(1);
array2[i2] = linia2;
i2++;
} while (c2.moveToNext());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array2);
final ListView llista2 = (ListView) findViewById(R.id.llista2);
llista2.setAdapter(adapter);
}
}
}
But when executing this activity, in this case the application stops.
Does anyone know why if I have done it the same way? Thank you
This is the error that appears in Logcat when executing the activity:
Logcat error
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
codijugador i codi are integers and it works correctly but adding another parameter codiexercici = exerici which are strings gives me an error, are they not done the same way?
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
Thanks, the bug was fixed. But now I have another problem with the query. How can I make the query for a string?
co-player i codi are integers and it works correctly but adding another parameter codiexercici = exerici which are strings gives me an error, are they not done the same way?
Cursor c = BaseDeDades.rawQuery("select * from resultats where codijugador = "+codi+" and codiexercici="+exercici, null);
String must be enclosed inside single quotes, but this is something that you should not do by concatenating the parameters and the single quotes.
Use ? placeholders for the parameters and the 2nd argument of rawQuery() to pass them:
Cursor c = BaseDeDades.rawQuery(
"select * from resultats where codijugador = ? and codiexercici = ?",
new String[] {String.valueOf(codi), exercici}
);

How to call a non-static method from another activity's java class in Android?

So I have one java class called Details, which contains a non-static method called loadFavourites() and another java class called Favourites, which is implemented when the Favourites activity is started in my app.
I want to be able to call the method loadFavourites() from Details class in Favourites onCreate() method, however I am not sure how to do this...
I understand that I cannot create an instance of the Details class in order to access the method e.g.
Details details = new Details();
details.loadFavourites();
...as this does not work.
Also, I do not want my class or my method to be static as I have dynamic data involved.
Therefore, does anyone know a way in which I can call this non-static method from another class?
Here is a simplified version of my code...
In Details Activity:
FloatingActionButton addFav = (FloatingActionButton) findViewById(R.id.addFavBtn);
addFav.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
loadFavourites();
}});
public void loadFavourites() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
String[] columns = {"favouriteId", "title", "owner", "url_m", "ownerPic", "description", "dateTaken"};
Cursor cursor = db.query("favourites", columns, null, null, null, null, "favouriteId");
Log.d("FavouritesDB", "" + cursor.getCount());
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
favID = cursor.getInt(0);
title = cursor.getString(1);
owner = cursor.getString(2);
url_m = cursor.getString(3);
ownerPic = cursor.getString(4);
description = cursor.getString(5);
date = cursor.getString(6);
// Add data to the array list for the recyclerview
ImageInfo favourite = new ImageInfo();
favourite.dateTaken = date;
favourite.description = description;
favourite.ownerPic = ownerPic;
favourite.url_m = url_m;
favourite.owner = owner;
favourite.title = title;
NetworkMgr.getInstance(this).favouritesImageList.add(favourite);
// Move to next entry
cursor.moveToNext();
}
cursor.close();
db.close();
}
In Favourites Activity:
public class Favourites extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourites_layout);
*this is where I want loadFavourites()*
}
}

Populating a ListView with SQLite - ListView appends rows but doesn't show text

I'm trying to populate a ListView with SQLite items. After reading about this here and in other tutorials/examples I tried the following code, but I can't spot where exactly is the issue with it, since it's not working as intended, ListView isn't showing any items. My database has only one type of data, a string called sentence. Any help that could at least point me a direction in solving the issue is appreciated.
First I made a FavoritesDataBaseCore.java:
package com.easyprojects.artgames;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by Vinicius on 19/05/2017.
*/
public class FavoritesDataBaseCore extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Favorites.db";
public FavoritesDataBaseCore(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table favorite(_id integer primary key autoincrement, sentence text not null)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists favorite");
onCreate(db);
}
}
The sentence is supposed to be added through a button click in CharacterActivity.java, relevant code:
ImageButton setFavoriteBtn;
private SQLiteDatabase database;
FavoritesDataBaseCore helper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_character);
setFavoriteBtn = (ImageButton) findViewById(R.id.setFavoriteBtnId);
setFavoriteBtn.setOnClickListener(this);
// Database stuff
helper = new FavoritesDataBaseCore(this);
database = helper.getWritableDatabase();
}
// Code below is inside public void onClick(View view)
case R.id.setFavoriteBtnId:
ContentValues values = new ContentValues();
values.put("sentence", characterTV.getText().toString());
database.insert("favorite", null, values);
// A Toast here showing values.toString() works well
break;
And finally the Activity that contains the ListView and creates the Cursor, I suspect the problem is here, since the Cursor is a major responsable for setting a correct adapter to the ListView, FavoritesActivity.java, relevant code:
private SQLiteDatabase database;
FavoritesDataBaseCore helper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_favorites);
helper = new FavoritesDataBaseCore(this);
database = helper.getReadableDatabase();
String[] field = {"sentence"};
int[] to = new int[]{R.id.SentenceAd};
Cursor cursor = getData();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, field, to, 0);
final ListView FavoritesListView = (ListView) findViewById(R.id.listviewID); // ListView
FavoritesListView.setAdapter(adapter);
}
public Cursor getData(){
Cursor cursor;
String[] field = {"sentence"};
cursor = database.query("favorite",null,null,null,null,null,null);
return cursor;
}
My database_adapter.xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/SentenceAd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Edit: After adapting the code with #MikeT's suggestions I've come to the conclusion my ListView is appending rows each time I add a value into the database, but sentence is never shown in those rows.
There are a number of issues. The first few are related to the creation of the Cursor in preparation for it's use by the SimpleCursorAdapter. Then there is an issue with how the SimpleCursorAdpater has been instantiated/ssetup.
The Cursor.
Cursor adpaters require that a column named _id exists. To overcome this issue the cursor should include both columns. The easiest way to accomplish this is to use null as the 2nd parameter to the query method.
Change
cursor = database.query("favorite",field,null,null,null,null,null);
to
cursor = database.query("favorite",null,null,null,null,null,null);
A Cursor returned from the query method will not be null (cusror.getCount() is how you would check for no rows), so there is no need or use checking if it is null. Additionally the Cursor Adpater (simple or custom) will do the necessary cursor navigation. There is no need to move the cursor. The original has been edited accordingly so no change is required.
Last in regard to the Cursor, closing the Database would close the Cursor (again already edited).
The SimpleCursorAdapter
The issue is that you are using a supplied layout as in android.R.layout.simple_list_item_1 (the 2nd parameter) this expects you to signify which Cursor column (you have signified sentence) will be displayed in it's specific TextView but you have provided a TextView in your own layout.
Changing
int[] to = new int[]{R.id.SentenceAd};
to
int[] to = new int[]{android.R.id.text1};
Is one way to resolve the problem, but it's a waste your time and effort in creating you own layout.
To utilise your own layout then don't make the above change (as you will want the id of the TextView in your layout) but instead change
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, field, to, 0);
to use your layout
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.database_adapter, cursor, field, to, 0);
In short the 2nd (The layout to be used) and the 4th (The Column from the Cursor, by name) and 5th (The ID of the TextView within the layout where the data from the column will be placed) parameters are interdependent/reliant upon each other.

Android - Wanting to alternate icon images in a listview using cursorLoader

I have an application that displays a listView of contacts sorted by Last, then first names. Beside each contact is an image (icon). There are 3 kinds of contacts for which I'd like to display 3 different images (customers/suppliers/other) I have a default image now that is set to customer. I'm wondering if there's a way using the cusorLoader shown below to alternate images on the fly, or whether it would just be best to add a method involving a cursor in my onResume. (onResume is called each time I need to display the images). I believe simpleCursorAdapter can only take textViews as args, so if it's possible, maybe a compound textview/image would work. My icons are not stored in the database, just in the drawables.
Thanks in advance for any replies.
#Override
protected void onResume() {
super.onResume();
//Starts a new or restarts an existing Loader in this manager
getLoaderManager().restartLoader(0, null, this);
}
/*
* The fillData method binds the simpleCursorAadapter to the listView.
*/
private void fillData() {
String[] from = new String[] { ContactsDB.COLUMN_LAST_NAME, ContactsDB.COLUMN_FIRST_NAME };
//The XML views that the data will be bound to:
int[] to = new int[] {R.id.label2, R.id.label};
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(this, R.layout.contact_row, null, from,
to, 0);
setListAdapter(adapter);
}
// Sort the names by last name, then by first name
String orderBy = ContactsDB.COLUMN_LAST_NAME + " COLLATE NOCASE ASC"
+ "," + ContactsDB.COLUMN_FIRST_NAME + " COLLATE NOCASE ASC" ;
// Creates a new loader after the initLoader () call
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { ContactsDB.ROW_ID, ContactsDB.COLUMN_LAST_NAME, ContactsDB.COLUMN_FIRST_NAME };
CursorLoader cursorLoader = new CursorLoader(this,
SomeContentProvider.CONTENT_URI, projection, null, null, orderBy);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in.
// (The framework will take care of closing the old cursor once we return.)
adapter.swapCursor(data); //Call requires Min API 11
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed.
// Data is no longer available, delete the reference
adapter.swapCursor(null);
}
}
Here is the code I use to dynamically show a drawable on a ListView, you have to use the function setViewBinder on your adapter:
mAdapter.setViewBinder(new ViewBinder() {
public boolean setViewValue(View aView, Cursor aCursor, int aColumnIndex) {
//Modification of the icon to display in the list
if (aColumnIndex == aCursor.getColumnIndex(DatabaseHandler.RATE_EMOTION)) {
int emotionID = aCursor.getInt(aColumnIndex);
Drawable emotionDrawable = resources.getDrawable(R.drawable.ic_unknown_rate);
//if emotion is set
if(emotionID > 0){
String emotionDrawablePath = "ic_smi" + emotionID;
int emotionDrawableID = resources.getIdentifier(emotionDrawablePath,"drawable", getPackageName());
//if a drawable is found
if(emotionDrawableID > 0){
emotionDrawable = resources.getDrawable(emotionDrawableID);
}
}
ImageView emotionImage = (ImageView) aView;
emotionImage.setImageDrawable(emotionDrawable);
return true;
}
return false;
}
});
You can see in this example that I change the drawable according to the data I get from the cursor for every row.

How do I implement autocomplete with cursoradapter

I have an SQLite database containing 2 tables 4000+ rows each used for autocomplete. I saw very simple examples that use an array of strings to provide autocomplete or they use the list of contacts to do the same. Obviously none of these work in my case. How do I use my own SQLite database with my own autocomplete data, for the autocomplete. Do I have to create content providers? How? Please give me some examples because I couldn't find any. I have managed to override SQLiteOpenHelper to copy the database from the assets folder to the /data/data/MY_PACKAGE/databases/ folder on the android. I have created a custom CursorAdapter that uses my custom SQLiteOpenHelper and returns a cursor from runQueryOnBackgroundThread. I get strange errors about some _id column missing. I have added the _id column to my tables. I also don't understand what is the Filterable interface doing and when does my data get filtered. What methods/classes do I need to override? Thanks.
It works.
You need the SQLiteOpenHelper from here. You basically have to copy your database into a specific folder from your assets folder. Then you need a custom CursorAdapter that uses your custom SQLiteOpenHelper.
Here is the onCreate method for my activity.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
KeywordsCursorAdapter kwadapter = new KeywordsCursorAdapter(this, null);
txtKeyword = (AutoCompleteTextView)this.findViewById(R.id.txtKeyword);
txtKeyword.setAdapter(kwadapter);
txtCity = (AutoCompleteTextView)this.findViewById(R.id.txtCity);
btnSearch = (Button)this.findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(this);
}
Here is the cursoradapter. You can pass null for cursor when constructing.
public class KeywordsCursorAdapter extends CursorAdapter {
private Context context;
public KeywordsCursorAdapter(Context context, Cursor c) {
super(context, c);
this.context = context;
}
//I store the autocomplete text view in a layout xml.
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.keyword_autocomplete, null);
return v;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
String keyword = cursor.getString(cursor.getColumnIndex("keyword"));
TextView tv = (TextView)view.findViewById(R.id.txtAutocomplete);
tv.setText(keyword);
}
//you need to override this to return the string value when
//selecting an item from the autocomplete suggestions
//just do cursor.getstring(whatevercolumn);
#Override
public CharSequence convertToString(Cursor cursor) {
//return super.convertToString(cursor);
String value = "";
switch (type) {
case Keywords:
value = cursor.getString(DatabaseHelper.KEYWORD_COLUMN);
break;
case Cities:
value = cursor.getString(DatabaseHelper.CITY_COLUMN);
break;
}
return value;
}
#Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
//return super.runQueryOnBackgroundThread(constraint);
String filter = "";
if (constraint == null) filter = "";
else
filter = constraint.toString();
//I have 2 DB-s and the one I use depends on user preference
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//String selectedCountryCode = prefs.getString("selectedCountry", "GB");
String selectedCountryCode = prefs.getString(context.getString(R.string.settings_selected_country), "GB");
selectedCountryCode += "";
//Here i have a static SQLiteOpenHelper instance that returns a cursor.
Cursor cursor = MyApplication.getDbHelpers().get(selectedCountryCode.toLowerCase()).getKeywordsCursor(filter);
return cursor;
}
}
Here is the part that returns the cursor: it's just a select with a like condition.
public class DatabaseHelper extends SQLiteOpenHelper {
...
public synchronized Cursor getKeywordsCursor (String prefix) {
if (database == null) database = this.getReadableDatabase();
String[] columns = {"_id", "keyword"};
String[] args = {prefix};
Cursor cursor;
cursor = database.query("keywords", columns, "keyword like '' || ? || '%'", args, null, null, "keyword", "40");
int idcol = cursor.getColumnIndexOrThrow("_id");
int kwcol = cursor.getColumnIndexOrThrow("keyword");
while(cursor.moveToNext()) {
int id = cursor.getInt(idcol);
String kw = cursor.getString(kwcol);
Log.i("keyword", kw);
}
cursor.moveToPosition(-1);
return cursor;
}
...
}
You can also create a custom content provider but in this case it would be just another useless class you need to override.

Categories