0

I followed this tutorial to send an image from my phone to the server, however the image never sends. In fact, the app doesn't even attempt to send the image (in logcat). All I see in the logcat is this:

EDIT 2:

I added this piece of code after "requestQueue(request)" and the image successfully sends to the server, but the image_name is not sent to the server for some reason. The file on the server is just ".jpg", no filename.

int x=1;// retry count
    request.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 48,
            x, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}

LOGCAT After EDIT 2:

09-06 20:59:04.530 4188-4194/com.example.android.projectlanguage W/art: Suspending all threads took: 19.394ms
09-06 20:59:10.752 4188-4198/com.example.android.projectlanguage I/art: Background partial concurrent mark sweep GC freed 344902(7MB) AllocSpace objects, 3(39MB) LOS objects, 20% free, 63MB/79MB, paused 1.815ms total 112.441ms
09-06 20:59:16.046 4188-4194/com.example.android.projectlanguage W/art: Suspending all threads took: 7.118ms
09-06 20:59:21.501 4188-9226/com.example.android.projectlanguage D/Volley: [1453] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://128.199.77.211/server/connection.php 0x9c36b58 NORMAL 1> [lifetime=14541], [size=314], [rc=200], [retryCount=0]

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.hardware.camera"
    android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

MainActivity.java

public class MainActivity extends AppCompatActivity {

private ImageButton ImageButton;
private String encoded_string, image_name;
private Bitmap bitmap;
private File file;
private Uri file_uri;


// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}


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

    ImageButton = (ImageButton) findViewById(R.id.camera);
    ImageButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view){
            Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            getFileUri();
            i.putExtra(MediaStore.EXTRA_OUTPUT,file_uri);
            startActivityForResult(i,10);
        }
    });
}

private void getFileUri() {
    image_name = "testing123.jpeg";
    file = new File(Environment.getExternalStorageDirectory().getAbsoluteFile(), image_name);

    file_uri = Uri.fromFile(file);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode == 10 && resultCode == RESULT_OK){
        new Encode_image().execute();
    }
}

private class Encode_image extends AsyncTask<Void,Void,Void> {
   @Override
   protected Void doInBackground(Void... voids){

       bitmap = BitmapFactory.decodeFile(file_uri.getPath());
       ByteArrayOutputStream stream = new ByteArrayOutputStream();
       bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);

       byte[] array = stream.toByteArray();
       encoded_string = Base64.encodeToString(array,0);
       return null;
   }

   @Override
   protected void onPostExecute(Void aVoid){
       makeRequest();
   }
}

private void makeRequest() {
    final TextView mTextView = (TextView) findViewById(R.id.text);
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    String URL = "http://128.199.77.211/server/connection.php";
    StringRequest request = new StringRequest(Request.Method.POST, URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    mTextView.setText(response);
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            mTextView.setText("That didn't work!");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            HashMap<String, String> map = new HashMap<>();
            map.put("encoded_string", encoded_string);
            map.put("image_name", image_name);

            return map;
        }
    };
    requestQueue.add(request);
  }
}

I have made sure to include the volley library in build.gradle as well.

Volley does however set the text to "That didn't work!"

EDIT:

After adding "Log.e("TAG", "err", error);" to onErrorResponse, this is what Logcat produced:

09-05 23:21:44.593 18677-18677/com.example.android.projectlanguage E/TAG: err
                                                                      com.android.volley.TimeoutError
                                                                          at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:147)
                                                                          at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:114)
0248881
  • 731
  • 1
  • 4
  • 21
  • volley is executing fine and returning the result in onErrorResponce and setting the text. Can you debug the VolleyError object in onErrorResponce? It will help in diagnosing the cause. – Arslan Sep 05 '16 at 13:10
  • So, what error do you get? Paste `Log.e("TAG", "err", error);` in `onErrorResponse` and tell us what you get – Mr Quattro Sep 05 '16 at 13:10
  • @Mr Quattro I have edited the error into the original question at the end – 0248881 Sep 05 '16 at 13:24
  • Where is the code executed? on an actual device or VM? The Adress seems suspicious to me. I would dry to connect via IP. Since localhost is only accessible through the same host. Even VM's cannot access a server bound to localhost or 127.0.0.1. Bind to 0.0.0.0 for accessibilty from the local network. – Hannes Sep 05 '16 at 13:31
  • when you build the request, you need to include the 'entity' ie the file you want in the POST.body. add that code . as it is , your post has no body – Robert Rowntree Sep 05 '16 at 14:23
  • @Hannes There is an actual address, i just didnt want to put it up – 0248881 Sep 06 '16 at 06:43
  • @RobertRowntree Could you please expand on that? – 0248881 Sep 06 '16 at 06:46
  • Doinbackground stream of encoded bytes needs to be in some type of entity for the POST. http://stackoverflow.com/a/11659665/560435 – Robert Rowntree Sep 06 '16 at 09:59
  • @RobertRowntree Shouldn't volley take care of that? This exact same code was working last week but not anymore – 0248881 Sep 06 '16 at 10:50
  • using 'stringrequest' as volley implementation is not going to handle getting the stream that you create into a request entity of any kind within volley. http://stackoverflow.com/questions/16797468/how-to-send-a-multipart-form-data-post-in-android-with-volley see the volley class "multipartReq..." – Robert Rowntree Sep 06 '16 at 14:30
  • @RobertRowntree What does "MultipartEntity is detracted" Mean? It was in one of the comments and doesnt sound too good – 0248881 Sep 07 '16 at 08:21
  • did u attempt the "multpart" request per @sagar? – Robert Rowntree Sep 07 '16 at 14:42

1 Answers1

0

Hey this is the class which may help you try it.

Use

connection = url.openConnection(); if you are not sending request over SSL

public class MultipartRequest extends AsyncTask<Void, Integer, String> {

    /**
     * Url for uploading form data to server
     */
    private String serverUrl;

    /**
     * Url for maintaining body paramters
     */
    private HashMap<String, String> bodyParams;

    /**
     * File for uploading
     */
    private File file;

    //Connection Object
    private HttpURLConnection connection = null;

    //Data output stream

    private DataOutputStream outputStream = null;

    private DataInputStream inputStream;

    //Content managers
    private String lineEnd = "\r\n";
    private String twoHyphens = "--";
    private String boundary = "*****";

    //Response callback for request
    private ResponseCallback responseCallback;

    //Response string
    private String responseString = null;

    /**
     * Constructor for multipart request
     *
     * @param url
     * @param bodyParams
     * @param file
     */
    public MultipartRequest(String url, HashMap<String, String> bodyParams,
                            File file, ResponseCallback responseCallback){
        this.serverUrl = url;
        this.bodyParams = bodyParams;
        this.file = file;
        this.responseCallback = responseCallback;
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            URL url = new URL(serverUrl);
            connection = (HttpsURLConnection) url.openConnection();

            // Allow Inputs & Outputs
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            // Enable POST method
            connection.setRequestMethod("POST");

            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            connection.addRequestProperty("Authorization", StorageUtility.getBasicAuth());
            outputStream = new DataOutputStream(connection.getOutputStream());

            // attach body params
            attachBodyParams(outputStream);

            if(file != null) {
                attachFileParams(outputStream);
            }

            System.out.println("+++++++++++++++++++++++"+twoHyphens + boundary + twoHyphens + lineEnd);

            // write bytes
            outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);


            inputStream = new DataInputStream(connection.getInputStream());
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = inputStream.readLine()) != null) {
                response.append(line).append('\n');
            }

            responseString = response.toString();
        }catch (ProtocolException pe){
            pe.printStackTrace();
        }catch (IOException io){
            io.printStackTrace();
        }

        return null;
    }

    /**
     * Attach body params
     * @param outputStream
     * @throws IOException
     */
    public void attachBodyParams(DataOutputStream outputStream) throws IOException{
        for(String key : bodyParams.keySet()) {
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            outputStream.writeBytes("Content-Disposition: form-data; name=\" " + key + "\"");
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(bodyParams.get(key));
            outputStream.writeBytes(lineEnd);
        }
    }

    /**
     * if there is file attach file at the end of
     * body
     *
     * @param outputStream
     * @throws IOException
     */
    public void attachFileParams(DataOutputStream outputStream) throws IOException{

        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1 * 1024 * 1024;

        FileInputStream fileInputStream = new FileInputStream(file);

        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"");
        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes("Content-Type: application/*");
        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(lineEnd);

        //hier File schreiben
        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, maxBufferSize);
        buffer = new byte[bufferSize];
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            outputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        outputStream.writeBytes(lineEnd);

        fileInputStream.close();
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        try {
            responseCallback.onResponse(new JSONObject(responseString.toString()));
        }catch (JSONException je){
            je.printStackTrace();
            logger.error(StackTraceUtility.getStackTrace(je));
        } catch (NullPointerException ne){
            ne.printStackTrace();
            logger.error((StackTraceUtility.getStackTrace(ne)));
        }
    }
}

AND JUST CREATE INTANCE WITH

new MultipartRequest(url, bodyParams,
                       file, responseCallback)
Sagar Yadav
  • 137
  • 2
  • 11