Welcome all
I have a content provider that must share images from getFilesDir folder. The problem is that the method openFile is never being called. What should i do to achieve it?
I'm using the solution proposed here, but with getFilesDir: Create and Share a File from Internal Storage
i'm sharing the image with this code:
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
theUri = Uri.parse("content://com.myapp.cap/img319058");
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM,theUri);
SectionManager.getCurrentActivity().startActivity(Intent.createChooser(shareIntent, ""));
The problem is that the method openFile is never being called. Instead of it, it is called the method openAssetFile but i don't want that! i want that the method openFile get's called
This is my content provider:
public class AssetsContentProvider extends ContentProvider{
#Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
return null;
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File root = getContext().getFilesDir();
File cacheDir = getContext().getCacheDir();
File path = new File(root, uri.getEncodedPath());
path.mkdirs();
File file = new File(path, "file_"+uri.getLastPathSegment());
int imode = 0;
if (mode.contains("w")) {
imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (mode.contains("r"))
imode |= ParcelFileDescriptor.MODE_READ_ONLY;
if (mode.contains("+"))
imode |= ParcelFileDescriptor.MODE_APPEND;
return ParcelFileDescriptor.open(file, imode);
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
#Override
public boolean onCreate() {
return false;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
Thanks for your help
Related
If I use ContentProvider in my app am getting error like "unfortunately camera has stopped" after Result_ok.This is my code:
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
How to to solve this?I don't want to save image in sd card.
This my MyFileContentProvider class:
public class MyFileContentProvider extends ContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://com.example.user.studentadmission/");
private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();
static {
MIME_TYPES.put(".jpg", "image/jpeg");
MIME_TYPES.put(".jpeg", "image/jpeg");
}
#Override
public boolean onCreate() {
try {
File mFile = new File(getContext().getFilesDir(), "student.jpg");
if(!mFile.exists()) {
mFile.createNewFile();
}
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
return (true);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#Override
public String getType(Uri uri) {
String path = uri.toString();
for (String extension : MIME_TYPES.keySet()) {
if (path.endsWith(extension)) {
return (MIME_TYPES.get(extension));
}
}
return (null);
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
File f = new File(getContext().getFilesDir(), "student.jpg");
if (f.exists()) {
return (ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_WRITE));
}
throw new FileNotFoundException(uri.getPath());
}
#Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
throw new RuntimeException("Operation not supported");
}
#Override
public Uri insert(Uri uri, ContentValues initialValues) {
throw new RuntimeException("Operation not supported");
}
#Override
public int update(Uri uri, ContentValues values, String where,
String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
#Override
public int delete(Uri uri, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
}
Few camera action works only on Kitkat, use condition for action:
Intent i = (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
? new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)
: new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
If still crash occur, try avoiding ContentProvider just for testing. Let me know.
Give permission for open Camera.
Give run-time permission for open Camera.
Hi I'm try to save different files with ContentProvider (videos and photos).But I don't know how to do it in the same class.
I try to do this...
public class MyFileContentProvider extends ContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://com.renata.ideary/picture");
public static final Uri CONTENT_URI_2 = Uri.parse("content://com.renata.ideary/video");
private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();
private static final HashMap<String, String> MIME_TYPES_2= new HashMap<String, String>();
static {
MIME_TYPES.put(".jpg", "image/jpeg");
MIME_TYPES.put(".jpeg", "image/jpeg");
MIME_TYPES_2.put(".mp4","video/mp4");
}
#Override
public boolean onCreate() {
try {
File mFile = new File(getContext().getFilesDir(), "/picture.jpg");
if(!mFile.exists()) {
mFile.createNewFile();
}
File mFile2 = new File(getContext().getFilesDir(), "/video.mp4");
if(!mFile2.exists()) {
mFile2.createNewFile();
}
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
getContext().getContentResolver().notifyChange(CONTENT_URI_2, null);
return (true);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#Override
public String getType(Uri uri) {
String path = uri.toString();
for (String extension : MIME_TYPES.keySet()) {
if (path.endsWith(extension)) {
return (MIME_TYPES.get(extension));
}
}
for (String extension : MIME_TYPES_2.keySet()) {
if (path.endsWith(extension)) {
return (MIME_TYPES_2.get(extension));
}
}
return (null);
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
if (uri.equals(CONTENT_URI)) {
File f = new File(getContext().getFilesDir(), "/picture.jpg");
if (f.exists()) {
return (ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_WRITE));
}
throw new FileNotFoundException(uri.getPath());
}
else {
File f2 = new File(getContext().getFilesDir(), "/video.mp4");
if (f2.exists()) {
return (ParcelFileDescriptor.open(f2,
ParcelFileDescriptor.MODE_READ_WRITE));
}
throw new FileNotFoundException(uri.getPath());
}
}
#Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
throw new RuntimeException("Operation not supported");
}
#Override
public Uri insert(Uri uri, ContentValues initialValues) {
throw new RuntimeException("Operation not supported");
}
#Override
public int update(Uri uri, ContentValues values, String where,
String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
#Override
public int delete(Uri uri, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
}
But always told me the same error:
05-06 22:42:37.932 21837-21849/com.renata.ideary E/JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.)
java.lang.RuntimeException: Operation not supported
at com.renata.ideary.MyFileContentProvider.query(MyFileContentProvider.java:137)
at android.content.ContentProvider.query(ContentProvider.java:980)
at android.content.ContentProvider$Transport.query(ContentProvider.java:213)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112)
at android.os.Binder.execTransact(Binder.java:446)
Someone can help me? Thanks
PD: Save my video but with that error :(
I am developing an android app where I have some pdf files stored in asset folder. On click of list items the files open through available pdf viewer. The following code runs fine in versions lower than Kitkat. But as Kitkat have its own Storage Access Framework(SAF) the code only opens the framework not the file.
FileContentProvider.java
public class FileContentProvider extends ContentProvider
{
#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(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;
}
}
The code block from where it is called:
if(android.os.Build.VERSION.SDK_INT <19) {
i = new Intent(Intent.ACTION_VIEW);
}
else {
i = new Intent();
}
/**Open PDF Forms*/
String fileName = "af1_version_7_december_2013.pdf";
i.setDataAndType(Uri.parse("content://package_name/"+fileName), "application/pdf");
try {
startActivity(i);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(getActivity(), "NO Pdf Viewer", Toast.LENGTH_SHORT).show();
}
After debugging I have seen that for Kitkat the Kitkat specific code in my FileContentProvider.java is not accessed.
Please let me know if anyone have the solution to this problem. My sincere thanks in advance.
Note: This question is not duplicate as previous questions and answers were not Kitkat specefic and after my detailed search I've found that there is no solution in stack overflow to this question as of now.
Following MediaContentProvider (a simple image file provider) is working correctly with all types of apps, but not with my SMS (or better MMS) app.
I know, the SMS app is expecting a Cursor instead of a ParcelFileDescriptor, does this mean I have to save my image file to a database and retrieve it from there? Or is there a better solution for that?
public class MediaContentProvider extends ContentProvider
{
public static final String AUTHORITY = "MEDIA";
#Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
return 0;
}
#Override
public String getType(Uri uri)
{
return null;
}
#Override
public Uri insert(Uri uri, ContentValues values)
{
return null;
}
#Override
public boolean onCreate()
{
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
return null;
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
return 0;
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
{
String fileName = uri.getLastPathSegment();
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(getContext().getFilesDir().getAbsolutePath() + "/" + fileName), ParcelFileDescriptor.MODE_READ_ONLY);
return pfd;
}
}
EDIT
as suggested, here my FileProvider... Actually, it results in the same behaviour... As I said, I think I have to somehow provide a cursor for the SMS app...
public class ImageFileProvider extends FileProvider
{
public static final String AUTHORITY = "ImageFileProvider";
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
{
String fileName = uri.getLastPathSegment();
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(getContext().getFilesDir().getAbsolutePath() + "/" + fileName), ParcelFileDescriptor.MODE_READ_ONLY);
return pfd;
}
}
It may be expecting you to support OpenableColumns in your query() method.
It may be needing you to grant it permission to access the data, as your ContentProvider should be appropriately secured.
It certainly is expecting you to return a real MIME type from getType(), rather than null.
I still recommend FileProvider, but if you want to roll something yourself, this sample app has the basics.
I have a video file which I want to store in custom content provider. And after that, I want to read it and want to play it through Uri.
Below is my code.
package com.videocon.nds;
public class FileProvider extends ContentProvider {
public static final Uri CONTENT_URI=Uri.parse("content://com.videocon.nds/");
private static final HashMap<String, String> MIME_TYPES=new HashMap<String, String>();
static {
MIME_TYPES.put(".mp4", "video/mp4");
}
#Override
public boolean onCreate() {
File f=new File(getContext().getFilesDir(), "Holy.mp4");
if (!f.exists()) {
AssetManager assets=getContext().getResources().getAssets();
try {
copy(assets.open("Holy.mp4"), f);
}
catch (IOException e) {
Log.e("FileProvider", "Exception copying from assets", e);
return(false);
}
}
return(true);
}
#Override
public String getType(Uri uri) {
String path=uri.toString();
for (String extension : MIME_TYPES.keySet()) {
if (path.endsWith(extension)) {
return(MIME_TYPES.get(extension));
}
}
return(null);
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
File f=new File(getContext().getFilesDir(), uri.getPath());
if (f.exists()) {
return(ParcelFileDescriptor.open(f,
ParcelFileDescriptor.MODE_READ_ONLY));
}
throw new FileNotFoundException(uri.getPath());
}
#Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
throw new RuntimeException("Operation not supported");
}
#Override
public Uri insert(Uri uri, ContentValues initialValues) {
throw new RuntimeException("Operation not supported");
}
#Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
#Override
public int delete(Uri uri, String where, String[] whereArgs) {
throw new RuntimeException("Operation not supported");
}
static private void copy(InputStream in, File dst) throws IOException {
FileOutputStream out=new FileOutputStream(dst);
byte[] buf=new byte[1024];
int len;
while((len=in.read(buf))>0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}