Berkan
Berkan

Reputation: 59

Trying to use SqLiteDatabase

I have editText1, editText2 and EditText3. Users need to write personal informations this areas. When they put save button, editText1, editText2 and EditText3 must save. They should find what they write when ever they want. But when i try to save 3 of them (editText1, editText2 and EditText3), this is not happens. I can save just editText1. Or i can save 3 spaces areas just in editText1. For example, i wrote in editText1 "hello", in editText2 "listen", in editText3 " guys", i am saving this and when i open in saved area i can see 3 times "listen". Others dont save. Can you help me? What should i change?

MainActivity:

public class MainActivity extends AppCompatActivity {

    static ArrayList<Bitmap> newImage;


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.add_new, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override //Menüyü seçersek ne olacak onu belirler.
    public boolean onOptionsItemSelected(MenuItem item) {

        if (item.getItemId() == R.id.add_new) {

            Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
            intent.putExtra("info", "new"); //Bu satırda amaç eğer yeni bir resimmi yoksa eski resimmi görentülenmek isteniyor onu anlamak
            startActivity(intent);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView listView = (ListView) findViewById(R.id.listView);

        //Databaseden çektiğimiz dataları kaydedeceğimiz bir arraylist oluşturalım ve listview ile bağlayalım
        final ArrayList<String> newName = new ArrayList<String>();
        final ArrayList<String> newName2 = new ArrayList<String>();
        final ArrayList<String> newName3 = new ArrayList<String>();
        newImage = new ArrayList<Bitmap>();

        ArrayAdapter arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,newName);
        listView.setAdapter(arrayAdapter);

        //uygulama ilk açıldığında database'de kayıtlı bir şey varmı bakmasını istiyoruz aşağıdaki aşamalarda

        try {

            Main2Activity.database = this.openOrCreateDatabase("Yeni", MODE_PRIVATE, null);
            Main2Activity.database.execSQL("CREATE TABLE IF NOT EXISTS yeni (name VARCHAR, name2 VARCHAR, name3 VARCHAR, image BLOB)");

            Cursor cursor = Main2Activity.database.rawQuery("SELECT * FROM yeni", null); //Data çekmek için cursoru kullanıyoruz

            int nameIx = cursor.getColumnIndex("name");
            int name2Ix = cursor.getColumnIndex("name2");
            int name3Ix = cursor.getColumnIndex("name3");
            int imageIx = cursor.getColumnIndex("image");

            cursor.moveToFirst();

            while (cursor != null) {

                newName.add(cursor.getString(nameIx)); //Kullanıcının girdği ismi newName'in içine ekle
                newName2.add(cursor.getString(name2Ix));
                newName3.add(cursor.getString(name3Ix));

                byte[] byteArray = cursor.getBlob((imageIx));
                Bitmap image = BitmapFactory.decodeByteArray(byteArray,0,byteArray.length);
                newImage.add(image); //newImage'in içine ekle diyoruz

                cursor.moveToNext();

                arrayAdapter.notifyDataSetChanged();//Eğer bir datayı değiştirdiysek hemen güncelleyen bir konut
            }

        } catch (Exception e) {

        }

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                Intent intent = new Intent (getApplicationContext(), Main2Activity.class);
                intent.putExtra("info", "old");
                intent.putExtra("name", newName.get(position));
                intent.putExtra("name2", newName2.get(position));
                intent.putExtra("name3", newName3.get(position));
                intent.putExtra("position", position);

                startActivity(intent);

            }
        });
    }

}

Main2Activity

public class Main2Activity extends AppCompatActivity {

    ImageView imageView; //imageView'i heryerde tanımladık
    EditText editText;
    EditText editText2;
    EditText editText3;

    static SQLiteDatabase database; //Buraya yazdığımız database'e MainActivity'den de ulaşabileceğiz çünkü statik yazdık
    Bitmap selectedImage; //seçilen resmi kaydetmek için burada bunu tanımladık

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        imageView = (ImageView) findViewById(R.id.imageView); //layouttaki imageView'i tanımladık
        editText = (EditText) findViewById(R.id.editText);
        editText2 = (EditText) findViewById(R.id.editText2);
        editText3 = (EditText) findViewById(R.id.editText3);
        Button button = (Button) findViewById(R.id.button); //Buton tanımladık

