Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added video capture support #322

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Changelog

**2.5.0**
- Add video capture functionality

**2.4.0**
- Add `getUri()` for convenient [#285](https://github.com/esafirm/android-image-picker/pull/285)
- Fixes for Android Q [#290](https://github.com/esafirm/android-image-picker/pull/290) [#293](https://github.com/esafirm/android-image-picker/pull/293)
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

<img src="https://github.com/esafirm/android-image-picker/blob/master/art/logo.png?raw=true" width="180" height="180"/>

# Forked from: https://github.com/esafirm/android-image-picker

A simple library to select images from the gallery and camera.

# Support Me!
Expand All @@ -23,7 +25,7 @@ Would you help me achieving this goals?
src="https://raw.githubusercontent.com/esafirm/android-image-picker/master/art/ss.gif" height="460" width="284"/>
</details>

## Download [![](https://jitpack.io/v/esafirm/android-image-picker.svg)](https://jitpack.io/#esafirm/android-image-picker)
## Download [![](https://jitpack.io/v/AhmedDroid/android-image-picker.svg)](https://jitpack.io/#AhmedDroid/android-image-picker)

Add this to your project's `build.gradle`

Expand All @@ -39,15 +41,15 @@ And add this to your module's `build.gradle`

```groovy
dependencies {
implementation 'com.github.esafirm.android-image-picker:imagepicker:x.y.z'
implementation 'com.github.AhmedDroid:android-image-picker:x.y.z'
// for experimental rx picker
implementation 'com.github.esafirm.android-image-picker:rximagepicker:x.y.z'
// If you have a problem with Glide, please use the same Glide version or simply open an issue
implementation 'com.github.bumptech.glide:glide:4.5.0'
}
```

change `x.y.z` to version in the [release page](https://github.com/esafirm/android-image-picker/releases)
change `x.y.z` to version in the [release page](https://github.com/AhmedDroid/android-image-picker/releases/)

# Usage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ public ImagePicker showCamera(boolean show) {
return this;
}

public ImagePicker showCamcorder(boolean show) {
config.setShowCamcorder(show);
return this;
}

public ImagePicker toolbarArrowColor(@ColorInt int color) {
config.setArrowColor(color);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ public boolean onPrepareOptionsMenu(Menu menu) {
menuDone.setTitle(ConfigUtils.getDoneButtonText(this, config));
menuDone.setVisible(imagePickerFragment.isShowDoneButton());
}

MenuItem menuCamcorder = menu.findItem(R.id.menu_camcorder);
if (menuCamcorder != null) {
if (config != null)
menuCamcorder.setVisible(config.isShowCamcorder());
}
return super.onPrepareOptionsMenu(menu);
}

Expand All @@ -126,6 +132,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
imagePickerFragment.captureImageWithPermission();
return true;
}
if (id == R.id.menu_camcorder) {
imagePickerFragment.captureVideoWithPermission();
return true;
}
return super.onOptionsItemSelected(item);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class ImagePickerConfig extends BaseConfig implements Parcelable {
private boolean onlyVideo;
private boolean includeAnimation;
private boolean showCamera;
private boolean showCamcorder;

private transient String language;

Expand Down Expand Up @@ -72,6 +73,14 @@ public void setShowCamera(boolean showCamera) {
this.showCamera = showCamera;
}

public boolean isShowCamcorder() {
return showCamcorder;
}

public void setShowCamcorder(boolean showCamcorder) {
this.showCamcorder = showCamcorder;
}

public boolean isIncludeVideo() {
return includeVideo;
}
Expand Down Expand Up @@ -202,6 +211,7 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeByte(this.onlyVideo ? (byte) 1 : (byte) 0);
dest.writeByte(this.includeAnimation ? (byte) 1 : (byte) 0);
dest.writeByte(this.showCamera ? (byte) 1 : (byte) 0);
dest.writeByte(this.showCamcorder ? (byte) 1 : (byte) 0);
}

protected ImagePickerConfig(Parcel in) {
Expand All @@ -226,6 +236,7 @@ protected ImagePickerConfig(Parcel in) {
this.onlyVideo = in.readByte() != 0;
this.includeAnimation = in.readByte() != 0;
this.showCamera = in.readByte() != 0;
this.showCamcorder = in.readByte() != 0;
}

public static final Creator<ImagePickerConfig> CREATOR = new Creator<ImagePickerConfig>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,26 @@ public void captureImageWithPermission() {
}
}

/**
* Request for camcorder permission
*/
public void captureVideoWithPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final boolean isCameraGranted = ActivityCompat
.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
final boolean isWriteGranted = ActivityCompat
.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (isCameraGranted && isWriteGranted) {
captureVideo();
} else {
logger.w("Camera permission is not granted. Requesting permission");
requestCameraPermissions();
}
} else {
captureVideo();
}
}

