Error Copying directory file downloads to another, open failed: EACCES (Permission denied) in api level 19

1

Good morning. I have the following problem in ANDROID STUDIO, I have an application in which the user chooses a pdf or word file, gets the path of the path and if the user decides to upload the file to the server, the application copies the file selected and paste it into an internal directory created and from there it just proceeds to upload the file to the server. The application works from a minimum of 18 to 27. has been tested on a device of Android 21 Android 5.0.2 and there are no problems; When I tested with a device of api level 19 android 4.4.2 of the downloads folder, the following problem arises in the Logcat:

11-15 13:53:27.303 4363-4363/? E/CrearCarpteaAlIn: Error: No se creo el directorio privado
11-15 13:53:27.303 4363-4363/? E/Error: java.io.IOException: open failed: EACCES (Permission denied)
11-15 13:53:27.303 4363-4363/? W/System.err: java.io.IOException: open failed: EACCES (Permission denied)
11-15 13:53:27.313 4363-4363/? W/System.err:     at java.io.File.createNewFile(File.java:972)
    at com.example.usuario.prueba.SubirArchivosPDFWORD.onClick(SubirArchivosPDFWORD.java:161)
    at android.view.View.performClick(View.java:4578)
    at android.view.View$PerformClick.run(View.java:18654)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5021)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:827)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:643)
11-15 13:53:27.323 4363-4363/? W/System.err:     at dalvik.system.NativeStart.main(Native Method)
Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
    at libcore.io.Posix.open(Native Method)
    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
    at java.io.File.createNewFile(File.java:965)
    ... 12 more

Although it says Permissions Error, I have attaching the permissions in the manifest:

<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" />

I have searched the problem on the internet and I can not find the solution to the problem, it seems to me that it is because it does not get the path correctly when it gets it from downlodas since what it gets is

   E/PATH: /data/user/0/com.android.providers.downloads/cache/ordcom64-doc2018-06-15.pdf

On the other hand, on the Path in another version of android it is

     E/PATH: /storge/emulated/0/Download/solucione.pdf

This is my complete manifesto:     

<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" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity" />
    <activity android:name=".DescargarArchivosPDF">
    </activity>
    <activity android:name=".SubirImagenes">


    </activity>
    <activity android:name=".Galeria">

    </activity>
    <activity android:name=".SubirArchivosPDFWORD">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

This is my activity:

import android.Manifest;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.channels.FileChannel;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

//FUNCIONA, SUBE ARCHIVOS DE INTERNO Y EXTERNO
public class SubirArchivosPDFWORD extends AppCompatActivity implements View.OnClickListener {
    private Button BtnExaminar_Archivos, BtnSubir_Archivos;
    private TextView TxVwNombre;
    private static final int SELECT_FILE = 1;
    private final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 124;
    private boolean PERM_WRITE = false;
    private String PATHIREAL, PATHREAL = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_subir_archivos_pdf_word);
    BtnExaminar_Archivos = (Button) findViewById(R.id.BtnExaminar_Archivos);
    BtnSubir_Archivos = (Button) findViewById(R.id.BtnSubir_Archivos);
    TxVwNombre = (TextView) findViewById(R.id.TxVwNombre);
    BtnExaminar_Archivos.setOnClickListener(this);
    BtnSubir_Archivos.setOnClickListener(this);
    SolicitarPermiso();
}

