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.
Related
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.
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
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();
}
}
I am trying to create a button in my android app that allows the user to share an image using their choice of social media network. The image file is stored in the assets folder of the app.
My plan is to implement a custom ContentProvider to give external access to the image, then send a TYPE_SEND intent specifying the uri of the image within my content provider.
I have done this and it works for Google+ and GMail, but for other services it fails. The hardest part has been finding information on what I'm supposed to return from the query() method of my ContentProvider. Some apps specify a projection (e.g. Google+ asks for _id and _data), while some apps pass null as the projection. Even where the projection is specified, I've no idea what actual data (types) are expected in the columns. I can find no documentation on this.
I have also implemented the openAssetFile method of the ContentProvider and this gets called (twice by Google+!) but then inevitably the query method get called as well. Only the result of the query method seems to count.
Any ideas where I'm going wrong? What should I be returning from my query method?
Code below:
// my intent
Intent i = new Intent(android.content.Intent.ACTION_SEND);
i.setType("image/jpeg");
Uri uri = Uri.parse("content://com.me.provider/ic_launcher.jpg");
i.putExtra(Intent.EXTRA_STREAM, uri);
i.putExtra(android.content.Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(i, "Share via"));
// my custom content provider
public class ImageProvider extends ContentProvider
{
private AssetManager _assetManager;
public static final Uri CONTENT_URI = Uri.parse("content://com.me.provider");
// not called
#Override
public int delete(Uri arg0, String arg1, String[] arg2)
{
return 0;
}
// not called
#Override
public String getType(Uri uri)
{
return "image/jpeg";
}
// not called
#Override
public Uri insert(Uri uri, ContentValues values)
{
return null;
}
#Override
public boolean onCreate()
{
_assetManager = getContext().getAssets();
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
MatrixCursor c = new MatrixCursor(new String[] { "_id", "_data" });
try
{
// just a guess!! works for g+ :/
c.addRow(new Object[] { "ic_launcher.jpg", _assetManager.openFd("ic_launcher.jpg") });
} catch (IOException e)
{
e.printStackTrace();
return null;
}
return c;
}
// not called
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
{
return 0;
}
// not called
#Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter)
{
return new String[] { "image/jpeg" };
}
// called by most apps
#Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException
{
try
{
AssetFileDescriptor afd = _assetManager.openFd("ic_launcher.jpg");
return afd;
} catch (IOException e)
{
throw new FileNotFoundException("No asset found: " + uri);
}
}
// not called
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException
{
return super.openFile(uri, mode);
}
}
Thanks, your question solved mine ;)
I was having the exactly inverse problem of yours: every service would work except g+.
I was returning null in the query method, that made g+ crash.
The only thing to actually expose my images was to implement openFile().
I have my images stored on the filesystem, not in the assets, but I suppose you
could get a ParcelFileDescriptor from your AssetFileDescriptor and return it.
My openFile() method looks like this:
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
String path = uri.getLastPathSegment();
if (path == null) {
throw new IllegalArgumentException("Not a Path");
}
File f = new File(getContext().getFilesDir() + File.separator + "solved" + path + ".jpg");
int iMode;
if ("r".equals(mode)) {
iMode = ParcelFileDescriptor.MODE_READ_ONLY;
} else if ("rw".equals(mode)) {
iMode = ParcelFileDescriptor.MODE_READ_WRITE;
} else if ("rwt".equals(mode)) {
iMode = ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_TRUNCATE;
} else {
throw new IllegalArgumentException("Invalid mode");
}
return ParcelFileDescriptor.open(f, iMode);
}
This works for every service I have installed with the ACTION_SEND intents except g+.
Using your query method makes it work for google plus, too.