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

添加视频选择页面内的录像功能 #9

Open
wants to merge 7 commits into
base: master
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
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public void onClick(View v) {
Boxing.of().withIntent(this, BoxingActivity.class).start(this, REQUEST_CODE);
break;
case R.id.video_btn:
BoxingConfig videoConfig = new BoxingConfig(BoxingConfig.Mode.VIDEO);
BoxingConfig videoConfig = new BoxingConfig(BoxingConfig.Mode.VIDEO).needCamera();
Boxing.of(videoConfig).withIntent(this, BoxingActivity.class).start(this, REQUEST_CODE);
break;
case R.id.outside_bs_btn:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.bilibili.boxing.model.BoxingManager;
import com.bilibili.boxing.model.config.BoxingConfig;
Expand Down Expand Up @@ -177,10 +178,16 @@ private static class ImageViewHolder extends RecyclerView.ViewHolder {

private static class CameraViewHolder extends RecyclerView.ViewHolder {
View mCameraLayout;
ImageView imageView;

CameraViewHolder(final View itemView) {
super(itemView);
mCameraLayout = itemView.findViewById(R.id.camera_layout);
imageView = (ImageView) itemView.findViewById(R.id.camera_txt);

if (BoxingManager.getInstance().getBoxingConfig().isVideoMode()) {
imageView.setImageResource(R.drawable.ic_video_white);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
Expand Down Expand Up @@ -99,9 +100,9 @@ public void onViewCreated(View view, Bundle savedInstanceState) {


@Override
public void onCameraActivityResult(int requestCode, int resultCode) {
public void onCameraActivityResult(int requestCode, int resultCode, Intent data) {
showProgressDialog();
super.onCameraActivityResult(requestCode, resultCode);
super.onCameraActivityResult(requestCode, resultCode, data);
}

private void showProgressDialog() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ private void onViewActivityRequest(List<BaseMedia> selectedMedias, List<BaseMedi


@Override
public void onCameraActivityResult(int requestCode, int resultCode) {
public void onCameraActivityResult(int requestCode, int resultCode, Intent data) {
showProgressDialog();
super.onCameraActivityResult(requestCode, resultCode);
super.onCameraActivityResult(requestCode, resultCode, data);
}

private void showProgressDialog() {
Expand Down
Binary file added boxing-impl/src/main/res/drawable-hdpi/ic_video.png
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.
Binary file added boxing-impl/src/main/res/drawable-mdpi/ic_video.png
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.
Binary file added boxing-impl/src/main/res/drawable-xhdpi/ic_video.png
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.
4 changes: 2 additions & 2 deletions boxing-impl/src/main/res/layout/layout_recycleview_header.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

<ImageView
android:id="@+id/camera_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_camera_white"
android:textColor="@color/white"
Expand Down
66 changes: 54 additions & 12 deletions boxing/src/main/java/com/bilibili/boxing/AbsBoxingViewFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
Expand All @@ -38,6 +41,7 @@
import com.bilibili.boxing.model.entity.AlbumEntity;
import com.bilibili.boxing.model.entity.BaseMedia;
import com.bilibili.boxing.model.entity.impl.ImageMedia;
import com.bilibili.boxing.model.entity.impl.VideoMedia;
import com.bilibili.boxing.presenter.PickerContract;
import com.bilibili.boxing.utils.CameraPickerHelper;

Expand Down Expand Up @@ -300,8 +304,8 @@ public final void setPickerConfig(@NonNull BoxingConfig config) {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (mCameraPicker != null && requestCode == CameraPickerHelper.REQ_CODE_CAMERA) {
onCameraActivityResult(requestCode, resultCode);
if (mCameraPicker != null && requestCode == CameraPickerHelper.REQ_CODE_CAMERA || requestCode == CameraPickerHelper.REQ_CODE_REC) {
onCameraActivityResult(requestCode, resultCode, data);
}
if (hasCropBehavior()) {
onCropActivityResult(requestCode, resultCode, data);
Expand Down Expand Up @@ -395,8 +399,8 @@ public final void onLoadNextPage() {
* successfully get result from camera in {@link #onActivityResult(int, int, Intent)}.
* call this after other operations.
*/
public void onCameraActivityResult(int requestCode, int resultCode) {
mCameraPicker.onActivityResult(requestCode, resultCode);
public void onCameraActivityResult(int requestCode, int resultCode, Intent data) {
mCameraPicker.onActivityResult(requestCode, resultCode, data);
}

/**
Expand Down Expand Up @@ -424,7 +428,9 @@ public final void startCamera(Activity activity, Fragment fragment, String subFo
if (!BoxingBuilderConfig.TESTING && ContextCompat.checkSelfPermission(getActivity(), CAMERA_PERMISSIONS[0]) != PERMISSION_GRANTED) {
requestPermissions(CAMERA_PERMISSIONS, REQUEST_CODE_PERMISSION);
} else {
if (!BoxingManager.getInstance().getBoxingConfig().isVideoMode()) {
if (BoxingManager.getInstance().getBoxingConfig().isVideoMode()) {
mCameraPicker.startRecord(activity, fragment, subFolderPath);
} else {
mCameraPicker.startCamera(activity, fragment, subFolderPath);
}
}
Expand All @@ -446,15 +452,51 @@ public void onFinish(@NonNull CameraPickerHelper helper) {
if (fragment == null) {
return;
}
File file = new File(helper.getSourceFilePath());

if (!file.exists()) {
onError(helper);
return;
String filePath = helper.getSourceFilePath();
if (BoxingManager.getInstance().getBoxingConfig().isVideoMode()) {
File file = new File(filePath);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(filePath);

String size = String.valueOf(file.length());
String date = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
String dur = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
String title = file.getName();
String type = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);

ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, filePath);
values.put(MediaStore.Video.Media.TITLE, title);
values.put(MediaStore.Video.Media.MIME_TYPE, type);
values.put(MediaStore.Video.Media.SIZE, size);
values.put(MediaStore.Video.Media.DATE_TAKEN, date);
values.put(MediaStore.Video.Media.DURATION, dur);
fragment
.getContext()
.getContentResolver()
.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);

VideoMedia media = new VideoMedia.Builder("", filePath)
.setTitle(title)
.setDuration(dur)
.setSize(size)
.setDateTaken(date)
.setMimeType(type)
.build();
fragment.onCameraFinish(media);
} else {
File file = new File(filePath);

if (!file.exists()) {
onError(helper);
return;
}

ImageMedia cameraMedia = new ImageMedia(file);
cameraMedia.saveMediaStore(fragment.getAppCr());
fragment.onCameraFinish(cameraMedia);
}
ImageMedia cameraMedia = new ImageMedia(file);
cameraMedia.saveMediaStore(fragment.getAppCr());
fragment.onCameraFinish(cameraMedia);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public Builder setSize(String size) {
return this;
}

public Builder setDataTaken(String dateTaken) {
public Builder setDateTaken(String dateTaken) {
this.mDateTaken = dateTaken;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private void loadVideos(ContentResolver cr, int page, @NonNull final IMediaTaskC
String date = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN));
String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION));
VideoMedia video = new VideoMedia.Builder(id, data).setTitle(title).setDuration(duration)
.setSize(size).setDataTaken(date).setMimeType(type).build();
.setSize(size).setDateTaken(date).setMimeType(type).build();
videoMedias.add(video);

} while (cursor.moveToNext() && !cursor.isLast() && !cursor.isLast());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
*/
public class CameraPickerHelper {
public static final int REQ_CODE_CAMERA = 0x2001;
public static final int REQ_CODE_REC = 0x1774;
private static final String STATE_SAVED_KEY = "com.bilibili.boxing.utils.CameraPickerHelper.saved_state";

private String mSourceFilePath;
Expand Down Expand Up @@ -122,6 +123,35 @@ public Boolean call() throws Exception {
}
}

/**
* start system camera to record a video
*
* @param activity not null if fragment is null.
* @param fragment not null if activity is null.
* @param subFolderPath a folder in external DCIM, must start with "/".
*/
public void startRecord(Activity activity, Fragment fragment, String subFolderPath) {
String cameraOutDir = BoxingFileHelper.getExternalDCIM(subFolderPath);
try {
if (BoxingFileHelper.createFile(cameraOutDir)) {
mOutputFile = new File(cameraOutDir, String.valueOf(System.currentTimeMillis()) + ".mp4");
mSourceFilePath = mOutputFile.getPath();
Uri uri = getFileUri(activity.getApplicationContext(), mOutputFile);

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0.9);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
try {
startActivityForResult(activity, fragment, intent, REQ_CODE_REC);
} catch (ActivityNotFoundException ignore) {
callbackError();
}
}
} catch (ExecutionException | InterruptedException e) {
BoxingLog.d("create file" + cameraOutDir + " error.");
}
}

private boolean takePhotoSecure(Activity activity, Fragment fragment, String subDir) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
try {
Expand Down Expand Up @@ -193,30 +223,37 @@ public String getSourceFilePath() {
/**
* deal with the system camera's shot.
*/
public boolean onActivityResult(final int requestCode, final int resultCode) {
if (requestCode != REQ_CODE_CAMERA) {
return false;
}
public boolean onActivityResult(final int requestCode, final int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
callbackError();
return false;
}
FutureTask<Boolean> task = BoxingExecutor.getInstance().runWorker(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return rotateImage(resultCode);
}
});
try {
if (task != null && task.get()) {
callbackFinish();
} else {

if (requestCode == REQ_CODE_CAMERA) {
FutureTask<Boolean> task = BoxingExecutor.getInstance().runWorker(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return rotateImage(resultCode);
}
});
try {
if (task != null && task.get()) {
callbackFinish();
} else {
callbackError();
}
} catch (InterruptedException | ExecutionException ignore) {
callbackError();
}
} catch (InterruptedException | ExecutionException ignore) {
callbackError();
return true;
} else if (requestCode == REQ_CODE_REC) {
Uri uri = data.getData();
if (uri == null) {
return false;
}
callbackFinish();
}
return true;
return false;
}

private boolean rotateSourceFile(File file) throws IOException {
Expand Down