/**
* Start camera intent
* Create a temporary file and pass file Uri to camera intent
Expand All @@ -445,6 +465,17 @@ private void captureImage() {
presenter.captureImage(this, getBaseConfig(), RC_CAPTURE);
}

/**
* Start camcorder intent
* Create a temporary file and pass file Uri to camcorder intent
*/
private void captureVideo() {
if (!CameraHelper.checkCameraAvailability(getActivity())) {
return;
}
presenter.captureVideo(this, getBaseConfig(), RC_CAPTURE);
}

private void startContentObserver() {
if (isCameraOnly) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ void captureImage(Fragment fragment, BaseConfig config, int requestCode) {
fragment.startActivityForResult(intent, requestCode);
}

void captureVideo(Fragment fragment, BaseConfig config, int requestCode) {
Context context = fragment.getActivity().getApplicationContext();
Intent intent = getCameraModule().getCamcorderIntent(fragment.getActivity(), config);
if (intent == null) {
Toast.makeText(context, context.getString(R.string.ef_error_create_image_file), Toast.LENGTH_LONG).show();
return;
}
fragment.startActivityForResult(intent, requestCode);
}

void finishCaptureImage(Context context, Intent data, final BaseConfig config) {
getCameraModule().getImage(context, data, images -> {
if (ConfigUtils.shouldReturn(config, true)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.esafirm.imagepicker.features.common.BaseConfig

interface CameraModule {
fun getCameraIntent(context: Context, config: BaseConfig): Intent?
fun getCamcorderIntent(context: Context, config: BaseConfig): Intent?
fun getImage(context: Context, intent: Intent?, imageReadyListener: OnImageReadyListener?)
fun removeImage()
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ class DefaultCameraModule : CameraModule, Serializable {
return null
}

override fun getCamcorderIntent(context: Context, config: BaseConfig): Intent? {
prepareForNewIntent()

val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
val imageFile = ImagePickerUtils.createVideoFile(config.imageDirectory, context)

if (imageFile != null) {
val appContext = context.applicationContext
val uri = createCamCorderUri(appContext, imageFile)
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
ImagePickerUtils.grantAppPermission(context, intent, uri)
currentUri = uri.toString()
return intent
}
return null
}

private fun prepareForNewIntent() {
currentImagePath = null
currentUri = null
Expand All @@ -64,6 +81,20 @@ class DefaultCameraModule : CameraModule, Serializable {
return UriUtils.uriForFile(appContext, imageFile)
}

private fun createCamCorderUri(appContext: Context, imageFile: File): Uri? {
currentImagePath = "file:" + imageFile.absolutePath
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, imageFile.name)
put(MediaStore.Images.Media.MIME_TYPE, "video/mp4")
}
val collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
return appContext.contentResolver.insert(collection, values)
}
return UriUtils.uriForFile(appContext, imageFile)
}

override fun getImage(context: Context, intent: Intent?, imageReadyListener: OnImageReadyListener?) {
checkNotNull(imageReadyListener) { "OnImageReadyListener must not be null" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ public static File createImageFile(ImagePickerSavePath savePath, Context context
return result;
}

public static File createVideoFile(ImagePickerSavePath savePath, Context context) {
final File mediaStorageDir = createFileInDirectory(savePath, context);
if (mediaStorageDir == null) return null;

// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.getDefault()).format(new Date());
File result = new File(mediaStorageDir, "VID_" + timeStamp + ".mp4");
int counter = 0;
while (result.exists()) {
counter++;
result = new File(mediaStorageDir, "VID_" + timeStamp + "(" + counter + ").mp4");
}
return result;
}

public static String getNameFromFilePath(String path) {
if (path.contains(File.separator)) {
return path.substring(path.lastIndexOf(File.separator) + 1);
Expand Down
11 changes: 11 additions & 0 deletions imagepicker/src/main/res/drawable-anydpi/ef_ic_camcorder.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="1.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
</vector>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions imagepicker/src/main/res/menu/ef_image_picker_menu_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
app:showAsAction="always"
tools:ignore="AlwaysShowAction"/>

<item
android:id="@+id/menu_camcorder"
android:icon="@drawable/ef_ic_camcorder"
android:title="@string/ef_camera"
app:showAsAction="always"
tools:ignore="AlwaysShowAction"/>

<item
android:id="@+id/menu_done"
android:title="@string/ef_done"
Expand Down
3 changes: 2 additions & 1 deletion imagepicker/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
<string name="ef_selected">إخترت %d</string>
<string name="ef_selected_with_limit">إخترت %1$d/%2$d</string>

<string name="ef_error_create_image_file">حدث خطأ في تسجيل الصوره</string>
<string name="ef_error_create_image_file">حدث خطأ في إنشاء الصوره</string>
<string name="ef_error_create_video_file">حدث خطأ في إنشاء الفيديو</string>
<string name="ef_error_no_camera">لا يوجد كاميرا</string>
<string name="ef_error_null_cursor">عذراً، هناك خطأ ما!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-da/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d valgt</string>

<string name="ef_error_create_image_file">Fejl, kunne ikke oprette billedfilen</string>
<string name="ef_error_create_video_file">Failed to create Video file</string>
<string name="ef_error_no_camera">Kamera blev ikke fundet</string>
<string name="ef_error_null_cursor">Beklager, der er sket en fejl!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d ausgewählt</string>

<string name="ef_error_create_image_file">Fehler beim Erstellen der Bilddatei</string>
<string name="ef_error_create_video_file">Failed to create Video file</string>
<string name="ef_error_no_camera">Keine Kamera gefunden</string>
<string name="ef_error_null_cursor">Ups, da ist was schiefgegangen!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d sélectionnées</string>

<string name="ef_error_create_image_file">Impossible de créer le fichier photo</string>
<string name="ef_error_create_video_file">Échec de la création du fichier vidéo</string>
<string name="ef_error_no_camera">Aucune caméra détectée</string>
<string name="ef_error_null_cursor">Oups, quelque chose s\'est mal déroulé!</string>

Expand Down
3 changes: 2 additions & 1 deletion imagepicker/src/main/res/values-in/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
<string name="ef_selected">%d terpilih</string>
<string name="ef_selected_with_limit">%1$d/%2$d terpilih</string>

<string name="ef_error_create_image_file">Gagal membuat berkas gambar</string>
<string name="ef_error_create_image_file">Gagal membuat file Gambar</string>
<string name="ef_error_create_video_file">Gagal membuat file Video</string>
<string name="ef_error_no_camera">Kamera tidak ditemukan</string>
<string name="ef_error_null_cursor">Ups, ada yang tidak beres!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d selezionate</string>

<string name="ef_error_create_image_file">Si è verificato un problema nella creazione dell\'immagine</string>
<string name="ef_error_create_video_file">Si è verificato un problema nella creazione dell\'video</string>
<string name="ef_error_no_camera">Nessuna fotocamera trovata</string>
<string name="ef_error_null_cursor">Oops, qualcosa è andato storto!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-ko/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d 선택됨</string>

<string name="ef_error_create_image_file">이미지 생성에 실패하였습니다.</string>
<string name="ef_error_create_video_file">비디오 파일을 생성하지 못했습니다.</string>
<string name="ef_error_no_camera">카메라를 찾을 수 없습니다.</string>
<string name="ef_error_null_cursor">알 수 없는 오류가 발생하였습니다.</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d selecionadas</string>

<string name="ef_error_create_image_file">Erro ao criar arquivo de imagem</string>
<string name="ef_error_create_video_file">Falha ao criar arquivo de vídeo</string>
<string name="ef_error_no_camera">Câmera não encontrada</string>
<string name="ef_error_null_cursor">Ops, algo deu errado!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-ro/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d selectate</string>

<string name="ef_error_create_image_file">Nu am putut crea imaginea</string>
<string name="ef_error_create_video_file">Nu s-a putut crea fișierul video</string>
<string name="ef_error_no_camera">Camera foto nu a fost găsită</string>
<string name="ef_error_null_cursor">Hopa, ceva a mers prost!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<string name="ef_selected">%d выбрано</string>
<string name="ef_selected_with_limit">%1$d/%2$d выбрано</string>
<string name="ef_error_create_image_file">Не удалось создать файл</string>
<string name="ef_error_create_video_file">Не удалось создать видео файл</string>
<string name="ef_error_no_camera">Камера недоступна</string>
<string name="ef_error_null_cursor">Ой! Что-то пошло не так!</string>
<string name="ef_msg_empty_images">Изображений не найдено</string>
Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-tr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<string name="ef_selected_with_limit">%1$d/%2$d seçili</string>

<string name="ef_error_create_image_file">Resim dosyası oluşturulamadı</string>
<string name="ef_error_create_video_file">Video dosyası oluşturulamadı</string>
<string name="ef_error_no_camera">Kamera bulunamadı</string>
<string name="ef_error_null_cursor">Hoop! Birşeyler yanlış gitti!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-uk/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<string name="ef_selected">%d обрано</string>
<string name="ef_selected_with_limit">%1$d/%2$d обрано</string>
<string name="ef_error_create_image_file">Не вдалося створити файл</string>
<string name="ef_error_create_video_file">Не вдалося створити відеофайл</string>
<string name="ef_error_no_camera">Камера недоступна</string>
<string name="ef_error_null_cursor">Ой! Щось пішло не так!</string>
<string name="ef_msg_empty_images">Зображень не знайдено</string>
Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<string name="ef_selected_with_limit">已选择 %1$d/%2$d</string>

<string name="ef_error_create_image_file">建立照片文件失败</string>
<string name="ef_error_create_video_file">创建视频文件失败</string>
<string name="ef_error_no_camera">找不到相机</string>
<string name="ef_error_null_cursor">啊哦,发生错误!</string>

Expand Down
1 change: 1 addition & 0 deletions imagepicker/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<string name="ef_selected_with_limit">已選擇 %1$d/%2$d</string>

<string name="ef_error_create_image_file">建立相片檔案失敗</string>
<string name="ef_error_create_video_file">創建視頻文件失敗</string>
<string name="ef_error_no_camera">找不到相機</string>
<string name="ef_error_null_cursor">噢,發生問題</string>

Expand Down
Loading