SQLite DB table not created in Android while DB created - java

I am working towards creating an Android app. I am beginner in Android and Java application development while I have good experience of web development.
I am trying to create a DB and then creating my first table in SQLite. It is creating DB but not DB table.
I have created Contaract class.
package com.haafiz.project;
import android.provider.BaseColumns;
public final class ProjectContaract {
public ProjectContaract(){}
public static abstract class Site implements BaseColumns{
public static final String TABLE_NAME = "site";
public static final String COLUMN_NAME_SITE_NAME = "site_name";
public static final String COLUMN_NAME_LOGIN = "login_name";
public static final String COLUMN_NAME_HOST = "host";
public static final String COLUMN_NAME_PASSWORD = "password";
}
}
And then DB helper class.
package com.haafiz.project;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + ProjectContaract.Site.TABLE_NAME + " (" +
projectContaract.Site._ID + " INTEGER PRIMARY KEY," +
projectContaract.Site.COLUMN_NAME_SITE_NAME + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_LOGIN + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_HOST + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_PASSWORD + TEXT_TYPE + " )";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + ProjectContaract.Site.TABLE_NAME;
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Project";
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
#Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
And here my main activity using that DB Helper as below:
package com.haafiz.project;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
projectDBHelper dbHelper = new projectDBHelper(getApplicationContext());
// Gets the data repository in read mode
SQLiteDatabase db = dbHelper.getWritableDatabase();
// Projection that specifies which columns from the database
String[] projection = {
projectContaract.Site._ID,
projectContaract.Site.COLUMN_NAME_SITE_NAME,
projectContaract.Site.COLUMN_NAME_LOGIN,
projectContaract.Site.COLUMN_NAME_HOST,
projectContaract.Site.COLUMN_NAME_PASSWORD
};
// How you want the results sorted in the resulting Cursor
String sortOrder =
projectContaract.Site.COLUMN_NAME_SITE_NAME + " DESC";
Cursor c = db.query(
projectContaract.Site.TABLE_NAME, // The table to query
projection, // The columns to return
null, // The columns for the WHERE clause
null, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
setContentView(R.layout.activity_main);
}
#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_main, 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);
}
}
DB is being created but table is not, I check that with adb shell attach with emulator. What am I doing wrong? The table is not being created.
And an important thing is that I am not getting errors related to this in log.
But in logcat with "no filter" in drop down where it was "show only selected application" previously and with "sql" in filter search box, it shows following messages in log cat:
08-04 00:41:35.494 403-474/android.process.media V/MediaScanner﹕ pruneDeadThumbnailFiles... android.database.sqlite.SQLiteCursor#41302da8
08-04 00:41:35.494 403-474/android.process.media V/MediaScanner﹕ /pruneDeadThumbnailFiles... android.database.sqlite.SQLiteCursor#41302da8
08-04 00:54:02.685 623-632/com.haafiz.project E/SQLiteDatabase﹕ close() was never explicitly called on database '/data/data/com.haafiz.project/databases/project'
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1943)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:770)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
at com.haafiz.project.MainActivity.onCreate(MainActivity.java:20)
at android.app.Activity.performCreate(Activity.java:4466)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
08-04 00:54:02.766 623-632/com.haafiz.project E/System﹕ java.lang.IllegalStateException: Don't have database lock!
at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2090)
at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2182)
at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2178)
at android.util.LruCache.trimToSize(LruCache.java:197)
at android.util.LruCache.evictAll(LruCache.java:285)
at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2143)
at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1126)
at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:1914)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
at java.lang.Thread.run(Thread.java:856)
Other than first two lines, other lines in output of log cat, all other lines are highlighted in red color.

Seems like the database didn't get closed correctly. Sometimes this can happen during development when you are often reinstalling builds of the app.
Uninstall the app and reinstall it. Alternatively open Settings > Apps > [your app] and tap the Clear Data button. Either of these will remove the existing database file so the next attempt to open it will create a new one.

