My app contains a series of long texts, and I'd like the user to be able to return to them at the point where they left off if they leave that View.
I've adapted the code from this answer for a ListView. The first Log is fine, but the second does not, which suggests to me that state is null.
Here's my StoryBodyActivity:
public class StoryBodyActivity extends AppCompatActivity {
private TextView storyBodyTextView;
private ScrollView storyBodyScrollView;
Parcelable state;
#Override
public void onPause() {
Log.d("pause", "saving listview state # onPause");
state = storyBodyTextView.onSaveInstanceState();
super.onPause();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_story_body);
Bundle extras = getIntent().getExtras();
String story = extras.getString("story");
setTitle(story);
storyBodyTextView = (TextView) findViewById(R.id.story_body_text_view);
storyBodyScrollView = (ScrollView) findViewById(R.id.story_body_scroll_view);
DatabaseHelper db = new DatabaseHelper(this);
String storyBody = db.getStoryBody(story);
storyBodyTextView.setText(Html.fromHtml(storyBody));
if(state != null) {
Log.d("pause", "trying to restore textview state..");
storyBodyTextView.onRestoreInstanceState(state);
}
}
}
I also need to ensure that the position of each individual long text is saved.
Here's the DatabaseHelper to show where the data is coming from:
public String getStoryBody(String story) {
Log.i("test", "hello");
String storyBody = "";
// Select all query
String selectQuery = "SELECT * FROM " + BOOKS + " WHERE title = '" + story + "'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
storyBody = cursor.getString(4);
} while (cursor.moveToNext());
}
return storyBody;
}
Related
I'm trying to get the values from a recyclerView item (Firestore as database) in a new activity by using intents if I click on it. Don't know if that is the best way, but I got so far.
In my second activity I only get Null in the textViews I want to populate.
I've tried to test it with Toasts. You will see there is two Toast messages. The first one in the mainActivity (UltraLiquors) show the data I want to pull correctly (the ID, product and price), but the second one in the details activity only shows "null", so I assume there is a problem with my getExtras in my detail activity. I just don't know where to look anymore.
Please be so kind and help, I really have been struggling with this a few days.
Here is my mainActivity (UltraLiquors.class)
public class UltraLiquors extends AppCompatActivity {
private FirebaseFirestore ultra_liquor_db = FirebaseFirestore.getInstance();
private CollectionReference promo_oneRef = ultra_liquor_db.collection("ultra_liquors");
private static final int ACTIVITY_NUM = 2;
private UltraLiquorsRecyclerAdapter ultra_liquors_adapter;
private static final String TAG = "Ultra Liquors";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ultra_liquors);
setUpPromoOneRecyclerView();
//setupBottomNavigationView();
setTitle("Ultra Liquors");
Context context;
}
private void setUpPromoOneRecyclerView() {
Query query = promo_oneRef.whereEqualTo("promo_number", "1").orderBy("department");
FirestoreRecyclerOptions<Ultra_liquors> options = new FirestoreRecyclerOptions.Builder<Ultra_liquors>()
.setQuery(query, Ultra_liquors.class)
.build();
ultra_liquors_adapter = new UltraLiquorsRecyclerAdapter(options);
RecyclerView promo_one_recyclerView = findViewById(R.id.recycler_view_ultra_liquors);
//recyclerView.setHasFixedSize(true);
promo_one_recyclerView.setLayoutManager(new LinearLayoutManager(this));
promo_one_recyclerView.setAdapter(ultra_liquors_adapter);
ultra_liquors_adapter.setOnItemClickListener(new UltraLiquorsRecyclerAdapter.OnItemClickListener() {
#Override
public void onItemClick(DocumentSnapshot documentSnapshot, int position) {
Ultra_liquors note = documentSnapshot.toObject(Ultra_liquors.class);
String id = documentSnapshot.getId();
String product = (String) documentSnapshot.get("product");
String price = (String) documentSnapshot.get("price");
String path = documentSnapshot.getReference().getPath();
Toast.makeText(UltraLiquors.this,
"Position: " + position + " ID: " + product + price, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(UltraLiquors.this, ViewProduct.class);
intent.putExtra("Product", product);
intent.putExtra("Price", price);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
ultra_liquors_adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
ultra_liquors_adapter.stopListening();
}
}
And here is the detailActivity (ViewProduct) where I want to pull the data from the intent:
public class ViewProduct extends AppCompatActivity {
private String edit_product_ID;
//private String edit_product_Product;
private String edit_product_Price;
private TextView productView, priceView;
private TextView mSave, mDelete;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_product);
Intent intent = getIntent();
String product;
String price;
product = String.valueOf(getIntent().getExtras().get("product"));
price = String.valueOf(getIntent().getExtras().get("price"));
Toast.makeText(this, "The Product ID: " + edit_product_ID +
" Product Name " + product + " Product Price " + price, Toast.LENGTH_LONG).show();
TextView productView = findViewById(R.id.product);
productView.setText(product);
TextView priceView = findViewById(R.id.price);
priceView.setText(price);
mSave = (TextView) findViewById(R.id.save);
mDelete = (TextView) findViewById(R.id.delete);
}}
I am not the best yet with Java or Android, so please be patient.
You're using:
intent.putExtra("Product", product);
intent.putExtra("Price", price);
But then you're trying to get them with:
product = String.valueOf(getIntent().getExtras().get("product"));
price = String.valueOf(getIntent().getExtras().get("price"));
See how these values are different ?
You need to use the same casing, as it's case sensitive, so use something like:
product = String.valueOf(getIntent().getExtras().get("Product"));
price = String.valueOf(getIntent().getExtras().get("Price"));
I want to make a to-do list app, and I wanted to delete the item in the list by tapping the checkbox.
I tried to make a "deleteTask"(as you see in the code) method in the database class. Also, you can see the "populateListView"
method, it provides data from the database into listview, I use it to refresh after each time a task got deleted from the database.
public void deleteTask(String task) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, COL2 , new String[]{task});
}
public void populateListView() {
try {
mDataBaseHelper = new DataBaseHelper(MainActivity.this);
data = mDataBaseHelper.getData();
mArrayList = new ArrayList<>();
if (data.getCount() != 0) {
while (data.moveToNext()) {
mArrayList.add(data.getString(1));
ListAdapter listAdapter = new ArrayAdapter(MainActivity.this, R.layout.list_items, R.id.checkBox, mArrayList);
list = (ListView) findViewById(R.id.myListId);
list.setAdapter(listAdapter);
}
mDataBaseHelper.close();
} else {
toastMessage("the Database is empty");
}
}catch(Exception e){
Log.e(TAG, "populateListView: error"+e.getStackTrace() );
}
}
when the application gets started, I tapped the item that I want to delete, but I see that the items start to be deleted by order from above!
one by one each time I tapped any checkbox.
You want :-
public void deleteTask(String task) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, COL2 + "=?" , new String[]{task});
}
If you weren't trapping the error by using the try/catch using db.delete(TABLE_NAME, COL2 , new String[]{task}); you would get an exception along the lines of :-
java.lang.IllegalArgumentException: Too many bind arguments. 1 arguments were provided but the statement needs 0 arguments.
However
Assuming that the issue with deleting rows sequentially rather than according to the checked item(s), is likely due to the handling of the checked items. However, as the code for this is not provided it would only be guess work to know where in the code you are going wrong.
One thing is that you do not want to be creating a new listadapter instance every time you populate the ListView.
As a hint to handling a ListView, but deleting an item when it is long-clicked based upon the COL2 value, perhaps consider the following which has been based upon your code (but deletes according to long clicking an item) :-
public void populateLisView() {
mDataBaseHelper = new DataBaseHelper(this); //<<<<<<<<<< NOTE 1
list = (ListView) this.findViewById(R.id.myListId); //<<<<<<<<<< NOTE 1
data = mDataBaseHelper.getData(); //<<<<<<<<<< get the data to be listed
if (listadapter == null) { //<<<<<<<<<< Only need to instantiate one adapter when it has not bee instantiated
listadapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data); // for convenience using a stock layout
list.setAdapter(listadapter);
//<<<<<<<<<<< add the onItemLongClick listener
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
mDataBaseHelper.deleteTaskByCol2(data.get(position)); //<<<<<<<<<< gets the value of the item according to it's position in the list
populateLisView(); //<<<<<<<<<< as the item has been deleted then refresh the Listview
return true; // flag the event as having been handled.
}
});
//<<<<<<<<<<< If the Adapter has been instantiated then refresh the ListView's data
} else {
listadapter.clear(); // Clear the data from the adapter
listadapter.addAll(data); // add the new changed data to the adapter
listadapter.notifyDataSetChanged(); // tell the adapter that the data has changed
}
}
NOTE 1
you would typically instantiate these variables once.
Check the comments
You may wish to edit your question to include how you are handling the check events.
The Full Working Example
DatabaseHelper.java
Note this may differ from yours a little
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TABLE_NAME = "mytable";
public static final String COL1 = "col1";
public static final String COL2 = "col2";
SQLiteDatabase db;
private static final String CRT_MYTABLE_SQL = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME +
"(" +
COL1 + " TEXT, " +
COL2 + " TEXT" +
")";
public DataBaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
db = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CRT_MYTABLE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addMytableRow(String col1, String col2) {
ContentValues cv = new ContentValues();
cv.put(COL1,col1);
cv.put(COL2,col2);
return db.insert(TABLE_NAME,null,cv);
}
public ArrayList<String> getData() {
ArrayList<String> rv = new ArrayList<>();
Cursor csr = db.query(TABLE_NAME,null,null,null,null,null,null);
while (csr.moveToNext()) {
rv.add(csr.getString(csr.getColumnIndex(COL2)));
}
csr.close();
return rv;
}
public void deleteTaskByCol2(String task) {
db.delete(TABLE_NAME,COL2 + "=?",new String[]{task});
}
}
MainActivity.java
i.e. an example activity that is based upon your code, but according to the above :-
public class MainActivity extends AppCompatActivity {
DataBaseHelper mDataBaseHelper;
ArrayList<String> data;
ListView list;
ArrayAdapter<String> listadapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addSomeTestData();
populateLisView();
}
private void example001() {
}
public void populateLisView() {
mDataBaseHelper = new DataBaseHelper(this);
list = (ListView) this.findViewById(R.id.myListId);
data = mDataBaseHelper.getData();
if (listadapter == null) {
listadapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data);
list.setAdapter(listadapter);
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//mDataBaseHelper.deleteTaskWrong(data.get(position)); // ooops
mDataBaseHelper.deleteTaskByCol2(data.get(position));
populateLisView();
return true;
}
});
} else {
listadapter.clear();
listadapter.addAll(data);
listadapter.notifyDataSetChanged();
}
}
private void addSomeTestData() {
if (mDataBaseHelper == null) {
mDataBaseHelper = new DataBaseHelper(this);
}
if (DatabaseUtils.queryNumEntries(mDataBaseHelper.getWritableDatabase(),DataBaseHelper.TABLE_NAME) > 0) return;
mDataBaseHelper.addMytableRow("Test1","Test1");
mDataBaseHelper.addMytableRow("Test2","Test2");
mDataBaseHelper.addMytableRow("Test3","Test3");
mDataBaseHelper.addMytableRow("Test4","Test4");
}
}
Note AddSomeTestData adds some data for testing/demonstration.
Result
When first run :-
After LongClicking Test 2
i.e. the long clicked item has been removed (from the list and the database) and the list refreshed.
Try to replace
db.delete(TABLE_NAME, COL2 , new String[]{task});
By
db.delete(TABLE_NAME, COL2 + " = ?" , new String[]{task});
This is my code and my CarsDbHelper, CarsContract for my CarsEntry.
It has no problems, but I am unsure from here on how to use information I have put in a Sqlite database.
String current_car_name = "TOYOTA YARIS";
String current_car_colour = "GREY";
int current_car_age = 3;
CarsDbHelper mDbHelper = new CarsDbHelper(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(CarsEntry.COLUMN_NAME,current_car_name);
values.put(CarsEntry.COLUMN_COLOUR,current_car_colour);
values.put(CarsEntry.COLUMN_AGE,current_car_age);
long newRowId = db.insert(CarsEntry.TABLE_NAME, null, values);
}
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projection = {
CarsEntry.COLUMN_NAME,
CarsEntry.COLUMN_COLOUR,
CarsEntry.COLUMN_AGE
};
public void button (View view) {
String selection = CarsEntry.COLUMN_NAME + " = ?";
String[] selectionArgs = {current_car_name};
TextView car_name = (TextView) findViewById(R.id.name);
car_name.setText();
TextView car_colour = (TextView) findViewById(R.id.colour);
car_colour.setText();
TextView car_age = (TextView) findViewById(R.id.age);
car_age.setText();
}
I am still a bit confused on how to input this data into my TextViews.
You type in them... Did you mean get values out of them?
First off, the purpose of the "helper" object is to help you not expose a SQLiteDatabase object.
Make a Car class and an addCar(Car car) method in your helper.
public long addCar(Car car) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(CarsEntry.COLUMN_NAME,car.getName());
values.put(CarsEntry.COLUMN_COLOUR,car.getColour());
values.put(CarsEntry.COLUMN_AGE,car.getAge());
long newRowId = db.insert(CarsEntry.TABLE_NAME, null, values);
return newRowId;
}
Then, in the Activity, you need to set the helper in onCreate, not outside
CarsDbHelper mDbHelper;
TextView mCarName, mCarColour, mCarAge;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCarName = (TextView) findViewById(R.id.name);
mCarColour = (TextView) findViewById(R.id.colour);
mCarAge = (TextView) findViewById(R.id.age);
mDbHelper = new CarsDbHelper(this); // Moved in here
}
public void button (View view) {
String name = mCarName.getText().toString();
String colour = mCarColour.getText().toString();
String age = mCarAge.getText().toString();
Car c = new Car(name, colour, Integer.parseInt(age));
mDbHelper.addCar(c); // This is the helper method
}
If you want to get data out of the database, you need a ListView and an Adapter (such as CursorAdapter)
If you would like to not mess with the details of raw SQLite, see the Room Persistence library
First, you should create db instance in onCreate Function.
Cursor cursor = db.query(
TABLE_NAME, // The table to query
projection, // The columns to return
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
Copied from Android Dev Site.
You will get cursor, iterate through it as follows:
if(!cursor.moveToFirst())
//No Data
//cache columns indexes in integers
int idIndex = cursor.getColumnIndex("id");
...
while(cursor.moveToNext()){
String id = cursor.getString(id); //Same for boolean, Int, long, etc.
...
}
//Never forget to close cursor
cursor.close();
So I have an imageArray it finds the 17 fields. But will not populate them to an Array at the end. It says the image array is empty. My debugger shows that the log is populated with 17 fields from the database. But the array fails to include them #
imageArray.add(rn);
Java onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_myreceipts);
ReceiptsOperations ro = new ReceiptsOperations(this);
List<Receipt> receipts = ro.getReceipts();
for(Receipt rn : receipts){
String log = "RECEIPTID:" + rn.getReceiptID() + "RECEIPTURI:" + rn.getReceiptURI();
Log.d("Result: ", log);
imageArray.add(rn);
}
Receipt List initialised
public List<Receipt>getReceipts() {
// This code will retrieve all images from database.
List<Receipt> receiptList = new ArrayList<Receipt>();
String selectQuery = "SELECT* FROM receipts_table ORDER BY receipt_ID";
// Check all rows and add to list.
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery,null);
if(cursor.moveToFirst())
{
do
{
Receipt receipt = new Receipt();
receipt.setReceiptID(new String(cursor.getString(0)));
receipt.setReceiptURI(new String(cursor.getString(2)));
receiptList.add(receipt);
}
while(cursor.moveToNext());
}
db.close();
return receiptList;
}
I wanted to display a specific row in my table. I have two Activities the first activity is to input the ID passed to the 2nd Activity which is going to display the row in my table based on the ID that I inputed.
Hope you can help with my problem. I don't know what is wrong in my code.
//MainActivity:
public class MainActivity extends Activity {
EditText et_id;
public void doView(View v){
String id = et_id.getText().toString();
if(!id.isEmpty()){
Intent i = new Intent(this.getApplicationContext(), ActivityView.class);
i.putExtra("id", id);
startActivity(i);
} else {
Dialog d = new Dialog(this);
d.setTitle("Message");
TextView tv = new TextView(this);
tv.setText("ID must be provided");
d.setContentView(tv);
d.show();
}
}
}
//ActivityView.class
public class ActivityView extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_view);
TextView tv_id = (TextView) findViewById(R.id.tvId);
TextView tv_name = (TextView) findViewById(R.id.tvName);
TextView tv_course = (TextView) findViewById(R.id.tvCourse);
Bundle extra = getIntent().getExtras();
String id = extra.getString("id");
DBase db = new DBase(this);
db.open();
String[] rec = db.getRecord(Integer.parseInt(id));
db.close();
if(rec[0]!=null){
tv_name.setText(rec[0]);
tv_course.setText(rec[1]);
} else {
Dialog d = new Dialog(this);
d.setTitle("Message");
TextView tv = new TextView(this);
tv.setText("There is no record");
d.setContentView(tv);
d.show();
}
}
}
//DBase.java
public String[] getRecord(int rid) throws SQLException{
String selectQuery = "SELECT * FROM "+DB_TABLE+"WHERE"+K_RID+"="+rid;
Cursor c = null;
c = dBase.rawQuery(selectQuery, null);
String[] data = new String[2];
if(c.moveToFirst()){
int indexName = c.getColumnIndex(K_NAME);
int indexCourse = c.getColumnIndex(K_COURSE);
data[0] = c.getString(indexName);
data[1] = c.getString(indexCourse);
}
return data;
}
I suspect the reason your code won't work is because your query is wrong:
String selectQuery = "SELECT * FROM "+DB_TABLE+"WHERE"+K_RID+"="+rid;
You don't have any white space, so your table name, where column, and id are all getting smashed together. Make sure there is a space between each item:
String selectQuery = "SELECT * FROM " + DB_TABLE + " WHERE " + K_RID + " = " + rid;