Разрешения времени выполнения

аюсь загрузить изображение на сервер, но почему-то код остановился на строке FileInputStream. не знаю почему, и я не знаю, как отладить или проверить это. вот мой исходный код:

 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;

        }
    }
}

Есть ли способ проверить, где проблема? logcat остановился на точке останова 2: пункт назначения 2

 Umar Hussain15 дек. 2017 г., 10:39
Ваша целевая версия SDK?
 Aswin P Ashok15 дек. 2017 г., 10:34
какое-то исключение?
 Gabriel15 дек. 2017 г., 10:38
я вижу в подробностях: java.io.FileNotFoundException: /storage/emulated/0/20171215-051851.jpg: открыть не удалось: EACCES (разрешение запрещено), но я разрешаю чтение файла в манифесте <использует-разрешение android: name = "android. Разрешение
 Aswin P Ashok15 дек. 2017 г., 10:42
Итак, вы тестируете на андроиде зефир или выше. Поэтому вам необходимо запросить EXTERNAL_STORAGE_PERMISSION. Читать далееВот

Ответы на вопрос(3)

добавьте это в ваш 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" />

и для API 23+, прочитайте этот учебник:

Разрешения времени выполнения

Решение Вопроса

что вы не запросили разрешение EXTERNAL_STORAGE.

Начиная с уровня API Android 23 (зефир), структура разрешений Android (я не знаю, подходит ли это термин или нет), изменилась.

Перед зефиром вам просто нужно было объявить разрешения в файле манифеста. Но на и выше зефира, разрешения Android были классифицированы вНормальные разрешения а такжеОпасные разрешения, Если вы используете нормальное разрешение, все одинаково на всех версиях Android. Ноесли вы используете опасное разрешение, вы должны попросить пользователя предоставить это разрешение во время выполнения.

В вашем случае вы загружаете изображение, для которого требуются разрешения READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE. Те относятся к категории опасных разрешений. Поэтому вы должны запросить эти разрешения, прежде чем выполнять какие-либо действия, требующие этих разрешений.

Но вам не нужно запрашивать оба разрешения по отдельности, так как эти разрешения подпадают под одногруппа разрешений.

Из официальных документов,

Если приложение запрашивает опасное разрешение, указанное в его манифесте, и приложение уже имеет другое опасное разрешение в той же группе разрешений, система немедленно предоставляет разрешение без какого-либо взаимодействия с пользователем.

то есть, если вы объявили пару разрешений, относящихся к одной группе разрешений, вы должны запросить только одно из этих разрешений. Если пользователь предоставит разрешение для этой группы разрешений, все заявленные вами разрешения, которые находятся в той же группе разрешений, будут предоставлены системой.

Вот код для запроса разрешения на хранение

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);
}

Все остальное примерно так же. (И извините за мой плохой английский)

Подробнее по запросуВот

пожалуйста, проверьте сначала Разрешения, такие как (Чтение Внешнего, Запись Внешнего и Камера, если используется), после этого поместите код разрешения времени выполнения для устройств Greater, а затем Marshmallow. И используйте File Provider, чтобы получить Image Uri с SD-карты.

И поместите ниже код в 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);
}

Надеюсь, это поможет.

Ваш ответ на вопрос