0

I am trying to send an image to a server using MultipartEntityBuilder and HttpURLConnection, and then recieve a String answer (nowadays it uses http protocol but then I will do it with https using this code, or something very similar). But when I press the button to send it, the app crashes and the logcat doesn't tell me anything about the catch. The code from the class where I do it is the next one:

public class EnvioImagenes extends AsyncTask<String, Void, String>
{
    public String direccion="";
    public EnvioImagenes(String cuerpo){
        direccion=cuerpo;
    }


    protected String doInBackground(String... url){
        Bitmap bitmap = null;
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
        ContentBody contentPart = new ByteArrayBody(bos.toByteArray(), direccion);
        MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
        multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntity.addPart("Picture",contentPart);

        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url[0]).openConnection();
            connection.setReadTimeout(10000);
            connection.setConnectTimeout(15000);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            //Si quiero enviar/recibir una respuesta en el cuerpo del mensaje, tiene que estar lo siguiente:
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Connection", "Keep-Alive");
            String boundary= "--------------"+System.currentTimeMillis();
            multipartEntity.setBoundary(boundary);
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            DataOutputStream dos=new DataOutputStream(connection.getOutputStream());
            //connection.addRequestProperty(multipartEntity.getClass().getName(), multipartEntity.getClass().toString());
            //OutputStream output=new BufferedOutputStream(connection.getOutputStream());
            dos.writeBytes("\r\n");
            dos.flush();
            dos.close();
            //output.write(body.getBytes());
            //output.flush();

            int responseCode = connection.getResponseCode();
            InputStream inputStream = connection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            StringBuilder result = new StringBuilder();

            while ((line = bufferedReader.readLine()) != null) {
                result.append(line);
            }

            String responseString = result.toString();
            inputStream.close();
            connection.disconnect();
            return responseString;

        } catch(Exception exc) {
            String error = exc.toString();
            Log.e("This is the mistake.....", exc.getMessage());
            return error;
        }
    }
}

I downloaded the MultipartEntityBuilder library downloading it like this link says: Android - MultipartEntity and dependencies. The problem is that when the build.gradle checks if everithing is okey, it shows me this warning:

Warning:WARNING: Dependency org.apache.httpcomponents:httpclient:4.5.3 is ignored for release as it may be conflicting with the internal version provided by Android.
         In case of problem, please repackage it with jarjar to change the class packages.

I have tried to solve it downloading the package from the browser and then pasting it in the folder /lib inside the library, and then changing the code from the build.gradle to make the program checks the libraries from there, but then I had the mistake that the libraries in the code where I use the MultipartEntityBuilder weren't detected; so I think the problem is on the code itself: especially because I don't use httpClient. For any question, the code from build.gradle is actually this one:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"

    defaultConfig {
        applicationId "com.example.franco.pruebalogin"
        minSdkVersion 10
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.android.support:design:24.0.0'
    compile 'org.apache.httpcomponents:httpmime:4.5.3'
}
Community
  • 1
  • 1
F. Riggio
  • 51
  • 1
  • 2
  • 13

1 Answers1

0

I went down that path but ultimately moved to use SyncHttpClient.

private static final String COMPRESSED_FILE_PREFIX = "yourapp_image_compressed_";
private static final String JPEG_FILE_EXTENSION = ".jpeg";
private static final int FIVE_MINUTE_INIT_TIMEOUT = 300000;

