1

Im trying to upload image to server, but somehow the code stopped at FileInputStream line. not sure why and i don't know how to debug or check it. here my source code:

 public class CreateSetcardStep1Activity extends AppCompatActivity {

    @Override
    protected void onCreate(final Bundle savedInstanceState) {


        String filename = appHelper.dateToString(new Date(), "yyyyMMdd-hhmmss");
        destination = new File(Environment.getExternalStorageDirectory(), filename + ".jpg");

        buttonTakePhoto.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
                startActivityForResult(intent, REQUEST_IMAGE);
            }
        });

        buttonSubmitPhoto.setVisibility(View.GONE);
        buttonSubmitPhoto.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                dialog = ProgressDialog.show(CreateSetcardStep1Activity.this, "", "Uploading file...", true);

                new Thread(new Runnable() {
                    public void run() {
                        uploadFile(imagePath);
                    }
                }).start();
            }
        });


    }

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

        if (requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK) {
            try {
                buttonSubmitPhoto.setVisibility(View.VISIBLE);
                Log.e(LOG, "breakpoint 1");
                setcardPic.setVisibility(View.VISIBLE); Log.e(LOG, "breakpoint 2 destination: "+destination);
                FileInputStream in = new FileInputStream(destination); Log.e(LOG, "breakpoint 3");
                BitmapFactory.Options options = new BitmapFactory.Options(); Log.e(LOG, "breakpoint 4");
                options.inSampleSize = 10; Log.e(LOG, "breakpoint 5");
                imagePath = destination.getAbsolutePath(); Log.e(LOG, "breakpoint 6 imagePath: "+imagePath);
                Log.e(LOG, "PATH === " + imagePath);
                //tvPath.setText(imagePath);
                Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
                setcardPic.setImageBitmap(bmp);
                showUploadButton = true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        } else {
            showUploadButton = false;
            Toast.makeText(getApplicationContext(),
                    R.string.request_cancelled,
                    Toast.LENGTH_LONG).show();
        }
    }

    public int uploadFile(String sourceFileUri) {

        String fileName = sourceFileUri;
        showUploadButton = false; //revert upload button to hidden
        HttpURLConnection conn = null;
        DataOutputStream dos = null;
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1024 * 1024;
        File sourceFile = new File(sourceFileUri);

        if (!sourceFile.isFile()) {
            dialog.dismiss();
            Log.e(LOG, "Source File not exist :" +imagePath);
            return 0;
        }
        else
        {
            try {

                // open a URL connection to the Servlet
                FileInputStream fileInputStream = new FileInputStream(sourceFile);
                URL url = new URL(upLoadServerUri);

                // Open a HTTP  connection to  the URL
                conn = (HttpURLConnection) url.openConnection();
                conn.setDoInput(true); // Allow Inputs
                conn.setDoOutput(true); // Allow Outputs
                conn.setUseCaches(false); // Don't use a Cached Copy
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Connection", "Keep-Alive");
                conn.setRequestProperty("ENCTYPE", "multipart/form-data");
                conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                conn.setRequestProperty("Filedata", fileName);

                dos = new DataOutputStream(conn.getOutputStream());

                dos.writeBytes(twoHyphens + boundary + lineEnd);
                dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename="+ fileName + "" + lineEnd);
                dos.writeBytes(lineEnd);

                // create a buffer of  maximum size
                bytesAvailable = fileInputStream.available();

                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                buffer = new byte[bufferSize];

                // read file and write it into form...
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {

                    dos.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                }

                // send multipart form data necesssary after file data...
                dos.writeBytes(lineEnd);
                dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

                // Responses from the server (code and message)
                serverResponseCode = conn.getResponseCode();
                String serverResponseMessage = conn.getResponseMessage();

                Log.i(LOG, "HTTP Response is : "+ serverResponseMessage + ": " + serverResponseCode);

                if(serverResponseCode == 200){

                    runOnUiThread(new Runnable() {
                        public void run() {

                            Toast.makeText(CreateSetcardStep1Activity.this, "File Upload Complete.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
                }

                //close the streams //
                fileInputStream.close();
                dos.flush();
                dos.close();

            } catch (MalformedURLException ex) {

                dialog.dismiss();
                ex.printStackTrace();

                runOnUiThread(new Runnable() {
                    public void run() {

                        Toast.makeText(CreateSetcardStep1Activity.this, "MalformedURLException",
                                Toast.LENGTH_SHORT).show();
                    }
                });

                Log.e(LOG, "error: " + ex.getMessage(), ex);
            } catch (Exception e) {

                dialog.dismiss();
                e.printStackTrace();

                runOnUiThread(new Runnable() {
                    public void run() {

                        Toast.makeText(CreateSetcardStep1Activity.this, "Got Exception : see logcat ",
                                Toast.LENGTH_SHORT).show();
                    }
                });
                Log.e(LOG, "Exception : "
                        + e.getMessage(), e);
            }
            dialog.dismiss();
            return serverResponseCode;

        }
    }
}

Is there any way to check where the issue is? the logcat stopped at breakpoint 2: breakpoint 2 destination: /storage/emulated/0/20171215-051851.jpg so the file is there if i check the explorer

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Gabriel
  • 229
  • 4
  • 19

3 Answers3

1

This happens because you haven't requested EXTERNAL_STORAGE permission.

Starting from android API level 23 (marshmallow), android permission framework (I don't know whether that's the right term for it or not), have changed.

Before marshmallow you just had to declare permissions in the manifest file. But on and above marshmallow, android permissions have been categorized into Normal permissions and Dangerous permissions. If you are using a normal permission, things are the same on all android versions. But if you are using a dangerous permission, you have to request the user to grant that permission at runtime.

In your case, you are uploading an image, which require READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions. Those are categorized as dangerous permissions. So you have to request those permissions before you do any actions that require those permissions.

But you don't have to request both the permissions separately, since those permissions fall under one permission group.

From official docs,

If an app requests a dangerous permission listed in its manifest, and the app already has another dangerous permission in the same permission group, the system immediately grants the permission without any interaction with the user..

ie, if you have declared a couple of permissions that are on a single permission group, you have to request for only one of those permissions. If the user grants permission for that permission group, all those permissions you declared, which are in the same permission group will be granted by the system.

Here is the code to request storage permission

private static final int STORAGE_REQ_ID=3465;

if (ContextCompat.checkSelfPermission(CreateSetcardStep1Activity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
            {

                if (ActivityCompat.shouldShowRequestPermissionRationale(CreateSetcardStep1Activity.this,
                        Manifest.permission.READ_EXTERNAL_STORAGE)) {

                    //THIS CONDITION WORKS WHEN WE ARE REQUSETING PERMISSION AGAIN SINCE USER DENIED PERMISSION ON PREVIOUS REQUEST(S)

                    ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
                                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                                STORAGE_REQ_ID);

                } else {

                    //REQUESTING PERMISSION FOR FIRST TIME, EXPLAIN WHY THE APPLICATION NEED PERMISSION

                    AlertDialog.Builder builder = new AlertDialog.Builder(CreateSetcardStep1Activity.this);
                    builder.setTitle("Permission Request");
                    builder.setMessage("To upload image, Application need External storage permission");
                    builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
                                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                                    STORAGE_REQ_ID);
                        }
                    });
                    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                        }
                    });
                    AlertDialog dialog = builder.create();
                    dialog.show();
                    ActivityCompat.requestPermissions(CreateSetcardStep1Activity.this,
                            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                           STORAGE_REQ_ID);
                }
            }
            else startImageCapture();
        }

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {

//HERE YOU HANDLE PERMISSION REQUEST RESULTS
    switch (requestCode) {
        case STORAGE_REQ_ID: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                //PERMISSION GRANTED!!
                startImageCapture();

            } else {

                //USER DENIED PERMISSION, NOTIFY THE USER THAT PERMISSION IS DENIED, MAY BE A TOAST?

            }
            return;
        }

    }
}