void SolicitarPermiso() {
    ///Pregunta los Permisos
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        //PERMISO DENEGADO
        //HAY RESPUESTA
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            Toast.makeText(this, "HAY RPA", Toast.LENGTH_SHORT).show();
            //PERMISO DENEGADO
            if (getPackageManager().PERMISSION_DENIED == -1) {
                //PERMISO DENEGADO ANTERIORMENTE
                Toast.makeText(this, "DENEGADO", Toast.LENGTH_SHORT).show();
                ///PIDE PERMISO
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);

            } else {///PERMISO ACEPTADO
                PERM_WRITE = true;
            }
        } else {
            ///NO HAY RESPUESTA
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
            Toast.makeText(this, "NOHAY RPA", Toast.LENGTH_SHORT).show();
            PERM_WRITE = false;
        }
    } else {//PERMISO ACEPTADO
        PERM_WRITE = true;
        Toast.makeText(this, "Aceptado Write", Toast.LENGTH_SHORT).show();
    }

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, "HAY RPTA READ", Toast.LENGTH_SHORT).show();

    } else {
        Toast.makeText(this, "Aceptado Read", Toast.LENGTH_SHORT).show();
    }


}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    //LLega Sirve para procesar la respuesta del Permiso
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "SI HAY PERMISO", Toast.LENGTH_SHORT).show();
                PERM_WRITE = true;
            } else {
                Toast.makeText(this, "NO HAY PERMISO", Toast.LENGTH_SHORT).show();
                PERM_WRITE = false;
            }
            break;
    }
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.BtnExaminar_Archivos:
            SolicitarPermiso();
            if (PERM_WRITE) {
                String[] mimeTypes = {"application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"};
                Intent intent = new Intent();
                intent.setType("application/*").putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
                //intent.setType("image/JPG");
                //intent.setType("image/jpeg");
                //intent.setType("image/jpg");
                //intent.setType("image/png");
                //intent.setAction(Intent.ACTION_GET_CONTENT);
                intent.setAction(Intent.ACTION_GET_CONTENT);
                Uri mImageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
                startActivityForResult(
                        Intent.createChooser(intent, "Seleccione un DOCUMENTO"),
                        1);
            }
            break;
        case R.id.BtnSubir_Archivos:
            try {
                File interno = new File(crearCarpetaAlmInterno() + "/" + new File(PATHREAL).getName());
                File temp = new File(PATHREAL);
                temp.createNewFile();
                copyFile(temp, interno);
                new UploadFile(interno.getAbsolutePath()).execute();
            } catch (IOException e) {
                Log.e("Error", e.toString());
                e.printStackTrace();
            }
            //new UploadFile(PATHREAL).execute();
            break;
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Uri selectedImage;
    if (requestCode == 1 && resultCode == RESULT_OK && null != data) {
        String name = data.getData().getLastPathSegment();
        PATHIREAL = data.getData().getPath();
        try {
            PATHREAL = getFilePath(this, data.getData());
            TxVwNombre.setText("name=" + name + " PATH=" + PATHREAL);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        Log.e("PATH", PATHREAL);
    }

}

public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
    String selection = null;
    String[] selectionArgs = null;
    // Uri is different in versions after KITKAT (Android 4.4), we need to
    if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            return Environment.getExternalStorageDirectory() + "/" + split[1];
        } else if (isDownloadsDocument(uri)) {
            final String id = DocumentsContract.getDocumentId(uri);
            uri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

        } else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            if ("image".equals(type)) {
                uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }
            selection = "_id=?";
            selectionArgs = new String[]{
                    split[1]
            };
        }
    }
    if ("content".equalsIgnoreCase(uri.getScheme())) {
        String[] projection = {
                MediaStore.Images.Media.DATA
        };
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver()
                    .query(uri, projection, selection, selectionArgs, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            if (cursor.moveToFirst()) {
                return cursor.getString(column_index);
            }
        } catch (Exception e) {
        }
    } else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}

public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());

}

public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/***crear Directorio en la memoria interna     */

public File crearCarpetaAlmInterno() {
    String nombreDirectorio = "TCompra";
    //Crear directorio en la memoria interna.
    File directorioInterno = new File(getFilesDir(), nombreDirectorio);
    //Muestro un mensaje en el logcat si no se creo la carpeta por algun motivo
    if (!directorioInterno.mkdirs()) {
        Log.e("CrearCarpteaAlIn", "Error: No se creo el directorio privado");
    }

    if (directorioInterno.exists() && directorioInterno.isDirectory()) {//SI EXISTE
        Toast.makeText(this, "DIRECTORIO EXISTE", Toast.LENGTH_SHORT).show();
    } else {//NO EXISTE
        Toast.makeText(this, "DIRECTORIO NO EXISTE", Toast.LENGTH_SHORT).show();

    }

    return directorioInterno;
}

