This is my code for database class (DatabaseHelper.java)
public Cursor getAllData(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("select * from "+TABLE_NAME,null);
return res;
}
This is another class which is (MainSuggestion.java)
public class MenuSuggestion extends AppCompatActivity {
DatabaseHelper myDb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu_suggestion);
<br/>
Cursor res = myDb.getAllData();
if (res.moveToFirst()) {
TextView bmi = (TextView) findViewById(R.id.textView9);
TextView kcal = (TextView) findViewById(R.id.textView10);
bmi.setText(res.getString(3));
kcal.setText(res.getString(4));
}
}
}
Can someone tell me, what's wrong with my code?
The exact reason this isn't working is because "myDb" is null on this line.
Cursor res = myDb.getAllData();
However, I recommend you Running a Query with a CursorLoader. It might seem overkill, loading stuff from the database on the main thread like you are can lead to ANR errors.
Query data from database, you have to use:
this.getReadableDatabase();
You use getWritableDatabase() when you want to write, update, delete data into/from database.
Related
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.
I have prepopulated a database with DB Browser for SQLite and tried to retrieve data from it using SQLiteAssetHelper (installed and used it using the guide at https://github.com/jgilfelt/android-sqlite-asset-helper ) and got a "No such table" error. I am sure that there is a table named that way in the database. I've tried to debug it and saw that I leave the DATABASE_VERSION as equal to one than it detects that there is already a database and doesn't copy it, though if I change the database version and setForceUpdate to (true) then it copies it, but I get the same error anyway. What should I do for SQLiteAssetHelper to copy my database properly and get rid of that annoying error?
Code:
DataBaseHelper class:
public class DataBaseHelper extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "DonRoll";
private static final int DATABASE_VERSION = 2;
private static DataBaseHelper instance;
public static DataBaseHelper getInstance(Context context){
if (null == instance){
instance = new DataBaseHelper(context);
}
return instance;
}
private DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public Cursor getAllCategoryNames() {
setForcedUpgrade(2);
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("MenuCategories");
Cursor c = qb.query(db, null, null, null, null, null, null);
c.moveToFirst();
return c;
}
}
Activity class:
public class CategoryListActivity extends ListActivity {
DataBaseHelper db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category_list);
db = DataBaseHelper.getInstance(this);
getData();
}
#SuppressWarnings("deprecation")
private void getData() {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
db.getAllCategoryNames(),
new String[] { "value" },
new int[] { android.R.id.text1 });
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(adapter);
}
}
Problem solved: I've used adb pull to get the database file from the assets folder and it somehow got corrupted - it had only the "android_metadata" table. I don't know why this happened (maybe because I renamed it after I have put it into Android studio?), but once I have deleted this file and replaced it with a proper one everything worked just fine.
I am trying to create a database of restaurants and their items for an app as a starter project to get familiar with android. I have a list from a previous activity where a user clicks on the name of the restaurant and the items are shown. I created a helperDB class to handle the insert statements and database setup, although when I called my insert method from inside a new thread, they do not seem to execute. I have provided the code below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_bar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
String barName = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
final TextView tv = (TextView) findViewById(R.id.name);
tv.setText(barName);
restaurants = new ArrayList<String>();
mydb = new DBHelper(this);
new Thread(new Runnable() {
#Override
public void run() {
mydb.insertDrink("cake", "McD's", 8);
mydb.insertDrink("muffin", "The Woods", 8);
restaurants = mydb.getDrinks("The Woods");
System.out.println(restaurants);
}
}).start();
ArrayAdapter arrayAdapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1, restaurants);
obj = (ListView)findViewById(R.id.listview);
obj.setAdapter(arrayAdapter);
}
The code for the insert statement and getDrinks method are as follows:
public boolean insertDrink(String drink, String name, int price){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("drink", drink);
contentValues.put("name", name);
contentValues.put("price", price);
db.insert("Bars", null, contentValues);
return true;
}
public ArrayList<String> getDrinks(String name){
ArrayList<String> arrayList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from Bars", null);
res.moveToFirst();
while(res.isAfterLast() == false){
arrayList.add(res.getString(res.getColumnIndex(BAR_COLUMN_DRINK)));
res.moveToNext();
}
return arrayList;
}
I know that I am not supposed to access any android toolkits from any thread besides the UI thread, although I don't think I am doing that. If this is not the normal way to populate a SQLite android database, I of course am willing to learn where to do that as well.
although when I called my insert method from inside a new thread, they
do not seem to execute.
How can you say that? Are you seeing data entries in database? Or by looking only for restaurant ArrayList?
My doubt is you are not getting your Restaurant ArrayList because your Thread runs asynchronously.
And your next statement after Thread executed without waiting to fill restaurnat arrayList.
Solution:
Use AsyncTask call your database stuff in doInBackground() and get result in onPostExecute() and set adapter with result in the same method.
I suggest you to use AsyncTask.
Maybe something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_bar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
String barName = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
final TextView tv = (TextView) findViewById(R.id.name);
tv.setText(barName);
new AsyncTask<Void, Void, ArrayList<String>> {
protected Long doInBackground() {
DBHelper mydb = new DBHelper(ThisActivityClassName.this);
mydb.insertDrink("cake", "McD's", 8);
mydb.insertDrink("muffin", "The Woods", 8);
return mydb.getDrinks("The Woods");
}
protected void onPostExecute(ArrayList<String> restaurants) {
ArrayAdapter arrayAdapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1, restaurants);
obj = (ListView)findViewById(R.id.listview);
obj.setAdapter(arrayAdapter);
}
}.execute();
}
I am using the bellow code to list a unique list of people that sent me SMS. It works fine but still its a bit slow it takes 4 to 5 seconds to load and I have 650 SMS on my device any suggestion ?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listSMS();
}
private void listSMS()
{
TextView tview = (TextView) findViewById(R.id.list);
Uri uriSMSURI = Uri.parse("content://sms/inbox");
ContentResolver cr= this.getContentResolver();
Cursor cur = cr.query(uriSMSURI, null, null, null, null);
LinkedHashSet contactList= new LinkedHashSet();
String sms = "";
while (cur.moveToNext()) {
if(!contactList.contains(cur.getString(2)))
{
contactList.add(cur.getString(2));
sms += "From :" + getContactName(cur.getString(2),cr)+"\n";
}
}
cur.close();
tview.append(sms);
}
public static String getContactName(String num, ContentResolver cr) {
Uri u = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,Uri.encode(num));
String[] projection = new String[] { ContactsContract.Contacts.DISPLAY_NAME};
Cursor c = cr.query(u, projection, null, null, null);
try {
if (!c.moveToFirst())
return num;
int index = c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
return c.getString(index);
} finally {
if (c != null)
c.close();
}
}
Instead of preparing the list of contacts with their names up front and then passing it to the adapter, try preparing the list with ids only and then fetch the corresponding names inside the adapter. This will solve the delay to start but will make scrolling of the ListView a bit slower which can be solved by using a View Holder or some caching mechanism to prevent fetching the same name more than once. Also note that the adapter will query for names of contacts that are currently visible to the user only.
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.