I am trying to post images from my android app to the database. I have successfully implemented the process in my PHP API and when I test it with Postman the image uploads successfully. To add the capability to my app using Retrofit 2 I have read some documents including this question and its answers but still, my app cant upload the image.
Here is my PHP API code:
$app->post('/createfood', function (Request $request, Response $response) {
    
    if(!haveEmptyParameters(array('fname', 'unitprice', 'availcount'),$request, $response)){
        
        if(!isset($_FILES['fpicpath']['name']))
        {
            $message = array();
            $message['error'] = true;
            $message['message'] = 'image is required';
            $response->write(json_encode($message));
            return $response
                        ->withHeader('Content-type', 'application/json')
                        ->withStatus(422);
        }
        $request_data = $request->getParsedBody();
        $fname = $request_data['fname'];
        $unitprice = $request_data['unitprice'];
        $availcount = $request_data['availcount'];
        //$fpicpath = $request_data['fpicpath'];
        $target_dir = "fpicuploads/";
        $target_file = $target_dir . uniqid() . '.' . pathinfo($_FILES['fpicpath']['name'], PATHINFO_EXTENSION);
                
        if(move_uploaded_file($_FILES['fpicpath']['tmp_name'], $target_file)){
            $db = new DbOperations;
        $result = $db->createFood($fname, $unitprice, $availcount, $target_file);
        if($result == FOOD_CREATED){
            
            $message = array();
            $message['error'] = false;
            $message['message'] = 'Food added successfully.';
            $message['image'] = getBaseURL() . $target_file;
            $response->write(json_encode($message));
            return $response
                        ->withHeader('Content-type', 'application/json')
                        ->withStatus(201);
        }else if($result == FOOD_FAILURE){
            $message = array();
             $message['error'] = true;
            $message['message'] = 'Some error occurred while trying to add food';
            $response->write(json_encode($message));
            return $response
                        ->withHeader('Content-type', 'application/json')
                        ->withStatus(422);
        }
        }else{
            $message = array();
            $message['error'] = true;
            $message['message'] = 'Try again later!';
            $response->write(json_encode($message));
            return $response
                        ->withHeader('Content-type', 'application/json')
                        ->withStatus(422);
        }
        
    }
    return $response
    ->withHeader('Content-type', 'application/json')
    ->withStatus(422);
});
public function createFood($fname, $unitprice, $availcount, $fpicpath){
            $stmt = $this->con->prepare("INSERT INTO foods (fname, unitprice, availcount, fpicpath) VALUES (?, ?, ?, ?)");
            $stmt->bind_param("ssss", $fname, $unitprice, $availcount, $fpicpath);
            if($stmt->execute()){
                return FOOD_CREATED;
            }else{
                return FOOD_FAILURE;
            }
        }
Here is my Activity code:
public class AddFoodActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText editTextFName, editTextUnitPrice, editTextAvailCount;
    private ImageView image_view;
    private static final int OPEN_DOCUMENT_CODE = 2;
    Uri imageUri;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_food);
        editTextFName = findViewById(R.id.editTextFName);
        editTextUnitPrice = findViewById(R.id.editTextUnitPrice);
        editTextAvailCount = findViewById(R.id.editTextAvailCount);
        image_view = findViewById(R.id.image_view);
        findViewById(R.id.button_add_food).setOnClickListener(this);
        image_view.setOnClickListener(this);
    } //End onCreate
    private void addFood(){
        String foodname = editTextFName.getText().toString().trim();
        if(foodname.isEmpty()){
            editTextFName.setError("input food name");
            editTextFName.requestFocus();
            return;
        }
        String unitprice = editTextUnitPrice.getText().toString().trim();
        if(unitprice.isEmpty()){
            editTextUnitPrice.setError("input unit price");
            editTextUnitPrice.requestFocus();
            return;
        }
        String availcount = editTextAvailCount.getText().toString().trim();
        if(availcount.isEmpty()){
            editTextAvailCount.setError("input available");
            editTextAvailCount.requestFocus();
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            }}
       
        File file = new File(getRealPathFromURI(imageUri));
        RequestBody requestFile =
                RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body =
                MultipartBody.Part.createFormData("image", file.getName(), requestFile);
        RequestBody fname =
                RequestBody.create(MediaType.parse("multipart/form-data"), foodname);
        RequestBody uprice =
                RequestBody.create(MediaType.parse("multipart/form-data"), unitprice);
        RequestBody acount =
                RequestBody.create(MediaType.parse("multipart/form-data"), availcount);
        Call<FoodPicAddedResponse> call = RetrofitClient
                .getInstance()
                .getApi()
                .createFood(fname, uprice, acount, body);
        call.enqueue(new Callback<FoodPicAddedResponse>() {
            @Override
            public void onResponse(Call<FoodPicAddedResponse> call, Response<FoodPicAddedResponse> response) {
                if(response.code() == 201){
                    FoodPicAddedResponse dr = response.body();
                    Toast.makeText(AddFoodActivity.this, dr.getMsg(), Toast.LENGTH_LONG).show();
                }else if(response.code() == 422){
                    Toast.makeText(AddFoodActivity.this, "This item already exists!", Toast.LENGTH_LONG).show();
                }
            }
            @Override
            public void onFailure(Call<FoodPicAddedResponse> call, Throwable t) {
                Toast.makeText(AddFoodActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    } // End addFood()
    private void openImageChooser(){
        Intent intent = new Intent(Intent.ACTION_PICK);
        //intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        startActivityForResult(intent, OPEN_DOCUMENT_CODE);
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
        if (requestCode == OPEN_DOCUMENT_CODE && resultCode == RESULT_OK) {
            if (resultData != null) {
                // this is the image selected by the user
                imageUri = resultData.getData();
                image_view.setImageURI(imageUri);
            }
        }
    }
    private String getRealPathFromURI(Uri contentURI) {
        String result;
        Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
        if (cursor == null) { // Source is Dropbox or other similar local file path
            result = contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            result = cursor.getString(idx);
            cursor.close();
        }
        return result;
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_add_food:
                addFood();
                break;
            case R.id.image_view:
                openImageChooser();
                break;
        }
    }
}
And, here is my Api.java code:
@Multipart
    @POST("createfood")
    Call<FoodPicAddedResponse> createFood(
            @Part("fname") RequestBody fname,
            @Part("unitprice") RequestBody uprice,
            @Part("availcount") RequestBody acount,
            @Part MultipartBody.Part body
    );
When I run the app and select a picture and then click addfood button my app shows this Toast message: "This item already exists!", whereas this is not the case!
Can you please tell me whats wrong with my code?!
