9

I am trying to retrieve a reference to a file stored in the assets directory to a file named myfile.pdf. I have tried to do it as follows:

File file = new File("android_assest/myfile.pdf);
Log.d("myTag", "" + file.isFile());

Somehow, I get false when the myfile.pdf do exists in the assets directory. I verified it using getAssets().list("") and Log.d() each element in the returned array.

More of which, I am trying to get a reference to a PDF file and then use any PDF viewer, which is already installed on the device, in order to view the PDF.

I guess that since the previous issue (retrieving a reference to the file) returns false then the next snipped code fails:

Intent i = new Intent(Intent.ACTION_VIEW,
    Uri.parse("file:///android_asset/myfile.pdf"));
startActivity(i);

Anyone has a clue why I am unable to retrieve a reference to the file? and why I cannot use already installed PDF viewer to display a PDF (after retrieving a reference to the PDF file)?

Thanks.

Gangnus
  • 24,044
  • 16
  • 90
  • 149
EviatarS
  • 684
  • 2
  • 7
  • 20
  • Check [how-to-open-a-pdf-stored-either-in-res-raw-or-assets-folder](http://stackoverflow.com/questions/6491210/how-to-open-a-pdf-stored-either-in-res-raw-or-assets-folder) – Imran Rana Jun 11 '12 at 13:31

3 Answers3

24

As Barak said you can copy it out of assets to internal storage or the SD card and open it from there using inbuilt pdf applications.

Following Snippet will help you. (I have updated this code to write to and read files from internal storage.

But i dont recommend this approach because pdf file can be more than 100mb in size.

So its not recommended to save that huge file into internal storage

Also make sure while saving file to internal storage you use

openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);

Then only other applications can read it.

Check following snippet.

package org.sample;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

public class SampleActivity extends Activity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        CopyReadAssets();

    }

    private void CopyReadAssets()
    {
        AssetManager assetManager = getAssets();

        InputStream in = null;
        OutputStream out = null;
        File file = new File(getFilesDir(), "git.pdf");
        try
        {
            in = assetManager.open("git.pdf");
            out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);

            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e)
        {
            Log.e("tag", e.getMessage());
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(
                Uri.parse("file://" + getFilesDir() + "/git.pdf"),
                "application/pdf");

        startActivity(intent);
    }

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

}

Make sure to include

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

in manifest

Vipul
  • 27,808
  • 7
  • 60
  • 75
  • 1
    +1, I should have posted something similar in my answer as the OP specifically asked about opening it with other apps. – Barak Jun 11 '12 at 13:38
  • How can I write the file into the internal storage (since I do not have a SD card)? – EviatarS Jun 11 '12 at 13:41
  • 1
    @VipulShah GREAT Solution and code snippet!!!! Who knew viewing local PDFs in Android would be such a pain! In iOS its a 1 liner!! – RyanG Dec 03 '12 at 18:28
  • @Vipul Shah: Document path is not valid.. while opening.. in fact its not even writing that pdf on to sdcard.. please help.. – Mitesh Shah Jan 30 '14 at 09:17
1

You can't do it like that. There is no directory structure in an apk, it is just data. The framework knows how to access it (getAssets), but you cannot look for it as a file in a directory.

You can open it as an input stream...

in = new BufferedReader(new InputStreamReader(activity.getAssets().open(myfile.pdf))); 

Or you can copy it out of assets to internal storage or the SD card and access it there.

Barak
  • 16,318
  • 9
  • 52
  • 84
  • But I able to do so for HTML files. E.g., I can access HTML files within the `assets` directory and view them on a `WebView`. – EviatarS Jun 11 '12 at 13:47
  • 1
    Took me a bit of searching, but I found out why. The URL "file:///android_asset/" doesn't point to a particular directory, it is only used by WebView to address assets. Pulled that from [here](http://stackoverflow.com/a/3281337/1105376) – Barak Jun 11 '12 at 13:56
0

like say Vipul Shah, but in the case for external.

import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        copyReadAssets();
    }


    private void copyReadAssets()
    {
        AssetManager assetManager = getAssets();

        InputStream in = null;
        OutputStream out = null;

        String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
        File fileDir = new File(strDir);
        fileDir.mkdirs();   // crear la ruta si no existe
        File file = new File(fileDir, "example2.pdf");



        try
        {

            in = assetManager.open("example.pdf");  //leer el archivo de assets
            out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo


            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
        } catch (Exception e)
        {
            Log.e("tag", e.getMessage());
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");
        startActivity(intent);
    }

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

change parts of code like these:

out = new BufferedOutputStream(new FileOutputStream(file));

the before example is for Pdfs, in case of to example .txt

FileOutputStream fos = new FileOutputStream(file);
Community
  • 1
  • 1
Alex Zaraos
  • 6,443
  • 2
  • 26
  • 21