安卓 日常问题 工作日志10

Posted 读书台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓 日常问题 工作日志10相关的知识,希望对你有一定的参考价值。

android 拍摄视频 拍摄照片的 流程    https://www.cnblogs.com/younghao/p/5089118.htmlhttps://www.jianshu.com/p/e5312fd916dd?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

代码 

package com.zsch.forestinventory.activity.left_activity.LandForm;

import android.content.Intent;
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.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import com.zsch.androidlib.activity.BaseActivity;
import com.zsch.androidlib.engine.CameraManager;
import com.zsch.androidlib.ui.MySurfaceView;
import com.zsch.androidlib.utils.AppConstants;
import com.zsch.androidlib.view.LVCircularRing;
import com.zsch.forestinventory.MyApplication;
import com.zsch.forestinventory.R;
import com.zsch.forestinventory.activity.MainActivity;
import com.zsch.forestinventory.db.gen.DaoSession;
import com.zsch.forestinventory.entity.landforms.LandForm;
import com.zsch.forestinventory.entity.landforms.Video;
import com.zsch.forestinventory.entity.outdoor_scene.Image;
import com.zsch.forestinventory.entity.outdoor_scene.OutdoorScene;
import com.zsch.forestinventory.entity.outdoor_scene.SceneGeoPoint;
import com.zsch.forestinventory.entity.outdoor_scene.ScenePoint;
import com.zsch.forestinventory.utils.DateUtils;
import android.hardware.Camera.Size;
import org.osmdroid.util.GeoPoint;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;

/**
* Created by TinySun on 2017/10/17.
* 拍照用的Activity
*/
public class CameraLandFormVideoActivity extends BaseActivity implements View.OnClickListener,CameraManager.IPhotoSaveStateListener{

public static final String PROJECT_NAME_ID = "projectNameId"; //
public static final String IMAGE_TYPE_ID= "imagetype_id";
public static final String LAND_FROM_ID = "landFromId"; //新增地质点id 将场景点去除 这里开始接受 mainactivity 传来的 项目名 和 地质点id
public static final String VIDEO_ID = "video_id";
public static final String VIDEO_TYPE = "video_type";



private ImageButton mShutter;;//录像按钮
private ImageButton ibBack;//返回按钮
private LVCircularRing ivLoading; //拍攝后的 圆圈动画


// private CameraManager mCameraManager;
private Camera mCamera;
private MediaRecorder mRecorder; //录制视频的类
// private MySurfaceView mSurfaceView; //显示视频的控件 实现这个接口的Callback接口
// private FrameLayout mSurfaceViewLayout;
private SurfaceHolder mSurfaceHolder;
private SurfaceView mCameraPreview; // 显示视频的控件 实现这个接口的Callback接
private final static int CAMERA_ID = 0;
private boolean mIsRecording = false;
private boolean mIsSufaceCreated = false; //判斷surfaceView是否创建成功


private DaoSession mSession;
private LandForm LandformsImages; //新增 实体LanfForm的
private String projectName;
private String imagetype_id;
private String video;
private String savePath;


@Override
protected void initVariables() { //初始化变量
long landFromId = getIntent().getLongExtra(LAND_FROM_ID, -1L); // 这里开始接受 mainactivity 传来的地质点id
projectName = getIntent().getStringExtra(PROJECT_NAME_ID); //获取传过来的项目名称 这个 必须得有 以后再写 目前 先做别的
imagetype_id=getIntent().getStringExtra(IMAGE_TYPE_ID);//获取传过来的imagetype_id
video=getIntent().getStringExtra(VIDEO_TYPE);//获取传过来的视频类型


if (landFromId < 0)
onBackPressed();
mSession = ((MyApplication) getApplication()).getSession(); //实例化
//例子 获取User对象时立即执行查询操作获取Friend对象 获取更深层的对象 1对1 表连接 通过这个对象获取 另一个表的对象
LandformsImages = mSession.getLandFormDao().loadDeep(landFromId); //1.通过传过来的id查两个表这两表一对一连接 一起的数据

savePath = AppConstants.APP_DIR + projectName + AppConstants.VIDEO_FILE; //视频的保存路径 APP_DIR为程序路径


startPreview(); //启动预览
}

@Override
protected void initView(Bundle savedInstanceState) {
setContentView(R.layout.activity_camera_land_form_video);
// mSurfaceViewLayout = (FrameLayout) findViewById(R.id.mSurfaceViewLayout);
mShutter = (ImageButton) findViewById(R.id.record_shutter);
ibBack = (ImageButton) findViewById(R.id.ibBack);
ivLoading = (LVCircularRing) findViewById(R.id.ivLoading); //拍照后的 旋转框
mCameraPreview = (SurfaceView) findViewById(R.id.camera_preview); //拍照预览

mSurfaceHolder = mCameraPreview.getHolder();// 取得holder
mSurfaceHolder.addCallback(mSurfaceCallback);// holder加入回调接口
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

mShutter.setOnClickListener(this);
ibBack.setOnClickListener(this);

ivLoading.setViewColor(getResources().getColor(R.color.colorProgressBarDefaultWheel));
ivLoading.setBarColor(getResources().getColor(R.color.colorProgressBarWheel));



}

@Override
protected void loadData() {


}
private SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsSufaceCreated = false;
}

