项目中有监控模块,准备使用海康的摄像机,方一运行所提供的Demo,就程序崩溃。
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.demo/com.test.demo.DemoActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x7f020000
低版本图标资源在手机上找不到的原因。
解决办法:重新更换一张存在的图标,重新运行即可
本Demo完成实时预览,回放,查找SD卡中的历史录像文件,截图功能。
1.登陆设备
public static boolean loginDevice(String ip, int port, String name, String psd) {
NET_DVR_DEVICEINFO_V30 netDvrDeviceInfoV30 = new NET_DVR_DEVICEINFO_V30();
int loginId = HCNetSDK.getInstance().NET_DVR_Login_V30(ip, port,
name, psd, netDvrDeviceInfoV30);
//登陆失败
if (loginId < 0) {
return false;
}
ExceptionCallBack exceptionCbf = getExceptionCbf();
if (!HCNetSDK.getInstance().NET_DVR_SetExceptionCallBack(
exceptionCbf)) {
return false;
}
return true;
}
2.实时预览:
public boolean startRealTimePlay() {
NET_DVR_PREVIEWINFO previewInfo = new NET_DVR_PREVIEWINFO();
previewInfo.lChannel = mStartChan;
previewInfo.dwStreamType = 0;
previewInfo.bBlocked = 1;
previewInfo.hHwnd = mSvPlayer.getHolder();
/* mPlayId = HCNetSDK.getInstance().NET_DVR_RealPlay_V40(mILogID,
previewInfo, null);*/
mPlayId = HCNetSDK.getInstance().NET_DVR_RealPlay_V40(0,
previewInfo, null);
if (mPlayId < 0) {
return false;
}
return true;
}
3.回放:
public boolean backPlay(NET_DVR_TIME beginDate, NET_DVR_TIME endDate) {
if (mPlayId >= 0) {
return false;
}
NET_DVR_VOD_PARA struVod = new NET_DVR_VOD_PARA();
struVod.struBeginTime = beginDate;
struVod.struEndTime = endDate;
struVod.byStreamType = 0;
struVod.struIDInfo.dwChannel = mStartChan;
struVod.hWnd = mSvPlayer.getHolder().getSurface();
mPlaybackId = HCNetSDK.getInstance().NET_DVR_PlayBackByTime_V40(mILogID, struVod);
if (mPlaybackId >= 0) {
if (!HCNetSDK.getInstance().NET_DVR_PlayBackControl_V40(mPlaybackId, PlaybackControlCommand.NET_DVR_PLAYSTART, null, 0, null)) {
return false;
}
return true;
}
return false;
}
如果需要实现进度条拖动回放进度功能,只需先停止回放再传入新的开始时间,结束时间不变再调用该方法就行。但是发现这种方式有的时候会出现问题,造成程序崩溃。sdk并没有提供相应的解决方法,使用海康ivms-4500APP拖动回放没有问题,实现方式不一样,ivms-4500会黑屏再回放,不知道是不是缓存了多个SurfaceView来回切换回放。
4.查找录像文件:
public static List<NET_DVR_FINDDATA_V30> findAllFile(NET_DVR_TIME beginDate, NET_DVR_TIME endDate){
List<NET_DVR_FINDDATA_V30> monitorFileList = new ArrayList<>(10);
NET_DVR_FILECOND netDvrFilecond = new NET_DVR_FILECOND();
netDvrFilecond.lChannel = 1;
netDvrFilecond.dwFileType = 0;
netDvrFilecond.dwIsLocked = 0xff;
netDvrFilecond.struStartTime = beginDate;
netDvrFilecond.struStopTime = endDate;
int findStatus = HCNetSDK.getInstance().NET_DVR_FindFile_V30(0, netDvrFilecond);
while (true) {
NET_DVR_FINDDATA_V30 file = new NET_DVR_FINDDATA_V30();
try {
//延时一点时间才能找到文件
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
HCNetSDK.getInstance().NET_DVR_FindNextFile_V30(findStatus, file);
if (file.dwFileSize == 0) {
break;
} else {
monitorFileList.add(file);
}
}
HCNetSDK.getInstance().NET_DVR_FindClose_V30(findStatus);
return monitorFileList;
}
5.截图:
public boolean generateCapture() {
NET_DVR_JPEGPARA jpeg = new NET_DVR_JPEGPARA();
INT_PTR a = new INT_PTR();
byte[] buffer = new byte[1024 * 1024];
// 设置图片的分辨率0-2,越小质量越高
jpeg.wPicSize = 2;
jpeg.wPicQuality = 2;
if (HCNetSDK.getInstance().NET_DVR_CaptureJPEGPicture_NEW(mILogID, mChanNum, jpeg, buffer, 1024 * 1024, a) && saveCapture(buffer)) {
return true;
}
return false;
}
备注:
1.目前测试登陆和播放都可以异步,其余应该也可以。
2.直接用SurfaceView即可,不需要用Demo所封装的。
3.如果需要全屏和小屏播放,只需要让Activity旋转就可以,可以在View中重写onConfigurationChanged处理切换时候的逻辑:
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//横屏
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
}else {
}
}
4.Activity,onStop()时会销毁SurfaceView,需要在SurfaceView的surfaceCreated()方法中处理恢复播放:
@Override
public void surfaceCreated(SurfaceHolder holder) {
//恢复播放
}
5.如果需要做成列表播放,只需要在RecyclerView的父View嵌套SurfaceView就行:
//RecyclerViewAdapter中item点击回调
@Override
public void onClick(View v) {
if(onVideoClickListener != null){
int[] point = new int[2];
v.getLocationOnScreen(point);
onVideoClickListener.onVideoClick(point);
}
}
public void onVideoClick(final int[] point) {
if (mPlayer == null) {
mPlayer = (Player) LayoutInflater.from(mContext).inflate(R.layout.player_min, mFlMonitor, false);
mPlayer.setOnSurfaceCreateCallBack(this);
mFlMonitor.addView(mPlayer);
mPlayer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
i++;
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ){
return;
}
alertPlayerPosition(point);
if(i == 2) {
mPlayer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
private void alertPlayerPosition(int[] point) {
int[] rlPoint = new int[2];
//标题栏和状态栏高度总和
if (mTitleStatusBarHeight <= 0) {
mFlMonitor.getLocationOnScreen(rlPoint);
mTitleStatusBarHeight = rlPoint[1];
}
int playItemY = point[1];
int measuredHeight = mPlayer.getMeasuredHeight();
int top = playItemY - mTitleStatusBarHeight;
int bottom = top + measuredHeight;
mPlayer.layout(mPlayer.getLeft(), top, mPlayer.getRight(), bottom);
}
6.由于特殊原因,恕不能提供完整Demo,有什么问题可以在论坛问我就行。