i\'ve a pdf file in my app assets directory that i want open using an external app, so wrote my content provider and i\'m tryng to make it work but nothing...
here i
setType()
resets your Uri
to null
. Try skipping the Uri
in the constructor and using setDataAndType()
instead.
I am new to android development and spent the whole day looking for the reason that my locally stored PDF could not be opened by external apps. I am glad having found this thread.
In the meantime Marco got it working and describes it here. Beware: Italian language- Google translation service might help ;-)
http://www.marcofaion.it/?p=7
http://web.archive.org/web/20111020204554/http://www.marcofaion.it/?p=7
Additional notes to his howto for beginners:
The line Marco mentions to be inserted in the Manifest.xml
<provider android:name=".FileContentProvider" android:authorities="package.name" />
should be inserted within the <application ...></application>
tag.
And if you plan to have custom filenames you should exchange
InputStream is = am.open("file.pdf");
with
InputStream is = am.open(uri.getLastPathSegment());
PDF files have to be put into already existing folder assets in your project (especially not in any newly added folder res/assets or sth.)! =)
My implementation is below. Note that if your filename is MyPdf.pdf, the file should be assets/public_pdfs/MyPdf.pdf.mp3. The path public_pdfs is to only export the pdfs you really want to export, and the .mp3 extension is to prevent compression.
AndroidManifest.xml
<provider android:authorities="my.app.PdfContentProvider" android:enabled="true" android:exported="true" android:name="my.app.PdfContentProvider">
</provider>
Opening a PDF
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.parse("content://my.app.PdfContentProvider/" + filename);
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
PdfContentProvider.java
public class PdfContentProvider extends ContentProvider
{
private static final String PDFPATH = "public_pdfs/";
@Override
public String getType(Uri uri)
{
return "application/pdf";
}
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException
{
AssetManager am = getContext().getAssets();
String file_name = uri.getLastPathSegment();
if (file_name == null) throw new FileNotFoundException();
AssetFileDescriptor afd = null;
try
{
afd = am.openFd(PDFPATH + file_name + ".mp3");
}
catch (IOException e)
{
e.printStackTrace();
}
return afd;
}
private final static String[] COLUMNS = {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
@Override
/**
* This function is required for it to work on the Quickoffice at Android 4.4 (KitKat)
*/
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
if (projection == null)
{
projection = COLUMNS;
}
String[] cols = new String[projection.length];
Object[] values = new Object[projection.length];
int i = 0;
for (String col : projection)
{
if (OpenableColumns.DISPLAY_NAME.equals(col))
{
cols[i] = OpenableColumns.DISPLAY_NAME;
values[i++] = uri.getLastPathSegment();
}
else if (OpenableColumns.SIZE.equals(col))
{
cols[i] = OpenableColumns.SIZE;
values[i++] = AssetFileDescriptor.UNKNOWN_LENGTH;
}
}
cols = copyOf(cols, i);
values = copyOf(values, i);
final MatrixCursor cursor = new MatrixCursor(cols, 1);
cursor.addRow(values);
return cursor;
}
private static String[] copyOf(String[] original, int newLength)
{
final String[] result = new String[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}
private static Object[] copyOf(Object[] original, int newLength)
{
final Object[] result = new Object[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}
@Override
public boolean onCreate()
{
return true;
}
@Override
public Uri insert(Uri uri, ContentValues values)
{
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
return 0;
}
}