Search code examples
androidpdfandroid-intentandroid-file

I try to copy from raw to external memory but it does not work


Good,

I am trying to open a pdf document from my raw folder, but I have read that it can not be opened directly from the raw folder, so I am copying it to external memory.

The problem is that I do not copy the file to external memory in order to open it.

This is my code:

public class OpenPdf {

private static final String TAG = "Open pdf";

public OpenPdf(Context ctx) {
if (checkMemory()){
    Toast.makeText(ctx, "There is access to the SD and you can write", Toast.LENGTH_SHORT).show();
    openPDF(ctx);
}else {
    Toast.makeText(ctx, "No access to SD or can not write", Toast.LENGTH_SHORT).show();
}
}

private boolean checkMemory(){
boolean sdAvailable = false;
boolean sdAccessWriter = false;
boolean value = false;
String state = Environment.getExternalStorageState();

if(state.equals(Environment.MEDIA_MOUNTED)){
    sdAvailable = true;
    sdAccessWriter = true;
}else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)){
    sdAvailable = true;
    sdAccessWriter = false;
}

if(sdAvailable && sdAccessWriter){
    value = true;
}
return value;
}

public void openPDF(Context ctx){

try {
    copyFile(ctx.getResources().openRawResource(R.raw.avisolegal), new FileOutputStream(new File(ctx.getFilesDir(), "Documents/avisolegal.pdf")));
} catch (IOException e) {
    e.printStackTrace();
}

try {
    File pdfFile = new File(ctx.getFilesDir(), "Documents/avisolegal.pdf");
    Uri path = Uri.fromFile(pdfFile);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(path, "application/pdf");
    ctx.startActivity(intent);
} catch (Exception e){
    Toast.makeText(ctx, "Fail to open file.", Toast.LENGTH_SHORT).show();
    Log.i(TAG, "Fail to open file" + e);
}

}

private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
    out.write(buffer, 0, read);
}
}

And these are the permissions on the AndroidManifest:

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

How can I have the file copied to open it?

This is the error log:

03-15 12:53:26.976 5267-5267/radio.ecca.gesenecca W/System.err: java.io.FileNotFoundException: /data/user/0/radio.ecca.gesenecca/files/Documents/avisolegal.pdf: open failed: ENOENT (No such file or directory)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:452)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at radio.ecca.gesenecca.Recursos.OpenPdf.openPDF(OpenPdf.java:59)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at radio.ecca.gesenecca.Recursos.OpenPdf.<init>(OpenPdf.java:30)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at radio.ecca.gesenecca.MainActivity$1.onNavigationItemSelected(MainActivity.java:89)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.support.design.widget.NavigationView$1.onMenuItemSelected(NavigationView.java:151)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.support.design.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:318)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.view.View.performClick(View.java:5280)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.view.View$PerformClick.run(View.java:21239)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.os.Looper.loop(Looper.java:234)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5526)
03-15 12:53:26.979 5267-5267/radio.ecca.gesenecca W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     at libcore.io.Posix.open(Native Method)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:438)
03-15 12:53:26.980 5267-5267/radio.ecca.gesenecca W/System.err:     ... 19 more
03-15 12:53:27.139 5267-5566/radio.ecca.gesenecca V/RenderScript: 0x9d2a3000 Launching thread(s), CPUs 4
03-15 12:53:44.030 5267-5267/radio.ecca.gesenecca I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@73b6028 time:138471792

Thank you very much in advance, I am learning a lot thanks to this community.

I'm sorry, I accidentally deleted the question.

EDIT 1:

If I change the route by "/avisolegal.pdf". It does not display the error, but does not copy the file to that path.


Solution

  • I have already solved my problem, I leave it here so that they can see it and I can help them

    The first thing I did, was to ask the user to write permissions to the external memory.

    static final Integer WRITE_EXST = 0x3;
    
    askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,WRITE_EXST);
    
    
       private void askForPermission(String permission, Integer requestCode) {
        if (ContextCompat.checkSelfPermission(MainActivity.this, permission) != PackageManager.PERMISSION_GRANTED) {
    
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
    
                //This is called if user has denied the permission before
                //In this case I am just asking the permission again
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
    
            } else {
    
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
            }
        } else {
            //Toast.makeText(this, "" + permission + " ya han sido consedidos.", Toast.LENGTH_SHORT).show();
            OpenPdf openPdf = new OpenPdf(getApplicationContext());
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "Permisos consedidos", Toast.LENGTH_SHORT).show();
            OpenPdf openPdf = new OpenPdf(getApplicationContext());
        }else{
            Toast.makeText(this, "Permisos denegados", Toast.LENGTH_SHORT).show();}
    }
    

    And this is my class that copies the raw file to the external memory and then opens it.

    public class OpenPdf {
    
    private static final String TAG = "Copiar fichero" ;
    
    public OpenPdf(Context ctx) {
    
        if (checkMemory()){
            //Toast.makeText(ctx, "Hay acceso a la SD y se puede escribir", Toast.LENGTH_SHORT).show();
            try
            {
                File ruta_sd = Environment.getExternalStorageDirectory();
                openPDF(ctx,ruta_sd);
            }
            catch (Exception ex)
            {
                Log.e("Ficheros", "Error al escribir el fichero en la tarjeta SD " + ex);
            }
        }else {
            Toast.makeText(ctx, "No hay acceso a la SD o no se puede escribir", Toast.LENGTH_SHORT).show();
        }
    }
    
    private boolean checkMemory(){
        boolean sdAvailable = false;
        boolean sdAccessWriter = false;
        boolean value = false;
        String state = Environment.getExternalStorageState();
    
        if(state.equals(Environment.MEDIA_MOUNTED)){
            sdAvailable = true;
            sdAccessWriter = true;
        }else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)){
            sdAvailable = true;
            sdAccessWriter = false;
        }
    
        if(sdAvailable && sdAccessWriter){
            value = true;
        }
        return value;
    }
    
    public void openPDF(Context ctx, File ruta){
    
        try {
            copyFile(ctx.getResources().openRawResource(R.raw.avisolegal), new FileOutputStream(new File(ruta, "avisolegal.pdf")));
        } catch (IOException e) {
            e.printStackTrace();
        }
    
       try {
            File pdfFile = new File(ruta, "avisolegal.pdf");
            Uri path = Uri.fromFile(pdfFile);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(path, "application/pdf");
            ctx.startActivity(intent);
        } catch (Exception e){
            Toast.makeText(ctx, "Error al abrir el archivo.\nDebe tener un visor de archivos PDF", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "Error al abrir el archivo" + e);
        }
    
    }
    
    private void copyFile(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int read;
        while((read = in.read(buffer)) != -1){
            out.write(buffer, 0, read);
        }
    }
    

    The problem was in the permissions for the new versions of android and the route I was using to copy the file.

    A greeting and thank you very much for the help