I'm trying to implement a FragmentPagerAdapter with dynamically created Tabs based on a Cursor that retrieves distinct values from an SQLite DB column.
Then the ListFragment loads data based on a 2nd Cursor that selects data with a filter based on the Tab name.
Finally I add a Tab to include "All" data, rather than a subset.
All is working well, except for getting the right data into the first "All" sheet. The ListFragment onCreateLoader never gets to select "All" and somehow pulls data in both the first and second Tab, based on the second Tab's name.
My code (filtered for relevance; hopefully not too much)
MainActivity
public class MainActivity extends AppCompatActivity {
// arraylist of tabs in which tab details are stored
private ArrayList<String> tabNames;
// to hold tabs data when first fetch from sqlite db
private Cursor tabCursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.simsolec.flavorsaver.R.layout.activity_main);
getTabs();
// Create an adapter that knows which fragment should be shown on each page
FlavorFragmentPagerAdapter adapter = new FlavorFragmentPagerAdapter(
getSupportFragmentManager(), MainActivity.this, tabNames);
// Find the view pager that will allow the user to swipe between fragments
ViewPager mViewPager = findViewById(com.simsolec.flavorsaver.R.id.viewpager);
// Set the adapter onto the view pager
mViewPager.setAdapter(adapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = findViewById(com.simsolec.flavorsaver.R.id.sliding_tabs);
tabLayout.setupWithViewPager(mViewPager);
}
private void getTabs( ){
try{
String[] Projection = { FlavorEntry.COLUMN_FLAVOR_RANGE };
tabCursor = getContentResolver().query(
FlavorEntry.CONTENT_URI_DISTINCT,
Projection,
null,
null,
FlavorEntry.COLUMN_FLAVOR_RANGE );
tabNames = new ArrayList();
tabNames.add("All");
if (tabCursor != null && tabCursor.getCount() > 0) {
if(tabCursor.moveToFirst()) {
do{
String tabName;
tabName = tabCursor.getString(0);
tabNames.add(tabName);
}while (tabCursor.moveToNext());
}
tabCursor.close();
}
}catch (NullPointerException | SQLException e) {
}
finally {
tabCursor.close();
}
}
}
FragmentPagerAdapter
public class FlavorFragmentPagerAdapter extends FragmentPagerAdapter {
private Context context;
private ArrayList<String> mTabNames;
public FlavorFragmentPagerAdapter(FragmentManager fm, Context context, ArrayList<String> tabNames) {
super(fm);
this.context = context;
mTabNames = tabNames;
}
#Override
public int getCount() {
//return PAGE_COUNT;
return mTabNames.size();
}
#Override
public Fragment getItem(int position) {
// return FlavorListFragment.newInstance(position + 1);
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
String tabName = mTabNames.get(position);
return FlavorListFragment.newInstance(tabName);
}
#Override
public CharSequence getPageTitle(int position) {
//Generate title based on item position
//return tabTitles[position];
String tabName = mTabNames.get(position);
return tabName;
}
}
ListFragment
public class FlavorListFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
// The fragment argument representing the tab name & number for this fragment.
private static final String ARG_TAB_NAME ="tabName";
// Store the tabName for later use
private static String mTabName;
public static FlavorListFragment newInstance(String tabName) {
FlavorListFragment fragment = new FlavorListFragment();
mTabName = tabName;
Bundle args = new Bundle();
args.putString(ARG_TAB_NAME, tabName);
fragment.setArguments(args);
return fragment;
}
/** Identifier for the flavor data loader */
private static final int FLAVOR_LOADER = 0;
/** Adapter for the ListView */
FlavorCursorAdapter mCursorAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(com.simsolec.flavorsaver.R.layout.fragment_flavor_list,
container, false);
// Find the ListView which will be populated with the flavor data
ListView flavorListView = rootView.findViewById(com.simsolec.flavorsaver.R.id.flavor_list);
// Setup an Adapter to create a list item for each row of flavor data in the Cursor.
// There is no flavor data yet (until the loader finishes) so pass in null for the Cursor.
mCursorAdapter = new FlavorCursorAdapter(getActivity(), null);
flavorListView.setAdapter(mCursorAdapter);
// Kick off the loader
getLoaderManager().initLoader(FLAVOR_LOADER, null, this);
// Setup the item click listener
flavorListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
// Create new intent to go to {#link FlavorActivity}
Intent intent = new Intent(getContext(), FlavorActivity.class);
// Form the content URI that represents the specific flavor that was clicked on,
// by appending the "id" (passed as input to this method) onto the
// {#link FlavorEntry#CONTENT_URI}.
// For example, the URI would be "content://com.simsolec.flavorsaver/flavors/2"
// if the flavor with ID 2 was clicked on.
Uri currentFlavorUri = ContentUris.withAppendedId(FlavorEntry.CONTENT_URI, id);
// Set the URI on the data field of the intent
intent.setData(currentFlavorUri);
// Launch the {#link FlavorActivity} to display the data for the current flavor.
startActivity(intent);
}
});
return rootView;
}
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// Define a projection that specifies the columns from the table we care about.
String[] projection = {
FlavorEntry._ID,
FlavorEntry.COLUMN_FLAVOR_NAME,
FlavorEntry.COLUMN_DESCRIPTION_SHORT,
FlavorEntry.COLUMN_CUP_IMAGE,
FlavorEntry.COLUMN_RATING };
// This loader will execute the ContentProvider's query method on a background thread
String[] selectionArgs;
if (mTabName=="All") {
selectionArgs = new String[] {"*"};
} else {
selectionArgs = new String[] {mTabName};
}
String selection = FlavorEntry.COLUMN_FLAVOR_RANGE + " in (";
for (int s = 0; s < selectionArgs.length; s++) {
selection += "?, ";
}
selection = selection.substring(0, selection.length() - 2) + ")";
return new CursorLoader(getActivity(), // Parent activity context
FlavorEntry.CONTENT_URI, // Provider content URI to query
projection, // Columns to include in the resulting Cursor
selection, // No selection clause
selectionArgs, // No selection arguments
FlavorEntry.COLUMN_FLAVOR_NAME + " ASC"); // Default sort order
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Update {#link FlavorCursorAdapter} with this new cursor containing updated flavor data
mCursorAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// Callback called when the data needs to be deleted
mCursorAdapter.swapCursor(null);
}
}
Can someone point me in the right direction?
Thank you,
-Joost
Set the value of mTabName from Bundle not from newInstance() method because mTabName is define as static so remove static keyword from mTabName
public static FlavorListFragment newInstance(String tabName) {
FlavorListFragment fragment = new FlavorListFragment();
// mTabName = tabName;
Bundle args = new Bundle();
args.putString(ARG_TAB_NAME, tabName);
fragment.setArguments(args);
return fragment;
}
OnCreateView of FlavorListFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(com.simsolec.flavorsaver.R.layout.fragment_flavor_list,
container, false);
Bundle b= getArguments();
//mTabName=b.getString(mTabName);
mTabName=b.getString(ARG_TAB_NAME);
}
Related
Mainly the application I am buiding should be able to insert the title, description time and date the title is created. This is the database table I have created
for inserting title, content, date and time for an journal application.
While I was executing " the error as journal table column does not have a date " error occurred.
public class JournalDatabase extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "JOURNal_db";
private static final String DATABASE_TABLE = "Journal_table";
private static final String KEY_ID = "id";
private static final String KEY_TITLE = "title";
private static final String KEY_CONTENT = "content";
private static final String KEY_DATE = "date";
private static final String KEY_TIME= "time";
public JournalDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String create = " CREATE TABLE "+DATABASE_TABLE+"("+KEY_ID+"INTEGER PRIMARY KEY,"+
KEY_TITLE+"TEXT,"+
KEY_CONTENT+"TEXT,"+
KEY_DATE+"TEXT,"+
KEY_TIME+"TEXT" +")";
Log.d("dbHarry","Query being run is : "+ create);
db.execSQL(create);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
if (i >= i1)
return;
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
public void addJournal(Journal journal){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_TITLE,journal.getTitle());
contentValues.put(KEY_CONTENT,journal.getContent());
contentValues.put(KEY_DATE,journal.getDate());
contentValues.put(KEY_TIME,journal.getTime());
db.insert(DATABASE_TABLE,null,contentValues);
db.close();
}
public Journal getJournal(long id){
// select * from the databaseTable where id = 1
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(DATABASE_TABLE,new String[]{KEY_ID,KEY_TITLE,KEY_CONTENT,KEY_DATE,KEY_TIME},KEY_ID+"?",
new String[]{String.valueOf(id)},null,null,null);
if(null != cursor) {
cursor.moveToFirst();
}
return new Journal(cursor.getLong(0),cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4));
}
public List<Journal> getJournals(){
SQLiteDatabase db = this.getReadableDatabase();
List<Journal> allJournals = new ArrayList<>();
// SELECT * FROM DATABASE NAME
String query = " SELECT * FROM " + DATABASE_TABLE;
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToFirst()) {
do {
Journal journal = new Journal();
journal.setID(cursor.getLong(0));
journal.setTitle(cursor.getString(1));
journal.setContent(cursor.getString(2));
journal.setDate(cursor.getString(3));
journal.setTime(cursor.getString(4));
allJournals.add(journal);
} while (cursor.moveToNext());
}
return allJournals;
}
}
Blockquote
Blockquote
This is the screenshot of error
According to your log, there is no column named "date" in your table, check it please.
I get the following error when running my app using android studio.
Error
==============================================
java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
My database is SQLite.
My app allows a user to register and login.
Sports app.
From here they can add "Players" to their team.
I have two tables set up in my db one for users and one for players with the "user_id" field from users table being used as the foreign key to link both dbs.
Basically only the logged in users who add a certain player can see that players information and not all others that other users created.
Originally the app was saving the players to the correct table.
However the foreign key was not getting filled.
I then re wrote the code to correct this.
However this is when i encountered this new problem.
Any help or advice at all is much appreciated.
1) DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "MyDB1.db";
private static final String TABLE_USER = "User";
private static final String COLUMN_USER_NAME = "User_name";
private static final String COLUMN_USER_ID = "User_id";
private static final String COLUMN_USER_EMAIL = "User_email";
private static final String COLUMN_USER_PASSWORD = "User_password";
private static final String TABLE_PLAYERS = "Player";
private static final String COLUMN_PLAYER_NAME = "Player_name";
private static final String COLUMN_PLAYER_AGE = "Player_age";
private static final String COLUMN_PLAYER_WEIGHT = "Player_weight";
private static final String COLUMN_PLAYER_HEIGHT = "Player_height";
private static final String COLUMN_PLAYER_ID = "Player_id";
private static final String FOREIGN_PLAYER_ID = COLUMN_USER_ID;
// private static final Image COLUMN_PLAYER_IMAGE ;
// Table 1 : Login/Register
private String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USER + "(" + COLUMN_USER_NAME + " TEXT,"
+ COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_USER_EMAIL + " TEXT," + COLUMN_USER_PASSWORD + " TEXT" + ")";
// Table 2 : Adding players
private String CREATE_PLAYER_TABLE = "CREATE TABLE " + TABLE_PLAYERS + "(" + COLUMN_PLAYER_NAME + " TEXT,"
+ COLUMN_PLAYER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_PLAYER_AGE + " INTEGER," + COLUMN_PLAYER_WEIGHT + " INTEGER," + COLUMN_PLAYER_HEIGHT + " INTEGER, " + FOREIGN_PLAYER_ID + " INTEGER," + "FOREIGN KEY(" + FOREIGN_PLAYER_ID + ") REFERENCES " + TABLE_USER + "(User_id) " + ")";
// Drop tables
private String DROP_USER_TABLE = "DROP TABLE IF EXISTS " + TABLE_USER ;
private String DROP_PLAYER_TABLE = "DROP TABLE IF EXISTS " + TABLE_PLAYERS ;
public DatabaseHelper(Context context){
//String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
// Enable foreign key constraints
db.execSQL("PRAGMA foreign_keys=ON;");
}
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_USER_TABLE);
db.execSQL(CREATE_PLAYER_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(DROP_USER_TABLE);
db.execSQL(DROP_PLAYER_TABLE);
onCreate(db);
}
// Adding a user to Users table
public void addUser(User user){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_USER_NAME, user.getName());
values.put(COLUMN_USER_EMAIL, user.getEmail());
values.put(COLUMN_USER_PASSWORD, user.getPassword());
values.put(FOREIGN_PLAYER_ID, user.getForeignID());
db.insert(TABLE_USER, null, values);
db.close();
}
// Adding a player to players table
public void addPlayer(Player player) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
// Table 2 : Add players info
values.put(COLUMN_PLAYER_NAME, player.getPlayerName());
values.put(COLUMN_PLAYER_AGE, player.getPlayerAge());
values.put(COLUMN_PLAYER_HEIGHT, player.getPlayerHeight());
values.put(COLUMN_PLAYER_WEIGHT, player.getPlayerWeight());
values.put(FOREIGN_PLAYER_ID, player.getForeignKey());
db.insert(TABLE_PLAYERS, null, values);
db.close();
}
// Checking the users email
public boolean checkUser(String email){
String[] columns = {
COLUMN_USER_ID
};
SQLiteDatabase db = this.getWritableDatabase();
String selection = COLUMN_USER_EMAIL + " = ?";
String[] selectionArgs = { email };
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
cursor.close();
db.close();
if (cursorCount > 0){
return true;
}
return false;
}
//
public String getColumnUserName(String email){
String user = "";
String[] columns = {
COLUMN_USER_ID
};
SQLiteDatabase db = this.getWritableDatabase();
String selection = COLUMN_USER_EMAIL + " = ?";
String[] selectionArgs = { email };
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
if (cursor.moveToFirst()) // data?{
user = cursor.getString(cursor.getColumnIndex("EMAIL"));
cursor.close(); // that's important too, otherwise you're gonna leak cursors
db.close();
if (cursorCount > 0){
return user;
}
return user;
}
// Checking the users email and password
public boolean checkUser(String email, String password){
String[] columns = {
COLUMN_USER_ID
};
SQLiteDatabase db = this.getWritableDatabase();
String selection = COLUMN_USER_EMAIL + " = ?" + " AND " + COLUMN_USER_PASSWORD + " =?";
String[] selectionArgs = { email, password };
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
cursor.close();
db.close();
if (cursorCount > 0){
return true;
}
return false;
}
}
2) Players.java
public class Players extends AppCompatActivity {
private Button insert;
private static final int PICK_IMAGE=100;
private String nameFromIntent = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_players);
//Open add players section
insert = (Button) findViewById(R.id.addPlayer);
insert.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick (View v)
{
openaAddPlayersActivity();
}
});
nameFromIntent = getIntent().getStringExtra("EMAIL");
}
private void openaAddPlayersActivity() {
Intent intent = new Intent(this, addPlayers.class );
String nameFromIntent = getIntent().getStringExtra("EMAIL");
intent.putExtra(("EMAIL") ,nameFroenter code heremIntent);
startActivity(intent);
}
}
3)addPlayers.java
public class addPlayers extends AppCompatActivity implements View.OnClickListener{
private Button insert;
private static final int PICK_IMAGE=100;
private final AppCompatActivity activity = addPlayers.this;
private EditText editTextPlayerName;
private EditText editTextPlayerAge;
private EditText editTextPlayerWeight;
private EditText editTextPlayerHeight;
private TextInputEditText textInputEditTextEmail;
private Inputvalidation inputvalidation;
private DatabaseHelper databaseHelper;
private Player player;
private Button appCompatButtonRegister;
private User user;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_players);
// insert = (Button) findViewById(R.id.profilePicture);
// insert.setOnClickListener(new View.OnClickListener()
getSupportActionBar().hide();
initViews();
initListeners();
initObjects();
}
private void initViews() {
editTextPlayerName = (EditText) findViewById(R.id.playerName);
editTextPlayerAge = (EditText) findViewById(R.id.playerAge);
editTextPlayerHeight = (EditText) findViewById(R.id.playerHeight);
editTextPlayerWeight = (EditText) findViewById(R.id.playerWeight);
textInputEditTextEmail = (TextInputEditText) findViewById(R.id.enterEmail);
appCompatButtonRegister = (Button) findViewById(R.id.savePlayer);
}
private void initListeners() {
appCompatButtonRegister.setOnClickListener(this);
}
private void initObjects() {
inputvalidation = new Inputvalidation(activity);
databaseHelper = new DatabaseHelper(activity);
player = new Player ();
}
// Table 2 : Add players info
#Override
public void onClick(View v) {
// Intent intent = new Intent(Intent.ACTION_PICK, Uri.parse("content://media/internal/images/media"));
//startActivityForResult(intent, PICK_IMAGE);
switch (v.getId()){
case R.id.savePlayer:
postDataToSQLite();
break;
}
}
private void postDataToSQLite() {
if(!databaseHelper.checkUser(editTextPlayerName.getText().toString().trim()))
//textInputEditTextPassword.getText().toString().trim()))
{
Bundle email= getIntent().getExtras();
String a = databaseHelper.getColumnUserName(email.getString("EMAIL"));
player.setPlayerName(editTextPlayerName.getText().toString().trim());
player.setPlayerAge(Integer.parseInt(editTextPlayerAge.getText().toString().trim()));
player.setPlayerHeight(Integer.parseInt(editTextPlayerHeight.getText().toString().trim()));
player.setPlayerWeight(Integer.parseInt(editTextPlayerWeight.getText().toString().trim()));
player.setForeignKey(Integer.parseInt(a));
//Integer.parseInt(databaseHelper.getColumnUserName(ContactsContract.CommonDataKinds.Email.getString("EMAIL"))));
databaseHelper.addPlayer(player);
Snackbar.make(findViewById(R.id.addPlayer), R.string.success_player_message,Snackbar.LENGTH_LONG).show();
// emptyEditText();
Intent accountIntent = new Intent(activity, Players.class);
accountIntent.putExtra("EMAIL", textInputEditTextEmail.getText().toString().trim());
//emptyInputEditText();
startActivity(accountIntent);
}
//else {
// Snack Bar to show error message that record already exists
// Snackbar.make(findViewById(R.id.Register), getString(R.string.error_email_exists), Snackbar.LENGTH_LONG).show();
// }
}
/*protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK && requestCode==PICK_IMAGE){
Uri uri = data.getData();
String x = getPath(uri);
Toast.makeText(getApplicationContext(), x, Toast.LENGTH_LONG).show();
}
}
private String getPath(Uri uri) {
if(uri==null)return null;
String [] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(uri, projection, null, null, null);
if(cursor!=null){
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
return uri.getPath();
}
*/
}
4) Login.java
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private final AppCompatActivity activity = LoginActivity.this;
private NestedScrollView nestedScrollView;
private TextInputLayout textInputLayoutEmail;
private TextInputLayout textInputLayoutPassword;
private TextInputEditText textInputEditTextEmail;
private TextInputEditText textInputEditTextPassword;
private AppCompatButton appCompatButtonLogin;
private AppCompatTextView textViewLinkRegister;
private Inputvalidation inputvalidation;
private DatabaseHelper databaseHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
getSupportActionBar().hide();
initViews();
initListeners();
initObjects();
}
private void initViews() {
textInputLayoutEmail = findViewById(R.id.textInputLayoutEmail);
textInputLayoutPassword = findViewById(R.id.textInputLayoutPassword);
textInputEditTextEmail = findViewById(R.id.enterEmail);
textInputEditTextPassword = findViewById(R.id.enterPassword);
appCompatButtonLogin = findViewById(R.id.Login);
textViewLinkRegister = findViewById(R.id.textViewLinkRegister);
}
private void initListeners() {
appCompatButtonLogin.setOnClickListener(this);
textViewLinkRegister.setOnClickListener(this);
}
private void initObjects() {
databaseHelper = new DatabaseHelper(activity);
inputvalidation = new Inputvalidation(activity);
}
#Override
public void onClick(View v){
switch (v.getId()){
case R.id.Login:
verifyFromSQLite();
break;
case R.id.textViewLinkRegister:
Intent intentRegister = new Intent(getApplicationContext(), Register.class);
startActivity(intentRegister);
break;
}
}
private void verifyFromSQLite() {
if (!inputvalidation.isInputEditTextFilled(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))){
return;
}
if (!inputvalidation.isInputEditTextEmail(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))){
return;
}
if (!inputvalidation.isInputEditTextFilled(textInputEditTextPassword, textInputLayoutPassword, getString(R.string.error_message_password))){
return;
}
if(databaseHelper.checkUser(textInputEditTextEmail.getText().toString().trim(), textInputEditTextPassword.getText().toString().trim()))
{
Intent accountIntent = new Intent(activity, LoggedIn.class);
accountIntent.putExtra("EMAIL", textInputEditTextEmail.getText().toString().trim());
emptyInputEditText();
startActivity(accountIntent);
}else {
Snackbar.make(findViewById(R.id.Login), R.string.error_valid_email_password,Snackbar.LENGTH_LONG).show();
//nestedScrollView, getString(R.string.error_valid_email_password), Snackbar.LENGTH_LONG).show();
}
}
private void emptyInputEditText() {
textInputEditTextEmail.setText(null);
textInputEditTextPassword.setText(null);
}
}
I believe that your issue may be that your foreign key is acting as it should and that a conflict is being raised because the the player passed to the addPlayer method doesn't appear to have the user set (unless dome within the construction of the Player object).
That is user may well be null or some other value that is not a value that is stored in the User_id column in the User table.
That is you only appear to pass the email from activity to activity and then only use the checkUser (only returns a boolean) and the getColumnsUserName (only returns a String that appears to be the email that was found according to the email used as the search argument).
The User_id however MUST be an integer value for it to be a valid User_id column in the User table.
That is as the User_id column being defined using INTEGER PRIMARY KEY (with or without AUTOINCREMENT) is an alias of the hidden rowid column and MUST be an INTEGER value (SQLite Autoincrement P.S. additionally note the summary in regards to using AUTOINCREMENT).
Determining the issue
I would suggest placing a breakpoint on the line db.insert(TABLE_PLAYERS, null, values); in the DatabaseHelper and running in Debug, when the breakpoint is reached to then inspect the value of foreignId in the player object.
You may wish to read Debug your app
However, if the cause is as suspected I also believe that the Stack-trace should also indicate the CONFLICT.
Personally rather than passing the email from activity to activity I'd suggest passing the User_id value as this will be UNIQUE and is also the most efficient means to locate the respective row as per :-
The data for rowid tables is stored as a B-Tree structure containing
one entry for each table row, using the rowid value as the key. This
means that retrieving or sorting records by rowid is fast. Searching
for a record with a specific rowid, or for all records with rowids
within a specified range is around twice as fast as a similar search
made by specifying any other PRIMARY KEY or indexed value.
ROWIDs and the INTEGER PRIMARY KEY
Additonal
There are two issues that will each result in the index -1 issue.
The -1 issue itself is because the Cursor getColumnIndex method returns -1 if the column passed to the method does not exist in the Cursor (note a Cursor only has the columns that have been specified).
The first issue is with the line :-
user = cursor.getString(cursor.getColumnIndex("EMAIL"));
There is no such column in the user table so this would always fail. Changing this to :-
user = cursor.getString(cursor.getColumnIndex(COLUMN_USER_EMAIL));
will specify a column that is in the table.
The second issue is that although COLUMN_USER_EMAIL is a valid column in the table, that column is not included in the Cursor.
To include that column in the Cursor then change :-
String[] columns = {
COLUMN_USER_ID
};
to :-
String[] columns = {
COLUMN_USER_ID,
COLUMN_USER_EMAIL
};
or to :-
String[] columns = {"*" }; //<<<<<<<<<< * means ALL columns
or instead change :-
Cursor cursor = db.query(TABLE_USER,
columns,
selection,
selectionArgs,
null,
null,
null);
int cursorCount = cursor.getCount();
to
Cursor cursor = db.query(TABLE_USER,
null, //<<<<<<<<<< null equates to * and thus ALL columns
selection,
selectionArgs,
null,
null,
null);
So the app is now working correctly after a rebuild.
Pretty strange behavior but i wont complain.
Thanks for you help.
Eamon
i would like to get my Marker info to textView, i am able to do that but it shows always only last one from JSON, any good ideas how to fix that?
My Plan was pretty easy, when user Clicks on Marker then it will make RealitveLayout "VISIBLE", it works so far, but my issue is that i gather my Markers from JSON, and then ads them to the MAP,
There is OnClick listener what makes the trick
(Sets layout VISIBLE and sends info to TextView what is on that Layout.)
IT works, but it only takes the last object from JSON array.
public GoogleMap.OnInfoWindowClickListener getInfoWindowClickListener()
{
return new GoogleMap.OnInfoWindowClickListener()
{
#Override
public void onInfoWindowClick(Marker marker)
{
RelativeLayout rl1 = (RelativeLayout) findViewById(R.id.popup);
rl1.setVisibility(View.VISIBLE); // Set the View to VISIBLE
//Title to TextView (also "Score" info)
TextView pealkiriTextView = (TextView) findViewById(R.id.pealkiriTextView);
pealkiriTextView.setText(title + " (" + punkte + " punkti)");
//Description to TextView
TextView pKirlejdusTextView = (TextView) findViewById(R.id.pKirlejdusTextView);
pKirlejdusTextView.setText(kirjeldus);
}
};}
Thats how i get info from JSON (from URL)
private void getMarkers() {
StringRequest strReq = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("Response: ", response.toString());
try {
JSONObject jObj = new JSONObject(response);
String getObject = jObj.getString("punktid");
JSONArray jsonArray = new JSONArray(getObject);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
nr = jsonObject.getString(NR);
title = jsonObject.getString(TITLE);
kirjeldus = jsonObject.getString(KIRJELDUS);
vahend = jsonObject.getString(VAHEND);
punkte = jsonObject.getString(PUNKTE);
latLng = new LatLng(Double.parseDouble(jsonObject.getString(LAT)), Double.parseDouble(jsonObject.getString(LNG)));
// Anname addMarkerile väärtused
addMarker(latLng, title, kirjeldus,punkte, nr, vahend);
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error: ", error.getMessage());
Toast.makeText(kaart.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
});
And ADDing Markers to Map :
private void addMarker(LatLng latlng,final String nr, final String title, final String kirjeldus,final String punkte, final String vahend) {
markerOptions.position(latlng);
//markerOptions.title(title +"(" + punkte +"p)");
markerOptions.title(punkte +" Punkti");
//markerOptions.snippet(kirjeldus);
if (vahend.equalsIgnoreCase("auto")) { markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.auto));
} else { markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.jala)); }
gMap.addMarker(markerOptions);} //addMarker
To get the Google map Marker information here i created one custom info window
public class CustomWindowInfo implements GoogleMap.InfoWindowAdapter {
// Use default InfoWindow frame
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
// Defines the contents of the InfoWindow
#Override
public View getInfoContents(Marker arg0) {
// Getting view from the layout file info_window_layout
View v = getLayoutInflater().inflate(R.layout.custom_map_window, null);
TextView texttitle = (TextView) v.findViewById(R.id.texttitle);
TextView text_description = (TextView) v.findViewById(R.id.text_description);
texttitle.setText(arg0.getTitle());
// Setting the location to the textview
text_description.setText(arg0.getSnippet());
return v;
}}
Setting a custom info window for the google map
googleMap.setInfoWindowAdapter(new CustomWindowInfo());
googleMap.setOnInfoWindowClickListener(listenerInfowindow_click);
and to get the inforamtion of marker on click
public GoogleMap.OnInfoWindowClickListener listenerInfowindow_click = new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(final Marker marker) {
AlertDialog.Builder builder = new AlertDialog.Builder(MapActivity.this);
builder.setTitle("");
builder.setMessage(dialog_mas);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (InterNet.isConnectedToInternet()) {
Geocoder selected_place_geocoder = new Geocoder(MapActivity.this);
address = selected_place_geocoder.getFromLocationName(marker.getSnippet(), 1);
} else {
Toast.makeText(MapActivity.this,InterNet.interNetMsg, Toast.LENGTH_LONG).show();
}
dialog.cancel();
}
});
builder.setNegativeButton("N0", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
};
First off, yes, I have done research on this question. And yes, I have found an answer here. But the whole process still isn't working for me. All I need to do is grab text off of a webpage like Google, and create a string from the text it grabs. Here is my code with the aforementioned tutorials code in it:
public class Searching_Animation_Screen extends ActionBarActivity {
TextView loading_txt;
Animation blink;
public String pre_split;
public String[] split_string;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_searchinganimationscreen);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
int width = getWindowManager().getDefaultDisplay().getWidth();
loading_txt = (TextView)findViewById(R.id.loading);
text =(TextView)findViewById(R.id.textView);
Typeface pacifico_typeface = Typeface.createFromAsset(getAssets(), "fonts/pacifico.ttf");
loading_txt.setTypeface(pacifico_typeface);
loading_txt.setTextSize(width / 20);
blink = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.blink);
loading_txt.setAnimation(blink);
Begin();
}
private void Begin() {
Intent SEARCH_INTENT = getIntent();
pre_split=SEARCH_INTENT.getStringExtra("Search_Text");
split_string = pre_split.split(" ");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_searchinganimationscreen, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
String google_url ="https://www.google.com/#safe=active&q=";
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
text.setText(Html.fromHtml(result));
//throw into summarizer
}
public void readWebpage(View view) {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] {"www.google.com"});
}
}
}
Android studio is saying that readWebpage is never used, along with the actual DownloadWebPageTask class. Any ideas? I would like this class to run immediately on Create. Thanks!
#Ethan, sure, I hope this is what you want, just adding the readWebpage method in the onCreate method, but I modified it and removed the View object since it is not being used,
public class Searching_Animation_Screen extends ActionBarActivity {
TextView loading_txt;
Animation blink;
public String pre_split;
public String[] split_string;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_searchinganimationscreen);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
int width = getWindowManager().getDefaultDisplay().getWidth();
loading_txt = (TextView)findViewById(R.id.loading);
text =(TextView)findViewById(R.id.textView);
Typeface pacifico_typeface = Typeface.createFromAsset(getAssets(), "fonts/pacifico.ttf");
loading_txt.setTypeface(pacifico_typeface);
loading_txt.setTextSize(width / 20);
blink = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.blink);
loading_txt.setAnimation(blink);
Begin();
//* call webpage here,
//* note, i removed passing the view object since it is not being used
readWebpage()
}
//* (modify) by remvoving it from the code below
//* and removing the view object since it is not being used
public void readWebpage() {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] {"http://www.google.com"});
}
private void Begin() {
Intent SEARCH_INTENT = getIntent();
pre_split=SEARCH_INTENT.getStringExtra("Search_Text");
split_string = pre_split.split(" ");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_searchinganimationscreen, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
String google_url ="https://www.google.com/#safe=active&q=";
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
text.setText(Html.fromHtml(result));
//throw into summarizer
}
}
}
i have another problem using a cordova plugin (3.2) in android. I create a custom plugin for cordova because the default one does not match with my expectation. I expect to create a custom alert dialog with item and checkboxes in it. Here is the source code:
Javascript:
cordova.exec(
function(listitem) {
console.log("select: " +interestResultName[listitem]);
selectedResult.push(interestResultName[listitem]);
},
function(error) {
alert("Error Occured");
}, "AlertList", "showlistitem", interestResultName );
Java:
public class AlertList extends CordovaPlugin {
public AlertList() {
}
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if(action.equals("showlistitem")) {
this.loadList(args, callbackContext);
}
return true;
}
public void loadList(final JSONArray thelist, final CallbackContext callbackContext) {
final CordovaInterface cordova = this.cordova;
Runnable runnable = new Runnable() {
public void run() {
List<String> list = new ArrayList<String>();
for( int x = 0; x < thelist.length(); x++) {
try {
list.add( thelist.getString(x) );
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
CharSequence[] items = list.toArray(new CharSequence[list.size()]);
boolean[] checkbox = new boolean[list.size()];
AlertDialog.Builder builder = new AlertDialog.Builder(cordova.getActivity());
builder.setTitle(" ");
builder.setMultiChoiceItems(items, checkbox, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int item, boolean isChecked) {
// TODO Auto-generated method stub
PluginResult result = new PluginResult(PluginResult.Status.OK, item);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}
});
AlertDialog alert = builder.create();
alert.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
alert.show();
}
};
this.cordova.getActivity().runOnUiThread(runnable);
}
}
The problem comes in the onClick method. Since its a checkbox i'm still keep callback open until user pressed back button. However i cannot implement the backbutton function as usual because my java class extends CordovaPlugin instead of Activity. Does anyone can help me with this ?
My expectation is: after user select item he wants and click back button. Then the callback context will send the selected item to my javascript function (the code: selectedResult.push(interestResultName[listitem]); ) .
Thank you,
Hary