'E/Volley: [904] NetworkUtility.shouldRetryException: Unexpected response code 400 for url
I am trying to upload image from android studio to my flask server running on local host. On POSTMAN the response is ok, image is uploaded and returns response in json format. But here I am getting below error as shown in logcat:
2022-03-07 20:11:27.008 13444-13484/com.example.finalflask E/Volley: [904] NetworkUtility.shouldRetryException: Unexpected response code 400 for http://192.168.2.81:5000/predict
2022-03-07 20:11:27.010 13444-13444/com.example.finalflask D/AndroidRuntime: Shutting down VM 2022-03-07 20:11:27.013 13444-13444/com.example.finalflask E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.finalflask, PID: 13444
java.lang.AssertionError
at com.example.finalflask.MainActivity$3.lambda$onClick$1$com-example-finalflask-MainActivity$3(MainActivity.java:104)
at com.example.finalflask.MainActivity$3$$ExternalSyntheticLambda0.onErrorResponse(Unknown Source:2)
at com.android.volley.Request.deliverError(Request.java:652)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:104)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Here is the link of image from POSTMAN POSTMAN Screenshot
Also, when i click on "upload" button to send image to flask, android studio is sending request on flask but somehow may be it is not being received in the required format i guess.
Here is the screenshot from flask terminal. Screenshot from flask terminal
Flask Code
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = upload
@app.route('/')
def index():
return 'Hello World'
@app.route('/predict', methods=['POST','GET'])
def predict():
if request.method == 'POST':
file = request.files['image']
filename = secure_filename(file.filename)
path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
image = cv2.imread(path)
.....
.....
.....
if __name__ == '__main__':
app.run(host='0.0.0.0')
Above code is working fine on POSTMAN
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int requestcamera_code = 12;
ImageView image;
Button choose, upload, capture;
int PICK_IMAGE_REQUEST = 111;
String URL ="http://192.168.2.81:5000/predict";
String url = URL.replaceAll(" ", "%20");
Bitmap bmp;
Bitmap bitmap;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
capture = (Button) findViewById(R.id.capture);
image = (ImageView) findViewById(R.id.image);
choose = (Button) findViewById(R.id.choose);
upload = (Button) findViewById(R.id.upload);
capture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera, requestcamera_code);
}
});
//opening image chooser option
choose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
startActivityForResult(Intent.createChooser(intent, "Select Image"), PICK_IMAGE_REQUEST);
}
});
upload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Uploading, please wait...");
progressDialog.show();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap = BitmapFactory.decodeResource(getResources(), R.id.image);
bitmap = ((BitmapDrawable) image.getDrawable()).getBitmap();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT);
StringRequest request = new StringRequest(Request.Method.POST, url, s -> {
progressDialog.dismiss();
if(s.equals("true")){
Toast.makeText(MainActivity.this, "Uploaded Successful", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(MainActivity.this, "Some error occurred!", Toast.LENGTH_LONG).show();
}
}, volleyError -> {
VolleyError error = null;
assert false;
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
String res = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Now you can use any deserializer to make sense of data
JSONObject obj = new JSONObject(res);
} catch (UnsupportedEncodingException | JSONException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
} // returned data is not JSONObject?
}
Toast.makeText(MainActivity.this, "Some error occurred -> "+volleyError, Toast.LENGTH_LONG).show();;
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
return headers;
}
@Override
protected Map<String, String> getParams() {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("image", imageString);
Log.d("tag", parameters.toString());
return parameters;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue rQueue = Volley.newRequestQueue(MainActivity.this);
rQueue.add(request);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST) {
Uri filePath = data.getData();
try {
//getting image from gallery
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
//Setting image to ImageView
image.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
} else if (requestCode == requestcamera_code) {
Bitmap imgbitmap = (Bitmap) data.getExtras().get("data");
image.setImageBitmap(imgbitmap);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="15dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
tools:context=".MainActivity"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="268dp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Capture"
android:id="@+id/capture"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Choose"
android:id="@+id/choose"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Upload"
android:id="@+id/upload"/></LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.finalflask">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.AppCompat"
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="MissingClass">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
build.gradle
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.finalflask"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.android.volley:volley:1.2.1'
}
I have read similar issues where mostly it was suggested to check url and make sure the value is in string. I have checked both of them, POSTMAN is working fine and parameter sent is specified as string.
Any kind of help and suggestion is appreciated. Thank you very much
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
