Here's a implementation I found in a app named Pawoo. I can choose take photo or pick a image from system built-in gallery or third-party gallery at the same time.
I wonder how to achieve it with just one Intent. Because it seems not implements by third-party library.
I already know how to achieve it. Inspired by Intent to choose between the camera or the gallery in Android
The answer of qustion is not just one Intent. Simply, in my question screentshot, there's 3 actions, that's means 3 Intents. The key method is Intent.createChooser()
Here's my complete code:
public void click(View view) {
File file = getExternalFilesDir(Environment.DIRECTORY_DCIM);
Uri cameraOutputUri = Uri.fromFile(file);
Intent intent = getPickIntent(cameraOutputUri);
startActivityForResult(intent, -1);
}
private Intent getPickIntent(Uri cameraOutputUri) {
final List<Intent> intents = new ArrayList<Intent>();
if (true) {
intents.add(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI));
}
if (true) {
setCameraIntents(intents, cameraOutputUri);
}
if (intents.isEmpty()) return null;
Intent result = Intent.createChooser(intents.remove(0), null);
if (!intents.isEmpty()) {
result.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[] {}));
}
return result;
}
private void setCameraIntents(List<Intent> cameraIntents, Uri output) {
final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
final PackageManager packageManager = getPackageManager();
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam) {
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
cameraIntents.add(intent);
}
}
Here's the my demo:
It's not one Intent. This dialog is a bottom sheet.
I have to select video or image on chooser intent like this
Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
getIntent.setType("image/* video/*");
Intent pickIntent = new Intent(Intent.ACTION_PICK);
pickIntent.setType("image/* video/*");
Intent chooserIntent = Intent.createChooser(getIntent, "Select Media");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
startActivityForResult(chooserIntent, 1);
Then I want to get the metadata of the file chosen in onActivityResult()
like height and width and length of the video and the size
Use this to get all your requirements.
MediaMetadataRetriever ret = new MediaMetadataRetriever();
Bitmap bmp = null;
try
{
ret.setDataSource("<<--Your retrieved data file-->>");
bmp = ret.getFrameAtTime();
videoHeight=bmp.getHeight();
videoWidth=bmp.getWidth();
videoSize = bmp.getAllocationByteCount()
}
Hope this helps, and let me know if any issue arises.
I am using following code to get picture from camera. Except samsung it is working fine in other mobiles. please let me know what i am doing wrong.
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "temp" + File.separator);
root.mkdir();
final String fname = "img_" + System.currentTimeMillis() + ".jpg";
final File sdImageMainDirectory = new File(root, fname);
outputFileUri = Uri.fromFile(sdImageMainDirectory);
// Camera.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final PackageManager packageManager = cordova.getActivity().getPackageManager();
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam){
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
cameraIntents.add(intent);
}
//FileSystem
final Intent galleryIntent = new Intent();
galleryIntent.setType("image/jpeg");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Image Source");
// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
startActivityForResult(chooserIntent, PICK_FILE_REQUEST);
And onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_FILE_REQUEST) {
if(data!=null){
Logv("Data","got some data");
}
}
}
Except samsung it is working fine in other mobiles
No, it is only working with the camera apps on the devices that you have tried. It generally will not work for ACTION_IMAGE_CAPTURE.
please let me know what i am doing wrong
You are assuming that ACTION_IMAGE_CAPTURE is supposed to return a result Intent. It is not required when you provide EXTRA_OUTPUT. You know where you asked for the image to be saved (the value you supplied to EXTRA_OUTPUT, so go look there for the image.
Note that there are some buggy camera apps that will ignore EXTRA_OUTPUT (storing the image where they want), so if the image from your ACTION_IMAGE_CAPTURE request is not in EXTRA_OUTPUT, you are out of luck.
I only want to call the system camera take picture not from the third-party. I can not get the result from the third-party or the method I can get result from the third party.
Below is my code;
Intent intent2 = new Intent();
Intent intent_camera = getPackageManager().getLaunchIntentForPackage("com.android.camera");
if (intent_camera != null) {
intent2.setPackage("com.android.camera");
}
intent2.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo: list) {
if (resolveInfo.activityInfo.applicationInfo.
// update to account for unlikely camera app update:
flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP))
// worse approach:
// sourceDir.startsWith("/system/app")) {
intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName, resolveInfo.activityInfo.name);
break;
}
}
startActivityForResult(intent, actionCode);
you have to do some thing like this. Implement onActivityResult to catch the result
String name = dateToString(new Date(), "yyyy-MM-dd-hh-mm-ss");
destination = new File(Environment
.getExternalStorageDirectory(), Filename + ".jpg");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(destination));
startActivityForResult(intent, PICK_Camera_IMAGE);
Is it possible to to start Gallery in such a way so both pictures and videos are shown?
Thanks
Pick Audio file from Gallery:
//Use MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
Pick Video file from Gallery:
//Use MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
Pick Image from gallery:
//Use MediaStore.Images.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Pick Media Files or images:
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/* video/*");
You start the gallery as such:
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/* video/*");
startActivityForResult(pickIntent, IMAGE_PICKER_SELECT);
then in your onActivityResult you can check if video or image was selected by doing this:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Uri selectedMediaUri = data.getData();
if (selectedMediaUri.toString().contains("image")) {
//handle image
} else if (selectedMediaUri.toString().contains("video")) {
//handle video
}
}
(EDIT: I don't use it anymore, we went back to the two choices "pick image" and "pick video". The problem was with some Sony phone. So, it's not 100% solution below, be careful! )
This is what I use:
if (Build.VERSION.SDK_INT < 19) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/* video/*");
startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.select_picture)), SELECT_GALLERY);
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
startActivityForResult(intent, SELECT_GALLERY_KITKAT);
}
The key here is intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
intent.setType("*/*");
This presents user with dialog but works on at least ICS. Haven't tested on other platforms.
When you need to determine what kind of content was returned, you can do it using content resolver to get the MIME type of the returned content:
if( data != null) {
Uri selectedUri = data.getData();
String[] columns = { MediaStore.Images.Media.DATA,
MediaStore.Images.Media.MIME_TYPE };
Cursor cursor = getContentResolver().query(selectedUri, columns, null, null, null);
cursor.moveToFirst();
int pathColumnIndex = cursor.getColumnIndex( columns[0] );
int mimeTypeColumnIndex = cursor.getColumnIndex( columns[1] );
String contentPath = cursor.getString(pathColumnIndex);
String mimeType = cursor.getString(mimeTypeColumnIndex);
cursor.close();
if(mimeType.startsWith("image")) {
//It's an image
}
else if(mimeType.startsWith("video")) {
//It's a video
}
}
else {
// show error or do nothing
}
CoolIris which came with my galaxy tab can do it. However the cooliris on my acer betouch will not :S
On my milestone you can not start the gallery with a pick intent on the video url however when you start it on the images url, you can select a video and it will return a video url too.
UPDATE 2021
FINALLY a solution working for Android 9.
This piece of code only open image apps, and you can select both images and videos. I tried a bunch of different combinations and this exact code will make it work.
libraryIntent.setType("video/*, image/*");
String[] mimetypes = {"image/*", "video/*"};
libraryIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
Still Working On Jan'2022
If This is Working For You Then Try it,
Intent intent = new Intent(Intent.ACTION_PICK, android.provider
.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/* video/*");
startActivityForResult(intent,PICK_FILE);
else For Older SDK's and For Some Devices Try the below one,
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
startActivityForResult(intent,PICK_FILE);
where, PICK_FILE is a variable,
private static final int PICK_FILE = 1;
This is working for me for Android 12 (SDK 32)
Pick multiple images & videos from the gallery
Also with the latest registerForActivityResult
val resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
onActivityResult(result)
}
fun pickMediaFiles() {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/* video/*"
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
resultLauncher.launch(intent)
}
fun onActivityResult(result: ActivityResult) {
if (result.resultCode == RESULT_OK && result.data != null) {
//If selected multiple medias
if (result.data?.clipData != null) {
val count: Int =
result.data!!.clipData!!.itemCount
for (i in 0 until count) {
val selectedUri: Uri? = result.data!!.clipData?.getItemAt(i)?.uri
}
}
//If selected single media
else if (result.data?.data != null) {
val selectedUri: Uri? = result.data?.data
}
}
}
You need use the following as picking Intent
Intent photoLibraryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoLibraryIntent.setType("image/* video/*");