private void startImageCapture(){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
    startActivityForResult(intent, REQUEST_IMAGE);
}

Everything else is pretty much the same. (And sorry for my poor English)

More on permission request here

Aswin P Ashok
  • 702
  • 8
  • 27
0

Hi please check first Permission like(Read External,Write External and Camera if used) into Manifest file after that put Runtime permission code for Greater then Marshmallow devices.And Use File Provider to get Image Uri from SD Card.

And put below code into onActivityResult().

                 if (mPhotouri != null) {
                    try {
                        mBitmap = MediaStore.Images.Media.getBitmap(
                                getContentResolver(), mPhotouri);
                        Uri tempUri = getImageUri(this, mBitmap);
                        finalFile = new File(getRealPathFromURI(tempUri, this));
                        mSelectedImagePath = finalFile.getAbsolutePath();

                        if (mSelectedImagePath != null)
                            mFileSelectedImage = new File(mSelectedImagePath);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

public static Uri getImageUri(Activity inContext, Bitmap inImage) {

        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
        String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
        return Uri.parse(path);
    }

public static String getRealPathFromURI(Uri uri, Activity signupActivity) {
    Cursor cursor = signupActivity.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
    return cursor.getString(idx);
}

hope it helps.

Jyubin Patel
  • 1,373
  • 7
  • 17
0

add this to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

and for api 23+ , read this tutorial:

Runtime Permissions

Sajad Rahmanipour
  • 397
  • 1
  • 3
  • 20