@Override
//必须监听surfaceView的创建,创建完毕后才可以处理播放
public void surfaceCreated(SurfaceHolder holder) {
mIsSufaceCreated = true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
startPreview();
}
};




//启动预览
private void startPreview() {
//保证仅仅有一个Camera对象
if (mCamera != null || !mIsSufaceCreated) { //当相机对象 ,和 sufaceView 对象 两个 有一个不存在时 就返回
return;
}
mCamera = Camera.open(CAMERA_ID); //获得照相机对象
Camera.Parameters parameters = mCamera.getParameters();//获取照相参数
List<Camera.Size> sizes = parameters.getSupportedPictureSizes(); //设置预览大小时,必须使用getSupportedPreviewSizes()的值
// List<Camera.Size> sizeVideos = parameters.getSupportedVideoSizes(); parameters.setVideoSize()方法怎么用 错误的没有这个方法 有mRecorder.setVideoSize(1920, 1080);
if (sizes.get(0).width > sizes.get(sizes.size() - 1).width) {
parameters.setPictureSize(sizes.get(0).width, sizes.get(0).height); //这里通过判断有无照相机镜头 去判断
} else {
parameters.setPictureSize(sizes.get(sizes.size() - 1).width, sizes.get(sizes.size() - 1).height);
}
// parameters.setPreviewSize(sizes.get(sizes.size() - 1).width, sizes.get(sizes.size() - 1).height); 我感觉 录像的这里应该为setPreviewSize




parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); //获得焦点
parameters.setPreviewFrameRate(20);

//设置相机预览方向 设置正确的预览方向
// mCamera.setDisplayOrientation(90); //调节 窗口的角度 90 是 竖排 默认横拍
mCamera.setParameters(parameters);

try {
mCamera.setPreviewDisplay(mSurfaceHolder); //设置SurfaceView的SurfaceHolder用于预览。
// mCamera.setPreviewCallback(mPreviewCallback);
} catch (Exception e) {
}
mCamera.startPreview(); //开始预览
}

//停止预览
private void stopPreview() {
//释放Camera对象
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(null);
} catch (Exception e) {

}

mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}


