i know android database keep two kinds of contact photo,
[[[ The photo may be stored in up to two ways - the default "photo" is a thumbnail-sized image stored directly in the data row, while the "display photo", if present, is a larger version stored as a file. ]]]
the small one is 96*96 and the large is 480 *480
now the questions:
i still can't find the large one while the small one is "data15"in the database,someone please show me how to get the large one?
i need to place the photo on the first screen of launcher , so i need a photo at least 800*480,there must be declare constant for the photo size....
PS: I tried:
intent.putExtra("outputX", 96);
intent.putExtra("outputY", 96);
but when i opened the database , it became 96*57 ....confused.... some help changed it?
好人一声平安 (that's chinese-good boy,good luck)
thanks ^_^
I'm not too sure what you mean by storing the photo twice?
Yes, a lot of the devices out there will generate thumbnails, but thats more due to the fact that displaying thumbail images is a regular use case.
Have you tried fetching the user ID and using that to query the contacts data table?
This may be a long winded approach but, (pseudocode)
Fetch contact id using the URI RawContacts.CONTENT_URI
Fetch Photo id using the URI Contacts.CONTENT_URI
Fetch Photo using the URI Data.CONTENT_URI, the projection you want here is Photo.PHOTO (this will give you a blob)
Google should provide easy to read examples of these actions :)
To get the larger image you can use the following code (provided you have the contactID):
public static InputStream getLargeContactPhoto(Long contactId, Context context) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd = context.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return fd.createInputStream();
} catch (Exception e) {
return null;
}
}
Related
Suppose I am writing an alternative Camera application and wish to write images exactly into the same place as Camera does and name them exactly in the same name Camera does.
How would I accomplish this?
How to know the location of camera files?
How to know current naming convention?
How to gain permissions to that directory?
Any of answer would be appreciated.
Okay, suppose it is not really camera alternative. Suppose I would like to write formats other than images, like audio, video, or something else.
How would I accomplish this?
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "You Dir. Name";
if you append any string to end this
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
it will create dir inside the folder
How to know the location of camera files?
By default camera uses this location
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
How to know current naming convention?
IMG_yyyyMMDD_timeStamp
How to gain permissions to that directory?
Using permission manager for Camera and External Storage permissions
You cannot write exactly into the same folder as the default camera app does. But you can make use of Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
mediaStorageDir = new File(Environment.getExternalStorageDirectory(), FOLDER_NAME);
Intent takePictureFromCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureFromCameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,
Uri.fromFile(mediaStorageDir));
startActivityForResult(takePictureFromCameraIntent, 100);
But, please note that this will create only a sub-folder in the DCIM directory and will not store exactly where the default camera does. But you can always create sub-folders with your required folder name.
Things to keep in mind for this answer:
Every phone producer creates it's own Camera App, tailored to their hardware.
With the right permissions, App's can write (almost) everywhere they want...
Now to your question(s):
First, we don't know where the photo's are stored, and what the naming convention is. Every one and their mother has a different idea about what is best. So no "Hey it's always there".
Those who seek will find: get read & write permissions for the whole device. With that search the whole device to find in what folders the images are in. Now subtract the folders that come from "social media". My guess would be that the folder with the most and or latest images is the one that you want. To be sure, you will need testers, that trust you.
All that are found were not unorganized: just find the pattern used. There may be a standard for this. The big companies will surely have one. You can ask the device what maker it has. Note, that that answer might not be correct.
Ain't that a picture, no, it's a photo: And then you get the fun part of accessing the camera. Good times. Remember: request picture => get location of picture in memory => save picture as file. Best part, there is no enforcement of all parts of this API, so different devices need different instructions...
Have fun & Good luck!
ps, the downvotes are probably for the lack of code
Try using this code you can save the image bitmap to the directory using insert query
String imgSaved = MediaStore.Images.Media.insertImage(
getContentResolver(), bitmap,
System.currentTimeMillis() + ".jpg", "DESCRIPTION HERE");
For more details see the link
I've found this code useful for choosing the last used DCIM/Camera folder.
String getDCIMCamera() {
try {
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE};
Cursor cursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if (cursor != null) {
cursor.moveToFirst();
do {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
if (path.contains("/DCIM/")) {
File file = new File(path);
path = file.getParent();
cursor.close();
return path;
}
} while (cursor.moveToNext());
cursor.close();
}
}
catch (Exception e) {
}
return "";
}
I am trying to get the metadata for the video files stored on my app's user's phone. I can get the file name, id, date taken and so on. However, latitude and longitude data always returns as 0.0. I have been referring to this:
developer.android.com/reference/android/provider/MediaStore.Video.VideoColumns.html
Yes, I am already enabling use location in my settings. I have a very similar function to this for images which works fine.
public void getLocalVideoFiles(Context context) {
ContentResolver videoResolver = context.getContentResolver();
Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String test = getRealPathFromURI(context, videoUri);
Cursor videoCursor = videoResolver.query(videoUri, null, null, null, null);
if(videoCursor!=null && videoCursor.moveToFirst()){
//get columns
int latColumn = videoCursor.getColumnIndex
(MediaStore.Video.Media.LATITUDE);
int lonColumn = videoCursor.getColumnIndex
(MediaStore.Video.Media.LONGITUDE);
do {
String thisLat = Double.toString(videoCursor.getDouble(latColumn));
String thisLon = Double.toString(videoCursor.getDouble(lonColumn));
Log.d("video Latitude",thisLat);
Log.d("video Longitude",thisLon);
}
while (videoCursor.moveToNext());
}
return localClips;
}
The approach described here: Geotagging a captured video yields similar results (null value in the METADATA_KEY_LOCATION column).
So, my question is: does the built-in Android video tool record location data when creating videos? It seems like the answer is no, but I don't understand why there are columns for the location data if this is the case. If that is not the case, how can I access the video location data? I need the location of video files that have already been taken.
Thanks in advance!
Well i've just tested your assumption that google does not keep location data while recording video and it's incorrect.
For example: using my nexus 5 with version 5.1 i was able to get a geotag on a video i just took. you can try it by yourself and if your phone is rooted, just browse the MediaStore external DB (com.android.providers.media) using some SQLITE viewer
but let's say that google does not keep GeoTag. there are number of reasons why they would keep such a column:
To support other video libraries that do want to keep geo taggging
To allow users who are implementing Video recorder a way to save current location ( using FusedLocation or something similar). a way of doing it is just updating the relevant row in the DB for example:
getContentResolver().update(MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon().appendPath("2152").build(), cv, null, null);
to support previous versions that did support tagging
I have some code that takes a screen capture from the app and saves it to the SD card and makes it available in the Gallery. The problem is it saves it with the camera pictures when you look for it in the gallery. I would rather it save under the download folder or create an app specific folder (PicSay does something like this) where all the screen shots will be accessible to the user. Currently, I'm using the following to save to the camera gallery:
MediaStore.Images.Media.insertImage(getContentResolver(), imagePath, fileName, desc);
How can you get it to save to a different location other than Camera?
You can use the normal Java API's to save the image file to any place you want in the external storage directory.. (Hint - using the FileOutputStream)
The only problem you need to solve is to tell Andriod that you have added a new content, so update the content databse. Which the gallery can use to display the images to the user.
So create a new ContentValue and just insert it into the ContentResolver. You can get a handle to the ContentResolver using the API getContentResolver()
The ContentValue contains relevant information like name of the image, absolute path to it, date it was created, size of the file etc., not all of these mandatory, go through the Android Doc and pick off values that are irrelevant to you.
ContentValues values = new ContentValues(7);
values.put(Images.Media.TITLE, title);
values.put(Images.Media.DISPLAY_NAME, fileName);
values.put(Images.Media.DATE_TAKEN, currTime);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(Images.Media.ORIENTATION, 0);
values.put(Images.Media.DATA, filePath);
values.put(Images.Media.SIZE, jpegData.length);
contentResolver.insert(STORAGE_URI, values);
And voila, the Gallery will show the image where it is placed :)
If you are able to convert your image to simple stream, you can use Android predefined methods: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
I'm trying to expose a .png file located in my application's /data directory through a ContentProvider but instead of reaching the openFile method query is being called. Now I only ever have a single image which I need to expose for sharing to other applications, how can I setup my Intent to goto openFile instead of query?
Intent shareImageIntent = new Intent(Intent.ACTION_SEND);
shareImageIntent.setType("image/*");
shareImageIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
startActivity(Intent.createChooser(shareImageIntent, "Share image"));
Where the Uri looks like
content://my.package.contentprovider/fileName
Or alternatively do I need to create a database for this and return a cursor?
UPDATE
So this appears to be working on everything except the SMS app (which is what I decided to test first) I would like to support sharing to it however.
Here's the relevant stack trace:
Caused by: java.lang.IllegalArgumentException: Query on
content://mypackage.myprovider/someImage.png returns null result. at
com.android.mms.ui.UriImage.initFromContentUri(UriImage.java:104) at
com.android.mms.ui.UriImage.(UriImage.java:63) at
com.android.mms.model.ImageModel.initModelFromUri(ImageModel.java:83)
at com.android.mms.model.ImageModel.(ImageModel.java:65) at
com.android.mms.data.WorkingMessage.changeMedia(WorkingMessage.java:481)
at
com.android.mms.data.WorkingMessage.setAttachment(WorkingMessage.java:375)
...
So the SMS app is performing a query instead of reading directly from openFile, which every other app on my phone seems to do (including other Google apps)
Does anyone know what I need to return here to fullfil the query appropriately? I'm going to go AOSP digging now.
After digging through the source code of the SMS (MMS really) app this is what I came up with.
Inside UriImage.initFromContentUri the application makes the query code and assumes there are 2 returned columns in the Cursor
} else {
filePath = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
mContentType = c.getString(c.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
}
So inorder for your ContentProvider to work with the MMS app, you need to return a Cursor in query that only has one row and the two columns (Images.Media.DATA & Images.Media.MIME_TYPE) with the appropriate data. The MMS will then make the call to openFile to actually retrieve the image.
An easier way to share a image resource is to save it to external storage (SD-card) and then do:
Uri imageUri = Uri.fromFile(pathToFile);
Update:
Try using
Uri imageUri = Uri.parse("android.resource://com.package.yourapp/" +imageResID);
Update2
Try saving file to Media Store and then sending it:
String url = Media.insertImage(context.getContentResolver(), imageFile.getAbsolutePath(), imageFile.getName(), imageFile.getName());
Uri imageUri = Uri.parse(url);
Final Update using ContentProvider and Cursor:
Your ContentProvider must implement query(..) method and it must return a Cursor. See the source code of UrlImage.initFromContentUri(..) (which is internally used by MMS app) to see how cursor is called. Take a look at the MatrixCursor if it fits the bill.
If your content provider is already working you can access to a ParcelFileDescriptor via the method openFileDescriptor in the content provider.
A quick, and dirty, example for this:
ParcelFileDescriptor descriptor = mContext.getContentResolver().openFileDescriptor(IMGURI, "r");
Bitmap bmp = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());
Cheers!
I want to show an images gallery. The problem is during the loading of them.
At the beginning, I was loading the images with :
images = new File("/sdcard/DCIM/Camera/");
if(images.listFiles().length==0)
//no images, do some other stuff...
else
//put images in the gallery and do some stuff
This code works with the emulator (Android 2.2 - API Level 8) and with a Samsung Galaxy S2 (Android 2.2.1). But I ask some friends to test this code with their own phones (HTC, LG...).
With an HTC Desire, there is a problem during this loading. The code is going into "//no images" but they have images in the album (for example from Camera...) My friend said to me that :
album is stored in the internal storage and not in the SD Card with HTC.
So i've tried to check others directory, like this :
//Get the internal content
images = new File(MediaStore.Images.Media.INTERNAL_CONTENT_URI.getPath());
if (!images.isDirectory()) {
//Get the external content
images = new File(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.getPath());
}
if (!images.isDirectory()) {
//Get the SD Card content
images = new File("/sdcard/DCIM/Camera/");
}
But still not working :( That is not the good directory :/
So, my question is : how can i get the good path for images with all android phone ? is their an Object which is able to return the path of the album ?
Thanks :)
(sorry for mistakes)
I did some checking and it looks like you are trying to access the MediaStore incorrectly. It should be accessed via a cursor and not directly as a file.
This is because as mentioned at http://developer.android.com/guide/topics/providers/content-providers.html
Content providers expose their data as a simple table on a database model, where each row is a record and each column is data of a particular type and meaning.
So basically you can't read the URI as a file. It is a table of data.
Here's an example from that same page on how to access it.
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);
Also, here's another Stackoverflow question that has some examples that shows how to use the cursor.
How to query Android MediaStore Content Provider, avoiding orphaned images?
Finally, based on the links above I would just use the mediastore object as a cursor on all devices and that will solve the problem you are having with different directories.
Hope this helps,
George