SQLLite operates in many modes, one of which is that everything is stored in memory and not flushed to disk unless certain conditions are met (like high mem usage or db being closed). You are not closing the db which is why you are not able to see the tables in the sqlite file.
For your example to work, store dbHelper as a class property, assign new object to it when activity initializes, and then close it before the activity is closed/destroyed. That should solve your issue.

You're missing a semicolon at the end of your create table SQL statement. Also, your primary key should be autoincrement.
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + ProjectContaract.Site.TABLE_NAME + " (" +
projectContaract.Site._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
projectContaract.Site.COLUMN_NAME_SITE_NAME + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_LOGIN + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_HOST + TEXT_TYPE + COMMA_SEP +
projectContaract.Site.COLUMN_NAME_PASSWORD + TEXT_TYPE + " );";

Related

SQLite database won't use WHERE properly?

The purpose of this app is to get workouts from a database based on what the user selects, and put them into a textview in a fragmented class. The user can select their experience and if they want to use weights. The database stores all the workouts associated with the experience and weights. For example, in my database I may have a workout that has ( "beginner","no weights", "inclined pushups"). At the end of the app, the database should researched for values that the user selected. For example, it should only find database entries that have beginner if that's what the user choice. I want the database to only return the workout. I am using Android Studio for this, and created the database (as well as populated it), but I keep getting the same error. The first method below is in another class that should get the workout by experience and weight preference in the database.
public ArrayList<String> getWorkoutByBeginnerAndNoWeights(){
Cursor cursor = database.query(MySQLiteHelper.TABLE_EXERCISES, workoutColumns, MySQLiteHelper.COLUMN_EXPERIENCE + "=" + "beginner" + "AND" + "" + MySQLiteHelper.COLUMN_EQUIPMENT + "=" + "no weights", null, null, null, null);
while(!cursor.isLast()){
int i=0;
String workouts =cursor.getString(i++);
workoutArray.add(workouts);
}
//return string array
return workoutArray;
}
----------
Class for making the database
public class MySQLiteHelper extends SQLiteOpenHelper {
public static final String TABLE_EXERCISES = "exercises";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_EXPERIENCE = "experience";
public static final String COLUMN_EQUIPMENT = "equipment";
public static final String COLUMN_WORKOUT = "workout";
public static final String DATABASE_NAME = "exercises.db";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table "
+ TABLE_EXERCISES + "(" + COLUMN_ID
+ " integer primary key autoincrement, "+ COLUMN_EXPERIENCE + " text not null, " + COLUMN_EQUIPMENT
+ " text not null, "+ COLUMN_WORKOUT
+ " text not null);";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(MySQLiteHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_EXERCISES);
onCreate(db);
}
}
-------
Code in fragment to display it as a text using textView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inf = inflater.inflate(R.layout.fragment_test, container, false);
TextView tv = (TextView) inf.findViewById(R.id.testText);
tv.setText(MainActivity.dataSource.getWorkoutByBeginnerAndNoWeights().toString());
// Inflate the layout for this fragment
return inf;
}
----------
error I am getting
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.hfad.workoutmaker, PID: 20245
android.database.sqlite.SQLiteException: no such column: beginner (code 1): , while compiling: SELECT _id, workout FROM exercises WHERE experience=beginner
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1318)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1165)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1036)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1204)
at com.hfad.workoutmaker.WorkoutsDataSource.getWorkoutByBeginnerAndNoWeights(WorkoutsDataSource.java:74)
at com.hfad.workoutmaker.TestFragment.onCreateView(TestFragment.java:41)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
You should always use 'beginner' not beginner as your value.
So a simple SQL statement should look like this:
SELECT * FROM `Table` WHERE `ID`='1'

My app keeps crashing when I go to another activity