@Override
public void onClick(View view) { //点击触发事件
switch (view.getId()) {
case R.id.record_shutter://录像按钮 和停止 点击为开始录像 再次点击 为停止
if (mIsRecording) { //mIsRecording 进行判断 是预览状态 还是 在拍摄状态
stopRecording();
} else {
initMediaRecorder();
startRecording();
}
break;
case R.id.ibBack://返回按钮
onBackPressed();
break;
}
}
//录像功能
private void initMediaRecorder() {
// Camera录制视频时,除了Camera.open()和Camera.release()调用外,还必须管理Camera.lock()和Camera.unlock()调用,以允许MediaRecorder访问摄像机硬件。
mRecorder = new MediaRecorder();//实例化 创建mediarecorder对象
mCamera.unlock(); //解锁相机以供MediaRecorder使用。从预览那解锁
mRecorder.reset();
//给Recorder设置Camera对象,保证录像跟预览的方向保持一致
mRecorder.setCamera(mCamera); //设置要用于视频捕获的摄像机,使用应用程序的当前摄像机实例
// mRecorder.setOrientationHint(90); //改变保存后的视频文件播放时是否横屏(不加这句。视频文件
// 设置视频来源Camera(相机)
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//设置声音来源
mRecorder.setAudiosource(MediaRecorder.AudioSource.MIC);
// 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// 设置录制的视频编码h263 h264
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//设置编码比特率,不设置会使视频图像模糊 且文件大小为3.26M(30秒) 有奇效
mRecorder.setVideoEncodingBitRate(5*900*1024);
// 设置音频的编码格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错
mRecorder.setVideoSize(1920, 1080);
// 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错
mRecorder.setVideoFrameRate(30);
//设置最大录像时间为30s
mRecorder.setMaxDuration(30000);
//将画面展示到surfaceView 上
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
// // 设置视频文件输出的路径
// mRecorder.setOutputFile("/sdcard/"+generateVideoName()+".mp4");

//设置视频存储路径 最后通过 uuid 去 建立文件 存储路径
//Environment类:提供访问环境变量.
//常用Environment.getExternalStorageState来获取SD卡的状态
//File.separator 路径分隔符 File file1 = new File ("C:\\tmp\\test.txt");中的 \\ 因为 window 和 linux中的分隔符不一样 所以 为了防止 识别错误 跨系统用File.separator
// File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + savePath); //创建文夹名
File file = new File(savePath); //创建文夹名
if (!file.exists()) {
//多级目录的创建
file.mkdirs();
}
String file_Name=generateVideoName() ;
//设置视频文件输出的路径
mRecorder.setOutputFile(file.getPath() +"/"+file_Name); //创建文件名
//进行数据库的存储 当点击 停止拍摄后 会 将这些数据 返回到 主函数
hasSaveVideo(file_Name);


}

private void hasSaveVideo(String file_Name) {
//存储 1.视频名称2.视频类型3.项目id4.地质点id5.项目名称
Video video = null;
video=new Video();
video.setLandForm_id(getIntent().getLongExtra(LAND_FROM_ID, -1L));//地质点id
// video.setProject_id();//.项目id
video.setProjectName(projectName);
video.setVideo_type(getIntent().getStringExtra(VIDEO_TYPE));//视频类型
video.setName(file_Name);//视频名称2
mSession.insert(video); //这步视频的id以及名字 存入数据库 将id类的相关名字

Intent data = new Intent();
data.putExtra(LAND_FROM_ID, video.getLandForm_id()); //将地质点id返回到主页面里
data.putExtra(VIDEO_ID, video.getId());//将照片id返回
data.putExtra(VIDEO_TYPE, video.getVideo_type());//将照片类型id返回 可以是平面图 也可以是照片
data.putExtra(PROJECT_NAME_ID,projectName);//将项目名称返回 表中无项目名 利用id就行 需要项目名称 实景里面可以 这里 不可以 会出现问题
setResult(RESULT_OK, data); //这里是将图片id 和实景id 返回 之前 应该是 mainactivity 返回后 进行判断 onActivityResult()方法里有


}

//开始拍摄
private void startRecording() {
if (mRecorder != null) {
try {
mRecorder.prepare(); //为提供的配置设置准备MediaRecorder。
mRecorder.start(); //开始录制视频
} catch (Exception e) {
mIsRecording = false; //mIsRecording 进行判断 是预览状态 还是 在拍摄状态
}
}
//設置 拍摄时 按钮的样式
// mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter_hl));
mIsRecording = true; //mIsRecording 进行判断 是预览状态 还是 在拍摄状态
// }
}



//停止 拍攝 將相机锁上 并将 mRecorder 释放 资源
private void stopRecording() {

if (mRecorder != null) {
mRecorder.stop(); //停止MediaRecorder
mRecorder.release(); //释放MediaRecorder
mRecorder = null;
}
if (mCamera != null) {
mCamera.lock(); // 锁定相机
mCamera.stopPreview();//停止预览
mCamera.release();//释放相机

}
//将按钮样式转变
// mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter));
// finish();//在Activity中执行this.finish()方法之后,执行如下过程: onPause(),onStop(),onDestory(),
mIsRecording = false; //mIsRecording 进行判断 是预览状态 还是 在拍摄状态
// 本項目 在拍照完需要 返回到 表格界面 不需要 重新预览
// 重新启动预览
// startPreview();

finish(); //刪除 onpasue()效果不錯 還是得 改onpasue() 让他的功能符合我的项目 他們 是將 medRecordi 以及camera的 釋放 都卸载了 onpause 和 ondestory里了
}





@Override
public void onBackPressed() {//为解决 当拍摄中 出现问题 这里需要修改 当 点击 finish() 会跳转到 onpuse 这是 因为mRecorder 程序走了stopPreview();

Intent data = new Intent();
if (LandformsImages != null) {
data.putExtra(LAND_FROM_ID, LandformsImages.getId().longValue()); //scenePoint不为空 则把地质点id传回去
setResult(RESULT_OK, data);
} else {
setResult(RESULT_CANCELED); //RESULT_CANCELED = 0;传回去
}
//两种 情况 一种 时 在 拍照前 一种是 拍照后
if(mRecorder!=null){ //说明是在拍摄中
mIsRecording = true;
stopRecording(); // 停止 拍攝 这处没问题 mIsRecording=true 说明在拍摄中

}else{ //说明在预览中
stopPreview(); //停止预览 mIsRecording=false 说明还没拍摄 在预览状态
}


finish();
}



private String generateVideoName() { //takePicture()里面获取照片名称 的修饰方法
Calendar calendar = Calendar.getInstance(); //日历类 这里初始化日历对象
StringBuffer buffer = new StringBuffer(); //字符串存储类
buffer.append("V");
String year = calendar.get(Calendar.YEAR) + "";
buffer.append(year.substring(2,4));
int month = calendar.get(Calendar.MONTH) + 1;
if (month < 10) {
buffer.append("0");
}
buffer.append(month);
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (day < 10) {
buffer.append("0");
}
buffer.append(day);

buffer.append(randomString());//添加随机字母

buffer.append(AppConstants.VIEW_SUFFIX);//添加后缀 .mp4

return buffer.toString();
}


/**
* 生成随机字符串,使用UUID
* @return
*/
public String randomString() {
String str = java.util.UUID.randomUUID().toString();
String text = str.substring(0,8) + str.substring(str.length() - 8,str.length());
return text;
}



public void notifySystemToScan(File file) { //其实就是通知系统创建或者删除了某个文件,系统需要扫描sd卡,进行更新
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
sendBroadcast(intent);
}


@Override
public void hasSavePhoto(String path) {

}
}

切记 两个 camera mRecorder 在录像 上 两个 都要打开 最后两个 都要关闭哦 camera 要早于 mRecorder 先进行预览 然后 设置 mrecorder

以上是关于安卓 日常问题 工作日志10的主要内容,如果未能解决你的问题,请参考以下文章

安卓 日常问题 工作日志23

安卓 日常问题 工作日志

安卓 日常问题 工作日志18

安卓 日常问题 工作日志7

片段从一开始就没有显示 |安卓工作室

argparse 代码片段只打印部分日志