public static void copyFile(File sourceFile, File destFile) throws IOException {
    if (!destFile.exists()) {
        destFile.createNewFile();
    }

    FileChannel origen = null;
    FileChannel destino = null;
    try {
        origen = new FileInputStream(sourceFile).getChannel();
        destino = new FileOutputStream(destFile).getChannel();

        long count = 0;
        long size = origen.size();
        while ((count += destino.transferFrom(origen, count, size - count)) < size) ;
    } finally {
        if (origen != null) {
            origen.close();
        }
        if (destino != null) {
            //destFile.mkdirs();
            destino.close();
        }
    }
}


private class UploadFile extends AsyncTask<String, String, String> {
    String PATREAL = null;

    public UploadFile(String PATREAL) {
        this.PATREAL = PATREAL;
    }

    @Override
    protected String doInBackground(String... strings) {
        File f = new File(this.PATREAL);


        //String content_type = getMimeType(this.PATREAL);
        String content_type = getMimeType2(PATREAL);
        Log.i("content_type ", content_type);
        String file_path = PATREAL;
        Log.d("File ", file_path);
        OkHttpClient client = new OkHttpClient();
        RequestBody file_body = RequestBody.create(MediaType.parse(content_type), f);
        RequestBody request_body = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("type", content_type)
                .addFormDataPart("uploaded_file", file_path.substring(file_path.lastIndexOf("/") + 1), file_body)
                .build();

        Request request = new Request.Builder()
                .url("http://www.nube.com/Surbir.php")
                .post(request_body)
                .build();

        try {
            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                //Toast.makeText(SubirImagenes.this, "Archivo no subido", Toast.LENGTH_SHORT).show();
                throw new IOException("Error : " + response);

            }


        } catch (IOException e) {
            e.printStackTrace();
            Log.e("Error", e.toString());
        }


        return null;
    }
}

private String getMimeType(String path) {

    String type = null;
    String extension = MimeTypeMap.getFileExtensionFromUrl(path);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
    }
    return type;


}

public static String getMimeType2(String url) {
    String extension = url.substring(url.lastIndexOf("."));
    String mimeTypeMap = MimeTypeMap.getFileExtensionFromUrl(extension);
    String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(mimeTypeMap);
    return mimeType;
}

}

Thank you for your time.

    
asked by jovad 15.11.2018 в 20:35
source

2 answers

1

To avoid this type of problem and obtain the download directory /Download we suggest using

Environment.getExternalStoragePublicDirectory (...) and define the type of directory to return that in this case would be Environment.DIRECTORY_DOWNLOADS

String dirDownloads = 
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";

This way you will get the route defined on any device.

Remember that for devices with an operating system greater than 6.0 you must require the permissions

Request permissions WRITE_EXTERNAL_STORAGE on android 6.0 or higher

    
answered by 15.11.2018 в 21:28
0

Reviewing the error several times, debugging other times, I got the surprise that the LG-D331 device with Android 4.4.2 version. When opening the file browser, it sent by default to DOWNLOADS, in which several files were listed, which are shown in the following image

In which after choosing one of the list showed the PATH OF THIS FORM, it is with which he had problems when copying to an internal folder.

Then after so much fustration send from another device a file by bluetooh, which had been stored in the internal memomria [download] and that in that directory the files listed in the first image are not observed.

In summary, the error was that the device could not access files that are listed in the Downloads directory (Default path when opening the file browser in the application), of which these files when looking for them and open the directory of the memory / Download are not (not visible). The device shows files that are not visible, apparently they are stored in cache, which are inaccessible when searching by name. Then the application wanting to copy the obtained path can not do it and shows the exception EACCES (Permission denied).

THANK YOU FOR YOUR HELP , it was my first post

    
answered by 16.11.2018 в 00:47