I am trying to make an app named 'moviesinfo', in which I have a login page, with sign up and forgot password option. When I try to log in, the app crashes. I also don't know if the data entered on the sign-up page is being stored in the database or not.
This is my mainactivity.java
package com.example.moviesinfo;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
SQLiteDatabase db;
SQLiteOpenHelper openHelper;
private EditText user;
private EditText password;
private Button btn;
private Button btn2;
private Button forgot;
Cursor cursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
forgot=findViewById(R.id.forgot);
btn2=(Button) findViewById(R.id.signup);
user= (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
btn = (Button) findViewById(R.id.login);
openHelper= new DatabaseHelper(this);
db=openHelper.getReadableDatabase();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String username1= user.getText().toString();
String password1= password.getText().toString();
cursor = db.rawQuery("SELECT * FROM " +DatabaseHelper.TABLENAME + " WHERE " + DatabaseHelper.COL2 + "=? AND " + DatabaseHelper.COL3+"=?", new String[]{username1,password1});
if (cursor!=null){
if (cursor.getCount()>0){
cursor.moveToNext();
Intent intent = new Intent(MainActivity.this,listmenu.class);
startActivity(intent);
//Toast.makeText(getApplicationContext(),"Login Successful", Toast.LENGTH_SHORT).show();//
}else{
Toast.makeText(getApplicationContext(),"Error" , Toast.LENGTH_SHORT).show();
}
}
}
});
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sign_up();
}
});
forgot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
forgot();
}
});
}
private void sign_up()
{
Intent intent= new Intent(MainActivity.this, signup.class);
startActivity(intent);
}
private void forgot()
{
Intent intent= new Intent(MainActivity.this, forgot.class);
startActivity(intent);
}
}
This is the signup.java class
package com.example.moviesinfo;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.lang.String;
import java.util.ArrayList;
public class signup extends AppCompatActivity {
SQLiteOpenHelper openHelper;
DatabaseHelper db;
SQLiteDatabase db1;
public String uname = "";
public String pwd = "";
public ArrayList<String> cpwd = new ArrayList<String>();
EditText e1, e2, e3;
Button b1,b2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
openHelper= new DatabaseHelper(this);
e1 = (EditText) findViewById(R.id.username);
e2 = (EditText) findViewById(R.id.password);
e3 = (EditText) findViewById(R.id.cpwd);
b1 = (Button) findViewById(R.id.save);
b2 = (Button) findViewById(R.id.login2);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1=openHelper.getWritableDatabase();
String username =e1.getText().toString();
String password =e2.getText().toString();
String confirm_password =e3.getText().toString();
insert_data(username,password,confirm_password);
}
});
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(signup.this,MainActivity.class);
startActivity(intent);
}
});
}
public void insert_data(String username, String password, String confirm_password)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.COL2, username);
contentValues.put(DatabaseHelper.COL3, password);
contentValues.put(DatabaseHelper.COL4, confirm_password);
long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
}
}
This is the DatabseHelper.java class
package com.example.moviesinfo;
import com.example.moviesinfo.signup;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME="userdetails.db";
public static final String TABLENAME="user details";
public static final String COL1="id";
public static final String COL2="username";
public static final String COL3="password";
public static final String COL4="confirmpassword";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null,1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + "TABLENAME(ID INTEGER PRIMARY KEY AUTOINCREMENT,USERNAME TEXT,PASSWORD TEXT,CONFIRMPASSWORD TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " +TABLENAME);
onCreate(db);
}
}
I expect that when I click the login button it should jump to the next activity with checking the login details from the database.
Issue 1
The first issue you will encounter is that the table name user details has a space. user will be extracted as the identifier but then the SQL parser is not expecting details, it is not a keyword or clause and thus a syntax error as per the following which would be found in the log :-
5-19 14:09:14.335 26779-26779/s.e.so56180693anotheractivity E/AndroidRuntime: FATAL EXCEPTION: main
Process: s.e.so56180693anotheractivity, PID: 26779
java.lang.RuntimeException: Unable to start activity ComponentInfo{s.e.so56180693anotheractivity/s.e.so56180693anotheractivity.MainActivity}: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:514)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1769)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1698)
at s.e.so56180693anotheractivity.DatabaseHelper.onCreate(DatabaseHelper.java:33)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:393)
at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
at s.e.so56180693anotheractivity.MainActivity.onCreate(MainActivity.java:35)
at android.app.Activity.performCreate(Activity.java:7136)
see Debug your app
An identifier can have normally unacceptable characters, such as a space, start with a number, if it is enclosed in specific characters as per :-
If you want to use a keyword as a name, you need to quote it. There are four ways of quoting keywords in SQLite:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not
standard SQL. This quoting mechanism is used by MS Access and SQL
Server and is included in SQLite for compatibility.
keyword A keyword enclosed in grave accents (ASCII code 96) is an identifier.
This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.
e.g. you could have :-
public static final String TABLENAME="user details"; //<<<<<<<<<< cannot have spaces in a name unless enclosed
//!!!!NOTE!!!! ONLY 1 of the below would be allowed
public static final String TABLENAME="`user details`"; //<<<<<<<<<< e.g (with space)
public static final String TABLENAME= "[user details]";
public static final String TABLENAME = "\"user details\"";
public static final String TABLENAME = "'user details'";
public static final String TABLENAME="user_details"; //<<<<<<<<<< changed to this for testing.
Read the comments
Fix for Issue 1
public static final String TABLENAME="user details";
was changed to :-
public static final String TABLENAME="user_details";
The App was uninstalled and rerun.
Issue 2
The next issue is that the SQL to create the table will not create a table named according to the value that the constant TABLENAME (user_details after applying the Fix 1) has. The table is named TABLENAME as the word TABLENAME is in quotes.
It results in the exception :-
2019-05-19 13:56:15.118 26443-26443/s.e.so56180693anotheractivity E/SQLiteLog: (1) no such table: user_details
Fix for Issue 2
The following is how it would be suggested that the CREATE TABLE sql is setup:-
//Uses the identifiers (names) as per the variables
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLENAME + "(" +
COL1 + " INTEGER PRIMARY KEY," + // NO NEED FOR INEFFICIENT AUTOINCREMENT
COL2 + " TEXT UNIQUE," + //ADDED UNIQUE so that user names are not duplicated
COL3 + " TEXT, " +
COL4 + " TEXT" +
")"
);
That is constants are used for the names.
IMPORTANT as this is a change to the database schema and that the database exists you MUST delete the database so that the DatabaseHelper onCreate method will run.
The keyword UNIQUE has been added, otherwise the same user could be added multiple times
Question
I also don't know if the data entered on the sign-up page is being
stored in the database or not.
To enable you to know or not and as you should now be aware of looking in the log then amending the insert_data method as follows will enable you to see if the data is being stored.
public long insert_data(String username, String password, String confirm_password) // Signature changed to return long (id)
{
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.COL2, username);
contentValues.put(DatabaseHelper.COL3, password);
contentValues.put(DatabaseHelper.COL4, confirm_password);
long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
//TODO REMOVE LOGGING BEFORE PUBLISHING THE APP
if (id > 0) {
Log.d("INSERTUSERDETAILSROW","The row was successfully inserted into the " + DatabaseHelper.TABLENAME + " table.");
} else {
Log.d("INSERTUSERDETAILSROW","Row not inserted!!!!!!!!!!");
}
return id; // Can be useful to have access to the id that was generated. Note method signature change
}
Example output :-
in the log :-
D/INSERTUSERDETAILSROW: The row was successfully inserted into the user_details table.
Issue 4
If the password and confirm_password values do not match, the row is still added i.e. the confirm_password values serves no purpose.
Fix for Issue 4
A check is added to only add data if the password and confirm_password values match. If they do not then a Toast is issued.
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1=openHelper.getWritableDatabase();
String username =e1.getText().toString();
String password =e2.getText().toString();
String confirm_password =e3.getText().toString();
if (password.equals(confirm_password)) {
insert_data(username, password, confirm_password);
} else {
Toast.makeText(v.getContext(),"Password and Confirm Password do not match. Data not added.",Toast.LENGTH_LONG).show();
}
}
});
Issue 5
Although it won't appear to be a problem your should not start the activity when you want to return from an activity as that will destroy the initial activity and start another. The correct way is to finish the activity and it will then return to the actual activity from which it is was started from.
Fix for Issue 5
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Intent intent = new Intent(signup.this,MainActivity.class);
//startActivity(intent);
finish(); //<<<<<<<<<< Proper way to return
}
});
Done
That's it. The App should now be relatively functional as far as logging in and signing up is concerned.