public void uploadImage(Context applicationContext, ArrayList<String> filePathsToUpload) {
        RequestParams requestParams = new RequestParams();

        File imagesCacheDir;

        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            imagesCacheDir = new File(
                    android.os.Environment.getExternalStorageDirectory(),
                    "/Android/data/com.example.yourapp/UploadPics");
        } else {
            imagesCacheDir = applicationContext.getCacheDir();
        }

        if (!imagesCacheDir.exists()) {
            if (!imagesCacheDir.mkdirs()) {
                throw new RuntimeException("Image directory could not be created.");
            }
        }

        for (String filePath : filePathsToUpload) {
            File file;

            try {
                FileOutputStream out = new FileOutputStream(new File(imagesCacheDir,
                        COMPRESSED_FILE_PREFIX + filePathsToUpload.size() + 1 + JPEG_FILE_EXTENSION));

                BitmapFactory.decodeFile(filePath).compress(Bitmap.CompressFormat.JPEG, compress ? 90 : 100, out);

                file = new File(imagesCacheDir, COMPRESSED_FILE_PREFIX + filePathsToUpload.size() + 1 + JPEG_FILE_EXTENSION);
                requestParams.put(file.getName(), file);
                out.close();
            } catch (FileNotFoundException fnfe) {
                throw new RuntimeException("Image file not found.");
            } catch (IOException ie) {
                throw new RuntimeException("Error writing image to file.);
            }
        }

        SyncHttpClient client = new SyncHttpClient();
        client.setTimeout(FIVE_MINUTE_INIT_TIMEOUT);

        Map<String, String> headers = VolleyUtils.getBigOvenHeaders();
        headers.putAll(VolleyUtils.getAuthenticationHeader());

        for (String headerKey : headers.keySet()) {
            client.addHeader(headerKey, headers.get(headerKey));
        }

        MySSLSocketFactory socketFactory;

        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            socketFactory = new MySSLSocketFactory(trustStore);
            socketFactory.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            client.setSSLSocketFactory(socketFactory);
        } catch (Exception e) {
            // Probably should die or something, unless http is okay (if you need https, this is no go)
        }

        client.setTimeout(FIVE_MINUTE_INIT_TIMEOUT);

        client.post(this, "https://www.myapp.com/imageUploader", requestParams, new RotatingBitmapTextHttpResponseHandler(filePathsToUpload, notificationBuilder, onCompletionText));
}

You can change the HttpResponseHandler to whatever you want. In this case, I made a class that tracks progress and shows it in a notification. You can do whatever you'd like there instead.

Chantell Osejo
  • 1,456
  • 15
  • 25
  • What I want to recieve as an answer is a string which says that the server recieved the image correctly. But with this didn't you have a problem with the library or directly you didn't need it? How you can recieve an answer from the server after that? I want to use something that then I can write an https answer (today I don't have the certificate, so I am using something which uses twice and then I will change it). I will write for any questions those things in the post – F. Riggio Feb 15 '17 at 21:34
  • You use TextHttpResponseHandler to get back the server's response. Pass it into the client.post() method above. The onSuccess(int statusCode, Header[] headers, String responseString) will give you what you're looking for. – Chantell Osejo Feb 15 '17 at 21:41
  • Can SyncHttpClient work with http and https without big changes like HttpUrlConnection? Does it need an extra library like MultipartEntityBuilder? – F. Riggio Feb 15 '17 at 21:43
  • I read that there is a class which name is AsyncHttpClient. Is it so different to the class that you are showing me? I read that class can use http and https...do you know something about it? – F. Riggio Feb 15 '17 at 21:55
  • yes to the first question or the second one? hahaha. You are telling me that it can do what I want to do and with http and https...that's all I need. Thanks :) – F. Riggio Feb 15 '17 at 21:56
  • Use SyncHttpClient if you're doing it in a background thread. Otherwise use AsyncHttpClient. (My code above is ran in a background IntentService). SyncHttpClient works with http and https (you need to use the SSL chunk of code there to enable HTTPS support). You don't need any other dependencies but the SyncHttpClient dependency in the documentation. – Chantell Osejo Feb 15 '17 at 22:02
  • Thank you so much @Chantell Osejo. I found it because I was searching for it in google and it asked me if I was looking for the async one haha. But I will use it in backgroud. I will investigate about it and what should I do when I write the code considering my demands. Thanks – F. Riggio Feb 15 '17 at 22:19
  • You're welcome. If this works for you, please be sure to mark it as the solution. Good luck! – Chantell Osejo Feb 15 '17 at 22:42