2

I am trying to figure out where I went wrong either coding or logical flaw, I created a Recipe App that takes a couple of strings and an image, all data get saved into database and on the main screen I get a list of recipes from database.

Main Screen

Main Screen

Add / Edit Screen

Add / Edit Screen

Creating or Adding new Data is working as expected, all data get saved. The problem is everything can be updated except for the Image once it has been saved any second attempt doesn't seem to affect the image, the image remains the same.

The core principle is to set data to the views (When user start the activity onCreate or resume the activity onResume) and get data from the views (When user leaves onPause and onSaveInstanceState just incase an update was made)

Code

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_edit);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                enableEdit();
                fab.hide();
            }
        });
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        recipeDAOImp = new RecipeDAOImp(this);
        recipeDAOImp.open();
        findViews();

        rowId = (savedInstanceState == null) ? null :
                (Long) savedInstanceState.getSerializable(RecipeDAOImp.KEY_ID);
        if (rowId == null) {
            Bundle extras = getIntent().getExtras();
            rowId = extras != null ? extras.getLong(RecipeDAOImp.KEY_ID)
                    : null;
        }
        populateData();
        disableEdit();
    }

    private void findViews() {
       // Finds Views and Set onClick to imageButton
    }


    private void disableEdit() {
        // Disable Views
    }

    private void enableEdit() {
        // Enables Views
    }

    private void populateData() {
        // If rowId is available then user is trying to Edit Recipe
        if (rowId != null) {
            setTitle("Edit Recipe");
            Recipe recipe = new Recipe(rowId);
            Cursor cursor = recipeDAOImp.getRecipe(recipe);
            startManagingCursor(cursor);
            title.setText(cursor.getString(
                    cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_TITLE)));
            ingredients.setText(cursor.getString(
                    cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_INGREDIENTS)));

            steps.setText(cursor.getString(
                    cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_STEPS)));

            category.setText(cursor.getString(
                    cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_CATEGORY)));

            BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), DbBitmapUtility.getImage(cursor.getBlob(
                    cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_IMAGE))));
            image.setBackground(bitmapDrawable);
        // Else user is Adding a new Recipe
        } else {
            fab.hide();
            setTitle("Add Recipe");
            enableEdit();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveState();
        outState.putSerializable(RecipeDAOImp.KEY_ID, rowId);
    }

    @Override
    protected void onPause() {
        super.onPause();
        saveState();
    }

    @Override
    protected void onResume() {
        super.onResume();
        populateData();
    }

    private void saveState() {
        // Get the values from the views
        String titleString = title.getText().toString();
        String ingredientString = ingredients.getText().toString();
        String stepsString = steps.getText().toString();
        String categoryString = category.getText().toString();
        // Get the image from imageButton
        Drawable drawable = image.getBackground();
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        byte[] imageData = DbBitmapUtility.getBytes(bitmap);
        // Just to clarify image is never null as the backround is a camre image
        if (titleString.equals(null) || "".equals(titleString) || ingredientString.equals(null) || "".equals(ingredientString) || stepsString.equals(null) || "".equals(stepsString) || categoryString.equals(null) || "".equals(categoryString) || imageData.equals(null) || "".equals(imageData)) {
            Toast.makeText(this, "No Data Saved", Toast.LENGTH_SHORT).show();
        } else {
            Recipe recipe = new Recipe(titleString, ingredientString, stepsString, categoryString, imageData);
            // If rowId is not Available then user is Creating a new Recipe
            if (rowId == null) {
                long id = recipeDAOImp.createRecipe(recipe);
                if (id > 0) {
                    rowId = id;
                }
            } else {
                recipe.setId(rowId);
                recipeDAOImp.updateRecipe(recipe);
            }
        }
    }

    @Override
    public void onClick(View view) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap imageBitmap = (Bitmap) extras.get("data");
            // Set the imageButton
            BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), imageBitmap);
            image.setBackground(bitmapDrawable);
        }
    }
}

DAO

@Override
public boolean updateRecipe(Recipe recipe) {
    ContentValues contentValues = new ContentValues();
    contentValues.put(KEY_TITLE, recipe.getTitle());
    contentValues.put(KEY_INGREDIENTS, recipe.getIngredients());
    contentValues.put(KEY_STEPS, recipe.getSteps());
    contentValues.put(KEY_CATEGORY, recipe.getCategory());
    contentValues.put(KEY_IMAGE, recipe.getImage());
    return sqLiteDatabase.update(DATABASE_TABLE, contentValues, KEY_ID + "=" + recipe.getId(), null) > 0;
}

What could be the problem that I can update string data but I can't really update the image once its saved?

alkathirikhalid
  • 887
  • 12
  • 18

2 Answers2

2

After much research and testing, the problem was simply the image button can not be reset.

image.setBackground(bitmapDrawable);

This method above seems not to work for an update, my quick fix was simply to leave the code as it is and simply add a detection onActivityResult to determine if its actually an update then, add the byte data to database directly, rather than updating the image button and then recreate() the Activity, expensive procedure but not costly for a simple app.

if (rowId != null) {
                ...
                recipe.setImage(DbBitmapUtility.getBytes(imageBitmap));
                recipeDAOImp.updateRecipe(recipe);
                recreate();
            }

All Working as expected.

alkathirikhalid
  • 887
  • 12
  • 18
0

My guess is that the problem is in your DAO code. I have a similar setup (sqlite table with text and blob columns, both get updated), so I know that what you're trying to do is possible.

Greg
  • 733
  • 6
  • 14
  • The problem it's not in the DAO code, I have edited the question to include the update part, have a look, the thing is the code works its just the logic I just can't get it to work yet. Its a simple app so all data comes from module to views, and from views to module, creation is all good but update its not, the image just doesn't change once its set. perhaps a rewrite or some other logic apart from what I have mentioned might be helpful and acceptable. – alkathirikhalid Jan 31 '17 at 15:17
  • Try changing the way you get the new bitmap out of your Bundle. You could try using Intent.getParcelableExtra (http://stackoverflow.com/a/12908133/678123) or you could pass it as a byte array (http://stackoverflow.com/a/11010565/678123). – Greg Jan 31 '17 at 19:01
  • No, if you look at the code above am only interested in the ID if a selection was made in previous activity then its a View/Edit mode, If no selection / ID is null then its a new/Creation mode that's the only thing am passing extras.getLong(RecipeDAOImp.KEY_ID) as each Activity handles its own job. All data comes from module to views, and from views to module but image doesn't change once set, once its saved in DB. I can get image from camera and set to imagebutton but once saved taking images from camera wont update the imagebutton, the image already comes from DB. I appreciate your input. – alkathirikhalid Feb 02 '17 at 02:03
  • I see that in #onCreate you're getting an ID; I was looking more at #onActivityResult, where you have the line " Bitmap imageBitmap = (Bitmap) extras.get("data"); ", which I think is invalid. You can pass byte[], and you can pass ParcelableExtra, but not Bitmap. Sorry I can't offer a solution, just hope that what you want to do is possible :) – Greg Feb 02 '17 at 06:01
  • No, onActivityResult is correct and is working, if it didn't I wouldn't be able to save any image on the first place, that method is called after the camera returns the data and I convert it to bitmap set it to view before saving in db, as with my code and picture you can see the coffee mug :) I guess I will have to rewrite or put a flag for an update, I appreciate your input. – alkathirikhalid Feb 02 '17 at 06:22