        Intent intent = getIntent();

        String info = intent.getStringExtra("info"); //MainActivity'deki 28. satırla bağlantılı

        if (info.equalsIgnoreCase("new")) {

            Bitmap background = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.dede); //Kullanıcı resim seçerkenki aşama

            imageView.setImageBitmap(background);

            button.setVisibility(View.VISIBLE); //Eğer yeni eklenecekse görünür yap
            editText.setText(""); //Bu satır eğer daha önceden bir şey yazdıysak onun orada kalmamasını bize boş yazma yeri açmasını sağlıyor
            editText2.setText("");
            editText3.setText("");

        } else {

            String name = intent.getStringExtra("name");
            editText.setText(name);
            String name2 = intent.getStringExtra("name2");
            editText2.setText(name2);
            String name3 = intent.getStringExtra("name3");
            editText3.setText(name3);
            int position = intent.getIntExtra("position", 0);

            imageView.setImageBitmap(MainActivity.newImage.get(position));

            button.setVisibility(View.INVISIBLE); //Eskiyse gösterme

        }
    }
    //Resim koyma yerine tıklandığında olacaklar
    public void select (View view) {

        if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, 2);
        } else {
            Intent intent = new Intent (Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); //Kullanıcının medyasına eriş diyoruz
            startActivityForResult(intent,1);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if (requestCode == 2) {

            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Intent intent = new Intent (Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); //Kullanıcının medyasına eriş diyoruz
                startActivityForResult(intent,1);
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    //Yukarıdaki medyaya erişime izin verildiyse resim seçme yeri
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == 1 && resultCode == RESULT_OK && data!= null) {

            Uri image = data.getData();
            //try ve catch ın içine aldık bu olayı çünkü bi sorun çıkarsa burda uygulama hata vermesin.
            try {
                selectedImage = MediaStore.Images.Media.getBitmap(this.getContentResolver(), image);
                imageView.setImageBitmap(selectedImage); //imageView'e burda ulaşmak için koyduk
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    // Kaydetme butonuna tıklandığında olacaklar
    public void save (View view) {

        String newName = editText.getText().toString(); //Kullanıcının kardettiği isme bu şekilde ulaştık
        String newName2 = editText2.getText().toString();
        String newName3 = editText3.getText().toString();
        //image'ler bytearray şeklinde kaydedilir!!!!!!!!!!

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); //selectedImage'i compress etmeliyiz kaydetme aşamalarından biri
        selectedImage.compress(Bitmap.CompressFormat.PNG,50,outputStream); //bu şekilde ziplemiş olduk resmi
        byte[] byteArray = outputStream.toByteArray(); //Bu outpuSteam'i al array'e çevir dedik! ve resmimiz kaydedilebilir oldu

        try { //Tüm bu alttaki aşamalarda kullanıcının girdiği isim ve resmi database'imize işlemiş olduk!
            database = this.openOrCreateDatabase("Yeni", MODE_PRIVATE, null);
            database.execSQL("CREATE TABLE IF NOT EXISTS yeni (name VARCHAR, image BLOB)");

            String sqlString = "INSERT INTO yeni (name, image) VALUES (?, ?, ?, ?)";
            SQLiteStatement statement =database.compileStatement(sqlString);
            statement.bindString(1,newName);
            statement.bindString(3,newName2);
            statement.bindString(4,newName3);
            statement.bindBlob(2,byteArray);
            statement.execute();

        } catch (Exception e) {
            e.printStackTrace();
        }

        Intent intent = new Intent(getApplicationContext(), MainActivity.class); //kaydet'e bastığında anasayfaya yönlendirilsin
        startActivity(intent);





    }
}

Upvotes: 0

Views: 95

Answers (2)

MikeT
MikeT

Reputation: 56953

Issues 1 is that you try defining the same table but with 4 columns (in the onCreate method of MainActivity) and then with 2 columns (in the save method of Main2Activity), the 2nd will not create the table as it will already have been created, so it appears that the 4 column version will exist (if it doesn't and the table gets create then you would end up with issues whenever you return to MainActivity as two columns (name2 and name3) will not exist and result in a column not found when int name2Ix = cursor.getColumnIndex("name2"); is attempted.

A 2nd issue is that you are trying to insert 2 values but with 4 values given as arguments i.e. INSERT INTO yeni (name,image) .... 2 values VALUES(?, ?, ? ,?) 4 arguments.

A 3rd issue is that you are not detecting the success or failure of the insert, rather just assuming that it will work (when it doesn't). Using try/catch around SQLiteDatabase methods is also not a good idea as very often they will handle many situations and only crash when something dire is wrong (and you'd want a crash).

A 4th issue is that you can click the Save button (assuming you have used android:onClick="save" in the layout) that selectedImage may well be null.

A 5th issue is that when done with Main2Activity you try to start MainActivity, which will start another activity, rather you you return to it by finishing Main2Activity. Currently, this works to your advantage in that the ListView the lists the newly inserted row. However, you end up with lots of activities and hitting the back button will progressively return through the stack of activities and will be very confusing.

Fixing the 5th issue, i.e. finishing Main2Activty introduces a 6th issue and that is that the List isn't refreshed, it remains as it was before a new row is inserted.

Fixing the 6th issue requires a number of code changes but ultimately you refresh the List by overriding the onResume method by rebuilding the source of the List (clearing the ArrayList and then adding all the elements to it).

Temporary Fix for 4th issue.

Ignoring the 1st issue, which won't cause an issue as it very much appears that the table having 4 columns is created first (certainly was in testing). And also initially ignoring the 2nd and 3rd issue. But using :-

    if (info.equalsIgnoreCase("new")) { // UNCHANGED

        Bitmap background = BitmapFactory.decodeResource(
                getApplicationContext().getResources(), 
                android.R.drawable.ic_dialog_alert //<<<< Use a stock Android image for testing
        ); //Kullanıcı resim seçerkenki aşama
        selectedImage = background; //<<<< ADDED to overcome null pointer exception
        imageView.setImageBitmap(background); //<<<< UNCHANGED
        //........ rest of the code

in Main2Activity's onCreate method and inputtin Test, Test and Test in the 3 EditText's and then Clicking on the button results in a return to MainActivity but with nothing displayed. However, the log shows the anticipated E/SQLiteLog: (1) 4 values for 2 columns:-

06-03 22:13:09.895 2647-2647/yeni.yeni E/SQLiteLog: (1) 4 values for 2 columns
06-03 22:13:09.895 2647-2647/yeni.yeni W/System.err: android.database.sqlite.SQLiteException: 4 values for 2 columns (code 1): , while compiling: INSERT INTO yeni (name, image) VALUES (?, ?, ?, ?)
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
        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.compileStatement(SQLiteDatabase.java:994)
        at yeni.yeni.Main2Activity.save(Main2Activity.java:145)
        at java.lang.reflect.Method.invoke(Native Method)
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:384)
        at android.view.View.performClick(View.java:5198)
        at android.view.View$PerformClick.run(View.java:21147)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Main Fix for the 2nd and 3rd issues

A suggested fix for the main issue, the insert not inserting a record, could be the following, which utilises the SQLiteDatabase insert convenience method :-

public void save (View view) {

    String newName = editText.getText().toString(); //Kullanıcının kardettiği isme bu şekilde ulaştık
    String newName2 = editText2.getText().toString();
    String newName3 = editText3.getText().toString();
    //image'ler bytearray şeklinde kaydedilir!!!!!!!!!!

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); //selectedImage'i compress etmeliyiz kaydetme aşamalarından biri
    selectedImage.compress(Bitmap.CompressFormat.PNG,50,outputStream); //bu şekilde ziplemiş olduk resmi
    byte[] byteArray = outputStream.toByteArray(); //Bu outpuSteam'i al array'e çevir dedik! ve resmimiz kaydedilebilir oldu

    ContentValues cv = new ContentValues();
    cv.put("name",newName);
    cv.put("name2",newName2);
    cv.put("name3",newName3);
    cv.put("image",byteArray);
    long new_row_id = database.insert("yeni",null,cv);
    //<<<< ADDED TO ISSUE TOAST WITH THE RESULT
    if (new_row_id > 0) {
        Toast.makeText(this,"Row Insereted.",Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this,"Row NOT Inserted",Toast.LENGTH_SHORT).show();
    }
    /*
    try { //Tüm bu alttaki aşamalarda kullanıcının girdiği isim ve resmi database'imize işlemiş olduk!
        Log.d("SAVE","Attempting OPEN Or CREATE DATABASE");
        database = this.openOrCreateDatabase("Yeni", MODE_PRIVATE, null);
        Log.d("SAVE","Attempting CREATE OF TABLE yeni");
        database.execSQL("CREATE TABLE IF NOT EXISTS yeni (name VARCHAR, image BLOB)");

        String sqlString = "INSERT INTO yeni (name, image) VALUES (?, ?, ?, ?)";
        SQLiteStatement statement =database.compileStatement(sqlString);
        statement.bindString(1,newName);
        statement.bindString(3,newName2);
        statement.bindString(4,newName3);
        statement.bindBlob(2,byteArray);
        Log.d("SAVE","Attempting EXECUTION of the SQL INSERT using :- " + statement.toString());
        statement.execute();

    } catch (Exception e) {
        e.printStackTrace();
    }
    */
    Intent intent = new Intent(getApplicationContext(), MainActivity.class); //kaydet'e bastığında anasayfaya yönlendirilsin
    startActivity(intent);

    //this.finish(); //<<<< Should not start a parent activity you should return to it by finishing the child activity
}

Fix for 6th issue (need before fixing the 5th issue)

This requires quite a few code changes but basically involves allowing the List to be refreshed, by the onResume method in the MainActivity

public class MainActivity extends AppCompatActivity {

    static ArrayList<Bitmap> newImage;
    ArrayList<String> nameList;
    ArrayList<String> name2List;
    ArrayList<String> name3List;
    ArrayAdapter<String> arrayadpater;
    ListView listView;

    Button addbutton; //<<<< Instead of menu for my convenience
    //<<<<<<<<<< Code Commented out for convenience of using button >>>>>>>>>
    /*
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.add_new, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override //Menüyü seçersek ne olacak onu belirler.
    public boolean onOptionsItemSelected(MenuItem item) {

        if (item.getItemId() == R.id.add_new) {

            Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
            intent.putExtra("info", "new"); //Bu satırda amaç eğer yeni bir resimmi yoksa eski resimmi görentülenmek isteniyor onu anlamak
            startActivity(intent);
        }

        return super.onOptionsItemSelected(item);
    }
    */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.listview); //<<<< CHANGED as declared as class variable

        //<<<<<<<<<< Code below for the conveince of using a button instead of Menu >>>>>>>>>>
        addbutton = (Button) findViewById(R.id.addnew);
        addbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
                intent.putExtra("info", "new"); //Bu satırda amaç eğer yeni bir resimmi yoksa eski resimmi görentülenmek isteniyor onu anlamak
                startActivity(intent);
            }
        });
        //<<<<<<<<<< End of code for Button handling >>>>>>>>>>

        setupListView();

        //<<<<<<<<<< NOTE commented out Code >>>>>>>>>>
        /*
        //Databaseden çektiğimiz dataları kaydedeceğimiz bir arraylist oluşturalım ve listview ile bağlayalım
        final ArrayList<String> newName = new ArrayList<String>();
        final ArrayList<String> newName2 = new ArrayList<String>();
        final ArrayList<String> newName3 = new ArrayList<String>();
        newImage = new ArrayList<Bitmap>();

        ArrayAdapter arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,newName);
        listView.setAdapter(arrayAdapter);

        //uygulama ilk açıldığında database'de kayıtlı bir şey varmı bakmasını istiyoruz aşağıdaki aşamalarda

        try {

            Main2Activity.database = this.openOrCreateDatabase("Yeni", MODE_PRIVATE, null);
            Main2Activity.database.execSQL("CREATE TABLE IF NOT EXISTS yeni (name VARCHAR, name2 VARCHAR, name3 VARCHAR, image BLOB)");

            Cursor cursor = Main2Activity.database.rawQuery("SELECT * FROM yeni", null); //Data çekmek için cursoru kullanıyoruz

            int nameIx = cursor.getColumnIndex("name");
            int name2Ix = cursor.getColumnIndex("name2");
            int name3Ix = cursor.getColumnIndex("name3");
            int imageIx = cursor.getColumnIndex("image");

            cursor.moveToFirst();

            while (cursor != null) {

                newName.add(cursor.getString(nameIx)); //Kullanıcının girdği ismi newName'in içine ekle
                newName2.add(cursor.getString(name2Ix));
                newName3.add(cursor.getString(name3Ix));

                byte[] byteArray = cursor.getBlob((imageIx));
                Bitmap image = BitmapFactory.decodeByteArray(byteArray,0,byteArray.length);
                newImage.add(image); //newImage'in içine ekle diyoruz

                cursor.moveToNext();

                arrayAdapter.notifyDataSetChanged();//Eğer bir datayı değiştirdiysek hemen güncelleyen bir konut
            }

        } catch (Exception e) {
        }
        */
    }
    //<<<< ADDED to handle return from child >>>>
    @Override
    public void onResume() {
        super.onResume();
        setupListView();
    }

    //<<<< ADDED to utilise a single refreshable ListView
    private void setupListView() {
        getListsFromDatabase();
        if (arrayadpater == null) {
            arrayadpater = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,nameList);
            listView.setAdapter(arrayadpater);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    Intent intent = new Intent (getApplicationContext(), Main2Activity.class);
                    intent.putExtra("info", "old");
                    intent.putExtra("name", nameList.get(position));
                    intent.putExtra("name2", name2List.get(position));
                    intent.putExtra("name3", name3List.get(position));
                    intent.putExtra("position", position);
                    startActivity(intent);
                }
            });
        } else {
            arrayadpater.notifyDataSetChanged();
        }
    }

    //<<<< Added to build/rebuild the Arraylist's used by the ListView
    private void getListsFromDatabase() {
        // Get the database (and set the databse for Main2Acticity)
        SQLiteDatabase db = openOrCreateDatabase(
                "Yeni",
                MODE_PRIVATE,
                null
        );
        db.execSQL("CREATE TABLE IF NOT EXISTS yeni (name VARCHAR, name2 VARCHAR, name3 VARCHAR, image BLOB)");
        Main2Activity.database = db;

        // Initialise or clear the array lists
        if (nameList == null) {
            nameList = new ArrayList<>();
        } else {
            nameList.clear();
        }
        if (name2List == null) {
            name2List = new ArrayList<>();
        } else {
            name2List.clear();
        }
        if (name3List == null) {
            name3List = new ArrayList<>();
        } else {
            name3List.clear();
        }
        if (newImage == null) {
            newImage = new ArrayList<>();
        } else {
            newImage.clear();
        }
        // get the
        Cursor cursor = db.query("yeni",
                null,
                null,
                null,
                null,
                null,
                null
        );
        while (cursor.moveToNext()) {
            nameList.add(cursor.getString(cursor.getColumnIndex("name")));
            name2List.add(cursor.getString(cursor.getColumnIndex("name2")));
            name3List.add(cursor.getString(cursor.getColumnIndex("name3")));
            byte[] b = cursor.getBlob(cursor.getColumnIndex("image"));
            Bitmap bmp = BitmapFactory.decodeByteArray(b,0,b.length);
            newImage.add(bmp);
        }
        cursor.close();
    }
}
  • Note for my convenience rather than a menu a button has been used.
    • To use the menu remove the code commented for button use and un-comment the code for using your menu.

Finally the Fix for the 5th issue

In Main2Activity remove the 2 lines :-

    Intent intent = new Intent(getApplicationContext(), MainActivity.class); //kaydet'e bastığında anasayfaya yönlendirilsin
    startActivity(intent);

and then add the line :-

    this.finish(); //<<<< ADD this to finish Main2Activity and return to MainActivity

Results

When first started :-

enter image description here

Click Add (equivalent to select Add from Menu) :-

enter image description here

Just before clicking Save (Hit Me) button :-

enter image description here

After clicking Save (Hit Me) button (i.e. return to MainActivity)

enter image description here

Clicking on item in the list (to update)

enter image description here

Upvotes: 1

Amirhossein
Amirhossein

Reputation: 323

Check your logcat! Maybe This statement has issue!

String sqlString = "INSERT INTO yeni (name, image) VALUES (?, ?, ?, ?)"

You selected two columns but you put 4 values to insert.

Upvotes: 0

Related Questions