I implemened a file ContentProvider to access a file server on a wifi network through http urls.
What I am trying to do is to launch the Android Gallery app with a particular intent and uri to display image files that are in a particular directory on my file server.
I am able to succeed if I launch the Gallery app with a single uri to display one image through this code :
Intent lance = new Intent();
lance.setAction(Intent.ACTION_VIEW);
String typedata = "image/*";
lance.setType(typedata);
String phuri = "content://" + URI_AUTORITE
+ "/" + URI_CONTENU_FICHIERS
+ directory + filename;
Uri uri = Uri.parse(phuri);
lance.setDataAndType(uri, "image/*");
startActivity(lance);
But I am trying to go one step further to implement the display of a directory containing images. I tried to use the ClipData object to display several images, through this code :
Intent lance = new Intent();
lance.setAction(Intent.ACTION_VIEW);
String typedata = "image/*";
lance.setType(typedata);
String phuri = "content://" + URI_AUTORITE
+ "/" + URI_CONTENU_FICHIERS
+ directory + filename;
Uri uri = Uri.parse(phuri);
ClipData ensemble = ClipData.newRawUri("Photos", uri);
lance.setClipData(ensemble);
startActivity(lance);
It doesn't work : the Gallery app is launched and display the list of albums and doesn't call my File ContentProvider.
Dis I miss something or is it a problem for the Gallery app developpers ?
You should override getType() method of your content provider to return mime type of image like so
#Override
public String getType(Uri uri) {
return "image/*";
}
Related
Using ACTION_VIEW with a FileProvider uri for a html file lets browsers like Chrome and Edge display the html page.
Also HTML-viewer app displays. And editor apps can handle the file.
If using a ContentProvider extended uri the browsers only offer to download the file.
HTML-viewer shows an indefinite progressbar.
My apps and external editor apps will still read and edit the file. So providing works.
I see that Chrome, Edge and HTML-viewer only call openFile() and getType().
content://com.jmg.expas.fileprovider/external_files/Documents/index.html
content://com.jmg.expas.simpleprovider/storage/emulated/0/Documents/index.html
I have no idea why both content scheme uries are treated differently.
This is the simple content provider code:
public class SimpleContentProvider extends ContentProvider
{
static String TAG = "simplecontentprovider";
public static Uri getUriForFile ( Context context, File file)
{
return Uri.parse("content://" + context.getPackageName() + ".simpleprovider" + file.getAbsolutePath());
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
{
Log.d(TAG, "open-File() mode: " + mode ); // "w"
Log.d(TAG, "uri.getEncodedPath(): " + uri.getEncodedPath() );
String path = uri.getEncodedPath();
File f = new File(path);
if ( ! f.exists() )
{
Log.d(TAG, "path does not exist" );
throw new FileNotFoundException(
"in SimpleContentProvider\n"
+
uri.getPath() );
}
if ( mode.equals("r") )
return (ParcelFileDescriptor.open(f,ParcelFileDescriptor.MODE_READ_ONLY));
return (ParcelFileDescriptor.open(f,ParcelFileDescriptor.MODE_READ_WRITE));
}
private String getExtension ( String fileName )
{
int index = fileName.lastIndexOf(".");
if ( index < 0 )
return "";
return fileName.substring(index+1);
}
#Override
public String getType(Uri uri)
{
Log.d(TAG, "get-Type() getPath(): " + uri.getPath() );
String path = uri.getPath();
String extension = getExtension(path);
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String mimeType = mimeTypeMap.getMimeTypeFromExtension(extension);
Log.d(TAG, "mimetype: " + mimeType + " for extension " + extension );
// O Oh Oh ..
//return extension;
return mimeType; // and problem solved ;-)
}
// Other member functions not used. They will be added by Android Studio
}
In manifest:
<provider
android:name=".SimpleContentProvider"
android:authorities="${applicationId}.simpleprovider"
android:enabled="true"
android:exported="true" />
Use:
String mimetype = "text/html";
String filePath = .... any filepath to a html file the app can read itself...
Uri uri = SimpleContentProvider.getUriForFile(context, new File(filePath));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimetype);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
);
context.startActivity(intent);
The question is: What do i have to do to let browsers display the source like when FileProvider used? Or what makes them to offer a download instead?
I am using an Intent to let the user select a file, and after the user has done that I want to know what kind of file-type the selected file is.
The intent:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
In my onActivityResult I want to extract the path from the intent through intent.getData() and all of it's "submethods" (getScheme(), getLastPathSegment() etc). However, I only get the Uri for the selected file.
Example of Uris':
Uri: content://media/external/audio/media/15185 //This is an audiofile
Uri: content://media/external/audio/media/20 //Another audiofile
Uri: content://media/external/images/media/20577 //this is a picture
Uri: file:///storage/emulated/0/testWed%20Apr%2017%2011%3A10%3A34%20CEST%202013 //This is a file
I've seen solutions of how to get the absolute path when the user is only allowed to chose images or audios. But how do I do I get the absolutePath (the real path with the name and file-ending, e.g. MyPicture.jpeg) if I want to allow the user to select from different file types?
The code I've been twiggling with to try to get the path-name in onActivityResult(int requestCode, int resultCode
String fileName = data.getData().getLastPathSegment().toString();
System.out.println("Uri: " +data.getData().toString());
File f = new File(fileName);
System.out.println("TrYinG wIWThA Da FiLE: " +f.getAbsolutePath());
System.out.println("FileNAME!!!: "+fileName);
By file-ending I'm assuming you mean the file extension? (i.e. mp4)
If so you can use the ContentResolver to get the mimetype:
String mimeType = getContentResolver().getType(sourceUri);
This will give you the mimetype assuming they are within the MediaStore which they should if you have the content Uri. so you'll get something like "image/png", "video/mp4", etc.
Then you can use MimeTypeMap to get the file extension from the mimetype:
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
Note that you should never substring the mimetype after "/" to get the extension as some mimetype does not use its extension such as ".mov" files which has the mimetype "video/quicktime"
(I have read a lot of similar questions, but bear with me here)
I need to send an image from one Activity (custom camera acitvity), where the second Activity is to upload the image to Picasa Web Album via Google API.
Every example I've found goes something like this:
File f = new File(cacheDir, "image_name.jpg");
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
startActivity(intent);
This works perfectly fine when I use the standard Android Picasa upload activity (or any other sharing app). I can also upload photos via the Picasa example app I am using, when sharing the image from gallery/camera etc.
But I cannot figure out how to build an Intent which uses a "content://---" uri and pass this to another application (neither for this example app or the Picasa standard app)...
Specificially: How can I create an Intent which is compatible with the code below (i.e. uses "content://" uri instead of "file://" uri)?
static class SendData {
String fileName;
Uri uri;
String contentType;
long contentLength;
SendData(Intent intent, ContentResolver contentResolver) {
Bundle extras = intent.getExtras();
if (extras.containsKey(Intent.EXTRA_STREAM)) {
Uri uri = this.uri = (Uri) extras.get(Intent.EXTRA_STREAM);
String scheme = uri.getScheme();
if (scheme.equals("content")) {
Cursor cursor = contentResolver.query(uri, null, null, null, null);
cursor.moveToFirst();
this.fileName = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.DISPLAY_NAME));
this.contentType = intent.getType();
this.contentLength = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.SIZE));
}
}
}
}
Retrieving the File-information from a File uri manually leads to NullPointerException with the Google Http Request used in the app.
Hardcoding the Content uri works. E.g:
uploadIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://media/external/images/media/11"));
Information related to Media files is stored by the MediaStore, which is a ContentProvider (http://developer.android.com/reference/android/provider/MediaStore.Images.html)
MediaStore.Images.DATA column corresponds to the file path and MediaStore.Images._ID column corresponds to the ID.
You need to query for the ID corresponding to your file path and then create a ContentUri out of it (which will be MediaStore.Images.Media.EXTERNAL_CONTENT_URI + id if the image is on the external storage, I'll try to think of a better way to translate the ID into a Content Uri).
http://developer.android.com/reference/android/provider/MediaStore.Images.Media.html#query(android.content.ContentResolver, android.net.Uri, java.lang.String[]
I'm trying to allow user to rename file name, after taking picture, but I need to allow renaming to it right after saving the picture. So I want the name of the image to be shown in an EditText.
My saving code:
Intent takePictureFromCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri mUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "/Folder/cam_"+ String.valueOf(System.currentTimeMillis()) + ".jpg"));
takePictureFromCameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(takePictureFromCameraIntent,1111);
String oriFileName = mUri.getPath();
My plan is : get the path with the name (oriFileName), then remove the front leave only the file name(cam_ ). But I have no idea on how to do so.
here you go:
String oriFileName = mUri.getPath();
oriFileName = oriFileName.substring(0, oriFileName.lastIndexOf("_"));
I want create a new 'album' in Android. I unserstood that you have to do it with your own ContentProvider. But i can't figure out how. If you take pictures, all the images appear in the album 'Camera'. If you have installed Google+ you'll see 2 extra albums: Instant Upload & Profile Picture.
We want to create something similar. We have an album per user online and we want that it appears as an album item in the Gallery app. Can someone point me in the right direction.
I already checked: http://developer.android.com/guide/topics/providers/content-providers.html
Actually im not really sure if it is possible.
You can use this way to create album in Gallery app. The name appears as 'app images'.
String path = Environment.getExternalStorageDirectory().toString();
File dir = new File(path, "/appname/media/app images/");
if (!dir.isDirectory()) {
dir.mkdirs();
}
File file = new File(dir, filename + ".jpg");
String imagePath = file.getAbsolutePath();
//scan the image so show up in album
MediaScannerConnection.scanFile(this,
new String[] { imagePath }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
if(Config.LOG_DEBUG_ENABLED) {
Log.d(Config.LOGTAG, "scanned : " + path);
}
}
});