I want to save user profile in local sqlite database and the user information

I've done firebase authentication for login and sign up and now i want
to save user profile in local sqlite database. I've fetched the user
information from firebase and storing them in a string variable and
passing these variables to the Adduser function to save this data in
the local database.But data is not getting stored and showing "Error
with saving user" ,that is rowid is "-1" always. i'm new to android.
please help me to solve this issue. thanks in advance
java file
package com.example.mansi.busezon;
import android.app.Application;
import android.content.ContentValues;
mport android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.example.mansi.busezon.data.dbContract;
import com.example.mansi.busezon.data.dbHelper;
import com.google.firebase.FirebaseApp;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
i
public class SELL_BUY extends AppCompatActivity {
// private dbHelper mDbHelper;
String name;
String email ;
String address ;
String phoneno ;
String password ;
//String userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file
setContentView(R.layout.activity_sell__buy);
check();
TextView BUY= (TextView) findViewById(R.id.buy);
BUY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//create intent to open the activity
Intent BUYintent= new Intent(SELL_BUY.this,HomeActivity.class);
//start the new activity
startActivity(BUYintent);
}
});
TextView SELL= (TextView) findViewById(R.id.sell);
SELL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//create intent to open the activity
Intent SELLintent= new Intent(SELL_BUY.this,SellHomepage.class);
//start the new activity
startActivity(SELLintent);
}
});
}
public void sendMessage(View view)
{
Intent intent = new Intent(SELL_BUY.this, profile_page.class);
startActivity(intent);
}
private void check()
{
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
//database reference pointing to demo node
// DatabaseReference demoRef = rootRef.child("CI8hvEW0sfZ0oU1GziTpGYPJv2z2");
// String value = "User22";
// //push creates a unique id in database
// demoRef.push().setValue(value);
rootRef.addListenerForSingleValueEvent(new ValueEventListener()
{
String userId=getIntent().getStringExtra("Id");
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren())
{
if(ds.getKey().equals(userId))
{
//name1="aakritijohar";
name = ds.child("name").getValue(String.class);
email = ds.child("email").getValue(String.class);
address = ds.child("addres").getValue(String.class);
phoneno = ds.child("phoneno").getValue(String.class);
TextView textView = (TextView) findViewById(R.id.test);
textView.setText(phoneno);
password = ds.child("password").getValue(String.class);
Toast.makeText(SELL_BUY.this, email + " " + ds.getKey(), Toast.LENGTH_SHORT).show();
insertUser(name,email,address,phoneno,password);
}
}
Bundle extras=getIntent().getExtras();
if(extras!=null) {
String name = extras.getString("name");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
private void insertUser(String nameString,String EMAILString,String addressString,String numbertString,String pass) {
// Create database helper
dbHelper mDbHelper = new dbHelper(this);
// Gets the database in write mode
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(dbContract.userEntry.COLUMN_USER_NAME, nameString);
values.put(dbContract.userEntry.COLUMN_EMAIL, EMAILString);
values.put(dbContract.userEntry.COLUMN_number, numbertString);
values.put(dbContract.userEntry.COLUMN_address, addressString);
values.put(dbContract.userEntry.COLUMN_password, pass);
// Insert a new row for user in the database, returning the ID of that new row.
long newRowId = db.insert(dbContract.userEntry.TABLE_NAME, null, values);
// Show a toast message depending on whether or not the insertion was successful
if (newRowId == -1) {
// If the row ID is -1, then there was an error with insertion.
Toast.makeText(this, "Error with saving user", Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the insertion was successful and we can display a toast with the row ID.
Toast.makeText(this, "user saved " + newRowId, Toast.LENGTH_SHORT).show();
}
}
}
database helper class
package com.example.mansi.busezon.data;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Database helper for Pets app. Manages database creation and version management.
*/
public class dbHelper extends SQLiteOpenHelper {
public static final String LOG_TAG = dbHelper.class.getSimpleName();
/** Name of the database file */
private static final String DATABASE_NAME = "user.db";
/**
* Database version. If you change the database schema, you must increment the database version.
*/
private static final int DATABASE_VERSION = 1;
/**
* Constructs a new instance of {#link dbHelper}.
*
* #param context of the app
*/
public dbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is created for the first time.
*/
#Override
public void onCreate(SQLiteDatabase db) {
// Create a String that contains the SQL statement to create the pets table
String SQL_CREATE_USER_TABLE = "CREATE TABLE " + dbContract.userEntry.TABLE_NAME + " ("
+ dbContract.userEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ dbContract.userEntry.COLUMN_USER_NAME + " TEXT NOT NULL, "
+ dbContract.userEntry.COLUMN_address + " VARCHAR, "
+ dbContract.userEntry.COLUMN_number + " VARCHAR NOT NULL, "
+ dbContract.userEntry.COLUMN_EMAIL + " VARCHAR NOT NULL, "
+ dbContract.userEntry.COLUMN_password + " VARCHAR NOT NULL );";
// Execute the SQL statement
db.execSQL(SQL_CREATE_USER_TABLE);
}
/**
* This is called when the database needs to be upgraded.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// The database is still at version 1, so there's nothing to do be done here.
}
}
There doesn't appear to be anything wrong with the code as it is.
As such I suspect that your issue may be that you have changed the table structure since running the App.
e.g. by adding a new column and then changing the code accordingly
However, that you have then not taken into consideration that the onCreate method only gets automatically invoked when the database is created.
That is the 'onCreate' method does not run every time the App is started.
I'd suggest that deleting the App's data or uninstalling the App and then rerunning the App will resolve the issue.
If that doesn't resolve the issue then please check the log as that should contain a stack-trace for when the insert comes across the issue even though the App doesn't itself crash (you could use the insertOrThrow method instead of insert which would then result in an exception/crash).
If you then still have issues, please update the question to include the stack-trace.

SQLite Android RunTimeError

I am trying to follow this tutorial (Part 3) about getting SQLite Database to work with Android application. I've made some changes to the content but the code should be the same. The android application crashes after it opens without displaying anything and this is the output from LogCat:
11-25 11:42:43.281: E/AndroidRuntime(1098): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.munroproject/com.example.munroproject.MainActivity}: android.database.sqlite.SQLiteException: near "drop": syntax error (code 1): , while compiling: CREATE TABLE munro (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, area TEXT, height TEXT, grid TEXT, drop TEXT, feature TEXT, country TEXT, geographurl TEXT, latitude TEXT, longitude TEXT)
and this is the contents of the database helper:
package com.example.munroproject;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "munro_directory";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
public void onCreate(SQLiteDatabase db){
String sql = "CREATE TABLE munro (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, " +
"area TEXT, " +
"height TEXT, " +
"grid TEXT, " +
"drop TEXT, " +
"feature TEXT, " +
"country TEXT, " +
"geographurl TEXT, " +
"latitude TEXT, " +
"longitude TEXT)";
db.execSQL(sql);
ContentValues values = new ContentValues();
String inputvalue = "Ben Chonzie,Loch Tay to Perth,931,NN773308,645,cairn/shelter,S,NN7732430857,56.453851,-3.992057");
String[] msplit = inputvalue.split(",");
int j=0;
values.put("name",msplit[j++]);
values.put("area",msplit[j++]);
values.put("height",msplit[j++]);
values.put("grid",msplit[j++]);
values.put("drop",msplit[j++]);
values.put("feature",msplit[j++]);
values.put("country",msplit[j++]);
values.put("geograph",msplit[j++]);
values.put("latitute",msplit[j++]);
values.put("longitude",msplit[j++]);
db.insert("munro", "name", values);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL("DROP TABLE IF EXISTS munro");
onCreate(db);
}
}
And the mainActivity file looks like this:
package com.example.munroproject;
import android.os.Bundle;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.View;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class MainActivity extends Activity {
protected EditText searchText;
protected SQLiteDatabase db;
protected Cursor cursor;
protected ListAdapter adapter;
protected ListView munroList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = (new DatabaseHelper(this)).getWritableDatabase();
searchText = (EditText) findViewById (R.id.searchText);
munroList = (ListView) findViewById (R.id.list);
}
#SuppressWarnings("deprecation")
public void search(View view) {
// || is the concatenation operation in SQLite
cursor = db.rawQuery("SELECT _id, name, height, region FROM munro WHERE name || ' ' || height LIKE ?",
new String[]{"%" + searchText.getText().toString() + "%"});
adapter = new SimpleCursorAdapter(this,R.layout.munro_list_item,cursor,new String[] {"name", "height", "region"},new int[] {R.id.name, R.id.height, R.id.region});
munroList.setAdapter(adapter);
}
Any suggestions ?
"drop" is a reserved keyword in SQLite used to drop (or delete) tables. If you really want to use it, you can, by enclosing it in double quotes. See example below
CREATE TABLE "[tablename]" ("drop" text)
In sqlite INTEGER PRIMARY KEY is Autoincrement by default no need to specify INTEGER PRIMARY KEY AUTOINCREMENT In addition sql has inbuilt command drop so change the column/attribute name

Eclipse inserting data into SQLite Database, no such table

I'm trying to insert data into the database but it tells me there's no such table. I also have another sqlite database inside the application, i'm not sure if that affects this one, but I don't think so. It uses the same database name, but a different table name. If you think it does affect it, tell me and I'll post up the code for that too.
The logcat gives me these messages:
(1) no such table: notes
Error inserting title=Bleh desc=bleh
android.database.sqlite.SQLiteException: no such table: notes (code 1): , while compiling: INSERT INTO notes(title,desc) VALUES (?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1467)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
at com.example.stepsaway.NoteActivity.addEntry(NoteActivity.java:102)
at com.example.stepsaway.NoteActivity.onClick(NoteActivity.java:75)
at android.view.View.performClick(View.java:4240)
at android.view.View$PerformClick.run(View.java:17721)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The Activity java is:
public class NoteActivity extends Activity implements OnClickListener {
Button buttonLeaveNote;
private EditText mTitle;
private EditText mDesc;
protected NoteDBHelper noteDB = new NoteDBHelper(NoteActivity.this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note);
buttonLeaveNote = (Button) findViewById(R.id.buttonLeaveNote);
buttonLeaveNote.setOnClickListener(this);
mTitle = (EditText)findViewById(R.id.etitle);
mDesc = (EditText)findViewById(R.id.edesc);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.note, menu);
return true;
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.buttonLeaveNote:
String title = mTitle.getText().toString();
String desc = mDesc.getText().toString();
boolean invalid = false;
if(title.equals(""))
{
invalid = true;
Toast.makeText(getApplicationContext(), "Please enter a title", Toast.LENGTH_SHORT).show();
}
else
if(desc.equals(""))
{
invalid = true;
Toast.makeText(getApplicationContext(), "Please enter description", Toast.LENGTH_SHORT).show();
}
else
if(invalid == false)
{
addEntry(title, desc);
Intent i_note = new Intent(NoteActivity.this, JustWanderingActivity.class);
startActivity(i_note);
//finish();
}
break;
}
}
public void onDestroy()
{
super.onDestroy();
noteDB.close();
}
private void addEntry(String title, String desc)
{
SQLiteDatabase notedb = noteDB.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("title", title);
values.put("desc", desc);
//values.put("lati", lati);
//values.put("lng", lng);
try
{
long newRowId;
newRowId = notedb.insert(NoteDBHelper.DATABASE_TABLE_NAME, null, values);
Toast.makeText(getApplicationContext(), "Note successfully added", Toast.LENGTH_SHORT).show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
And the Database java is:
public class NoteDBHelper extends SQLiteOpenHelper
{
private SQLiteDatabase notedb;
public static final String NOTE_ID = "_nid";
public static final String NOTE_TITLE = "title";
public static final String NOTE_DESC = "desc";
public static final String NOTE_LAT = "lati";
public static final String NOTE_LONG = "lng";
NoteDBHelper noteDB = null;
private static final String DATABASE_NAME = "stepsaway.db";
private static final int DATABASE_VERSION = 2;
public static final String DATABASE_TABLE_NAME = "notes";
private static final String DATABASE_TABLE_CREATE =
"CREATE TABLE " + DATABASE_TABLE_NAME + "(" +
"_nid INTEGER PRIMARY KEY AUTOINCREMENT," +
"title TEXT NOT NULL, desc LONGTEXT NOT NULL);";
public NoteDBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
System.out.println("In constructor");
}
#Override
public void onCreate(SQLiteDatabase notedb) {
try{
notedb.execSQL(DATABASE_TABLE_CREATE);
}catch(Exception e){
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase notedb, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
public Cursor rawQuery(String string, String[] strings) {
// TODO Auto-generated method stub
return null;
}
public void open() {
getWritableDatabase();
}
public Cursor getDetails(String text) throws SQLException
{
Cursor mCursor =
notedb.query(true, DATABASE_TABLE_NAME,
new String[]{NOTE_ID, NOTE_TITLE, NOTE_DESC},
NOTE_TITLE + "=" + text,
null, null, null, null, null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
}
Any help would be appreciated, thank you.
Edit: Looks like the problem is creating a second table within the same database name. It won't let me create a second one. The first time creating the DB works fine, but it gives the SQLite Exception with no such table when trying to create another table. Is there some code I need to alter or add to create a second table? Because all i did was create another sqlite database java with the same DATABASE_NAME, but a different DATABASE_TABLE_NAME.
My best guess is when you create nodeDB object, the activity is still not available. Therefore you will failed creating the table.
You can try moving how you initialise the noteDB into inside onCreate():
protected NoteDBHelper noteDB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note);
noteDB = new NoteDBHelper(NoteActivity.this);
buttonLeaveNote = (Button) findViewById(R.id.buttonLeaveNote);
buttonLeaveNote.setOnClickListener(this);
mTitle = (EditText)findViewById(R.id.etitle);
mDesc = (EditText)findViewById(R.id.edesc);
}
Your onUpgrade() is empty and database schema version is 2. My guess is that your initial version of the database didn't have the notes table and when it was later added, the empty upgrade code couldn't add it. But SQLiteOpenHelper is satisfied as it is now running version 2 of the database.
To fix it once, clean your app data. E.g. in settings app, go to manage apps -> downloaded -> select your app and click on the "Clear application data" button. Or just uninstall and reinstall the app. This approach is good enough during development.
To fix it for released versions, implement onUpgrade() so that is updates the database schema and does any necessary data migration. If you're not concerned about data loss, you can just call DROP TABLE on the old tables and then call onCreate() to recreate the tables.
To your follow-up question regarding multiple tables: Just use the same helper class to manage the database. One helper per database file. Create all tables in onCreate() and do any required migrations in onUpgrade().
Regarding to First issue : as I explained in my comment >
If you have created the DB before and adding a table afterwards this can cause the problem. Tables are created for the first time DB created. So uninstall or clean the data in the app from device and run it again.
For the Second Issue :
If you want to Create a table, do the same that you are already doing for the table you have.
#Override
public void onCreate(SQLiteDatabase notedb) {
try{
notedb.execSQL(DATABASE_TABLE_CREATE);
notedb.execSQL(DATABASE_TABLE_CREATE_STRING_2);
}catch(Exception e){
e.printStackTrace();
}
}

Categories

Resources