Commit d7f9680c by mReturn

学习模块功能开发

parent 634b34c9
Showing with 5592 additions and 176 deletions
......@@ -141,7 +141,11 @@ public class MainPresenter extends MainContract.Presenter {
@Override
public void getUserInfo(int accountId) {
UserApiFactory.getEngineerInfo(accountId).subscribe(baseObserver(
engineerInfo -> SPUtils.put("USER_IDENTITY", engineerInfo.getIdentity())));
engineerInfo -> {
SPUtils.put("USER_IDENTITY", engineerInfo.getIdentity());
mUser.setMobile(engineerInfo.getMobile());
UserManager.getInstance().saveUser(mUser);
}));
}
}
......@@ -70,7 +70,8 @@ dependencies {
api 'com.journeyapps:zxing-android-embedded:3.5.0'
api project(':locationComponent')
api project(':pickerview')
api 'cn.jzvd:jiaozivideoplayer:7.2.4'
// api 'cn.jzvd:jiaozivideoplayer:7.2.4'
api 'cn.jzvd:jiaozivideoplayer:7.1.0'
api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.35'
api 'com.badoo.mobile:android-weak-handler:1.1'
api 'com.youth.banner:banner:1.4.10'
......@@ -79,8 +80,9 @@ dependencies {
api 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.0'
api 'com.google.android:flexbox:1.0.0'
api 'com.github.chrisbanes:PhotoView:2.0.0'
api 'cjt.library.wheel:camera:1.1.9'
// api 'cjt.library.wheel:camera:1.1.9'
api project(':umeng')
api project(':camera')
}
......@@ -51,6 +51,17 @@ public interface APIService {
@Part MultipartBody.Part part);
/**
* 上传单个视频.
*
* @param part
* @return
*/
@Multipart
@POST(Constants.UP_VIDEO)
Observable<BaseResponse<String>> uploadVideo(
@Part MultipartBody.Part part);
/**
* 上传图片多张,无水印.
*
* @param partMap
......
......@@ -19,6 +19,9 @@ public class BaseApiFactory {
public static Observable<List<String>> uploadPhoto(MultipartBody.Part part) {
return Api.getService(APIService.class).uploadPhoto(part).compose(Api.applySchedulers());
}
public static Observable<String> uploadVideo(MultipartBody.Part part) {
return Api.getService(APIService.class).uploadVideo(part).compose(Api.applySchedulers());
}
public static Observable<List<String>> uploadPhoto(MultipartBody.Part[] part, String style) {
return Api.getService(APIService.class).uploadPhoto(part, style).compose(Api.applySchedulers());
......
......@@ -46,7 +46,7 @@ public class CameraActivity extends AppCompatActivity {
jCameraView = (JCameraView) findViewById(R.id.jcameraview);
//设置视频保存路径
jCameraView.setSaveVideoPath(Environment.getExternalStorageDirectory().getPath() + File.separator + VIDEO_PATH);
jCameraView.setMediaQuality(JCameraView.MEDIA_QUALITY_HIGH*10);
jCameraView.setMediaQuality(JCameraView.MEDIA_QUALITY_HIGH);
if (getIntent().hasExtra(Constants.ONLY_VIDEO)) {
jCameraView.setTip(getResources().getString(R.string.moment_take_video));
jCameraView.setFeatures(jCameraView.BUTTON_STATE_ONLY_RECORDER);
......@@ -85,6 +85,10 @@ public class CameraActivity extends AppCompatActivity {
public void recordSuccess(String url, Bitmap firstFrame) {
//获取视频路径
String path = FileUtil.saveBitmap(VIDEO_PATH, firstFrame);
final File file = new File(url);
if (file.exists())
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(file.getPath()))));
// sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
// if (getIntent().hasExtra(Constants.ONLY_VIDEO)){
//// EventBus.getDefault().post(new VideoRecordedEvent(path,url));
// }else {
......@@ -93,9 +97,6 @@ public class CameraActivity extends AppCompatActivity {
intent.putExtra("videoPath", url);
setResult(Constants.CAMERA_VIDEO, intent);
Uri localUri = Uri.parse(url);
Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri);
sendBroadcast(localIntent);
// }
finish();
}
......
......@@ -33,12 +33,13 @@ public class Constants {
public static final String INVITE_NEW_SHARE_URL = "http://app.dl.kf.ai/ext/#/shareMaster?code="; //邀请新人分享链接
/**
* 测试环境配置.
* dev环境配置.
*/
public static final int LOG_LEVEL = LogUtils.LEVEL_ALL;
public static final String ENVIROMENT = "debug";
public static final String BASE_URL = "http://47.94.101.239:3112";
public final static String UP_PHOTO = "/file/uploadMore?targetPath=test/sp/mobile/android/business/checkApply";
public final static String UP_VIDEO = "/file/uploadVideoOne?targetPath=dev/video";
public final static String WEB_SOP = "http://47.94.101.239:9004/#/sop";
public final static String CHECK_MULTI_WEB_SOP = "http://47.94.101.239:9004/#/manyServiceResult";
public final static String MULTI_WEB_SOP = "http://47.94.101.239:9004/#/manySop";
......@@ -47,12 +48,13 @@ public class Constants {
public static final boolean IS_DEBUG = true;
/**
* uat环境配置.
* uat测试环境配置.
*/
// public static final String ENVIROMENT = "uat";
// public static final int LOG_LEVEL = LogUtils.LEVEL_ALL;
// public static final String BASE_URL = "http://47.95.223.6:3112";
// public final static String UP_PHOTO = "/file/uploadMore?targetPath=test/sp/mobile/android/business/checkApply";
// public final static String UP_VIDEO = "/file/uploadVideoOne?targetPath=test/video";
// public final static String WEB_SOP = "http://47.95.223.6:9004/#/sop";
// public final static String WEB_SOP_DETAIL = "http://47.95.223.6:9004/#/sopdetail";
// public final static String WEB_ZHI_SHI = "http://47.95.223.6:9004/#/detail";
......@@ -67,6 +69,7 @@ public class Constants {
// public static final int LOG_LEVEL = LogUtils.LEVEL_OFF;
// public static final String BASE_URL = "https://mobile.kf.ai";
// public final static String UP_PHOTO = "/file/uploadMore?targetPath=online/sp/mobile/android/business/checkApply";
// public final static String UP_VIDEO = "/file/uploadVideoOne?targetPath=online/video";
// public final static String WEB_SOP = "https://sop.kf.ai/#/sop";
// public final static String WEB_SOP_DETAIL = "https://sop.kf.ai/#/sopdetail";
// public final static String WEB_ZHI_SHI = "https://sop.kf.ai/#/detail";
......@@ -178,6 +181,7 @@ public class Constants {
public final static String ORDER_ID = "orderId";
public final static String ORDER_SOURCE = "order_source"; //1.服务站自建 4.小程序单 5.服务商自建 6.服务商EU单
public final static String TO_DETAIL = "toDetail";
public final static String DETAIL = "detail";
public final static String UMENG_DEVICE_TOKEN = "umeng_device_token";
public final static String ORDER_POSTION = "order_position";
//是否显示去设置alipay账户de对话框
......
......@@ -34,6 +34,15 @@ public class UserInfo {
private int status;
private int detectStatus;
private List<Integer> roles;
private String mobile;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public List<Integer> getRoles() {
return roles;
......
......@@ -4,10 +4,12 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.TextView;
import com.dayu.baselibrary.R;
......@@ -26,6 +28,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import cn.jzvd.JzvdStd;
/**
* Created by mReturn
* on 2020\1\8 0008.
......@@ -228,6 +232,28 @@ public class CommonUtils {
}
}
/**
* 获取视频时长
* @param videoPath
* @return 毫秒
*/
public static long getVideoLength(String videoPath) {
long duration;
try {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(videoPath);
duration = Long.parseLong(mmr.extractMetadata
(MediaMetadataRetriever.METADATA_KEY_DURATION));
} catch (Exception e) {
e.printStackTrace();
return 0;
}
return duration;
}
public static void setVideoThumb(Context context, JzvdStd jzvdStd, String url) {
GlideImageLoader.load(context, jzvdStd.thumbImageView,url, R.drawable.icon_video_default);
}
/**
* 微信(朋友圈)分享链接(包含标题内容)
......
......@@ -41,7 +41,9 @@ public class MediaChooseUtils {
* 选择单个视频
*/
public static void chooseSigleVideo(Activity activity,int videoLength) {
chooseMedia(activity,PictureMimeType.ofVideo(),1,videoLength);
// chooseMedia(activity,PictureMimeType.ofVideo(),1,videoLength);
PictureSelectionModel selector = getPictureSelectionModel(activity, PictureMimeType.ofVideo(),1, videoLength);
selector.isCamera(false).forResult(PictureConfig.CHOOSE_REQUEST);
}
/**
......
......@@ -24,6 +24,8 @@ public class SPUtils {
* @param object 存储的数据类型
*/
public static void put(String key, Object object) {
if (object == null)
return;
SharedPreferences sp = BaseApplication.getContext().getSharedPreferences(FILE_NAME,
Context.MODE_PRIVATE);
......
......@@ -327,4 +327,8 @@ public class LRecyclerView<M, B> extends FrameLayout {
public void setOnEndListener(onEndListener listener) {
onEndListener = listener;
}
public void addOnChildAttachStateChangeListener(RecyclerView.OnChildAttachStateChangeListener listener){
recyclerview.addOnChildAttachStateChangeListener(listener);
}
}
......@@ -2,6 +2,7 @@ package com.dayu.widgets;
import android.app.Activity;
import android.app.Dialog;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
......@@ -33,6 +34,43 @@ public class TextDialog {
}
public void showBottomDialog(final Activity activity, List<String> strs,onItemClickListener listener) {
View mView = View.inflate(activity, R.layout.dialog_text_bottom , null);
RecyclerView recyclerView = mView.findViewById(R.id.rv_text);
BaseQuickAdapter<String,BaseViewHolder> mAdapter = new BaseQuickAdapter<String, BaseViewHolder>
(R.layout.item_dialog_text_bottom,strs) {
@Override
protected void convert(BaseViewHolder helper, String item) {
helper.setText(R.id.tv_text,item);
}
};
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
recyclerView.setAdapter(mAdapter);
recyclerView.addItemDecoration(new DividerItemDecoration(activity,DividerItemDecoration.VERTICAL));
Dialog textDialog = new Dialog(activity, R.style.CustomDialog);
textDialog.setContentView(mView);
Window window = textDialog.getWindow();
WindowManager.LayoutParams wl = window.getAttributes();
wl.width = ViewGroup.LayoutParams.MATCH_PARENT;
wl.height = ViewGroup.LayoutParams.WRAP_CONTENT;
wl.gravity = Gravity.BOTTOM;
textDialog.onWindowAttributesChanged(wl);
textDialog.show();
textDialog.setCanceledOnTouchOutside(true);
textDialog.setCancelable(true);
mAdapter.setOnItemClickListener((adapter,view,pos)->{
if (listener != null){
listener.onClick(pos);
}
textDialog.dismiss();
});
}
public void showCenterDialog(final Activity activity, List<String> strs,onItemClickListener listener) {
View mView = View.inflate(activity, R.layout.dialog_text , null);
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp"/>
<solid android:color="#aaa"/>
</shape>
\ No newline at end of file
......@@ -9,7 +9,7 @@
android:id="@+id/jcameraview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:duration_max="10000"
app:duration_max="180000"
app:iconLeft="@drawable/ic_back"
app:iconMargin="20dp"
app:iconRight="@null"
......
......@@ -2,6 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_text"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:gravity="center"
android:padding="10dp"
android:text='aaa'
android:textColor="@color/cl_home_title_text_color"
......
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:text='aaa'
android:textColor="@color/cl_home_title_text_color"
android:textSize="@dimen/sp_14" />
\ No newline at end of file
......@@ -98,7 +98,6 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:orientation">horizontal</item>
<item name="android:gravity">center_vertical</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:layout_marginLeft">5dp</item>
<item name="android:layout_marginRight">5dp</item>
......@@ -202,7 +201,7 @@
<style name="btn_common_gray" parent="btn_common">
<item name="android:background">@drawable/tab_gray_react</item>
<item name="android:background">@drawable/btn_grayaa_commom</item>
</style>
<style name="btn_common_blue" parent="btn_common">
<item name="android:background">@drawable/tab_blue_react</item>
......
apply plugin: 'com.android.library'
android {
compileSdkVersion compile_sdk_version
buildToolsVersion build_tools_version
defaultConfig {
minSdkVersion min_sdk_version
targetSdkVersion target_sdk_version
versionCode version_code
versionName verson_name
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled isReleaseMinify
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api 'com.android.support:design:27.1.1'
// api project(':apt')
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\AndroidStudio\AndroidSDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
package com.cjt2325.cameralibrary;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cjt2325.cameralibrary">
<application android:allowBackup="true" android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>
package com.cjt2325.cameralibrary;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.widget.ImageView;
import com.cjt2325.cameralibrary.listener.ErrorListener;
import com.cjt2325.cameralibrary.util.AngleUtil;
import com.cjt2325.cameralibrary.util.CameraParamUtil;
import com.cjt2325.cameralibrary.util.CheckPermission;
import com.cjt2325.cameralibrary.util.DeviceUtil;
import com.cjt2325.cameralibrary.util.FileUtil;
import com.cjt2325.cameralibrary.util.LogUtil;
import com.cjt2325.cameralibrary.util.ScreenUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static android.graphics.Bitmap.createBitmap;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/25
* 描 述:camera操作单例
* =====================================
*/
@SuppressWarnings("deprecation")
public class CameraInterface implements Camera.PreviewCallback {
private static final String TAG = "CJT";
private volatile static CameraInterface mCameraInterface;
public static void destroyCameraInterface() {
if (mCameraInterface != null) {
mCameraInterface = null;
}
}
private Camera mCamera;
private Camera.Parameters mParams;
private boolean isPreviewing = false;
private int SELECTED_CAMERA = -1;
private int CAMERA_POST_POSITION = -1;
private int CAMERA_FRONT_POSITION = -1;
private SurfaceHolder mHolder = null;
private float screenProp = -1.0f;
private boolean isRecorder = false;
private MediaRecorder mediaRecorder;
private String videoFileName;
private String saveVideoPath;
private String videoFileAbsPath;
private Bitmap videoFirstFrame = null;
private ErrorListener errorLisenter;
private ImageView mSwitchView;
private ImageView mFlashLamp;
private int preview_width;
private int preview_height;
private int angle = 0;
private int cameraAngle = 90;//摄像头角度 默认为90度
private int rotation = 0;
private byte[] firstFrame_data;
public static final int TYPE_RECORDER = 0x090;
public static final int TYPE_CAPTURE = 0x091;
private int nowScaleRate = 0;
private int recordScleRate = 0;
//视频质量
private int mediaQuality = JCameraView.MEDIA_QUALITY_MIDDLE;
private SensorManager sm = null;
//获取CameraInterface单例
public static synchronized CameraInterface getInstance() {
if (mCameraInterface == null)
synchronized (CameraInterface.class) {
if (mCameraInterface == null)
mCameraInterface = new CameraInterface();
}
return mCameraInterface;
}
public void setSwitchView(ImageView mSwitchView, ImageView mFlashLamp) {
this.mSwitchView = mSwitchView;
this.mFlashLamp = mFlashLamp;
if (mSwitchView != null) {
cameraAngle = CameraParamUtil.getInstance().getCameraDisplayOrientation(mSwitchView.getContext(),
SELECTED_CAMERA);
}
}
private SensorEventListener sensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent event) {
if (Sensor.TYPE_ACCELEROMETER != event.sensor.getType()) {
return;
}
float[] values = event.values;
angle = AngleUtil.getSensorAngle(values[0], values[1]);
rotationAnimation();
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
//切换摄像头icon跟随手机角度进行旋转
private void rotationAnimation() {
if (mSwitchView == null) {
return;
}
if (rotation != angle) {
int start_rotaion = 0;
int end_rotation = 0;
switch (rotation) {
case 0:
start_rotaion = 0;
switch (angle) {
case 90:
end_rotation = -90;
break;
case 270:
end_rotation = 90;
break;
}
break;
case 90:
start_rotaion = -90;
switch (angle) {
case 0:
end_rotation = 0;
break;
case 180:
end_rotation = -180;
break;
}
break;
case 180:
start_rotaion = 180;
switch (angle) {
case 90:
end_rotation = 270;
break;
case 270:
end_rotation = 90;
break;
}
break;
case 270:
start_rotaion = 90;
switch (angle) {
case 0:
end_rotation = 0;
break;
case 180:
end_rotation = 180;
break;
}
break;
}
ObjectAnimator animC = ObjectAnimator.ofFloat(mSwitchView, "rotation", start_rotaion, end_rotation);
ObjectAnimator animF = ObjectAnimator.ofFloat(mFlashLamp, "rotation", start_rotaion, end_rotation);
AnimatorSet set = new AnimatorSet();
set.playTogether(animC, animF);
set.setDuration(500);
set.start();
rotation = angle;
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
void setSaveVideoPath(String saveVideoPath) {
this.saveVideoPath = saveVideoPath;
File file = new File(saveVideoPath);
if (!file.exists()) {
file.mkdirs();
}
}
public void setZoom(float zoom, int type) {
if (mCamera == null) {
return;
}
if (mParams == null) {
mParams = mCamera.getParameters();
}
if (!mParams.isZoomSupported() || !mParams.isSmoothZoomSupported()) {
return;
}
switch (type) {
case TYPE_RECORDER:
//如果不是录制视频中,上滑不会缩放
if (!isRecorder) {
return;
}
if (zoom >= 0) {
//每移动50个像素缩放一个级别
int scaleRate = (int) (zoom / 40);
if (scaleRate <= mParams.getMaxZoom() && scaleRate >= nowScaleRate && recordScleRate != scaleRate) {
mParams.setZoom(scaleRate);
mCamera.setParameters(mParams);
recordScleRate = scaleRate;
}
}
break;
case TYPE_CAPTURE:
if (isRecorder) {
return;
}
//每移动50个像素缩放一个级别
int scaleRate = (int) (zoom / 50);
if (scaleRate < mParams.getMaxZoom()) {
nowScaleRate += scaleRate;
if (nowScaleRate < 0) {
nowScaleRate = 0;
} else if (nowScaleRate > mParams.getMaxZoom()) {
nowScaleRate = mParams.getMaxZoom();
}
mParams.setZoom(nowScaleRate);
mCamera.setParameters(mParams);
}
LogUtil.i("setZoom = " + nowScaleRate);
break;
}
}
void setMediaQuality(int quality) {
this.mediaQuality = quality;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
firstFrame_data = data;
}
public void setFlashMode(String flashMode) {
if (mCamera == null)
return;
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(flashMode);
mCamera.setParameters(params);
}
public interface CameraOpenOverCallback {
void cameraHasOpened();
}
private CameraInterface() {
findAvailableCameras();
SELECTED_CAMERA = CAMERA_POST_POSITION;
saveVideoPath = "";
}
/**
* open Camera
*/
void doOpenCamera(CameraOpenOverCallback callback) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (!CheckPermission.isCameraUseable(SELECTED_CAMERA) && this.errorLisenter != null) {
this.errorLisenter.onError();
return;
}
}
if (mCamera == null) {
openCamera(SELECTED_CAMERA);
}
callback.cameraHasOpened();
}
private void setFlashModel() {
mParams = mCamera.getParameters();
mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); //设置camera参数为Torch模式
mCamera.setParameters(mParams);
}
private synchronized void openCamera(int id) {
try {
this.mCamera = Camera.open(id);
} catch (Exception var3) {
var3.printStackTrace();
if (this.errorLisenter != null) {
this.errorLisenter.onError();
}
}
if (Build.VERSION.SDK_INT > 17 && this.mCamera != null) {
try {
this.mCamera.enableShutterSound(false);
} catch (Exception e) {
e.printStackTrace();
Log.e("CJT", "enable shutter sound faild");
}
}
}
public synchronized void switchCamera(SurfaceHolder holder, float screenProp) {
if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
SELECTED_CAMERA = CAMERA_FRONT_POSITION;
} else {
SELECTED_CAMERA = CAMERA_POST_POSITION;
}
doDestroyCamera();
LogUtil.i("open start");
openCamera(SELECTED_CAMERA);
// mCamera = Camera.open();
if (Build.VERSION.SDK_INT > 17 && this.mCamera != null) {
try {
this.mCamera.enableShutterSound(false);
} catch (Exception e) {
e.printStackTrace();
}
}
LogUtil.i("open end");
doStartPreview(holder, screenProp);
}
/**
* doStartPreview
*/
public void doStartPreview(SurfaceHolder holder, float screenProp) {
if (isPreviewing) {
LogUtil.i("doStartPreview isPreviewing");
}
if (this.screenProp < 0) {
this.screenProp = screenProp;
}
if (holder == null) {
return;
}
this.mHolder = holder;
if (mCamera != null) {
try {
mParams = mCamera.getParameters();
Camera.Size previewSize = CameraParamUtil.getInstance().getPreviewSize(mParams
.getSupportedPreviewSizes(), 1000, screenProp);
Camera.Size pictureSize = CameraParamUtil.getInstance().getPictureSize(mParams
.getSupportedPictureSizes(), 1200, screenProp);
mParams.setPreviewSize(previewSize.width, previewSize.height);
preview_width = previewSize.width;
preview_height = previewSize.height;
mParams.setPictureSize(pictureSize.width, pictureSize.height);
if (CameraParamUtil.getInstance().isSupportedFocusMode(
mParams.getSupportedFocusModes(),
Camera.Parameters.FOCUS_MODE_AUTO)) {
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
if (CameraParamUtil.getInstance().isSupportedPictureFormats(mParams.getSupportedPictureFormats(),
ImageFormat.JPEG)) {
mParams.setPictureFormat(ImageFormat.JPEG);
mParams.setJpegQuality(100);
}
mCamera.setParameters(mParams);
mParams = mCamera.getParameters();
mCamera.setPreviewDisplay(holder); //SurfaceView
mCamera.setDisplayOrientation(cameraAngle);//浏览角度
mCamera.setPreviewCallback(this); //每一帧回调
mCamera.startPreview();//启动浏览
isPreviewing = true;
Log.i(TAG, "=== Start Preview ===");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 停止预览
*/
public void doStopPreview() {
if (null != mCamera) {
try {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
//这句要在stopPreview后执行,不然会卡顿或者花屏
mCamera.setPreviewDisplay(null);
isPreviewing = false;
Log.i(TAG, "=== Stop Preview ===");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 销毁Camera
*/
void doDestroyCamera() {
errorLisenter = null;
if (null != mCamera) {
try {
mCamera.setPreviewCallback(null);
mSwitchView = null;
mFlashLamp = null;
mCamera.stopPreview();
//这句要在stopPreview后执行,不然会卡顿或者花屏
mCamera.setPreviewDisplay(null);
mHolder = null;
isPreviewing = false;
mCamera.release();
mCamera = null;
// destroyCameraInterface();
Log.i(TAG, "=== Destroy Camera ===");
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "=== Camera Null===");
}
}
/**
* 拍照
*/
private int nowAngle;
public void takePicture(final TakePictureCallback callback) {
if (mCamera == null) {
return;
}
switch (cameraAngle) {
case 90:
nowAngle = Math.abs(angle + cameraAngle) % 360;
break;
case 270:
nowAngle = Math.abs(cameraAngle - angle);
break;
}
//
Log.i("CJT", angle + " = " + cameraAngle + " = " + nowAngle);
mCamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
matrix.setRotate(nowAngle);
} else if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
matrix.setRotate(360 - nowAngle);
matrix.postScale(-1, 1);
}
bitmap = createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (callback != null) {
if (nowAngle == 90 || nowAngle == 270) {
callback.captureResult(bitmap, true);
} else {
callback.captureResult(bitmap, false);
}
}
}
});
}
//启动录像
public void startRecord(Surface surface, float screenProp, ErrorCallback callback) {
mCamera.setPreviewCallback(null);
final int nowAngle = (angle + 90) % 360;
//获取第一帧图片
Camera.Parameters parameters = mCamera.getParameters();
int width = parameters.getPreviewSize().width;
int height = parameters.getPreviewSize().height;
YuvImage yuv = new YuvImage(firstFrame_data, parameters.getPreviewFormat(), width, height, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, width, height), 50, out);
byte[] bytes = out.toByteArray();
videoFirstFrame = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix matrix = new Matrix();
if (SELECTED_CAMERA == CAMERA_POST_POSITION) {
matrix.setRotate(nowAngle);
} else if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
matrix.setRotate(270);
}
videoFirstFrame = createBitmap(videoFirstFrame, 0, 0, videoFirstFrame.getWidth(), videoFirstFrame
.getHeight(), matrix, true);
if (isRecorder) {
return;
}
if (mCamera == null) {
openCamera(SELECTED_CAMERA);
}
if (mediaRecorder == null) {
mediaRecorder = new MediaRecorder();
}
if (mParams == null) {
mParams = mCamera.getParameters();
}
List<String> focusModes = mParams.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(mParams);
mCamera.unlock();
mediaRecorder.reset();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
int th = 1000;
if (ScreenUtils.screenWidth > 700)
th = ScreenUtils.screenWidth;
Camera.Size videoSize;
if (mParams.getSupportedVideoSizes() == null) {
videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedPreviewSizes(), th,
screenProp);
} else {
videoSize = CameraParamUtil.getInstance().getPreviewSize(mParams.getSupportedVideoSizes(), th,
screenProp);
}
Log.i(TAG, "setVideoSize width = " + videoSize.width + "height = " + videoSize.height);
// Log.i(TAG, "setVideoSize2 width = " + ScreenUtils.screenWidth + "height = " + ScreenUtils.screenHeight);
// if (ScreenUtils.screenWidth > 700 && ScreenUtils.screenHeight > 1000) {
// mediaRecorder.setVideoSize(ScreenUtils.screenWidth, ScreenUtils.screenHeight);
// } else {
if (videoSize.width == videoSize.height) {
mediaRecorder.setVideoSize(preview_width, preview_height);
} else {
mediaRecorder.setVideoSize(videoSize.width, videoSize.height);
}
// }
// if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
// mediaRecorder.setOrientationHint(270);
// } else {
// mediaRecorder.setOrientationHint(nowAngle);
//// mediaRecorder.setOrientationHint(90);
// }
if (SELECTED_CAMERA == CAMERA_FRONT_POSITION) {
//手机预览倒立的处理
if (cameraAngle == 270) {
//横屏
if (nowAngle == 0) {
mediaRecorder.setOrientationHint(180);
} else if (nowAngle == 270) {
mediaRecorder.setOrientationHint(270);
} else {
mediaRecorder.setOrientationHint(90);
}
} else {
if (nowAngle == 90) {
mediaRecorder.setOrientationHint(270);
} else if (nowAngle == 270) {
mediaRecorder.setOrientationHint(90);
} else {
mediaRecorder.setOrientationHint(nowAngle);
}
}
} else {
mediaRecorder.setOrientationHint(nowAngle);
}
if (DeviceUtil.isHuaWeiRongyao()) {
mediaRecorder.setVideoEncodingBitRate(4 * 100000);
} else {
mediaRecorder.setVideoEncodingBitRate(mediaQuality);
}
mediaRecorder.setPreviewDisplay(surface);
videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
if (saveVideoPath.equals("")) {
saveVideoPath = Environment.getExternalStorageDirectory().getPath();
}
videoFileAbsPath = saveVideoPath + File.separator + videoFileName;
mediaRecorder.setOutputFile(videoFileAbsPath);
try {
mediaRecorder.prepare();
mediaRecorder.start();
isRecorder = true;
} catch (IllegalStateException e) {
e.printStackTrace();
Log.i("CJT", "startRecord IllegalStateException");
if (this.errorLisenter != null) {
this.errorLisenter.onError();
}
} catch (IOException e) {
e.printStackTrace();
Log.i("CJT", "startRecord IOException");
if (this.errorLisenter != null) {
this.errorLisenter.onError();
}
} catch (RuntimeException e) {
Log.i("CJT", "startRecord RuntimeException");
}
}
//停止录像
public void stopRecord(boolean isShort, StopRecordCallback callback) {
if (!isRecorder) {
return;
}
if (mediaRecorder != null) {
mediaRecorder.setOnErrorListener(null);
mediaRecorder.setOnInfoListener(null);
mediaRecorder.setPreviewDisplay(null);
try {
mediaRecorder.stop();
} catch (RuntimeException e) {
e.printStackTrace();
mediaRecorder = null;
mediaRecorder = new MediaRecorder();
} finally {
if (mediaRecorder != null) {
mediaRecorder.release();
}
mediaRecorder = null;
isRecorder = false;
}
if (isShort) {
if (FileUtil.deleteFile(videoFileAbsPath)) {
callback.recordResult(null, null);
}
return;
}
doStopPreview();
String fileName = saveVideoPath + File.separator + videoFileName;
callback.recordResult(fileName, videoFirstFrame);
}
}
private void findAvailableCameras() {
Camera.CameraInfo info = new Camera.CameraInfo();
int cameraNum = Camera.getNumberOfCameras();
for (int i = 0; i < cameraNum; i++) {
Camera.getCameraInfo(i, info);
switch (info.facing) {
case Camera.CameraInfo.CAMERA_FACING_FRONT:
CAMERA_FRONT_POSITION = info.facing;
break;
case Camera.CameraInfo.CAMERA_FACING_BACK:
CAMERA_POST_POSITION = info.facing;
break;
}
}
}
int handlerTime = 0;
public void handleFocus(final Context context, final float x, final float y, final FocusCallback callback) {
if (mCamera == null) {
return;
}
final Camera.Parameters params = mCamera.getParameters();
Rect focusRect = calculateTapArea(x, y, 1f, context);
mCamera.cancelAutoFocus();
if (params.getMaxNumFocusAreas() > 0) {
List<Camera.Area> focusAreas = new ArrayList<>();
focusAreas.add(new Camera.Area(focusRect, 800));
params.setFocusAreas(focusAreas);
} else {
Log.i(TAG, "focus areas not supported");
callback.focusSuccess();
return;
}
final String currentFocusMode = params.getFocusMode();
try {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success || handlerTime > 10) {
Camera.Parameters params = camera.getParameters();
params.setFocusMode(currentFocusMode);
camera.setParameters(params);
handlerTime = 0;
callback.focusSuccess();
} else {
handlerTime++;
handleFocus(context, x, y, callback);
}
}
});
} catch (Exception e) {
Log.e(TAG, "autoFocus failer");
}
}
private static Rect calculateTapArea(float x, float y, float coefficient, Context context) {
float focusAreaSize = 300;
int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
int centerX = (int) (x / ScreenUtils.getScreenWidth(context) * 2000 - 1000);
int centerY = (int) (y / ScreenUtils.getScreenHeight(context) * 2000 - 1000);
int left = clamp(centerX - areaSize / 2, -1000, 1000);
int top = clamp(centerY - areaSize / 2, -1000, 1000);
RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF
.bottom));
}
private static int clamp(int x, int min, int max) {
if (x > max) {
return max;
}
if (x < min) {
return min;
}
return x;
}
void setErrorLinsenter(ErrorListener errorLisenter) {
this.errorLisenter = errorLisenter;
}
public interface StopRecordCallback {
void recordResult(String url, Bitmap firstFrame);
}
interface ErrorCallback {
void onError();
}
public interface TakePictureCallback {
void captureResult(Bitmap bitmap, boolean isVertical);
}
public interface FocusCallback {
void focusSuccess();
}
void registerSensorManager(Context context) {
if (sm == null) {
sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}
sm.registerListener(sensorEventListener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager
.SENSOR_DELAY_NORMAL);
}
void unregisterSensorManager(Context context) {
if (sm == null) {
sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}
sm.unregisterListener(sensorEventListener);
}
void isPreview(boolean res) {
this.isPreviewing = res;
}
}
package com.cjt2325.cameralibrary;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.view.MotionEvent;
import android.view.View;
import com.cjt2325.cameralibrary.listener.CaptureListener;
import com.cjt2325.cameralibrary.util.CheckPermission;
import com.cjt2325.cameralibrary.util.LogUtil;
import static com.cjt2325.cameralibrary.JCameraView.BUTTON_STATE_BOTH;
import static com.cjt2325.cameralibrary.JCameraView.BUTTON_STATE_ONLY_CAPTURE;
import static com.cjt2325.cameralibrary.JCameraView.BUTTON_STATE_ONLY_RECORDER;
/**
* =====================================
* 作 者: 陈嘉桐 445263848@qq.com
* 版 本:1.1.4
* 创建日期:2017/4/25
* 描 述:拍照按钮
* =====================================
*/
public class CaptureButton extends View {
private int state; //当前按钮状态
private int button_state; //按钮可执行的功能状态(拍照,录制,两者)
public static final int STATE_IDLE = 0x001; //空闲状态
public static final int STATE_PRESS = 0x002; //按下状态
public static final int STATE_LONG_PRESS = 0x003; //长按状态
public static final int STATE_RECORDERING = 0x004; //录制状态
public static final int STATE_BAN = 0x005; //禁止状态
private int progress_color = 0xEE16AE16; //进度条颜色
private int outside_color = 0xEEDCDCDC; //外圆背景色
private int inside_color = 0xFFFFFFFF; //内圆背景色
private float event_Y; //Touch_Event_Down时候记录的Y值
private Paint mPaint;
private float strokeWidth; //进度条宽度
private int outside_add_size; //长按外圆半径变大的Size
private int inside_reduce_size; //长安内圆缩小的Size
//中心坐标
private float center_X;
private float center_Y;
private float button_radius; //按钮半径
private float button_outside_radius; //外圆半径
private float button_inside_radius; //内圆半径
private int button_size; //按钮大小
private float progress; //录制视频的进度
private int duration; //录制视频最大时间长度
private int min_duration; //最短录制时间限制
private int recorded_time; //记录当前录制的时间
private RectF rectF;
private LongPressRunnable longPressRunnable; //长按后处理的逻辑Runnable
private CaptureListener captureLisenter; //按钮回调接口
private RecordCountDownTimer timer; //计时器
public CaptureButton(Context context) {
super(context);
}
public CaptureButton(Context context, int size) {
super(context);
this.button_size = size;
button_radius = size / 2.0f;
button_outside_radius = button_radius;
button_inside_radius = button_radius * 0.75f;
strokeWidth = size / 15;
outside_add_size = size / 5;
inside_reduce_size = size / 8;
mPaint = new Paint();
mPaint.setAntiAlias(true);
progress = 0;
longPressRunnable = new LongPressRunnable();
state = STATE_IDLE; //初始化为空闲状态
button_state = BUTTON_STATE_BOTH; //初始化按钮为可录制可拍照
LogUtil.i("CaptureButtom start");
duration = 10 * 1000; //默认最长录制时间为10s
LogUtil.i("CaptureButtom end");
min_duration = 1500; //默认最短录制时间为1.5s
center_X = (button_size + outside_add_size * 2) / 2;
center_Y = (button_size + outside_add_size * 2) / 2;
rectF = new RectF(
center_X - (button_radius + outside_add_size - strokeWidth / 2),
center_Y - (button_radius + outside_add_size - strokeWidth / 2),
center_X + (button_radius + outside_add_size - strokeWidth / 2),
center_Y + (button_radius + outside_add_size - strokeWidth / 2));
timer = new RecordCountDownTimer(duration, duration / 360); //录制定时器
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(button_size + outside_add_size * 2, button_size + outside_add_size * 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(outside_color); //外圆(半透明灰色)
canvas.drawCircle(center_X, center_Y, button_outside_radius, mPaint);
mPaint.setColor(inside_color); //内圆(白色)
canvas.drawCircle(center_X, center_Y, button_inside_radius, mPaint);
//如果状态为录制状态,则绘制录制进度条
if (state == STATE_RECORDERING) {
mPaint.setColor(progress_color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(strokeWidth);
canvas.drawArc(rectF, -90, progress, false, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
LogUtil.i("state = " + state);
if (event.getPointerCount() > 1 || state != STATE_IDLE)
break;
event_Y = event.getY(); //记录Y值
state = STATE_PRESS; //修改当前状态为点击按下
//判断按钮状态是否为可录制状态
if ((button_state == BUTTON_STATE_ONLY_RECORDER || button_state == BUTTON_STATE_BOTH))
postDelayed(longPressRunnable, 500); //同时延长500启动长按后处理的逻辑Runnable
break;
case MotionEvent.ACTION_MOVE:
if (captureLisenter != null
&& state == STATE_RECORDERING
&& (button_state == BUTTON_STATE_ONLY_RECORDER || button_state == BUTTON_STATE_BOTH)) {
//记录当前Y值与按下时候Y值的差值,调用缩放回调接口
captureLisenter.recordZoom(event_Y - event.getY());
}
break;
case MotionEvent.ACTION_UP:
//根据当前按钮的状态进行相应的处理
handlerUnpressByState();
break;
}
return true;
}
//当手指松开按钮时候处理的逻辑
private void handlerUnpressByState() {
removeCallbacks(longPressRunnable); //移除长按逻辑的Runnable
//根据当前状态处理
switch (state) {
//当前是点击按下
case STATE_PRESS:
if (captureLisenter != null && (button_state == BUTTON_STATE_ONLY_CAPTURE || button_state ==
BUTTON_STATE_BOTH)) {
startCaptureAnimation(button_inside_radius);
} else {
state = STATE_IDLE;
}
break;
//当前是长按状态
case STATE_RECORDERING:
timer.cancel(); //停止计时器
recordEnd(); //录制结束
break;
}
}
//录制结束
private void recordEnd() {
if (captureLisenter != null) {
if (recorded_time < min_duration)
captureLisenter.recordShort(recorded_time);//回调录制时间过短
else
captureLisenter.recordEnd(recorded_time); //回调录制结束
}
resetRecordAnim(); //重制按钮状态
}
//重制状态
private void resetRecordAnim() {
state = STATE_BAN;
progress = 0; //重制进度
invalidate();
//还原按钮初始状态动画
startRecordAnimation(
button_outside_radius,
button_radius,
button_inside_radius,
button_radius * 0.75f
);
}
//内圆动画
private void startCaptureAnimation(float inside_start) {
ValueAnimator inside_anim = ValueAnimator.ofFloat(inside_start, inside_start * 0.75f, inside_start);
inside_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
button_inside_radius = (float) animation.getAnimatedValue();
invalidate();
}
});
inside_anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//回调拍照接口
captureLisenter.takePictures();
state = STATE_BAN;
}
});
inside_anim.setDuration(100);
inside_anim.start();
}
//内外圆动画
private void startRecordAnimation(float outside_start, float outside_end, float inside_start, float inside_end) {
ValueAnimator outside_anim = ValueAnimator.ofFloat(outside_start, outside_end);
ValueAnimator inside_anim = ValueAnimator.ofFloat(inside_start, inside_end);
//外圆动画监听
outside_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
button_outside_radius = (float) animation.getAnimatedValue();
invalidate();
}
});
//内圆动画监听
inside_anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
button_inside_radius = (float) animation.getAnimatedValue();
invalidate();
}
});
AnimatorSet set = new AnimatorSet();
//当动画结束后启动录像Runnable并且回调录像开始接口
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//设置为录制状态
if (state == STATE_LONG_PRESS) {
if (captureLisenter != null)
captureLisenter.recordStart();
state = STATE_RECORDERING;
timer.start();
}
}
});
set.playTogether(outside_anim, inside_anim);
set.setDuration(100);
set.start();
}
//更新进度条
private void updateProgress(long millisUntilFinished) {
recorded_time = (int) (duration - millisUntilFinished);
progress = 360f - millisUntilFinished / (float) duration * 360f;
invalidate();
}
//录制视频计时器
private class RecordCountDownTimer extends CountDownTimer {
RecordCountDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onTick(long millisUntilFinished) {
updateProgress(millisUntilFinished);
}
@Override
public void onFinish() {
updateProgress(0);
recordEnd();
}
}
//长按线程
private class LongPressRunnable implements Runnable {
@Override
public void run() {
state = STATE_LONG_PRESS; //如果按下后经过500毫秒则会修改当前状态为长按状态
//没有录制权限
if (CheckPermission.getRecordState() != CheckPermission.STATE_SUCCESS) {
state = STATE_IDLE;
if (captureLisenter != null) {
captureLisenter.recordError();
return;
}
}
//启动按钮动画,外圆变大,内圆缩小
startRecordAnimation(
button_outside_radius,
button_outside_radius + outside_add_size,
button_inside_radius,
button_inside_radius - inside_reduce_size
);
}
}
/**************************************************
* 对外提供的API *
**************************************************/
//设置最长录制时间
public void setDuration(int duration) {
this.duration = duration;
timer = new RecordCountDownTimer(duration, duration / 360); //录制定时器
}
//设置最短录制时间
public void setMinDuration(int duration) {
this.min_duration = duration;
}
//设置回调接口
public void setCaptureLisenter(CaptureListener captureLisenter) {
this.captureLisenter = captureLisenter;
}
//设置按钮功能(拍照和录像)
public void setButtonFeatures(int state) {
this.button_state = state;
}
//是否空闲状态
public boolean isIdle() {
return state == STATE_IDLE ? true : false;
}
//设置状态
public void resetState() {
state = STATE_IDLE;
}
}
package com.cjt2325.cameralibrary;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.cjt2325.cameralibrary.listener.CaptureListener;
import com.cjt2325.cameralibrary.listener.ClickListener;
import com.cjt2325.cameralibrary.listener.ReturnListener;
import com.cjt2325.cameralibrary.listener.TypeListener;
/**
* =====================================
* 作 者: 陈嘉桐 445263848@qq.com
* 版 本:1.0.4
* 创建日期:2017/4/26
* 描 述:集成各个控件的布局
* =====================================
*/
public class CaptureLayout extends FrameLayout {
private CaptureListener captureLisenter; //拍照按钮监听
private TypeListener typeLisenter; //拍照或录制后接结果按钮监听
private ReturnListener returnListener; //退出按钮监听
private ClickListener leftClickListener; //左边按钮监听
private ClickListener rightClickListener; //右边按钮监听
public void setTypeLisenter(TypeListener typeLisenter) {
this.typeLisenter = typeLisenter;
}
public void setCaptureLisenter(CaptureListener captureLisenter) {
this.captureLisenter = captureLisenter;
}
public void setReturnLisenter(ReturnListener returnListener) {
this.returnListener = returnListener;
}
private CaptureButton btn_capture; //拍照按钮
private TypeButton btn_confirm; //确认按钮
private TypeButton btn_cancel; //取消按钮
private ReturnButton btn_return; //返回按钮
private ImageView iv_custom_left; //左边自定义按钮
private ImageView iv_custom_right; //右边自定义按钮
private TextView txt_tip; //提示文本
private int layout_width;
private int layout_height;
private int button_size;
private int iconLeft = 0;
private int iconRight = 0;
private boolean isFirst = true;
public CaptureLayout(Context context) {
this(context, null);
}
public CaptureLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CaptureLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
layout_width = outMetrics.widthPixels;
} else {
layout_width = outMetrics.widthPixels / 2;
}
button_size = (int) (layout_width / 4.5f);
layout_height = button_size + (button_size / 5) * 2 + 100;
initView();
initEvent();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(layout_width, layout_height);
}
public void initEvent() {
//默认Typebutton为隐藏
iv_custom_right.setVisibility(GONE);
btn_cancel.setVisibility(GONE);
btn_confirm.setVisibility(GONE);
}
public void startTypeBtnAnimator() {
//拍照录制结果后的动画
if (this.iconLeft != 0)
iv_custom_left.setVisibility(GONE);
else
btn_return.setVisibility(GONE);
if (this.iconRight != 0)
iv_custom_right.setVisibility(GONE);
btn_capture.setVisibility(GONE);
btn_cancel.setVisibility(VISIBLE);
btn_confirm.setVisibility(VISIBLE);
btn_cancel.setClickable(false);
btn_confirm.setClickable(false);
ObjectAnimator animator_cancel = ObjectAnimator.ofFloat(btn_cancel, "translationX", layout_width / 4, 0);
ObjectAnimator animator_confirm = ObjectAnimator.ofFloat(btn_confirm, "translationX", -layout_width / 4, 0);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator_cancel, animator_confirm);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
btn_cancel.setClickable(true);
btn_confirm.setClickable(true);
}
});
set.setDuration(200);
set.start();
}
private void initView() {
setWillNotDraw(false);
//拍照按钮
btn_capture = new CaptureButton(getContext(), button_size);
LayoutParams btn_capture_param = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
btn_capture_param.gravity = Gravity.CENTER;
btn_capture.setLayoutParams(btn_capture_param);
btn_capture.setCaptureLisenter(new CaptureListener() {
@Override
public void takePictures() {
if (captureLisenter != null) {
captureLisenter.takePictures();
}
}
@Override
public void recordShort(long time) {
if (captureLisenter != null) {
captureLisenter.recordShort(time);
}
startAlphaAnimation();
}
@Override
public void recordStart() {
if (captureLisenter != null) {
captureLisenter.recordStart();
}
startAlphaAnimation();
}
@Override
public void recordEnd(long time) {
if (captureLisenter != null) {
captureLisenter.recordEnd(time);
}
startAlphaAnimation();
startTypeBtnAnimator();
}
@Override
public void recordZoom(float zoom) {
if (captureLisenter != null) {
captureLisenter.recordZoom(zoom);
}
}
@Override
public void recordError() {
if (captureLisenter != null) {
captureLisenter.recordError();
}
}
});
//取消按钮
btn_cancel = new TypeButton(getContext(), TypeButton.TYPE_CANCEL, button_size);
final LayoutParams btn_cancel_param = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
btn_cancel_param.gravity = Gravity.CENTER_VERTICAL;
btn_cancel_param.setMargins((layout_width / 4) - button_size / 2, 0, 0, 0);
btn_cancel.setLayoutParams(btn_cancel_param);
btn_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (typeLisenter != null) {
typeLisenter.cancel();
}
startAlphaAnimation();
// resetCaptureLayout();
}
});
//确认按钮
btn_confirm = new TypeButton(getContext(), TypeButton.TYPE_CONFIRM, button_size);
LayoutParams btn_confirm_param = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
btn_confirm_param.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
btn_confirm_param.setMargins(0, 0, (layout_width / 4) - button_size / 2, 0);
btn_confirm.setLayoutParams(btn_confirm_param);
btn_confirm.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (typeLisenter != null) {
typeLisenter.confirm();
}
startAlphaAnimation();
// resetCaptureLayout();
}
});
//返回按钮
btn_return = new ReturnButton(getContext(), (int) (button_size / 2.5f));
LayoutParams btn_return_param = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
btn_return_param.gravity = Gravity.CENTER_VERTICAL;
btn_return_param.setMargins(layout_width / 6, 0, 0, 0);
btn_return.setLayoutParams(btn_return_param);
btn_return.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (leftClickListener != null) {
leftClickListener.onClick();
}
}
});
//左边自定义按钮
iv_custom_left = new ImageView(getContext());
LayoutParams iv_custom_param_left = new LayoutParams((int) (button_size / 2.5f), (int) (button_size / 2.5f));
iv_custom_param_left.gravity = Gravity.CENTER_VERTICAL;
iv_custom_param_left.setMargins(layout_width / 6, 0, 0, 0);
iv_custom_left.setLayoutParams(iv_custom_param_left);
iv_custom_left.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (leftClickListener != null) {
leftClickListener.onClick();
}
}
});
//右边自定义按钮
iv_custom_right = new ImageView(getContext());
LayoutParams iv_custom_param_right = new LayoutParams((int) (button_size / 2.5f), (int) (button_size / 2.5f));
iv_custom_param_right.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
iv_custom_param_right.setMargins(0, 0, layout_width / 6, 0);
iv_custom_right.setLayoutParams(iv_custom_param_right);
iv_custom_right.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (rightClickListener != null) {
rightClickListener.onClick();
}
}
});
txt_tip = new TextView(getContext());
LayoutParams txt_param = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
txt_param.gravity = Gravity.CENTER_HORIZONTAL;
txt_param.setMargins(0, 0, 0, 0);
txt_tip.setText("轻触拍照,长按摄像");
txt_tip.setTextColor(0xFFFFFFFF);
txt_tip.setGravity(Gravity.CENTER);
txt_tip.setLayoutParams(txt_param);
this.addView(btn_capture);
this.addView(btn_cancel);
this.addView(btn_confirm);
this.addView(btn_return);
this.addView(iv_custom_left);
this.addView(iv_custom_right);
this.addView(txt_tip);
}
/**************************************************
* 对外提供的API *
**************************************************/
public void resetCaptureLayout() {
btn_capture.resetState();
btn_cancel.setVisibility(GONE);
btn_confirm.setVisibility(GONE);
btn_capture.setVisibility(VISIBLE);
if (this.iconLeft != 0)
iv_custom_left.setVisibility(VISIBLE);
else
btn_return.setVisibility(VISIBLE);
if (this.iconRight != 0)
iv_custom_right.setVisibility(VISIBLE);
}
public void startAlphaAnimation() {
if (isFirst) {
ObjectAnimator animator_txt_tip = ObjectAnimator.ofFloat(txt_tip, "alpha", 1f, 0f);
animator_txt_tip.setDuration(500);
animator_txt_tip.start();
isFirst = false;
}
}
public void setTextWithAnimation(String tip) {
txt_tip.setText(tip);
ObjectAnimator animator_txt_tip = ObjectAnimator.ofFloat(txt_tip, "alpha", 0f, 1f, 1f, 0f);
animator_txt_tip.setDuration(2500);
animator_txt_tip.start();
}
public void setDuration(int duration) {
btn_capture.setDuration(duration);
}
public void setButtonFeatures(int state) {
btn_capture.setButtonFeatures(state);
}
public void setTip(String tip) {
txt_tip.setText(tip);
}
public void showTip() {
txt_tip.setVisibility(VISIBLE);
}
public void setIconSrc(int iconLeft, int iconRight) {
this.iconLeft = iconLeft;
this.iconRight = iconRight;
if (this.iconLeft != 0) {
iv_custom_left.setImageResource(iconLeft);
iv_custom_left.setVisibility(VISIBLE);
btn_return.setVisibility(GONE);
} else {
iv_custom_left.setVisibility(GONE);
btn_return.setVisibility(VISIBLE);
}
if (this.iconRight != 0) {
iv_custom_right.setImageResource(iconRight);
iv_custom_right.setVisibility(VISIBLE);
} else {
iv_custom_right.setVisibility(GONE);
}
}
public void setLeftClickListener(ClickListener leftClickListener) {
this.leftClickListener = leftClickListener;
}
public void setRightClickListener(ClickListener rightClickListener) {
this.rightClickListener = rightClickListener;
}
}
package com.cjt2325.cameralibrary;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.cjt2325.cameralibrary.util.ScreenUtils;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/26
* 描 述:对焦框
* =====================================
*/
public class FoucsView extends View {
private int size;
private int center_x;
private int center_y;
private int length;
private Paint mPaint;
public FoucsView(Context context) {
this(context, null);
}
public FoucsView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public FoucsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.size = ScreenUtils.getScreenWidth(context) / 3;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xEE16AE16);
mPaint.setStrokeWidth(4);
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
center_x = (int) (size / 2.0);
center_y = (int) (size / 2.0);
length = (int) (size / 2.0) - 2;
setMeasuredDimension(size, size);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(center_x - length, center_y - length, center_x + length, center_y + length, mPaint);
canvas.drawLine(2, getHeight() / 2, size / 10, getHeight() / 2, mPaint);
canvas.drawLine(getWidth() - 2, getHeight() / 2, getWidth() - size / 10, getHeight() / 2, mPaint);
canvas.drawLine(getWidth() / 2, 2, getWidth() / 2, size / 10, mPaint);
canvas.drawLine(getWidth() / 2, getHeight() - 2, getWidth() / 2, getHeight() - size / 10, mPaint);
}
}
package com.cjt2325.cameralibrary;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.VideoView;
import com.cjt2325.cameralibrary.listener.CaptureListener;
import com.cjt2325.cameralibrary.listener.ClickListener;
import com.cjt2325.cameralibrary.listener.ErrorListener;
import com.cjt2325.cameralibrary.listener.JCameraListener;
import com.cjt2325.cameralibrary.listener.TypeListener;
import com.cjt2325.cameralibrary.state.CameraMachine;
import com.cjt2325.cameralibrary.util.FileUtil;
import com.cjt2325.cameralibrary.util.LogUtil;
import com.cjt2325.cameralibrary.util.ScreenUtils;
import com.cjt2325.cameralibrary.view.CameraView;
import java.io.IOException;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.0.4
* 创建日期:2017/4/25
* 描 述:
* =====================================
*/
public class JCameraView extends FrameLayout implements CameraInterface.CameraOpenOverCallback, SurfaceHolder
.Callback, CameraView {
// private static final String TAG = "JCameraView";
//Camera状态机
private CameraMachine machine;
//闪关灯状态
private static final int TYPE_FLASH_AUTO = 0x021;
private static final int TYPE_FLASH_ON = 0x022;
private static final int TYPE_FLASH_OFF = 0x023;
private int type_flash = TYPE_FLASH_OFF;
//拍照浏览时候的类型
public static final int TYPE_PICTURE = 0x001;
public static final int TYPE_VIDEO = 0x002;
public static final int TYPE_SHORT = 0x003;
public static final int TYPE_DEFAULT = 0x004;
//录制视频比特率
public static final int MEDIA_QUALITY_HIGH = 20 * 100000;
public static final int MEDIA_QUALITY_MIDDLE = 16 * 100000;
public static final int MEDIA_QUALITY_LOW = 12 * 100000;
public static final int MEDIA_QUALITY_POOR = 8 * 100000;
public static final int MEDIA_QUALITY_FUNNY = 4 * 100000;
public static final int MEDIA_QUALITY_DESPAIR = 2 * 100000;
public static final int MEDIA_QUALITY_SORRY = 1 * 80000;
public static final int BUTTON_STATE_ONLY_CAPTURE = 0x101; //只能拍照
public static final int BUTTON_STATE_ONLY_RECORDER = 0x102; //只能录像
public static final int BUTTON_STATE_BOTH = 0x103; //两者都可以
//回调监听
private JCameraListener jCameraLisenter;
private ClickListener leftClickListener;
private ClickListener rightClickListener;
private Context mContext;
private VideoView mVideoView;
private ImageView mPhoto;
private ImageView mSwitchCamera;
private ImageView mFlashLamp;
private CaptureLayout mCaptureLayout;
private FoucsView mFoucsView;
private MediaPlayer mMediaPlayer;
private int layout_width;
private int layout_Height;
private float screenProp = 0f;
private Bitmap captureBitmap; //捕获的图片
private Bitmap firstFrame; //第一帧图片
private String videoUrl; //视频URL
//切换摄像头按钮的参数
private int iconSize = 0; //图标大小
private int iconMargin = 0; //右上边距
private int iconSrc = 0; //图标资源
private int iconLeft = 0; //左图标
private int iconRight = 0; //右图标
private int duration = 0; //录制时间
//缩放梯度
private int zoomGradient = 0;
private boolean firstTouch = true;
private float firstTouchLength = 0;
public JCameraView(Context context) {
this(context, null);
}
public JCameraView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public JCameraView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
//get AttributeSet
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.JCameraView, defStyleAttr, 0);
iconSize = a.getDimensionPixelSize(R.styleable.JCameraView_iconSize, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 35, getResources().getDisplayMetrics()));
iconMargin = a.getDimensionPixelSize(R.styleable.JCameraView_iconMargin, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 15, getResources().getDisplayMetrics()));
iconSrc = a.getResourceId(R.styleable.JCameraView_iconSrc, R.drawable.ic_camera);
iconLeft = a.getResourceId(R.styleable.JCameraView_iconLeft, 0);
iconRight = a.getResourceId(R.styleable.JCameraView_iconRight, 0);
duration = a.getInteger(R.styleable.JCameraView_duration_max, 10 * 1000); //没设置默认为10s
a.recycle();
initData();
initView();
}
private void initData() {
layout_width = ScreenUtils.getScreenWidth(mContext);
layout_Height= ScreenUtils.getScreenHeight(mContext);
//缩放梯度
zoomGradient = (int) (layout_width / 16f);
LogUtil.i("zoom = " + zoomGradient);
machine = new CameraMachine(getContext(), this, this);
}
private void initView() {
setWillNotDraw(false);
View view = LayoutInflater.from(mContext).inflate(R.layout.camera_view, this);
mVideoView = (VideoView) view.findViewById(R.id.video_preview);
mPhoto = (ImageView) view.findViewById(R.id.image_photo);
mSwitchCamera = (ImageView) view.findViewById(R.id.image_switch);
mSwitchCamera.setImageResource(iconSrc);
mFlashLamp = (ImageView) view.findViewById(R.id.image_flash);
setFlashRes();
mFlashLamp.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
type_flash++;
if (type_flash > 0x023)
type_flash = TYPE_FLASH_AUTO;
setFlashRes();
}
});
mCaptureLayout = (CaptureLayout) view.findViewById(R.id.capture_layout);
mCaptureLayout.setDuration(duration);
mCaptureLayout.setIconSrc(iconLeft, iconRight);
mFoucsView = (FoucsView) view.findViewById(R.id.fouce_view);
mVideoView.getHolder().addCallback(this);
//切换摄像头
mSwitchCamera.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
machine.swtich(mVideoView.getHolder(), screenProp);
}
});
//拍照 录像
mCaptureLayout.setCaptureLisenter(new CaptureListener() {
@Override
public void takePictures() {
mSwitchCamera.setVisibility(INVISIBLE);
mFlashLamp.setVisibility(INVISIBLE);
machine.capture();
}
@Override
public void recordStart() {
mSwitchCamera.setVisibility(INVISIBLE);
mFlashLamp.setVisibility(INVISIBLE);
machine.record(mVideoView.getHolder().getSurface(), screenProp);
}
@Override
public void recordShort(final long time) {
mCaptureLayout.setTextWithAnimation("录制时间过短");
mSwitchCamera.setVisibility(VISIBLE);
mFlashLamp.setVisibility(VISIBLE);
postDelayed(new Runnable() {
@Override
public void run() {
machine.stopRecord(true, time);
}
}, 1500 - time);
}
@Override
public void recordEnd(long time) {
machine.stopRecord(false, time);
}
@Override
public void recordZoom(float zoom) {
LogUtil.i("recordZoom");
machine.zoom(zoom, CameraInterface.TYPE_RECORDER);
}
@Override
public void recordError() {
if (errorLisenter != null) {
errorLisenter.AudioPermissionError();
}
}
});
//确认 取消
mCaptureLayout.setTypeLisenter(new TypeListener() {
@Override
public void cancel() {
machine.cancle(mVideoView.getHolder(), screenProp);
}
@Override
public void confirm() {
machine.confirm();
}
});
//退出
// mCaptureLayout.setReturnLisenter(new ReturnListener() {
// @Override
// public void onReturn() {
// if (jCameraLisenter != null) {
// jCameraLisenter.quit();
// }
// }
// });
mCaptureLayout.setLeftClickListener(new ClickListener() {
@Override
public void onClick() {
if (leftClickListener != null) {
leftClickListener.onClick();
}
}
});
mCaptureLayout.setRightClickListener(new ClickListener() {
@Override
public void onClick() {
if (rightClickListener != null) {
rightClickListener.onClick();
}
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
float widthSize = mVideoView.getMeasuredWidth();
float heightSize = mVideoView.getMeasuredHeight();
if (screenProp == 0) {
screenProp = heightSize / widthSize;
}
}
@Override
public void cameraHasOpened() {
CameraInterface.getInstance().doStartPreview(mVideoView.getHolder(), screenProp);
}
//生命周期onResume
public void onResume() {
LogUtil.i("JCameraView onResume");
resetState(TYPE_DEFAULT); //重置状态
CameraInterface.getInstance().registerSensorManager(mContext);
CameraInterface.getInstance().setSwitchView(mSwitchCamera, mFlashLamp);
machine.start(mVideoView.getHolder(), screenProp);
}
//生命周期onPause
public void onPause() {
LogUtil.i("JCameraView onPause");
stopVideo();
resetState(TYPE_PICTURE);
CameraInterface.getInstance().isPreview(false);
CameraInterface.getInstance().unregisterSensorManager(mContext);
}
//SurfaceView生命周期
@Override
public void surfaceCreated(SurfaceHolder holder) {
LogUtil.i("JCameraView SurfaceCreated");
new Thread() {
@Override
public void run() {
CameraInterface.getInstance().doOpenCamera(JCameraView.this);
}
}.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
LogUtil.i("JCameraView SurfaceDestroyed");
CameraInterface.getInstance().doDestroyCamera();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (event.getPointerCount() == 1) {
//显示对焦指示器
setFocusViewWidthAnimation(event.getX(), event.getY());
}
if (event.getPointerCount() == 2) {
Log.i("CJT", "ACTION_DOWN = " + 2);
}
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 1) {
firstTouch = true;
}
if (event.getPointerCount() == 2) {
//第一个点
float point_1_X = event.getX(0);
float point_1_Y = event.getY(0);
//第二个点
float point_2_X = event.getX(1);
float point_2_Y = event.getY(1);
float result = (float) Math.sqrt(Math.pow(point_1_X - point_2_X, 2) + Math.pow(point_1_Y -
point_2_Y, 2));
if (firstTouch) {
firstTouchLength = result;
firstTouch = false;
}
if ((int) (result - firstTouchLength) / zoomGradient != 0) {
firstTouch = true;
machine.zoom(result - firstTouchLength, CameraInterface.TYPE_CAPTURE);
}
// Log.i("CJT", "result = " + (result - firstTouchLength));
}
break;
case MotionEvent.ACTION_UP:
firstTouch = true;
break;
}
return true;
}
//对焦框指示器动画
private void setFocusViewWidthAnimation(float x, float y) {
machine.foucs(x, y, new CameraInterface.FocusCallback() {
@Override
public void focusSuccess() {
mFoucsView.setVisibility(INVISIBLE);
}
});
}
private void updateVideoViewSize(float videoWidth, float videoHeight) {
if (videoWidth > videoHeight) {
LayoutParams videoViewParam;
int height = (int) ((videoHeight / videoWidth) * getWidth());
videoViewParam = new LayoutParams(LayoutParams.MATCH_PARENT, height);
videoViewParam.gravity = Gravity.CENTER;
mVideoView.setLayoutParams(videoViewParam);
}
}
/**************************************************
* 对外提供的API *
**************************************************/
public void setSaveVideoPath(String path) {
CameraInterface.getInstance().setSaveVideoPath(path);
}
public void setJCameraLisenter(JCameraListener jCameraLisenter) {
this.jCameraLisenter = jCameraLisenter;
}
private ErrorListener errorLisenter;
//启动Camera错误回调
public void setErrorLisenter(ErrorListener errorLisenter) {
this.errorLisenter = errorLisenter;
CameraInterface.getInstance().setErrorLinsenter(errorLisenter);
}
//设置CaptureButton功能(拍照和录像)
public void setFeatures(int state) {
this.mCaptureLayout.setButtonFeatures(state);
}
//设置录制质量
public void setMediaQuality(int quality) {
CameraInterface.getInstance().setMediaQuality(quality);
}
@Override
public void resetState(int type) {
switch (type) {
case TYPE_VIDEO:
stopVideo(); //停止播放
//初始化VideoView
FileUtil.deleteFile(videoUrl);
mVideoView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
machine.start(mVideoView.getHolder(), screenProp);
break;
case TYPE_PICTURE:
mPhoto.setVisibility(INVISIBLE);
break;
case TYPE_SHORT:
break;
case TYPE_DEFAULT:
mVideoView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
break;
}
mSwitchCamera.setVisibility(VISIBLE);
mFlashLamp.setVisibility(VISIBLE);
mCaptureLayout.resetCaptureLayout();
}
@Override
public void confirmState(int type) {
switch (type) {
case TYPE_VIDEO:
stopVideo(); //停止播放
mVideoView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
machine.start(mVideoView.getHolder(), screenProp);
if (jCameraLisenter != null) {
jCameraLisenter.recordSuccess(videoUrl, firstFrame);
}
break;
case TYPE_PICTURE:
mPhoto.setVisibility(INVISIBLE);
if (jCameraLisenter != null) {
jCameraLisenter.captureSuccess(captureBitmap);
}
break;
case TYPE_SHORT:
break;
case TYPE_DEFAULT:
break;
}
mCaptureLayout.resetCaptureLayout();
}
@Override
public void showPicture(Bitmap bitmap, boolean isVertical) {
if (isVertical) {
mPhoto.setScaleType(ImageView.ScaleType.FIT_XY);
} else {
mPhoto.setScaleType(ImageView.ScaleType.FIT_CENTER);
}
captureBitmap = bitmap;
mPhoto.setImageBitmap(bitmap);
mPhoto.setVisibility(VISIBLE);
mCaptureLayout.startAlphaAnimation();
mCaptureLayout.startTypeBtnAnimator();
}
@Override
public void playVideo(Bitmap firstFrame, final String url) {
videoUrl = url;
JCameraView.this.firstFrame = firstFrame;
new Thread(new Runnable() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void run() {
try {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
} else {
mMediaPlayer.reset();
}
mMediaPlayer.setDataSource(url);
mMediaPlayer.setSurface(mVideoView.getHolder().getSurface());
mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer
.OnVideoSizeChangedListener() {
@Override
public void
onVideoSizeChanged(MediaPlayer mp, int width, int height) {
updateVideoViewSize(mMediaPlayer.getVideoWidth(), mMediaPlayer
.getVideoHeight());
}
});
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
});
mMediaPlayer.setLooping(true);
mMediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void stopVideo() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
@Override
public void setTip(String tip) {
mCaptureLayout.setTip(tip);
}
@Override
public void startPreviewCallback() {
LogUtil.i("startPreviewCallback");
handlerFoucs(mFoucsView.getWidth() / 2, mFoucsView.getHeight() / 2);
}
@Override
public boolean handlerFoucs(float x, float y) {
if (y > mCaptureLayout.getTop()) {
return false;
}
mFoucsView.setVisibility(VISIBLE);
if (x < mFoucsView.getWidth() / 2) {
x = mFoucsView.getWidth() / 2;
}
if (x > layout_width - mFoucsView.getWidth() / 2) {
x = layout_width - mFoucsView.getWidth() / 2;
}
if (y < mFoucsView.getWidth() / 2) {
y = mFoucsView.getWidth() / 2;
}
if (y > mCaptureLayout.getTop() - mFoucsView.getWidth() / 2) {
y = mCaptureLayout.getTop() - mFoucsView.getWidth() / 2;
}
mFoucsView.setX(x - mFoucsView.getWidth() / 2);
mFoucsView.setY(y - mFoucsView.getHeight() / 2);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mFoucsView, "scaleX", 1, 0.6f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(mFoucsView, "scaleY", 1, 0.6f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(mFoucsView, "alpha", 1f, 0.4f, 1f, 0.4f, 1f, 0.4f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(scaleX).with(scaleY).before(alpha);
animSet.setDuration(400);
animSet.start();
return true;
}
public void setLeftClickListener(ClickListener clickListener) {
this.leftClickListener = clickListener;
}
public void setRightClickListener(ClickListener clickListener) {
this.rightClickListener = clickListener;
}
private void setFlashRes() {
switch (type_flash) {
case TYPE_FLASH_AUTO:
mFlashLamp.setImageResource(R.drawable.ic_flash_auto);
machine.flash(Camera.Parameters.FLASH_MODE_AUTO);
break;
case TYPE_FLASH_ON:
mFlashLamp.setImageResource(R.drawable.ic_flash_on);
machine.flash(Camera.Parameters.FLASH_MODE_ON);
break;
case TYPE_FLASH_OFF:
mFlashLamp.setImageResource(R.drawable.ic_flash_off);
machine.flash(Camera.Parameters.FLASH_MODE_OFF);
break;
}
}
}
package com.cjt2325.cameralibrary;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;
/**
* =====================================
* 作 者: 陈嘉桐 445263848@qq.com
* 版 本:1.0.4
* 创建日期:2017/4/26
* 描 述:向下箭头的退出按钮
* =====================================
*/
public class ReturnButton extends View {
private int size;
private int center_X;
private int center_Y;
private float strokeWidth;
private Paint paint;
Path path;
public ReturnButton(Context context, int size) {
this(context);
this.size = size;
center_X = size / 2;
center_Y = size / 2;
strokeWidth = size / 15f;
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
path = new Path();
}
public ReturnButton(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(size, size / 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo(strokeWidth, strokeWidth/2);
path.lineTo(center_X, center_Y - strokeWidth/2);
path.lineTo(size - strokeWidth, strokeWidth/2);
canvas.drawPath(path, paint);
}
}
package com.cjt2325.cameralibrary;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.View;
/**
* =====================================
* 作 者: 陈嘉桐 445263848@qq.com
* 版 本:1.0.4
* 创建日期:2017/4/26
* 描 述:拍照或录制完成后弹出的确认和返回按钮
* =====================================
*/
public class TypeButton extends View{
public static final int TYPE_CANCEL = 0x001;
public static final int TYPE_CONFIRM = 0x002;
private int button_type;
private int button_size;
private float center_X;
private float center_Y;
private float button_radius;
private Paint mPaint;
private Path path;
private float strokeWidth;
private float index;
private RectF rectF;
public TypeButton(Context context) {
super(context);
}
public TypeButton(Context context, int type, int size) {
super(context);
this.button_type = type;
button_size = size;
button_radius = size / 2.0f;
center_X = size / 2.0f;
center_Y = size / 2.0f;
mPaint = new Paint();
path = new Path();
strokeWidth = size / 50f;
index = button_size / 12f;
rectF = new RectF(center_X, center_Y - index, center_X + index * 2, center_Y + index);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(button_size, button_size);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//如果类型为取消,则绘制内部为返回箭头
if (button_type == TYPE_CANCEL) {
mPaint.setAntiAlias(true);
mPaint.setColor(0xEEDCDCDC);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(center_X, center_Y, button_radius, mPaint);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(strokeWidth);
path.moveTo(center_X - index / 7, center_Y + index);
path.lineTo(center_X + index, center_Y + index);
path.arcTo(rectF, 90, -180);
path.lineTo(center_X - index, center_Y - index);
canvas.drawPath(path, mPaint);
mPaint.setStyle(Paint.Style.FILL);
path.reset();
path.moveTo(center_X - index, (float) (center_Y - index * 1.5));
path.lineTo(center_X - index, (float) (center_Y - index / 2.3));
path.lineTo((float) (center_X - index * 1.6), center_Y - index);
path.close();
canvas.drawPath(path, mPaint);
}
//如果类型为确认,则绘制绿色勾
if (button_type == TYPE_CONFIRM) {
mPaint.setAntiAlias(true);
mPaint.setColor(0xFFFFFFFF);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(center_X, center_Y, button_radius, mPaint);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0xFF00CC00);
mPaint.setStrokeWidth(strokeWidth);
path.moveTo(center_X - button_size / 6f, center_Y);
path.lineTo(center_X - button_size / 21.2f, center_Y + button_size / 7.7f);
path.lineTo(center_X + button_size / 4.0f, center_Y - button_size / 8.5f);
path.lineTo(center_X - button_size / 21.2f, center_Y + button_size / 9.4f);
path.close();
canvas.drawPath(path, mPaint);
}
}
}
package com.cjt2325.cameralibrary.listener;
/**
* create by CJT2325
* 445263848@qq.com.
*/
public interface CaptureListener {
void takePictures();
void recordShort(long time);
void recordStart();
void recordEnd(long time);
void recordZoom(float zoom);
void recordError();
}
package com.cjt2325.cameralibrary.listener;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.9
* 创建日期:2017/10/7
* 描 述:
* =====================================
*/
public interface ClickListener {
void onClick();
}
package com.cjt2325.cameralibrary.listener;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/6/5
* 描 述:
* =====================================
*/
public interface ErrorListener {
void onError();
void AudioPermissionError();
}
package com.cjt2325.cameralibrary.listener;
import android.graphics.Bitmap;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/26
* 描 述:
* =====================================
*/
public interface JCameraListener {
void captureSuccess(Bitmap bitmap);
void recordSuccess(String url, Bitmap firstFrame);
}
package com.cjt2325.cameralibrary.listener;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public interface ResultListener {
void callback();
}
package com.cjt2325.cameralibrary.listener;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/26
* 描 述:
* =====================================
*/
public interface ReturnListener {
void onReturn();
}
package com.cjt2325.cameralibrary.listener;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/25
* 描 述:
* =====================================
*/
public interface TypeListener {
void cancel();
void confirm();
}
package com.cjt2325.cameralibrary.state;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.cjt2325.cameralibrary.CameraInterface;
import com.cjt2325.cameralibrary.JCameraView;
import com.cjt2325.cameralibrary.util.LogUtil;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public class BorrowPictureState implements State {
private final String TAG = "BorrowPictureState";
private CameraMachine machine;
public BorrowPictureState(CameraMachine machine) {
this.machine = machine;
}
@Override
public void start(SurfaceHolder holder, float screenProp) {
CameraInterface.getInstance().doStartPreview(holder, screenProp);
machine.setState(machine.getPreviewState());
}
@Override
public void stop() {
}
@Override
public void foucs(float x, float y, CameraInterface.FocusCallback callback) {
}
@Override
public void swtich(SurfaceHolder holder, float screenProp) {
}
@Override
public void restart() {
}
@Override
public void capture() {
}
@Override
public void record(Surface surface,float screenProp) {
}
@Override
public void stopRecord(boolean isShort, long time) {
}
@Override
public void cancle(SurfaceHolder holder, float screenProp) {
CameraInterface.getInstance().doStartPreview(holder, screenProp);
machine.getView().resetState(JCameraView.TYPE_PICTURE);
machine.setState(machine.getPreviewState());
}
@Override
public void confirm() {
machine.getView().confirmState(JCameraView.TYPE_PICTURE);
machine.setState(machine.getPreviewState());
}
@Override
public void zoom(float zoom, int type) {
LogUtil.i(TAG, "zoom");
}
@Override
public void flash(String mode) {
}
}
package com.cjt2325.cameralibrary.state;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.cjt2325.cameralibrary.CameraInterface;
import com.cjt2325.cameralibrary.JCameraView;
import com.cjt2325.cameralibrary.util.LogUtil;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public class BorrowVideoState implements State {
private final String TAG = "BorrowVideoState";
private CameraMachine machine;
public BorrowVideoState(CameraMachine machine) {
this.machine = machine;
}
@Override
public void start(SurfaceHolder holder, float screenProp) {
CameraInterface.getInstance().doStartPreview(holder, screenProp);
machine.setState(machine.getPreviewState());
}
@Override
public void stop() {
}
@Override
public void foucs(float x, float y, CameraInterface.FocusCallback callback) {
}
@Override
public void swtich(SurfaceHolder holder, float screenProp) {
}
@Override
public void restart() {
}
@Override
public void capture() {
}
@Override
public void record(Surface surface, float screenProp) {
}
@Override
public void stopRecord(boolean isShort, long time) {
}
@Override
public void cancle(SurfaceHolder holder, float screenProp) {
machine.getView().resetState(JCameraView.TYPE_VIDEO);
machine.setState(machine.getPreviewState());
}
@Override
public void confirm() {
machine.getView().confirmState(JCameraView.TYPE_VIDEO);
machine.setState(machine.getPreviewState());
}
@Override
public void zoom(float zoom, int type) {
LogUtil.i(TAG, "zoom");
}
@Override
public void flash(String mode) {
}
}
package com.cjt2325.cameralibrary.state;
import android.content.Context;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.cjt2325.cameralibrary.CameraInterface;
import com.cjt2325.cameralibrary.view.CameraView;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public class CameraMachine implements State {
private Context context;
private State state;
private CameraView view;
// private CameraInterface.CameraOpenOverCallback cameraOpenOverCallback;
private State previewState; //浏览状态(空闲)
private State borrowPictureState; //浏览图片
private State borrowVideoState; //浏览视频
public CameraMachine(Context context, CameraView view, CameraInterface.CameraOpenOverCallback
cameraOpenOverCallback) {
this.context = context;
previewState = new PreviewState(this);
borrowPictureState = new BorrowPictureState(this);
borrowVideoState = new BorrowVideoState(this);
//默认设置为空闲状态
this.state = previewState;
// this.cameraOpenOverCallback = cameraOpenOverCallback;
this.view = view;
}
public CameraView getView() {
return view;
}
public Context getContext() {
return context;
}
public void setState(State state) {
this.state = state;
}
//获取浏览图片状态
State getBorrowPictureState() {
return borrowPictureState;
}
//获取浏览视频状态
State getBorrowVideoState() {
return borrowVideoState;
}
//获取空闲状态
State getPreviewState() {
return previewState;
}
@Override
public void start(SurfaceHolder holder, float screenProp) {
state.start(holder, screenProp);
}
@Override
public void stop() {
state.stop();
}
@Override
public void foucs(float x, float y, CameraInterface.FocusCallback callback) {
state.foucs(x, y, callback);
}
@Override
public void swtich(SurfaceHolder holder, float screenProp) {
state.swtich(holder, screenProp);
}
@Override
public void restart() {
state.restart();
}
@Override
public void capture() {
state.capture();
}
@Override
public void record(Surface surface, float screenProp) {
state.record(surface, screenProp);
}
@Override
public void stopRecord(boolean isShort, long time) {
state.stopRecord(isShort, time);
}
@Override
public void cancle(SurfaceHolder holder, float screenProp) {
state.cancle(holder, screenProp);
}
@Override
public void confirm() {
state.confirm();
}
@Override
public void zoom(float zoom, int type) {
state.zoom(zoom, type);
}
@Override
public void flash(String mode) {
state.flash(mode);
}
public State getState() {
return this.state;
}
}
package com.cjt2325.cameralibrary.state;
import android.graphics.Bitmap;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.cjt2325.cameralibrary.CameraInterface;
import com.cjt2325.cameralibrary.JCameraView;
import com.cjt2325.cameralibrary.util.LogUtil;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:空闲状态
* =====================================
*/
class PreviewState implements State {
public static final String TAG = "PreviewState";
private CameraMachine machine;
PreviewState(CameraMachine machine) {
this.machine = machine;
}
@Override
public void start(SurfaceHolder holder, float screenProp) {
CameraInterface.getInstance().doStartPreview(holder, screenProp);
}
@Override
public void stop() {
CameraInterface.getInstance().doStopPreview();
}
@Override
public void foucs(float x, float y, CameraInterface.FocusCallback callback) {
LogUtil.i("preview state foucs");
if (machine.getView().handlerFoucs(x, y)) {
CameraInterface.getInstance().handleFocus(machine.getContext(), x, y, callback);
}
}
@Override
public void swtich(SurfaceHolder holder, float screenProp) {
CameraInterface.getInstance().switchCamera(holder, screenProp);
}
@Override
public void restart() {
}
@Override
public void capture() {
CameraInterface.getInstance().takePicture(new CameraInterface.TakePictureCallback() {
@Override
public void captureResult(Bitmap bitmap, boolean isVertical) {
machine.getView().showPicture(bitmap, isVertical);
machine.setState(machine.getBorrowPictureState());
LogUtil.i("capture");
}
});
}
@Override
public void record(Surface surface, float screenProp) {
CameraInterface.getInstance().startRecord(surface, screenProp, null);
}
@Override
public void stopRecord(final boolean isShort, long time) {
CameraInterface.getInstance().stopRecord(isShort, new CameraInterface.StopRecordCallback() {
@Override
public void recordResult(String url, Bitmap firstFrame) {
if (isShort) {
machine.getView().resetState(JCameraView.TYPE_SHORT);
} else {
machine.getView().playVideo(firstFrame, url);
machine.setState(machine.getBorrowVideoState());
}
}
});
}
@Override
public void cancle(SurfaceHolder holder, float screenProp) {
LogUtil.i("浏览状态下,没有 cancle 事件");
}
@Override
public void confirm() {
LogUtil.i("浏览状态下,没有 confirm 事件");
}
@Override
public void zoom(float zoom, int type) {
LogUtil.i(TAG, "zoom");
CameraInterface.getInstance().setZoom(zoom, type);
}
@Override
public void flash(String mode) {
CameraInterface.getInstance().setFlashMode(mode);
}
}
package com.cjt2325.cameralibrary.state;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.cjt2325.cameralibrary.CameraInterface;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public interface State {
void start(SurfaceHolder holder, float screenProp);
void stop();
void foucs(float x, float y, CameraInterface.FocusCallback callback);
void swtich(SurfaceHolder holder, float screenProp);
void restart();
void capture();
void record(Surface surface, float screenProp);
void stopRecord(boolean isShort, long time);
void cancle(SurfaceHolder holder, float screenProp);
void confirm();
void zoom(float zoom, int type);
void flash(String mode);
}
package com.cjt2325.cameralibrary.util;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/5/2
* 描 述:
* =====================================
*/
public class AngleUtil {
public static int getSensorAngle(float x, float y) {
if (Math.abs(x) > Math.abs(y)) {
/**
* 横屏倾斜角度比较大
*/
if (x > 4) {
/**
* 左边倾斜
*/
return 270;
} else if (x < -4) {
/**
* 右边倾斜
*/
return 90;
} else {
/**
* 倾斜角度不够大
*/
return 0;
}
} else {
if (y > 7) {
/**
* 左边倾斜
*/
return 0;
} else if (y < -7) {
/**
* 右边倾斜
*/
return 180;
} else {
/**
* 倾斜角度不够大
*/
return 0;
}
}
}
}
package com.cjt2325.cameralibrary.util;
import android.content.Context;
import android.media.AudioManager;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/26
* 描 述:
* =====================================
*/
public class AudioUtil {
public static void setAudioManage(Context context) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
audioManager.setStreamVolume(AudioManager.STREAM_DTMF, 0, 0);
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 0, 0);
audioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
}
}
package com.cjt2325.cameralibrary.util;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;
import android.view.WindowManager;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/25
* 描 述:
* =====================================
*/
public class CameraParamUtil {
private static final String TAG = "JCameraView";
private CameraSizeComparator sizeComparator = new CameraSizeComparator();
private static CameraParamUtil cameraParamUtil = null;
private CameraParamUtil() {
}
public static CameraParamUtil getInstance() {
if (cameraParamUtil == null) {
cameraParamUtil = new CameraParamUtil();
return cameraParamUtil;
} else {
return cameraParamUtil;
}
}
public Camera.Size getPreviewSize(List<Camera.Size> list, int th, float rate) {
Collections.sort(list, sizeComparator);
int i = 0;
for (Camera.Size s : list) {
if ((s.width > th) && equalRate(s, rate)) {
Log.i(TAG, "MakeSure Preview :w = " + s.width + " h = " + s.height);
break;
}
i++;
}
if (i == list.size()) {
return getBestSize(list, rate);
} else {
return list.get(i);
}
}
public Camera.Size getPictureSize(List<Camera.Size> list, int th, float rate) {
Collections.sort(list, sizeComparator);
int i = 0;
for (Camera.Size s : list) {
if ((s.width > th) && equalRate(s, rate)) {
Log.i(TAG, "MakeSure Picture :w = " + s.width + " h = " + s.height);
break;
}
i++;
}
if (i == list.size()) {
return getBestSize(list, rate);
} else {
return list.get(i);
}
}
private Camera.Size getBestSize(List<Camera.Size> list, float rate) {
float previewDisparity = 100;
int index = 0;
for (int i = 0; i < list.size(); i++) {
Camera.Size cur = list.get(i);
float prop = (float) cur.width / (float) cur.height;
if (Math.abs(rate - prop) < previewDisparity) {
previewDisparity = Math.abs(rate - prop);
index = i;
}
}
return list.get(index);
}
private boolean equalRate(Camera.Size s, float rate) {
float r = (float) (s.width) / (float) (s.height);
return Math.abs(r - rate) <= 0.2;
}
public boolean isSupportedFocusMode(List<String> focusList, String focusMode) {
for (int i = 0; i < focusList.size(); i++) {
if (focusMode.equals(focusList.get(i))) {
Log.i(TAG, "FocusMode supported " + focusMode);
return true;
}
}
Log.i(TAG, "FocusMode not supported " + focusMode);
return false;
}
public boolean isSupportedPictureFormats(List<Integer> supportedPictureFormats, int jpeg) {
for (int i = 0; i < supportedPictureFormats.size(); i++) {
if (jpeg == supportedPictureFormats.get(i)) {
Log.i(TAG, "Formats supported " + jpeg);
return true;
}
}
Log.i(TAG, "Formats not supported " + jpeg);
return false;
}
private class CameraSizeComparator implements Comparator<Camera.Size> {
public int compare(Camera.Size lhs, Camera.Size rhs) {
if (lhs.width == rhs.width) {
return 0;
} else if (lhs.width > rhs.width) {
return 1;
} else {
return -1;
}
}
}
public int getCameraDisplayOrientation(Context context, int cameraId) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int rotation = wm.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else {
// back-facing
result = (info.orientation - degrees + 360) % 360;
}
return result;
}
}
package com.cjt2325.cameralibrary.util;
import android.hardware.Camera;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/6/8
* 描 述:
* =====================================
*/
public class CheckPermission {
public static final int STATE_RECORDING = -1;
public static final int STATE_NO_PERMISSION = -2;
public static final int STATE_SUCCESS = 1;
/**
* 用于检测是否具有录音权限
*
* @return
*/
public static int getRecordState() {
int minBuffer = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat
.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat
.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, (minBuffer * 100));
short[] point = new short[minBuffer];
int readSize = 0;
try {
audioRecord.startRecording();//检测是否可以进入初始化状态
} catch (Exception e) {
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
return STATE_NO_PERMISSION;
}
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
//6.0以下机型都会返回此状态,故使用时需要判断bulid版本
//检测是否在录音中
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
Log.d("CheckAudioPermission", "录音机被占用");
}
return STATE_RECORDING;
} else {
//检测是否可以获取录音结果
readSize = audioRecord.read(point, 0, point.length);
if (readSize <= 0) {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
Log.d("CheckAudioPermission", "录音的结果为空");
return STATE_NO_PERMISSION;
} else {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_SUCCESS;
}
}
}
public synchronized static boolean isCameraUseable(int cameraID) {
boolean canUse = true;
Camera mCamera = null;
try {
mCamera = Camera.open(cameraID);
// setParameters 是针对魅族MX5。MX5通过Camera.open()拿到的Camera对象不为null
Camera.Parameters mParameters = mCamera.getParameters();
mCamera.setParameters(mParameters);
} catch (Exception e) {
e.printStackTrace();
canUse = false;
} finally {
if (mCamera != null) {
mCamera.release();
} else {
canUse = false;
}
mCamera = null;
}
return canUse;
}
}
\ No newline at end of file
package com.cjt2325.cameralibrary.util;
import android.os.Build;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/6/9
* 描 述:
* =====================================
*/
public class DeviceUtil {
private static String[] huaweiRongyao = {
"hwH60", //荣耀6
"hwPE", //荣耀6 plus
"hwH30", //3c
"hwHol", //3c畅玩版
"hwG750", //3x
"hw7D", //x1
"hwChe2", //x1
};
public static String getDeviceInfo() {
String handSetInfo =
"手机型号:" + Build.DEVICE +
"\n系统版本:" + Build.VERSION.RELEASE +
"\nSDK版本:" + Build.VERSION.SDK_INT;
return handSetInfo;
}
public static String getDeviceModel() {
return Build.DEVICE;
}
public static boolean isHuaWeiRongyao() {
int length = huaweiRongyao.length;
for (int i = 0; i < length; i++) {
if (huaweiRongyao[i].equals(getDeviceModel())) {
return true;
}
}
return false;
}
}
package com.cjt2325.cameralibrary.util;
import android.graphics.Bitmap;
import android.os.Environment;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/4/25
* 描 述:
* =====================================
*/
public class FileUtil {
private static final String TAG = "CJT";
private static final File parentPath = Environment.getExternalStorageDirectory();
private static String storagePath = "";
private static String DST_FOLDER_NAME = "JCamera";
private static String initPath() {
if (storagePath.equals("")) {
storagePath = parentPath.getAbsolutePath() + File.separator + DST_FOLDER_NAME;
File f = new File(storagePath);
if (!f.exists()) {
f.mkdir();
}
}
return storagePath;
}
public static String saveBitmap(String dir, Bitmap b) {
DST_FOLDER_NAME = dir;
String path = initPath();
long dataTake = System.currentTimeMillis();
String jpegName = path + File.separator + "picture_" + dataTake + ".jpg";
try {
FileOutputStream fout = new FileOutputStream(jpegName);
BufferedOutputStream bos = new BufferedOutputStream(fout);
b.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
return jpegName;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
public static boolean deleteFile(String url) {
boolean result = false;
File file = new File(url);
if (file.exists()) {
result = file.delete();
}
return result;
}
public static boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
}
package com.cjt2325.cameralibrary.util;
import android.util.Log;
import static com.cjt2325.cameralibrary.BuildConfig.DEBUG;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/7
* 描 述:
* =====================================
*/
public class LogUtil {
private static final String DEFAULT_TAG = "CJT";
public static void i(String tag, String msg) {
// if (DEBUG)
Log.i(tag, msg);
}
public static void v(String tag, String msg) {
if (DEBUG)
Log.v(tag, msg);
}
public static void d(String tag, String msg) {
if (DEBUG)
Log.d(tag, msg);
}
public static void e(String tag, String msg) {
if (DEBUG)
Log.e(tag, msg);
}
public static void i(String msg) {
i(DEFAULT_TAG, msg);
}
public static void v(String msg) {
v(DEFAULT_TAG, msg);
}
public static void d(String msg) {
d(DEFAULT_TAG, msg);
}
public static void e(String msg) {
e(DEFAULT_TAG, msg);
}
}
package com.cjt2325.cameralibrary.util;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/5/25
* 描 述:
* =====================================
*/
public class ScreenUtils {
public static int screenWidth;
public static int screenHeight;
public static int getScreenHeight(Context context) {
DisplayMetrics metric = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metric);
screenHeight = metric.heightPixels;
return metric.heightPixels;
}
public static int getScreenWidth(Context context) {
DisplayMetrics metric = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metric);
screenWidth = metric.widthPixels;
return metric.widthPixels;
}
}
package com.cjt2325.cameralibrary.view;
import android.graphics.Bitmap;
/**
* =====================================
* 作 者: 陈嘉桐
* 版 本:1.1.4
* 创建日期:2017/9/8
* 描 述:
* =====================================
*/
public interface CameraView {
void resetState(int type);
void confirmState(int type);
void showPicture(Bitmap bitmap, boolean isVertical);
void playVideo(Bitmap firstFrame, String url);
void stopVideo();
void setTip(String tip);
void startPreviewCallback();
boolean handlerFoucs(float x, float y);
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M9,3L7.17,5L4,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,7c0,-1.1 -0.9,-2 -2,-2h-3.17L15,3L9,3zM12,18c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,17l1.25,-2.75L16,13l-2.75,-1.25L12,9l-1.25,2.75L8,13l2.75,1.25z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3,2v12h3v9l7,-12L9,11l4,-9L3,2zM19,2h-2l-3.2,9h1.9l0.7,-2h3.2l0.7,2h1.9L19,2zM16.85,7.65L18,4l1.15,3.65h-2.3z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.27,3L2,4.27l5,5V13h3v9l3.58,-6.14L17.73,20 19,18.73 3.27,3zM17,10h-4l4,-8H7v2.18l8.46,8.46L17,10z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M7,2v11h3v9l7,-12h-4l4,-8z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<VideoView
android:id="@+id/video_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/image_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
android:visibility="invisible"/>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_flash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_flash_on"/>
<ImageView
android:id="@+id/image_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_camera"/>
</LinearLayout>
<com.cjt2325.cameralibrary.CaptureLayout
android:id="@+id/capture_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
<com.cjt2325.cameralibrary.FoucsView
android:id="@+id/fouce_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"/>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="iconSize" format="dimension"/>
<attr name="iconMargin" format="dimension"/>
<attr name="iconSrc" format="reference"/>
<attr name="iconLeft" format="reference"/>
<attr name="iconRight" format="reference"/>
<attr name="duration_max" format="integer"/>
<declare-styleable name="JCameraView">
<attr name="iconSize"/>
<attr name="iconMargin"/>
<attr name="iconSrc"/>
<attr name="iconLeft"/>
<attr name="iconRight"/>
<attr name="duration_max"/>
</declare-styleable>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">CameraLibrary</string>
</resources>
package com.cjt2325.cameralibrary;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
......@@ -5,16 +5,25 @@ import android.view.View;
import com.dayu.base.ui.adapter.CoreAdapter;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.bean.CommonLearnBean;
import com.dayu.learncenter.api.data.StudyCourseData;
import com.dayu.learncenter.databinding.ItemCommonLearnBinding;
import com.dayu.learncenter.presenter.common_learn.CommonLearnPresenter;
import com.dayu.utils.CommonUtils;
import com.dayu.utils.GlideImageLoader;
import com.dayu.utils.LogUtils;
import com.dayu.utils.ToastUtils;
import com.dayu.widgets.MyJzvdStd;
public class LearnAdapter extends CoreAdapter<CommonLearnBean,ItemCommonLearnBinding> {
private int type;
import cn.jzvd.JzvdStd;
public LearnAdapter(boolean needFoot,int type) {
public class LearnAdapter extends CoreAdapter<CommonLearnBean, ItemCommonLearnBinding> {
private int type; //1.全部 2.已学习 3.已发布
private CommonLearnPresenter mPresenter;
public void setPresenter(CommonLearnPresenter mPresenter) {
this.mPresenter = mPresenter;
}
public LearnAdapter(boolean needFoot, int type) {
super(needFoot);
this.type = type;
}
......@@ -22,32 +31,48 @@ public class LearnAdapter extends CoreAdapter<CommonLearnBean,ItemCommonLearnBin
@Override
protected void onBind(ItemCommonLearnBinding holder, CommonLearnBean item, int position) {
super.onBind(holder, item, position);
holder.tvTitle.setText(item.title);
holder.jzVideo.setUp(item.url,"");
GlideImageLoader.load(mContext, holder.jzVideo.posterImageView, item.url, R.drawable.icon_video_default);
holder.tvTitle.setText(item.getName());
holder.tvLooks.setText(item.getLearners() + "");
holder.tvLike.setText(item.getPoints() + "");
if (type == 2){
holder.tvProgress.setVisibility(View.VISIBLE);
holder.tvProgress.setText(mContext.getString(R.string.learn_progress)+item.getProgressPercentage()+"%");
}
holder.tvDisable.setVisibility(type == 3 && item.getStatus() != 1?View.VISIBLE:View.GONE);
holder.jzVideo.setUp(item.getUrl(), "",JzvdStd.SCREEN_NORMAL);
CommonUtils.setVideoThumb(mContext, holder.jzVideo, item.getUrl());
holder.jzVideo.setPlayCallBack(new MyJzvdStd.PlayCallBack() {
@Override
public void onstart() {
LogUtils.e("videoState start "+item.id);
item.showDate = false;
holder.tvDate.setVisibility(View.GONE);
if (item.getPlayStatus() == 2 && item.getProgressTimes()>0){
holder.jzVideo.seekToInAdvance = item.getProgressTimes();
}
LogUtils.e("videoState start " + item.getId());
holder.rlCover.setVisibility(View.GONE);
if (item.getPlayStatus() != 2 && item.getPlayStatus() != 3)
mPresenter.studyCourse(item.getId(), 0, 0, 1);
}
@Override
public void onPrepare() {
LogUtils.e("videoState prepa3 "+item.id);
holder.tvDate.setVisibility(View.VISIBLE);
LogUtils.e("videoState prepa3 " + item.getId());
holder.rlCover.setVisibility(View.VISIBLE);
}
@Override
public void onPause() {
LogUtils.e("videoState pause: "+item.id+" "+holder.jzVideo.curProgress
+" "+holder.jzVideo.curPosition+" "+holder.jzVideo.getDuration());
LogUtils.e("videoState pause: " + item.getId() + " " + holder.jzVideo.curProgress
+ " " + holder.jzVideo.curPosition + " " + holder.jzVideo.getDuration());
if (item.getPlayStatus() != 3)
mPresenter.studyCourse(item.getId(), holder.jzVideo.curProgress, holder.jzVideo.curPosition, 2);
}
@Override
public void onComplete() {
LogUtils.e("videoState complete");
if (item.getPlayStatus() != 3)
mPresenter.studyCourse(item.getId(), 100, holder.jzVideo.getDuration(), 3);
}
});
}
......
package com.dayu.learncenter.api;
import com.dayu.base.api.protocol.BasePageBean;
import com.dayu.base.api.protocol.BaseResponse;
import com.dayu.common.Constants;
import com.dayu.learncenter.api.bean.CommonLearnBean;
import com.dayu.learncenter.api.bean.CourseDeatilBean;
import com.dayu.learncenter.api.bean.LearnTabBean;
import com.dayu.learncenter.api.data.EditCourseData;
import com.dayu.learncenter.api.data.PubCourseData;
import com.dayu.learncenter.api.data.StudyCourseData;
import java.security.Key;
import io.reactivex.Observable;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface LearnService {
/**
* 获取学习顶部tab对应数量
*
* @return
*/
@GET(Constants.API_7900 + "/courses/courseCount/{enginnerId}")
Observable<BaseResponse<LearnTabBean>> getLearTabNum(@Path("enginnerId") int engineerId);
/**
* 发布学习课程
*
* @param data
* @return
*/
@POST(Constants.API_7900 + "/courses")
Observable<BaseResponse<Boolean>> pubCourse(@Body PubCourseData data);
/**
* 修改已发布的学习课程
*
* @param data
* @return
*/
@PUT(Constants.API_7900 + "/courses")
Observable<BaseResponse<Boolean>> modifyCourse(@Body EditCourseData data);
/**
* 学习课程
*
* @param data
* @return
*/
@POST(Constants.API_7900 + "/courses/studyCourse")
Observable<BaseResponse<Boolean>> studyCourse(@Body StudyCourseData data);
/**
* 获取全部课程
*
* @param key 查询关键字
* @return
*/
@GET(Constants.API_7900 + "/courses/all")
Observable<BaseResponse<BasePageBean<CommonLearnBean>>> getAllCourse(@Query("enginnerId") int enginnerId,
@Query("key") String key,
@Query("page") int page,
@Query("pageSize") int pageSize);
/**
* 获取已学习课程
*
* @param key 查询关键字
* @return
*/
@GET(Constants.API_7900 + "/courses/learn")
Observable<BaseResponse<BasePageBean<CommonLearnBean>>> getLearnedCourse(@Query("enginnerId") int enginnerId,
@Query("key") String key,
@Query("page") int page,
@Query("pageSize") int pageSize);
/**
* 获取已发布的课程
*
* @return
*/
@GET(Constants.API_7900 + "/courses")
Observable<BaseResponse<BasePageBean<CommonLearnBean>>> getPubedCourse(@Query("createId") int createId,
@Query("page") int page,
@Query("pageSize") int pageSize);
/**
* 获取课程详情
*
* @return
*/
@GET(Constants.API_7900 + "/courses/detail/courseId/{courseId}/engineerId/{engineerId}")
Observable<BaseResponse<CourseDeatilBean>> getCourseDetail(@Path("courseId") int courseId,
@Path("engineerId") int engineerId);
/**
* 课程 点赞/取消点赞
* @param type 1点赞 2取消点赞
* @return
*/
@GET(Constants.API_7900 + "/courses/point/courseId/{courseId}/engineerId/{engineerId}/type/{type}")
Observable<BaseResponse<Boolean>> pointCourse(@Path("courseId") int courseId,
@Path("engineerId") int engineerId,
@Path("type") int type);
}
package com.dayu.learncenter.api.bean;
public class CommonLearnBean {
public int id;
public String url;
public String title;
public boolean showDate = true;
public CommonLearnBean(int id, String url, String title) {
/**
* brief : string
* courseNum : string
* courseTimes : 0
* createId : 0
* createTime : 2020-04-24T01:48:47.432Z
* created : string
* engineerId : 0
* engineerMobile : string
* engineerName : string
* id : 0
* learners : 0
* leaves : 0
* name : string
* playStatus : 0
* points : 0
* progressPercentage : 0
* progressTimes : 0
* status : 0
* type : 0
* url : string
*/
private String brief;
private String courseNum;
private int courseTimes;
private int createId;
private String createTime;
private String created;
private int engineerId;
private String engineerMobile;
private String engineerName;
private int id;
private int learners;
private int leaves;
private String name;
private int playStatus;
private int points;
private int progressPercentage;
private long progressTimes;
private int status;
private int type;
private String url;
public String getBrief() {
return brief;
}
public void setBrief(String brief) {
this.brief = brief;
}
public String getCourseNum() {
return courseNum;
}
public void setCourseNum(String courseNum) {
this.courseNum = courseNum;
}
public int getCourseTimes() {
return courseTimes;
}
public void setCourseTimes(int courseTimes) {
this.courseTimes = courseTimes;
}
public int getCreateId() {
return createId;
}
public void setCreateId(int createId) {
this.createId = createId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public int getEngineerId() {
return engineerId;
}
public void setEngineerId(int engineerId) {
this.engineerId = engineerId;
}
public String getEngineerMobile() {
return engineerMobile;
}
public void setEngineerMobile(String engineerMobile) {
this.engineerMobile = engineerMobile;
}
public String getEngineerName() {
return engineerName;
}
public void setEngineerName(String engineerName) {
this.engineerName = engineerName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getLearners() {
return learners;
}
public void setLearners(int learners) {
this.learners = learners;
}
public int getLeaves() {
return leaves;
}
public void setLeaves(int leaves) {
this.leaves = leaves;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPlayStatus() {
return playStatus;
}
public void setPlayStatus(int playStatus) {
this.playStatus = playStatus;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public int getProgressPercentage() {
return progressPercentage;
}
public void setProgressPercentage(int progressPercentage) {
this.progressPercentage = progressPercentage;
}
public long getProgressTimes() {
return progressTimes;
}
public void setProgressTimes(long progressTimes) {
this.progressTimes = progressTimes;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
this.title = title;
}
}
package com.dayu.learncenter.api.bean;
import java.io.Serializable;
public class CourseDeatilBean implements Serializable {
/**
* brief : string
* courseNum : string
* coursePointsVO : {"courseId":0,"createTime":"2020-04-24T01:52:07.088Z","engineerId":0,"id":0,"pointStatus":0}
* courseStudyVO : {"courseId":0,"engineerId":0,"engineerMobile":"string","engineerName":"string","finTime":"2020-04-24T01:52:07.088Z","id":0,"pointStatus":0,"progressPercentage":0,"progressTimes":0,"startTime":"2020-04-24T01:52:07.088Z","status":0}
* courseTimes : 0
* createId : 0
* createTime : 2020-04-24T01:52:07.088Z
* created : string
* id : 0
* learners : 0
* leaves : 0
* name : string
* points : 0
* status : 0
* type : 0
* url : string
*/
private String brief;
private String courseNum;
private CoursePointsVOBean coursePointsVO;
private CourseStudyVOBean courseStudyVO;
private int courseTimes;
private int createId;
private String createTime;
private String created;
private int id;
private int learners;
private int leaves;
private String name;
private int points;
private int status;
private int type;
private String url;
public String getBrief() {
return brief;
}
public void setBrief(String brief) {
this.brief = brief;
}
public String getCourseNum() {
return courseNum;
}
public void setCourseNum(String courseNum) {
this.courseNum = courseNum;
}
public CoursePointsVOBean getCoursePointsVO() {
return coursePointsVO;
}
public void setCoursePointsVO(CoursePointsVOBean coursePointsVO) {
this.coursePointsVO = coursePointsVO;
}
public CourseStudyVOBean getCourseStudyVO() {
return courseStudyVO;
}
public void setCourseStudyVO(CourseStudyVOBean courseStudyVO) {
this.courseStudyVO = courseStudyVO;
}
public int getCourseTimes() {
return courseTimes;
}
public void setCourseTimes(int courseTimes) {
this.courseTimes = courseTimes;
}
public int getCreateId() {
return createId;
}
public void setCreateId(int createId) {
this.createId = createId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getLearners() {
return learners;
}
public void setLearners(int learners) {
this.learners = learners;
}
public int getLeaves() {
return leaves;
}
public void setLeaves(int leaves) {
this.leaves = leaves;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public static class CoursePointsVOBean implements Serializable{
/**
* courseId : 0
* createTime : 2020-04-24T01:52:07.088Z
* engineerId : 0
* id : 0
* pointStatus : 0
*/
private int courseId;
private String createTime;
private int engineerId;
private int id;
private int pointStatus;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public int getEngineerId() {
return engineerId;
}
public void setEngineerId(int engineerId) {
this.engineerId = engineerId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPointStatus() {
return pointStatus;
}
public void setPointStatus(int pointStatus) {
this.pointStatus = pointStatus;
}
}
public static class CourseStudyVOBean implements Serializable{
/**
* courseId : 0
* engineerId : 0
* engineerMobile : string
* engineerName : string
* finTime : 2020-04-24T01:52:07.088Z
* id : 0
* pointStatus : 0
* progressPercentage : 0
* progressTimes : 0
* startTime : 2020-04-24T01:52:07.088Z
* status : 0
*/
private int courseId;
private int engineerId;
private String engineerMobile;
private String engineerName;
private String finTime;
private int id;
private int pointStatus;
private int progressPercentage;
private int progressTimes;
private String startTime;
private int status;
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public int getEngineerId() {
return engineerId;
}
public void setEngineerId(int engineerId) {
this.engineerId = engineerId;
}
public String getEngineerMobile() {
return engineerMobile;
}
public void setEngineerMobile(String engineerMobile) {
this.engineerMobile = engineerMobile;
}
public String getEngineerName() {
return engineerName;
}
public void setEngineerName(String engineerName) {
this.engineerName = engineerName;
}
public String getFinTime() {
return finTime;
}
public void setFinTime(String finTime) {
this.finTime = finTime;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPointStatus() {
return pointStatus;
}
public void setPointStatus(int pointStatus) {
this.pointStatus = pointStatus;
}
public int getProgressPercentage() {
return progressPercentage;
}
public void setProgressPercentage(int progressPercentage) {
this.progressPercentage = progressPercentage;
}
public int getProgressTimes() {
return progressTimes;
}
public void setProgressTimes(int progressTimes) {
this.progressTimes = progressTimes;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
}
package com.dayu.learncenter.api.bean;
public class LearnTabBean {
/**
* leaners : 0
* publishes : 0
* totalCourses : 6
*/
private int leaners;
private int publishes;
private int totalCourses;
public int getLeaners() {
return leaners;
}
public void setLeaners(int leaners) {
this.leaners = leaners;
}
public int getPublishes() {
return publishes;
}
public void setPublishes(int publishes) {
this.publishes = publishes;
}
public int getTotalCourses() {
return totalCourses;
}
public void setTotalCourses(int totalCourses) {
this.totalCourses = totalCourses;
}
}
package com.dayu.learncenter.api.data;
public class EditCourseData {
public int id; //课程id
public int createId; //发布人id
public int type = 2; //发布方 1.服务商 2.师傅
public int status = 1; //状态 1启用2禁用3删除 ,
public String name; //主题
public String brief; //简介
public String created; //发布人名称
public long courseTimes; //视频时长
public String url; //视频上传后的地址
public EditCourseData() {
}
public EditCourseData(int createId, String name, String brief, String created) {
this.createId = createId;
this.name = name;
this.brief = brief;
this.created = created;
}
public EditCourseData(int createId, String name, String brief, String created, long courseTimes) {
this.createId = createId;
this.name = name;
this.brief = brief;
this.created = created;
this.courseTimes = courseTimes;
}
}
package com.dayu.learncenter.api.data;
public class PubCourseData {
public int createId; //发布人id
public int type = 2; //发布方 1.服务商 2.师傅
public int status = 1; //状态 1启用2禁用3删除 ,
public String name; //主题
public String brief; //简介
public String created; //发布人名称
public long courseTimes; //视频时长
public String url; //视频上传后的地址
public PubCourseData() {
}
public PubCourseData(int createId, String name, String brief, String created) {
this.createId = createId;
this.name = name;
this.brief = brief;
this.created = created;
}
public PubCourseData(int createId, String name, String brief, String created, long courseTimes) {
this.createId = createId;
this.name = name;
this.brief = brief;
this.created = created;
this.courseTimes = courseTimes;
}
}
package com.dayu.learncenter.api.data;
public class StudyCourseData {
public int courseId ; // 课程ID
public int engineerId; //师傅ID
public String engineerMobile; //工程师手机号
public String engineerName; // 工程师姓名
public int progressPercentage; // 已播放的百分比
public long progressTimes; //已播放的时间
public int status; //1首次开始播放 2首次播放中 3首次已完成播放
public StudyCourseData() {
}
public StudyCourseData(int courseId, int engineerId, String engineerMobile, String engineerName, int progressPercentage, long progressTimes, int status) {
this.courseId = courseId;
this.engineerId = engineerId;
this.engineerMobile = engineerMobile;
this.engineerName = engineerName;
this.progressPercentage = progressPercentage;
this.progressTimes = progressTimes;
this.status = status;
}
}
package com.dayu.learncenter.event;
public class CourseChangeEvent {
}
package com.dayu.learncenter.event;
public class RefreshLeanTabEvent {
}
package com.dayu.learncenter.presenter.common_learn;
import android.databinding.ObservableField;
import android.text.TextUtils;
import com.dayu.base.api.Api;
import com.dayu.base.api.protocol.BasePageBean;
import com.dayu.base.api.protocol.BaseResponse;
import com.dayu.common.Constants;
import com.dayu.event.UserInfo;
import com.dayu.learncenter.api.LearnService;
import com.dayu.learncenter.api.bean.CommonLearnBean;
import com.dayu.learncenter.api.data.StudyCourseData;
import com.dayu.learncenter.event.RefreshLeanTabEvent;
import com.dayu.utils.ToastUtils;
import com.dayu.utils.UserManager;
public class CommonLearnPresenter extends CommonLearnContract.Presenter{
import org.greenrobot.eventbus.EventBus;
import org.json.JSONObject;
import java.util.HashMap;
import cn.jzvd.JzvdStd;
import io.reactivex.Observable;
import okhttp3.MediaType;
import okhttp3.RequestBody;
public class CommonLearnPresenter extends CommonLearnContract.Presenter {
private int mUserId;
private int type;
private UserInfo mUserInfo;
private int type;//1.全部 2.已学习 3.已发布
private int mPage;
private int requestCount; //判断请求次数,不是第一次时释放jzvd
public String keyStr; //搜索关键字
private ObservableField<Object> datas = new ObservableField<>();
public void setType(int type) {
......@@ -17,12 +41,62 @@ public class CommonLearnPresenter extends CommonLearnContract.Presenter{
@Override
public void onAttached() {
UserInfo userInfo = UserManager.getInstance().getUser();
mUserId = Integer.parseInt(userInfo.getAccountId());
mUserInfo = UserManager.getInstance().getUser();
mUserId = Integer.parseInt(mUserInfo.getAccountId());
}
@Override
public ObservableField<Object> getSourceDatas() {
return datas;
}
@Override
public void refresh() {
mPage = 1;
requestData();
if (TextUtils.isEmpty(keyStr)) {
EventBus.getDefault().post(new RefreshLeanTabEvent());
}
}
private void requestData() {
if (requestCount > 0)
JzvdStd.releaseAllVideos();
Observable<BaseResponse<BasePageBean<CommonLearnBean>>> observable = null;
switch (type) {
case 1:
observable = Api.getService(LearnService.class).getAllCourse(mUserId, keyStr, mPage, Constants.PAGESIZE);
break;
case 2:
observable = Api.getService(LearnService.class).getLearnedCourse(mUserId, keyStr, mPage, Constants.PAGESIZE);
break;
case 3:
observable = Api.getService(LearnService.class).getPubedCourse(mUserId, mPage, Constants.PAGESIZE);
break;
}
if (observable != null) {
observable.compose(Api.applySchedulers()).subscribe(baseObserver(courses -> {
datas.set(courses);
mPage++;
requestCount++;
}, responeThrowable -> datas.set(Constants.FAILED)));
}
}
@Override
public void loadMore() {
requestData();
}
//学习课程
public void studyCourse(int courseId, int progress, long progressTime, int status) {
StudyCourseData studyData = new StudyCourseData(courseId, mUserId, mUserInfo.getMobile(),
mUserInfo.getAccountName(), progress, progressTime, status);
Api.getService(LearnService.class).studyCourse(studyData).compose(Api.applySchedulers())
.subscribe(baseObserver(success -> {
// ToastUtils.showShortToast("result "+success);
}));
}
}
package com.dayu.learncenter.presenter.pubcourse;
import com.dayu.base.ui.presenter.BaseListPresenter;
import com.dayu.base.ui.presenter.BasePresenter;
import com.dayu.common.BaseView;
import com.dayu.learncenter.api.bean.CourseDeatilBean;
public interface PubCourseContract {
interface View extends BaseView {
void setDetailData(CourseDeatilBean data);
}
abstract class Presenter extends BasePresenter<View> {
}
}
package com.dayu.learncenter.presenter.pubcourse;
import android.databinding.ObservableField;
import android.media.MediaMetadataRetriever;
import android.text.TextUtils;
import com.cjt2325.cameralibrary.util.LogUtil;
import com.dayu.base.api.Api;
import com.dayu.base.api.BaseApiFactory;
import com.dayu.event.UserInfo;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.LearnService;
import com.dayu.learncenter.api.data.EditCourseData;
import com.dayu.learncenter.api.data.PubCourseData;
import com.dayu.learncenter.event.CourseChangeEvent;
import com.dayu.learncenter.presenter.common_learn.CommonLearnContract;
import com.dayu.utils.CommonUtils;
import com.dayu.utils.ToastUtils;
import com.dayu.utils.UserManager;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class PubCoursePresenter extends PubCourseContract.Presenter {
private int mUserId;
private UserInfo userInfo;
private String videoUrl; //视频上传成功后的地址
PubCourseData mPubData;
EditCourseData mEditData;
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
@Override
public void onAttached() {
userInfo = UserManager.getInstance().getUser();
mUserId = Integer.parseInt(userInfo.getAccountId());
}
public void getCourseDetail(int courseId){
mView.showDialog();
Api.getService(LearnService.class).getCourseDetail(courseId, mUserId).compose(Api.applySchedulers())
.subscribe(baseObserver(data -> mView.setDetailData(data)));
}
public void pubVideo(String videoPath, PubCourseData data) {
// ToastUtils.showShortToast("length: "+CommonUtils.getVideoLength(videoPath));
mPubData = data;
if (!TextUtils.isEmpty(data.url))
videoUrl = data.url;
if (TextUtils.isEmpty(videoUrl)) {
uploadVideo(videoPath,false);
} else {
pubCourse();
}
}
public void editVideo(String videoPath, EditCourseData data) {
// ToastUtils.showShortToast("length: "+CommonUtils.getVideoLength(videoPath));
mEditData = data;
if (videoPath.startsWith("http"))
videoUrl = videoPath;
if (TextUtils.isEmpty(videoUrl)) {
mPubData.courseTimes = CommonUtils.getVideoLength(videoPath);
uploadVideo(videoPath,true);
} else {
modifyCourse();
}
}
private void uploadVideo(String videoPath,boolean isModify) {
mView.showDialog();
File file = new File(videoPath);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("fileUpload", file.getName(), requestFile);
BaseApiFactory.uploadVideo(body).subscribe(baseObserver(data -> {
if (!TextUtils.isEmpty(data)) {
videoUrl = data;
if (isModify){
modifyCourse();
}else {
pubCourse();
}
} else {
mView.showToast(R.string.video_upload_fail);
}
}));
}
private void pubCourse() {
mView.showDialog();
mPubData.url = videoUrl;
Api.getService(LearnService.class).pubCourse(mPubData).compose(Api.applySchedulers())
.subscribe(baseObserver(success -> {
if (success) {
ToastUtils.showShortToast(R.string.pub_course_success);
mView.dumpBack();
EventBus.getDefault().post(new CourseChangeEvent());
} else {
ToastUtils.showShortToast(R.string.pub_course_fail);
}
}));
}
private void modifyCourse() {
mView.showDialog();
mEditData.url = videoUrl;
Api.getService(LearnService.class).modifyCourse(mEditData).compose(Api.applySchedulers())
.subscribe(baseObserver(success -> {
if (success) {
ToastUtils.showShortToast(R.string.modify_course_success);
mView.dumpBack();
EventBus.getDefault().post(new CourseChangeEvent());
} else {
ToastUtils.showShortToast(R.string.modify_course_fail);
}
}));
}
}
package com.dayu.learncenter.ui.activity;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import com.dayu.base.api.Api;
import com.dayu.base.ui.activity.BaseActivity;
import com.dayu.base.ui.presenter.SImplePresenter;
import com.dayu.common.Constants;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.LearnService;
import com.dayu.learncenter.api.bean.CourseDeatilBean;
import com.dayu.learncenter.databinding.ActivityCourseDetailBinding;
import com.dayu.utils.CommonUtils;
import com.dayu.utils.GlideImageLoader;
import cn.jzvd.Jzvd;
/**
* 课程详情
*/
public class CourseDetailActivity extends BaseActivity<SImplePresenter,ActivityCourseDetailBinding> {
public class CourseDetailActivity extends BaseActivity<SImplePresenter, ActivityCourseDetailBinding> {
private int courseId;
private CourseDeatilBean courseDetail;
private boolean isPointed; //是否已点赞
private int pointNum; //点赞数
@Override
public void setPresenter() {
}
@Override
......@@ -21,6 +37,72 @@ public class CourseDetailActivity extends BaseActivity<SImplePresenter,ActivityC
@Override
public void initView() {
mBind.titleBack.setOnClickListener(v->dumpBack());
initUser();
mBind.titleBack.setOnClickListener(v -> dumpBack());
courseId = getBundle().getInt(Constants.ID, 0);
initData();
mBind.ivLike.setOnClickListener(v -> pointVideo());
}
//点赞
private void pointVideo() {
showDialog();
int type = isPointed ? 2 : 1;
Api.getService(LearnService.class).pointCourse(courseId, mUserId, type).compose(Api.applySchedulers())
.subscribe(mPresenter.baseObserver(success -> {
if (success) {
if (isPointed) {
pointNum -= 1;
mBind.tvLike.setText(pointNum + "");
mBind.ivLike.setImageResource(R.drawable.icon_like_gray);
} else {
pointNum += 1;
mBind.tvLike.setText(pointNum + "");
mBind.ivLike.setImageResource(R.drawable.icon_like_red);
}
isPointed = !isPointed;
}
}));
}
private void initData() {
Api.getService(LearnService.class).getCourseDetail(courseId, mUserId).compose(Api.applySchedulers())
.subscribe(mPresenter.baseObserver(data -> setDetailData(data)));
}
private void setDetailData(CourseDeatilBean data) {
if (data != null) {
courseDetail = data;
pointNum = data.getPoints();
mBind.tvTheme.setText(data.getName());
mBind.tvDesc.setText(data.getBrief());
mBind.tvPuber.setText(data.getCreated());
mBind.jzVideo.setUp(data.getUrl(), "");
CommonUtils.setVideoThumb(mActivity, mBind.jzVideo, data.getUrl());
mBind.tvLooks.setText(data.getLearners() + "");
mBind.tvLike.setText(pointNum + "");
mBind.tvComponent.setText("留言. " + data.getLeaves());
if (data.getCoursePointsVO() != null && data.getCoursePointsVO().getPointStatus() == 1) {
mBind.ivLike.setImageResource(R.drawable.icon_like_red);
isPointed = true;
} else {
isPointed = false;
mBind.ivLike.setImageResource(R.drawable.icon_like_gray);
}
// if (data.getCreateId() == mUserId)
// mBind.tvEdit.setVisibility(View.VISIBLE);
// mBind.tvEdit.setOnClickListener(v->{
// Bundle bundle = new Bundle();
// bundle.putSerializable(Constants.DETAIL,courseDetail);
// startActivity(PubCourseActivity.class,bundle);
// });
}
}
@Override
public void onBackPressed() {
if (!Jzvd.backPress()) {
super.onBackPressed();
}
}
}
package com.dayu.learncenter.ui.activity;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.text.TextUtils;
import android.view.View;
import com.dayu.base.ui.activity.BaseActivity;
import com.dayu.base.ui.activity.CameraActivity;
import com.dayu.common.Constants;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.bean.CourseDeatilBean;
import com.dayu.learncenter.api.data.EditCourseData;
import com.dayu.learncenter.api.data.PubCourseData;
import com.dayu.learncenter.databinding.ActivityPubCourseBinding;
import com.dayu.learncenter.presenter.pubcourse.PubCourseContract;
import com.dayu.learncenter.presenter.pubcourse.PubCoursePresenter;
import com.dayu.utils.CommonUtils;
import com.dayu.utils.GlideImageLoader;
import com.dayu.utils.MPermissionUtils;
import com.dayu.utils.MediaChooseUtils;
import com.dayu.utils.ToastUtils;
import com.dayu.widgets.TextDialog;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.entity.LocalMedia;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import cn.jzvd.Jzvd;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
public class EditCourseActivity extends BaseActivity<PubCoursePresenter, ActivityPubCourseBinding>
implements PubCourseContract.View {
private CourseDeatilBean courseDetail;
private int courseId;
private boolean canEdit = false;
private String theme;
private String desc;
private String videoPath;
@Override
public void setPresenter() {
}
@Override
public int getLayoutId() {
return R.layout.activity_pub_course;
}
@Override
public void initView() {
initUser();
setListener();
courseId = getBundle().getInt(Constants.ID, 0);
mBind.tvTitle.setText(R.string.course_detail);
mBind.btnCancle.setText("");
setInitState();
mPresenter.getCourseDetail(courseId);
}
private void setListener() {
mBind.titleBack.setOnClickListener(view -> dumpBack());
mBind.btnCancle.setOnClickListener(view -> onCancleClick());
mBind.btnConfirm.setOnClickListener(view -> onConfimClick());
mBind.rlVideo.setOnClickListener(v -> {
if (canEdit && TextUtils.isEmpty(videoPath)) {
showVideoDailog();
}
});
mBind.ivDelete.setOnClickListener(v -> {
videoPath = "";
setVideoView();
});
mBind.jzVideo.setOnClickListener(v -> showToast("click"));
}
//设置控件的基本状态
private void setInitState() {
mBind.btnConfirm.setText(canEdit ? R.string.save_str : R.string.edit_str);
mBind.edtTheme.setEnabled(canEdit);
mBind.edtDesc.setEnabled(canEdit);
if (!TextUtils.isEmpty(videoPath) && canEdit) {
mBind.ivDelete.setVisibility(View.VISIBLE);
} else {
mBind.ivDelete.setVisibility(View.GONE);
}
}
private void onCancleClick() {
if (canSubmit() && courseDetail != null ){
EditCourseData editData = new EditCourseData(mUserId,theme,desc,mUserInfo.getAccountName(),courseDetail.getCourseTimes());
editData.id = courseId;
if (courseDetail.getStatus() == 1){
editData.status = 2;
}else {
editData.status = 1;
}
mPresenter.editVideo(videoPath, editData);
}
}
protected void onConfimClick() {
if (!canEdit) {
canEdit = true;
setInitState();
}else {
if (canSubmit()){
EditCourseData editData = new EditCourseData(mUserId,theme,desc,mUserInfo.getAccountName());
editData.id = courseId;
if (courseDetail != null){
editData.status = courseDetail.getStatus();
editData.courseTimes = courseDetail.getCourseTimes();
}
mPresenter.editVideo(videoPath, editData);
}
}
}
//设置基本信息
@Override
public void setDetailData(CourseDeatilBean data) {
if (data != null) {
courseDetail = data;
if (courseDetail.getStatus() == 1) {
mBind.btnCancle.setText(R.string.disable_video);
} else {
mBind.btnCancle.setText(R.string.enable_video);
}
mBind.edtTheme.setText(courseDetail.getName());
mBind.edtDesc.setText(courseDetail.getBrief());
videoPath = courseDetail.getUrl();
setVideoView();
if (!canEdit)
mBind.ivDelete.setVisibility(View.GONE);
}
}
//选中视频弹框
private void showVideoDailog() {
List<String> list = new ArrayList<>();
list.add(getString(R.string.take_video));
list.add(getString(R.string.select_from_local));
TextDialog.getInstance().showBottomDialog(mActivity, list, pos -> {
if (pos == 0) {
recordVideo();
} else {
MediaChooseUtils.chooseSigleVideo(this, 180);
}
});
}
//录制视频
private void recordVideo() {
String[] mPerArr = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE
, Manifest.permission.CAMERA};
MPermissionUtils.requestPermissionsResult(mActivity, 1, mPerArr, new MPermissionUtils.OnPermissionListener() {
@SuppressLint("CheckResult")
@Override
public void onPermissionGranted() {
Observable.timer(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> {
Intent intent = new Intent(EditCourseActivity.this, CameraActivity.class);
intent.putExtra(Constants.ONLY_VIDEO, true);
startActivityForResult(intent, Constants.CAMERA_CODE);
});
}
@Override
public void onPermissionDenied() {
ToastUtils.showShortToast(R.string.request_permission_failure);
}
});
}
//判断是否能提交
protected boolean canSubmit() {
theme = mBind.edtTheme.getText().toString().trim();
desc = mBind.edtDesc.getText().toString();
if (TextUtils.isEmpty(theme)) {
showToast(R.string.pls_input_course_theme);
return false;
}
if (TextUtils.isEmpty(desc) || TextUtils.isEmpty(desc.trim())) {
showToast(R.string.pls_input_course_desc);
return false;
}
if (TextUtils.isEmpty(videoPath)) {
showToast(R.string.pls_choose_video);
return false;
}
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PictureConfig.CHOOSE_REQUEST:
List<LocalMedia> mSelectList = PictureSelector.obtainMultipleResult(data);
if (mSelectList != null) {
videoPath = mSelectList.get(0).getPath();
File file = new File(videoPath);
if (file.length() > 300 * 1024 * 1024) {
showToast(R.string.video_file_too_large);
videoPath = "";
} else {
setVideoView();
}
}
break;
}
} else if (resultCode == Constants.CAMERA_VIDEO) {
videoPath = data.getStringExtra("videoPath");
setVideoView();
}
}
//设置视频布局显示状态
protected void setVideoView() {
if (TextUtils.isEmpty(videoPath)) {
mBind.jzVideo.setVisibility(View.GONE);
mBind.ivDelete.setVisibility(View.GONE);
} else {
mBind.ivDelete.setVisibility(View.VISIBLE);
mBind.jzVideo.setVisibility(View.VISIBLE);
mBind.jzVideo.setUp(videoPath, "");
CommonUtils.setVideoThumb(mActivity,mBind.jzVideo,videoPath);
}
}
@Override
public void onBackPressed() {
if (!Jzvd.backPress()) {
super.onBackPressed();
}
}
}
......@@ -3,37 +3,51 @@ package com.dayu.learncenter.ui.activity;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import com.bigkoo.pickerview.builder.OptionsPickerBuilder;
import com.bigkoo.pickerview.view.OptionsPickerView;
import com.dayu.base.ui.activity.BaseActivity;
import com.dayu.base.ui.activity.CameraActivity;
import com.dayu.base.ui.presenter.SImplePresenter;
import com.dayu.common.Constants;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.bean.CourseDeatilBean;
import com.dayu.learncenter.api.data.PubCourseData;
import com.dayu.learncenter.databinding.ActivityPubCourseBinding;
import com.dayu.learncenter.presenter.pubcourse.PubCourseContract;
import com.dayu.learncenter.presenter.pubcourse.PubCoursePresenter;
import com.dayu.utils.CommonUtils;
import com.dayu.utils.GlideImageLoader;
import com.dayu.utils.MPermissionUtils;
import com.dayu.utils.MediaChooseUtils;
import com.dayu.utils.ToastUtils;
import com.dayu.widgets.TextDialog;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.entity.LocalMedia;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import cn.jzvd.Jzvd;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
/**
* 开课
*/
public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPubCourseBinding> {
public class PubCourseActivity extends BaseActivity<PubCoursePresenter, ActivityPubCourseBinding>
implements PubCourseContract.View {
private String theme;
private String desc;
private String videoPath;
@Override
public void setPresenter() {
......@@ -46,26 +60,45 @@ public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPub
@Override
public void initView() {
initUser();
setListener();
}
private void setListener() {
mBind.titleBack.setOnClickListener(view -> dumpBack());
mBind.btnCancle.setOnClickListener(view -> dumpBack());
mBind.btnConfirm.setOnClickListener(view -> onConfimClick());
mBind.rlVideo.setOnClickListener(v -> {
if (TextUtils.isEmpty(videoPath)) {
// recordVideo();
MediaChooseUtils.chooseSigleVideo(this, 180);
}
});
mBind.rlVideo.setOnClickListener(v -> chooseVideo());
mBind.ivDelete.setOnClickListener(v -> {
videoPath = "";
setVideoView();
});
mBind.jzVideo.setOnClickListener(v->showToast("click"));
mBind.jzVideo.setOnClickListener(v -> showToast("click"));
}
protected void chooseVideo() {
if (TextUtils.isEmpty(videoPath)) {
showVideoDailog();
}
}
//选中视频弹框
private void showVideoDailog() {
List<String> list = new ArrayList<>();
list.add(getString(R.string.take_video));
list.add(getString(R.string.select_from_local));
TextDialog.getInstance().showBottomDialog(mActivity, list, pos -> {
if (pos == 0) {
recordVideo();
} else {
MediaChooseUtils.chooseSigleVideo(this, 180);
}
});
}
//录制视频
private void recordVideo() {
String[] mPerArr = new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE
, Manifest.permission.CAMERA};
......@@ -74,7 +107,7 @@ public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPub
@SuppressLint("CheckResult")
@Override
public void onPermissionGranted() {
Observable.timer(200, TimeUnit.MILLISECONDS)
Observable.timer(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> {
Intent intent = new Intent(PubCourseActivity.this, CameraActivity.class);
......@@ -90,16 +123,18 @@ public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPub
});
}
private void onConfimClick() {
protected void onConfimClick() {
if (canSubmit()) {
showToast("submit");
PubCourseData pubData = new PubCourseData(mUserId,theme,desc,mUserInfo.getAccountName()
,CommonUtils.getVideoLength(videoPath));
mPresenter.pubVideo(videoPath, pubData);
}
}
//判断是否能提交
private boolean canSubmit() {
String theme = mBind.edtTheme.getText().toString().trim();
String desc = mBind.edtDesc.getText().toString();
protected boolean canSubmit() {
theme = mBind.edtTheme.getText().toString().trim();
desc = mBind.edtDesc.getText().toString();
if (TextUtils.isEmpty(theme)) {
showToast(R.string.pls_input_course_theme);
return false;
......@@ -124,15 +159,24 @@ public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPub
List<LocalMedia> mSelectList = PictureSelector.obtainMultipleResult(data);
if (mSelectList != null) {
videoPath = mSelectList.get(0).getPath();
File file = new File(videoPath);
if (file.length() > 300 * 1024 * 1024) {
showToast(R.string.video_file_too_large);
videoPath = "";
}else{
setVideoView();
}
}
break;
}
} else if (resultCode == Constants.CAMERA_VIDEO) {
videoPath = data.getStringExtra("videoPath");
setVideoView();
}
}
//设置视频布局显示状态
private void setVideoView() {
protected void setVideoView() {
if (TextUtils.isEmpty(videoPath)) {
mBind.jzVideo.setVisibility(View.GONE);
mBind.ivDelete.setVisibility(View.GONE);
......@@ -140,7 +184,20 @@ public class PubCourseActivity extends BaseActivity<SImplePresenter, ActivityPub
mBind.ivDelete.setVisibility(View.VISIBLE);
mBind.jzVideo.setVisibility(View.VISIBLE);
mBind.jzVideo.setUp(videoPath, "");
GlideImageLoader.load(mActivity, mBind.jzVideo.posterImageView, videoPath, R.drawable.icon_video_default);
CommonUtils.setVideoThumb(mActivity,mBind.jzVideo,videoPath);
}
}
@Override
public void onBackPressed() {
if (!Jzvd.backPress()) {
super.onBackPressed();
}
}
@Override
public void setDetailData(CourseDeatilBean data) {
}
}
package com.dayu.learncenter.ui.fragment;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.dayu.base.ui.fragment.BaseFragment;
import com.dayu.common.Constants;
import com.dayu.common.MyTextWatcher;
import com.dayu.learncenter.R;
import com.dayu.learncenter.adapter.LearnAdapter;
import com.dayu.learncenter.api.bean.CommonLearnBean;
import com.dayu.learncenter.databinding.FragmentCommonLearnBinding;
import com.dayu.learncenter.databinding.ItemCommonLearnBinding;
import com.dayu.learncenter.event.CourseChangeEvent;
import com.dayu.learncenter.presenter.common_learn.CommonLearnContract;
import com.dayu.learncenter.presenter.common_learn.CommonLearnPresenter;
import com.dayu.learncenter.ui.activity.CourseDetailActivity;
import com.dayu.learncenter.ui.activity.EditCourseActivity;
import com.dayu.learncenter.ui.activity.PubCourseActivity;
import com.dayu.widgets.listener.OnItemClickListener;
import com.dayu.utils.CommonUtils;
import java.util.ArrayList;
import java.util.List;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import cn.jzvd.Jzvd;
import cn.jzvd.JzvdStd;
public class CommonLearnFragment extends BaseFragment<CommonLearnPresenter,FragmentCommonLearnBinding>
public class CommonLearnFragment extends BaseFragment<CommonLearnPresenter, FragmentCommonLearnBinding>
implements CommonLearnContract.View {
private int type; //1.商品 2.收藏
private int type; //1.全部 2.已学习 3.已发布
public static CommonLearnFragment newInstance(int type) {
......@@ -58,27 +62,79 @@ public class CommonLearnFragment extends BaseFragment<CommonLearnPresenter,Fragm
Bundle bundle = getArguments();
type = bundle.getInt("type");
mPresenter.setType(type);
mBind.edtSeacher.setText(getString(R.string.find_course)+type);
initSearchView();
setAdapter();
EventBus.getDefault().register(this);
}
mBind.rlSeacher.setVisibility(type==3?View.GONE:View.VISIBLE);
mBind.ivPubCourse.setOnClickListener(view -> startActivity(PubCourseActivity.class));
//搜索框
private void initSearchView() {
if (type != 3)
mBind.rlSeacher.setVisibility(View.VISIBLE);
mBind.edtSeacher.addTextChangedListener(new MyTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
super.afterTextChanged(s);
if (s.toString().trim().length() > 0)
mBind.tvCancel.setVisibility(View.VISIBLE);
}
});
setAdapter();
mBind.edtSeacher.setOnEditorActionListener((v, actionId, event) -> {
String str = mBind.edtSeacher.getText().toString();
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
if (str.length() > 0) {
mPresenter.keyStr = mBind.edtSeacher.getText().toString();
mPresenter.refresh();
CommonUtils.hideSoftInput(mActivity);
return true;
}
}
return false;
});
private void setAdapter() {
List<CommonLearnBean> items = new ArrayList<>();
String url = "http://dl.kf.ai/online/ka/spu/serviceDetailVideo/c8f6169b1272663588a24b48c6261a0f.mp4";
for (int i=0;i<10;i++){
items.add(new CommonLearnBean(i,url,"Video Title "+i));
mBind.tvCancel.setOnClickListener(view -> {
mBind.edtSeacher.setText("");
mBind.tvCancel.setVisibility(View.GONE);
CommonUtils.hideSoftInput(mActivity);
if (!TextUtils.isEmpty(mPresenter.keyStr)) {
mPresenter.keyStr = "";
mPresenter.refresh();
}
});
}
LearnAdapter mAdapter = new LearnAdapter(true,type);
private void setAdapter() {
LearnAdapter mAdapter = new LearnAdapter(true, type);
mAdapter.setViewType(R.layout.item_common_learn);
mAdapter.setPresenter(mPresenter);
mBind.recyclerView.setAdapter(mAdapter);
mAdapter.setData(items);
mAdapter.setOnItemClickListener((item, bind) -> {
startActivity(CourseDetailActivity.class);
Bundle bundle = new Bundle();
bundle.putInt(Constants.ID,item.getId());
if (type == 3){
startActivity(EditCourseActivity.class,bundle);
}else{
startActivity(CourseDetailActivity.class,bundle);
}
});
mBind.recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
}
@Override
public void onChildViewDetachedFromWindow(View view) {
Jzvd jzvd = view.findViewById(R.id.jz_video);
if (jzvd != null && Jzvd.CURRENT_JZVD != null &&
jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())) {
if (Jzvd.CURRENT_JZVD != null && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
Jzvd.goOnPlayOnPause();
}
}
}
});
}
......@@ -87,4 +143,16 @@ public class CommonLearnFragment extends BaseFragment<CommonLearnPresenter,Fragm
super.onPause();
JzvdStd.goOnPlayOnPause();
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe
public void refershData(CourseChangeEvent event){
if (type == 1 || type == 3)
mPresenter.refresh();
}
}
......@@ -8,21 +8,29 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.dayu.base.api.Api;
import com.dayu.base.ui.adapter.FragmentAdapter;
import com.dayu.base.ui.fragment.BaseFragment;
import com.dayu.base.ui.presenter.SImplePresenter;
import com.dayu.event.LearnTabNumEvent;
import com.dayu.learncenter.R;
import com.dayu.learncenter.api.LearnService;
import com.dayu.learncenter.api.bean.LearnTabBean;
import com.dayu.learncenter.databinding.FragmentHomeLearnBinding;
import com.dayu.learncenter.event.RefreshLeanTabEvent;
import com.dayu.learncenter.ui.activity.PubCourseActivity;
import com.dayu.utils.TabLayoutUtils;
import com.dayu.utils.ToastUtils;
import com.dayu.utils.UIUtils;
import com.umeng.analytics.MobclickAgent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List;
import cn.jzvd.JzvdStd;
public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHomeLearnBinding> {
public List<Fragment> list_fragments;
private FragmentAdapter adapter;
......@@ -30,6 +38,7 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
private TextView mTabTextTv;
private boolean isFirstAddTab = true;
private String[] tabDesc;
private LearnTabBean tabBean;
@Override
public void setPresenter() {
......@@ -42,11 +51,25 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
@Override
public void initView() {
initUser();
tabDesc = UIUtils.getStrings(R.array.learn_top_tab_item);
initData();
mBind.ivPubCourse.setOnClickListener(view -> startActivity(PubCourseActivity.class));
initTabPage();
getTabData();
EventBus.getDefault().register(this);
}
//获取tab数量
private void getTabData() {
Api.getService(LearnService.class).getLearTabNum(mUserId).compose(Api.applySchedulers())
.subscribe(mPresenter.baseObserver(data->{
tabBean = data;
setTabNum();
}));
}
private void initData() {
//初始化Tab及页面
private void initTabPage() {
list_fragments = new ArrayList<>();
list_fragments.add(CommonLearnFragment.newInstance(1));
list_fragments.add(CommonLearnFragment.newInstance(2));
......@@ -61,6 +84,7 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
mBind.tabLearn.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
JzvdStd.goOnPlayOnPause();
int temp = tab.getPosition();
if (tab.getCustomView() == null) {
return;
......@@ -88,14 +112,16 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
}
});
setTabNum(0);
// mPresenter.chooseTab(0);
setTabNum();
mBind.tabLearn.getTabAt(0).select();
}
public void setTabNum(int myTabIndex) {
public void setTabNum() {
// EventBus.getDefault().post(new LearnTabNumEvent(1));
String[] tabNum = new String[]{0 + "", 0 + "", 0 + ""};
int[] tabNum = new int[]{0 , 0 , 0};
if (tabBean != null){
tabNum = new int[]{tabBean.getTotalCourses(),tabBean.getLeaners(),tabBean.getPublishes()};
}
if (isFirstAddTab) {
mBind.tabLearn.removeAllTabs();
mBind.tabLearn.addTab(mBind.tabLearn.newTab().setCustomView(CreatTab(0, tabNum[0], tabDesc[0])));
......@@ -106,17 +132,13 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
for (int i = 0; i < mBind.tabLearn.getTabCount(); i++) {
TextView tv = mBind.tabLearn.getTabAt(i).getCustomView().findViewById(R.id.tabtext);
TextView tvIcon = mBind.tabLearn.getTabAt(i).getCustomView().findViewById(R.id.tabicon);
tv.setText(tabNum[i]);
tv.setText(tabNum[i]+"");
tvIcon.setText(tabDesc[i]);
}
}
if (myTabIndex != -1) {
// mBind.vpLearn.setCurrentItem(myTabIndex);
mBind.tabLearn.getTabAt(myTabIndex).select();
}
}
private View CreatTab(int index, String number, String iconID) {
private View CreatTab(int index, int number, String iconID) {
View newtab = LayoutInflater.from(mActivity).inflate(R.layout.layout_common_top_tab, null);
TextView textView_number = newtab.findViewById(R.id.tabtext);
AssetManager mgr = mActivity.getAssets();
......@@ -125,9 +147,20 @@ public class HomeLearnFragment extends BaseFragment<SImplePresenter, FragmentHom
}
Typeface tf = Typeface.createFromAsset(mgr, "fonts/DIN Alternate Bold.ttf");
textView_number.setTypeface(tf);
textView_number.setText(number);
textView_number.setText(number+"");
TextView textView = newtab.findViewById(R.id.tabicon);
textView.setText(iconID);
return newtab;
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe
public void refreTab(RefreshLeanTabEvent event){
getTabData();
}
}
......@@ -12,6 +12,10 @@
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
/>
<activity android:name=".ui.activity.EditCourseActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
/>
</application>
</manifest>
......
......@@ -15,6 +15,15 @@
style="@style/text_title"
android:text="@string/course_detail" />
<TextView
android:id="@+id/tv_edit"
style="@style/common_text_style"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:padding="15dp"
android:text="@string/edit_str"
android:visibility="gone" />
<ImageView
android:id="@+id/title_back"
style="@style/title_image_back" />
......@@ -28,8 +37,8 @@
android:id="@+id/nsv_operate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/rl_title"
>
android:layout_below="@id/rl_title">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
......@@ -43,32 +52,29 @@
<TextView
android:id="@+id/tv_theme"
style="@style/tv_course_content"
/>
style="@style/tv_course_content" />
</LinearLayout>
<LinearLayout style="@style/ll_course_content">
<TextView
style="@style/tv_course_left"
android:text="@string/course_desc"
/>
android:text="@string/course_desc" />
<TextView
android:id="@+id/tv_desc"
style="@style/tv_course_content"
/>
style="@style/tv_course_content" />
</LinearLayout>
<LinearLayout style="@style/ll_course_content">
<TextView
style="@style/tv_course_left"
android:text="@string/course_puber"
/>
android:text="@string/course_puber" />
<TextView
android:id="@+id/tv_puber"
style="@style/tv_course_content"
/>
style="@style/tv_course_content" />
</LinearLayout>
<LinearLayout
......@@ -86,16 +92,16 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
>
android:orientation="horizontal">
<TextView
android:id="@+id/tv_component"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="43dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="留言"
android:textColor="@color/cl_home_title_text_color"
......@@ -105,29 +111,28 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_looks"
android:layout_marginLeft="10dp"
/>
android:src="@drawable/icon_looks" />
<TextView
android:id="@+id/tv_looks"
style="@style/common_text_style"
android:text="12345"
android:layout_marginLeft="5dp"
/>
android:paddingLeft="5dp"
android:text="0" />
<ImageView
android:id="@+id/iv_like"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="@drawable/icon_like_gray"
android:layout_marginLeft="10dp"
/>
android:src="@drawable/icon_like_gray" />
<TextView
android:id="@+id/tv_like"
style="@style/common_text_style"
android:text="12345"
android:layout_marginLeft="5dp"
android:paddingLeft="5dp"
android:layout_marginRight="10dp"
/>
android:text="0" />
</LinearLayout>
......@@ -148,8 +153,8 @@
android:id="@+id/iv_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:src="@drawable/icon_user_default"
android:layout_marginRight="10dp" />
android:layout_marginRight="10dp"
android:src="@drawable/icon_user_default" />
<EditText
android:id="@+id/edt_comment"
......@@ -181,8 +186,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
android:layout_marginRight="10dp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
......
......@@ -2,6 +2,13 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
<variable
name="presenter"
type="com.dayu.learncenter.presenter.pubcourse.PubCoursePresenter" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
......
......@@ -9,7 +9,7 @@
type="com.dayu.base.ui.presenter.BaseListPresenter" />
</data>
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
......@@ -18,6 +18,7 @@
android:orientation="vertical">
<RelativeLayout
android:visibility="gone"
android:id="@+id/rl_seacher"
android:layout_width="match_parent"
android:layout_height="45dp"
......@@ -68,22 +69,11 @@
<com.dayu.widgets.LRecyclerView
android:layout_below="@id/rl_seacher"
android:id="@+id/recyclerView"
setPresenter="@{presenter}"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_pub_course"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="50dp"
android:layout_marginRight="30dp"
android:src="@drawable/icon_add_blue"
/>
</RelativeLayout>
</LinearLayout>
</layout>
\ No newline at end of file
......@@ -2,6 +2,9 @@
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
......@@ -22,10 +25,10 @@
android:id="@+id/tab_learn"
android:layout_width="match_parent"
android:layout_height="78dp"
app:tabBackground="@drawable/top_tab_selector"
app:tabIndicatorColor="@color/cl_tab_line"
app:tabMaxWidth="0dp"
app:tabIndicatorHeight="0dp"
app:tabBackground="@drawable/top_tab_selector"
app:tabMaxWidth="0dp"
app:tabMode="fixed" />
<ImageView style="@style/card_line" />
......@@ -37,4 +40,16 @@
android:layout_weight="1" />
</LinearLayout>
<ImageView
android:id="@+id/iv_pub_course"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="50dp"
android:layout_marginRight="30dp"
android:src="@drawable/icon_add_blue"
/>
</RelativeLayout>
</layout>
\ No newline at end of file
......@@ -3,17 +3,13 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_13.3"
android:layout_marginTop="5dp"
android:layout_marginRight="@dimen/dp_13.3"
android:background="@drawable/item_shape">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_shape"
android:orientation="vertical">
<RelativeLayout
......@@ -25,6 +21,48 @@
android:id="@+id/jz_video"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/rl_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent">
<TextView
android:id="@+id/tv_progress"
style="@style/common_text_style"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:padding="10dp"
android:text="@string/learn_progress"
android:textColor="@color/text_common_blue"
android:textSize="20sp"
android:visibility="gone" />
<TextView
android:id="@+id/tv_date"
style="@style/common_text_style"
android:layout_centerHorizontal="true"
android:layout_marginTop="130dp"
android:height="36dp"
android:background="#80ffffff"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="发布时间 2020-01-01" />
<TextView
android:id="@+id/tv_disable"
style="@style/common_text_style"
android:height="36dp"
android:background="#80ffffff"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:layout_alignParentRight="true"
android:text="@string/already_disable" />
</RelativeLayout>
</RelativeLayout>
<LinearLayout
......@@ -52,7 +90,7 @@
android:id="@+id/tv_looks"
style="@style/common_text_style"
android:layout_marginLeft="5dp"
android:text="12345" />
android:text="0" />
<ImageView
android:id="@+id/iv_like"
......@@ -66,35 +104,9 @@
style="@style/common_text_style"
android:layout_marginLeft="5dp"
android:layout_marginRight="10dp"
android:text="12345" />
android:text="0" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_progress"
style="@style/common_text_style"
android:padding="10dp"
android:text="学习进度 0%"
android:textColor="@color/text_common_blue"
android:textSize="20sp"
android:layout_marginTop="15dp"
android:visibility="gone"
android:layout_centerHorizontal="true"
/>
<TextView
android:id="@+id/tv_date"
style="@style/common_text_style"
android:height="36dp"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="发布时间 2020-01-01"
android:background="#80ffffff"
android:layout_marginTop="130dp"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
</layout>
\ No newline at end of file
<resources>
<string name="app_name">LearnCenter</string>
<string name="video_file_too_large">视频文件过大</string>
<string name="take_video">拍摄</string>
<string name="select_from_local">从本地选择</string>
<string name="video_upload_fail">视频上传失败</string>
<string name="pub_course_success">发布成功</string>
<string name="modify_course_success">修改成功</string>
<string name="pub_course_fail">发布失败,请稍后重试</string>
<string name="modify_course_fail">修改失败,请稍后重试</string>
<string name="disable_video">下架</string>
<string name="enable_video">上架</string>
<string name="learn_progress">学习进度</string>
<string name="already_disable">已下架</string>
</resources>
......@@ -89,7 +89,7 @@ public class OperateDetailFragment extends BaseFragment<SImplePresenter, Fragmen
// String url = "http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4";
String url = operateInfo.getVideoUrl();
mBind.jzVideo.setUp(url, "");
GlideImageLoader.load(mActivity, mBind.jzVideo.posterImageView, url, R.drawable.icon_video_default);
CommonUtils.setVideoThumb(mActivity,mBind.jzVideo,url);
setListener();
}
......
......@@ -120,7 +120,7 @@ public class ProductInstructionFragment extends BaseFragment<SImplePresenter, Fr
} else {
mBind.llVideo.setVisibility(View.VISIBLE);
mBind.jzVideo.setUp(url, "");
GlideImageLoader.load(mActivity, mBind.jzVideo.posterImageView, url, R.drawable.icon_video_default);
CommonUtils.setVideoThumb(mActivity,mBind.jzVideo,url);
}
}
......
......@@ -9,4 +9,4 @@ include ':app', ':saleCenter', ':learnCenter',
':pickerview',
':wheelview',
':IDCardLib',
':umeng'
':umeng', ':camera'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment