diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e3538da --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,1465 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //如需兼容 Android P,需要添加使用 Apache HTTP client 库,在 AndroidManifest 的 application 节点内添加以下配置即可 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //暂时语音遥控器还是要单独改 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //乐橙界面 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + f + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/Root-en.crt b/app/src/main/assets/Root-en.crt new file mode 100644 index 0000000..c2b2907 --- /dev/null +++ b/app/src/main/assets/Root-en.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- diff --git a/app/src/main/assets/Root.crt b/app/src/main/assets/Root.crt new file mode 100644 index 0000000..1e6967f Binary files /dev/null and b/app/src/main/assets/Root.crt differ diff --git a/app/src/main/assets/fonts/font.ttf b/app/src/main/assets/fonts/font.ttf new file mode 100644 index 0000000..9ce5131 Binary files /dev/null and b/app/src/main/assets/fonts/font.ttf differ diff --git a/app/src/main/assets/privacyas.txt b/app/src/main/assets/privacyas.txt new file mode 100644 index 0000000..d9b91ba --- /dev/null +++ b/app/src/main/assets/privacyas.txt @@ -0,0 +1,11 @@ +欢迎您使用安顺祥智控。您可使用本应用以实现智能设备的控制、情景、设备分享等功能。 +我们深知隐私保护对您的重要性,为了更全面地呈现我们收集和使用您的个人信息的相关情况,我们依据最新法律法规要求在您使用我们的产品或服务(统称“服务”)重点内容包括一下信息: +必要权限(用于该应用的基本服务和功能) +· 获取手机帐号信息: +用于应用内使用安顺祥智控帐号登录; +· 获取位置信息: +基于位置信息为您提供的服务,如配网,家庭切换天气服务; +· 相册权限:基于图片/视频相关服务,用于从相册中选择图片、视频文件; +· 麦克风权限:基于语音实现服务,如在线语音控制设备; +· 消息通知权限:向您推送有关产品或服务、安防类的通知等功能。 +如果您不统一调用以上必须权限或功能,或不同意我们收集并使用以上信息,将导致本应用无法正常运行,您可选择退出本应用终止服务。 \ No newline at end of file diff --git a/app/src/main/assets/privacycw.txt b/app/src/main/assets/privacycw.txt new file mode 100644 index 0000000..1ff1633 --- /dev/null +++ b/app/src/main/assets/privacycw.txt @@ -0,0 +1,11 @@ +欢迎您使用Swaiot智控。您可使用本应用以实现智能设备的控制、情景、设备分享等功能。 +我们深知隐私保护对您的重要性,为了更全面地呈现我们收集和使用您的个人信息的相关情况,我们依据最新法律法规要求在您使用我们的产品或服务(统称“服务”)重点内容包括一下信息: +必要权限(用于该应用的基本服务和功能) +· 获取手机帐号信息: +用于应用内使用Swaiot智控帐号登录; +· 获取位置信息: +基于位置信息为您提供的服务,如配网,家庭切换天气服务; +· 相册权限:基于图片/视频相关服务,用于从相册中选择图片、视频文件; +· 麦克风权限:基于语音实现服务,如在线语音控制设备; +· 消息通知权限:向您推送有关产品或服务、安防类的通知等功能。 +如果您不统一调用以上必须权限或功能,或不同意我们收集并使用以上信息,将导致本应用无法正常运行,您可选择退出本应用终止服务。 \ No newline at end of file diff --git a/app/src/main/assets/privacyyj.txt b/app/src/main/assets/privacyyj.txt new file mode 100644 index 0000000..040eb24 --- /dev/null +++ b/app/src/main/assets/privacyyj.txt @@ -0,0 +1,11 @@ +欢迎您使用雅今智慧生活。您可使用本应用以实现智能设备的控制、情景、设备分享等功能。 +我们深知隐私保护对您的重要性,为了更全面地呈现我们收集和使用您的个人信息的相关情况,我们依据最新法律法规要求在您使用我们的产品或服务(统称“服务”)重点内容包括一下信息: +必要权限(用于该应用的基本服务和功能) +· 获取手机帐号信息: +用于应用内使用雅今智慧生活帐号登录; +· 获取位置信息: +基于位置信息为您提供的服务,如配网,家庭切换天气服务; +· 相册权限:基于图片/视频相关服务,用于从相册中选择图片、视频文件; +· 麦克风权限:基于语音实现服务,如在线语音控制设备; +· 消息通知权限:向您推送有关产品或服务、安防类的通知等功能。 +如果您不统一调用以上必须权限或功能,或不同意我们收集并使用以上信息,将导致本应用无法正常运行,您可选择退出本应用终止服务。 \ No newline at end of file diff --git a/app/src/main/assets/t_s.bmp b/app/src/main/assets/t_s.bmp new file mode 100644 index 0000000..8081e09 Binary files /dev/null and b/app/src/main/assets/t_s.bmp differ diff --git a/app/src/main/java/com/common/openapi/ClassInstanceManager.java b/app/src/main/java/com/common/openapi/ClassInstanceManager.java new file mode 100644 index 0000000..ed4c976 --- /dev/null +++ b/app/src/main/java/com/common/openapi/ClassInstanceManager.java @@ -0,0 +1,58 @@ +package com.common.openapi; + +import android.content.Context; + +public class ClassInstanceManager { + private volatile static ClassInstanceManager classInstanceManager; + private DeviceLocalCacheManager deviceLocalCacheManager; + private DeviceDetailService deviceDetailService; + private DeviceListService deviceListService; + private DeviceRecordService deviceRecordService; + private DeviceLocalCacheService deviceLocalCacheService; + private DeviceSubAccountListService deviceSubAccountListService; + + public static ClassInstanceManager newInstance() { + if (classInstanceManager == null) { + synchronized (ClassInstanceManager.class) { + if (classInstanceManager == null) { + classInstanceManager = new ClassInstanceManager(); + } + } + } + return classInstanceManager; + } + + public void init(Context context) { + deviceLocalCacheManager = new DeviceLocalCacheManager(); + deviceLocalCacheManager.init(context); + deviceDetailService = new DeviceDetailService(); + deviceListService = new DeviceListService(); + deviceRecordService = new DeviceRecordService(); + deviceLocalCacheService = new DeviceLocalCacheService(); + deviceSubAccountListService = new DeviceSubAccountListService(); + } + + public DeviceLocalCacheManager getDeviceLocalCacheManager() { + return deviceLocalCacheManager; + } + + public DeviceDetailService getDeviceDetailService() { + return deviceDetailService; + } + + public DeviceListService getDeviceListService() { + return deviceListService; + } + + public DeviceRecordService getDeviceRecordService() { + return deviceRecordService; + } + + public DeviceLocalCacheService getDeviceLocalCacheService() { + return deviceLocalCacheService; + } + + public DeviceSubAccountListService getDeviceSubAccountListService() { + return deviceSubAccountListService; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceDetailService.java b/app/src/main/java/com/common/openapi/DeviceDetailService.java new file mode 100644 index 0000000..14a7260 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceDetailService.java @@ -0,0 +1,295 @@ +package com.common.openapi; + +import android.os.Message; + +import com.common.openapi.entity.DeviceAlarmStatusData; +import com.common.openapi.entity.DeviceChannelInfoData; +import com.common.openapi.entity.DeviceModifyNameData; +import com.common.openapi.entity.DeviceUnBindData; +import com.common.openapi.entity.DeviceVersionListData; +import com.mm.android.deviceaddmodule.device_wifi.CurWifiInfo; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessRunnable; +import com.mm.android.deviceaddmodule.mobilecommon.base.LCBusinessHandler; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.BusinessErrorTip; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.HandleMessageCode; +import com.mm.android.deviceaddmodule.openapi.DeviceAddOpenApiManager; + +public class DeviceDetailService { + + + /** + * 获取设备版本和可升级信息 + * + * @param deviceVersionListData + * @param deviceVersionCallBack + */ + public void deviceVersionList(final DeviceVersionListData deviceVersionListData, final IGetDeviceInfoCallBack.IDeviceVersionCallBack deviceVersionCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceVersionCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceVersionCallBack.deviceVersion((DeviceVersionListData.Response) msg.obj); + } else { + //失败 + deviceVersionCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + DeviceVersionListData.Response response = DeviceInfoOpenApiManager.deviceVersionList(deviceVersionListData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 修改设备或通道名称 + * + * @param deviceModifyNameData + * @param modifyDeviceCallBack + */ + public void modifyDeviceName(final DeviceModifyNameData deviceModifyNameData, final IGetDeviceInfoCallBack.IModifyDeviceCallBack modifyDeviceCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (modifyDeviceCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + modifyDeviceCallBack.deviceModify((boolean) msg.obj); + } else { + //失败 + modifyDeviceCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + boolean b = DeviceInfoOpenApiManager.modifyDeviceName(deviceModifyNameData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, b).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 解绑设备 + * + * @param deviceUnBindData + * @param unbindDeviceCallBack + */ + public void unBindDevice(final DeviceUnBindData deviceUnBindData, final IGetDeviceInfoCallBack.IUnbindDeviceCallBack unbindDeviceCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (unbindDeviceCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + unbindDeviceCallBack.unBindDevice((boolean) msg.obj); + } else { + //失败 + unbindDeviceCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + boolean b = DeviceInfoOpenApiManager.unBindDevice(deviceUnBindData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, b).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + public void deletePermission(final String deviceId, final String channelId, final IGetDeviceInfoCallBack.IUnbindDeviceCallBack unbindDeviceCallBack){ + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (unbindDeviceCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + unbindDeviceCallBack.unBindDevice((boolean) msg.obj); + } else { + //失败 + unbindDeviceCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + boolean b = DeviceInfoOpenApiManager.deletePermission(deviceId,channelId); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, b).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 单个设备通道的详细信息获取 + * + * @param deviceChannelInfoData + * @param deviceChannelInfoCallBack + */ + public void bindDeviceChannelInfo(final DeviceChannelInfoData deviceChannelInfoData, final IGetDeviceInfoCallBack.IDeviceChannelInfoCallBack deviceChannelInfoCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceChannelInfoCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceChannelInfoCallBack.deviceChannelInfo((DeviceChannelInfoData.Response) msg.obj); + } else { + //失败 + deviceChannelInfoCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + DeviceChannelInfoData.Response response = DeviceInfoOpenApiManager.bindDeviceChannelInfo(deviceChannelInfoData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 设置动检开关 + * + * @param deviceAlarmStatusData + * @param deviceAlarmStatusCallBack + */ + public void modifyDeviceAlarmStatus(final DeviceAlarmStatusData deviceAlarmStatusData, final IGetDeviceInfoCallBack.IDeviceAlarmStatusCallBack deviceAlarmStatusCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceAlarmStatusCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceAlarmStatusCallBack.deviceAlarmStatus((boolean) msg.obj); + } else { + //失败 + deviceAlarmStatusCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + boolean b = DeviceInfoOpenApiManager.modifyDeviceAlarmStatus(deviceAlarmStatusData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, b).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 设备升级 + * + * @param deviceId + * @param deviceUpdateCallBack + */ + public void upgradeDevice(final String deviceId, final IGetDeviceInfoCallBack.IDeviceUpdateCallBack deviceUpdateCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceUpdateCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceUpdateCallBack.deviceUpdate((boolean) msg.obj); + } else { + //失败 + deviceUpdateCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + boolean b = DeviceInfoOpenApiManager.upgradeDevice(deviceId); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, b).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 设备当前连接热点信息 + * + * @param deviceId + * @param deviceCurrentWifiInfoCallBack + */ + public void currentDeviceWifi(final String deviceId, final IGetDeviceInfoCallBack.IDeviceCurrentWifiInfoCallBack deviceCurrentWifiInfoCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceCurrentWifiInfoCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceCurrentWifiInfoCallBack.deviceCurrentWifiInfo((CurWifiInfo) msg.obj); + } else { + //失败 + deviceCurrentWifiInfoCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + CurWifiInfo curWifiInfo = DeviceAddOpenApiManager.currentDeviceWifi(deviceId); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, curWifiInfo).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + +} diff --git a/app/src/main/java/com/common/openapi/DeviceInfoOpenApiManager.java b/app/src/main/java/com/common/openapi/DeviceInfoOpenApiManager.java new file mode 100644 index 0000000..98276ac --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceInfoOpenApiManager.java @@ -0,0 +1,337 @@ +package com.common.openapi; + +import com.common.openapi.entity.CloudRecordsData; +import com.common.openapi.entity.ControlMovePTZData; +import com.common.openapi.entity.DeviceAlarmStatusData; +import com.common.openapi.entity.DeviceChannelInfoData; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceListData; +import com.common.openapi.entity.DeviceModifyNameData; +import com.common.openapi.entity.DeviceUnBindData; +import com.common.openapi.entity.DeviceVersionListData; +import com.common.openapi.entity.LocalRecordsData; +import com.common.openapi.entity.SubAccountDeviceData; +import com.google.gson.JsonObject; +import com.mm.android.deviceaddmodule.LCDeviceEngine; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.openapi.HttpSend; + +import java.util.HashMap; + +public class DeviceInfoOpenApiManager { + + private static int TIME_OUT = 10 * 1000; + private static int DMS_TIME_OUT = 45 * 1000; + + /** + * 分页获取乐橙app添加或分享的设备通道基本信息 + * + * @param deviceListData + * @return + * @throws BusinessException + */ + public static DeviceListData.Response deviceBaseList(DeviceListData deviceListData) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("bindId", deviceListData.data.baseBindId); + paramsMap.put("limit", deviceListData.data.limit); + paramsMap.put("type", deviceListData.data.type); + paramsMap.put("needApInfo", deviceListData.data.needApInfo); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_BASE_LIST,TIME_OUT); + DeviceListData.Response response = new DeviceListData.Response(); + response.parseData(json); + return response; + } + + /** + * 分页获取开放平台添加设备的通道基本信息 + * + * @param deviceListData + * @return + * @throws BusinessException + */ + public static DeviceListData.Response deviceOpenList(DeviceListData deviceListData) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("bindId", deviceListData.data.openBindId); + paramsMap.put("limit", deviceListData.data.limit); + paramsMap.put("type", deviceListData.data.type); + paramsMap.put("needApInfo", deviceListData.data.needApInfo); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_OPEN_LIST,TIME_OUT); + DeviceListData.Response response = new DeviceListData.Response(); + response.parseData(json); + return response; + } + + /** + * 批量根据设备序列号、通道号列表和配件号列表,获取设备的详细信息 + * + * @param deviceDetailListData + * @return + * @throws BusinessException + */ + public static DeviceDetailListData.Response deviceOpenDetailList(DeviceDetailListData deviceDetailListData) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceList", deviceDetailListData.data.deviceList); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_OPEN_DETAIL_LIST,TIME_OUT); + DeviceDetailListData.Response response = new DeviceDetailListData.Response(); + response.parseData(json); + return response; + } + + /** + * 批量根据设备序列号、通道号列表和配件号列表,获取乐橙app添加或分享的设备的详细信息 + * + * @param deviceDetailListData + * @return + * @throws BusinessException + */ + public static DeviceDetailListData.Response deviceBaseDetailList(DeviceDetailListData deviceDetailListData) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceList", deviceDetailListData.data.deviceList); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_BASE_DETAIL_LIST,TIME_OUT); + DeviceDetailListData.Response response = new DeviceDetailListData.Response(); + response.parseData(json); + return response; + } + + /** + * 解绑设备 + * + * @param deviceUnBindData + * @return + * @throws BusinessException + */ + public static boolean unBindDevice(DeviceUnBindData deviceUnBindData) throws BusinessException { + // 解绑设备 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceUnBindData.data.deviceId); + HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_UN_BIND,TIME_OUT); + return true; + } + + public static boolean deletePermission(String deviceId,String channelId) throws BusinessException { + HashMap paramsMap = new HashMap(); +// paramsMap.put("openid", LCDeviceEngine.newInstance().openid); + paramsMap.put("channelId", channelId); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceId); + HttpSend.execute(paramsMap, MethodConst.DELETE_DEVICE_PERMISSION,TIME_OUT); + return true; + } + + /** + * 获取设备版本和可升级信息 + * + * @param deviceVersionListData + * @return + * @throws BusinessException + */ + public static DeviceVersionListData.Response deviceVersionList(DeviceVersionListData deviceVersionListData) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceIds", deviceVersionListData.data.deviceIds); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_VERSION_LIST,TIME_OUT); + DeviceVersionListData.Response response = new DeviceVersionListData.Response(); + response.parseData(json); + return response; + } + + /** + * 修改设备或通道名称 + * + * @param deviceModifyNameData + * @return + * @throws BusinessException + */ + public static boolean modifyDeviceName(DeviceModifyNameData deviceModifyNameData) throws BusinessException { + // 解绑设备 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceModifyNameData.data.deviceId); + paramsMap.put("channelId", deviceModifyNameData.data.channelId); + paramsMap.put("name", deviceModifyNameData.data.name); + HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_MODIFY_NAME,TIME_OUT); + return true; + } + + /** + * 单个设备通道的详细信息获取 + * + * @param deviceChannelInfoData + * @return + * @throws BusinessException + */ + public static DeviceChannelInfoData.Response bindDeviceChannelInfo(DeviceChannelInfoData deviceChannelInfoData) throws BusinessException { + // 单个设备通道的详细信息获取 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceChannelInfoData.data.deviceId); + paramsMap.put("channelId", deviceChannelInfoData.data.channelId); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_CHANNEL_INFO, DMS_TIME_OUT); + DeviceChannelInfoData.Response response = new DeviceChannelInfoData.Response(); + response.parseData(json); + return response; + } + + /** + * 设置动检开关 + * + * @param deviceAlarmStatusData + * @return + * @throws BusinessException + */ + public static boolean modifyDeviceAlarmStatus(DeviceAlarmStatusData deviceAlarmStatusData) throws BusinessException { + // 解绑设备 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceAlarmStatusData.data.deviceId); + paramsMap.put("channelId", deviceAlarmStatusData.data.channelId); + paramsMap.put("enable", deviceAlarmStatusData.data.enable); + HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_MODIFY_ALARM_STATUS, DMS_TIME_OUT); + return true; + } + + /** + * 设备升级 + * + * @param deviceId + * @return + * @throws BusinessException + */ + public static boolean upgradeDevice(String deviceId) throws BusinessException { + // 解绑设备 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceId); + HttpSend.execute(paramsMap, MethodConst.METHOD_DEVICE_UPDATE, DMS_TIME_OUT); + return true; + } + + /** + * 倒序查询设备云录像片段 + * + * @param cloudRecordsData + * @return + * @throws BusinessException + */ + public static CloudRecordsData.Response getCloudRecords(CloudRecordsData cloudRecordsData) throws BusinessException { + // 倒序查询设备云录像片段 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", cloudRecordsData.data.deviceId); + paramsMap.put("channelId", cloudRecordsData.data.channelId); + paramsMap.put("beginTime", cloudRecordsData.data.beginTime); + paramsMap.put("endTime", cloudRecordsData.data.endTime); + paramsMap.put("nextRecordId", cloudRecordsData.data.nextRecordId); + paramsMap.put("count", cloudRecordsData.data.count); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_GET_CLOUND_RECORDS,TIME_OUT); + CloudRecordsData.Response response = new CloudRecordsData.Response(); + response.parseData(json); + return response; + } + + /** + * 查询设备设备录像片段 + * + * @param localRecordsData + * @return + * @throws BusinessException + */ + public static LocalRecordsData.Response queryLocalRecords(LocalRecordsData localRecordsData) throws BusinessException { + // 查询设备设备录像片段 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", localRecordsData.data.deviceId); + paramsMap.put("channelId", localRecordsData.data.channelId); + paramsMap.put("beginTime", localRecordsData.data.beginTime); + paramsMap.put("endTime", localRecordsData.data.endTime); + paramsMap.put("type", localRecordsData.data.type); + paramsMap.put("queryRange", localRecordsData.data.queryRange); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.METHOD_QUERY_LOCAL_RECORD, DMS_TIME_OUT); + LocalRecordsData.Response response = new LocalRecordsData.Response(); + response.parseData(json); + return response; + } + + public static int queryCloudUse(String deviceId,String channelId) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceId); + paramsMap.put("channelId", channelId); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.GET_DEVICE_CLOUD, DMS_TIME_OUT); + Integer state = json.get("strategyStatus").getAsInt(); + return state; + } + + public static String querySDState(String deviceId) throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", deviceId); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.SD_STATUE_QUERY, DMS_TIME_OUT); + String state = json.get("status").getAsString(); + return state; + } + + /** + * 云台移动控制接口(V2版本) + * + * @param controlMovePTZData + * @return + * @throws BusinessException + */ + public static void controlMovePTZ(ControlMovePTZData controlMovePTZData) throws BusinessException { + // 云台移动控制接口(V2版本) + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("deviceId", controlMovePTZData.data.deviceId); + paramsMap.put("channelId", controlMovePTZData.data.channelId); + paramsMap.put("operation", controlMovePTZData.data.operation); + paramsMap.put("duration", controlMovePTZData.data.duration); + HttpSend.execute(paramsMap, MethodConst.METHOD_CONTROL_MOVE_PTZ, DMS_TIME_OUT); + } + + /** + * 删除设备云录像片段 + * + * @param recordRegionId + * @return + * @throws BusinessException + */ + public static boolean deleteCloudRecords(String recordRegionId) throws BusinessException { + // 删除设备云录像片段 + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("recordRegionId", recordRegionId); + HttpSend.execute(paramsMap, MethodConst.METHOD_DELETE_CLOUND_RECORDS,TIME_OUT); + return true; + } + + //V7.12新增 + public static SubAccountDeviceData.Response getSubAccountDeviceListLight(int pageNo, int pageSize, String openid)throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("pageNo", pageNo); + paramsMap.put("pageSize",pageSize); + paramsMap.put("openid",openid); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.LIST_SUB_ACCOUNT_DEVICE,TIME_OUT); + SubAccountDeviceData.Response response = new SubAccountDeviceData.Response(); + response.parseData(json); + return response; + } + + public static DeviceDetailListData.Response getSubAccountDeviceList(int pageNo, int pageSize)throws BusinessException { + HashMap paramsMap = new HashMap(); + paramsMap.put("token", LCDeviceEngine.newInstance().accessToken); + paramsMap.put("page", pageNo); + paramsMap.put("pageSize",pageSize); + JsonObject json = HttpSend.execute(paramsMap, MethodConst.SUB_ACCOUNT_DEVICE_LIST,TIME_OUT); + DeviceDetailListData.Response response = new DeviceDetailListData.Response(); + response.parseData(json); + return response; + } + +} diff --git a/app/src/main/java/com/common/openapi/DeviceListService.java b/app/src/main/java/com/common/openapi/DeviceListService.java new file mode 100644 index 0000000..0edff80 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceListService.java @@ -0,0 +1,164 @@ +package com.common.openapi; + +import android.os.Message; + +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceListData; +import com.google.gson.Gson; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessRunnable; +import com.mm.android.deviceaddmodule.mobilecommon.base.LCBusinessHandler; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.BusinessErrorTip; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.HandleMessageCode; + +import java.util.ArrayList; +import java.util.List; + +public class DeviceListService { + + public static final int pageSize=8; + + + /** + * 获取设备列表 1:开放平台添加的 2:乐橙App添加的 + * + * @param deviceListData + * @param getDeviceListCallBack + */ + public void deviceBaseList(final DeviceListData deviceListData, final IGetDeviceInfoCallBack.IDeviceListCallBack getDeviceListCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (getDeviceListCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + getDeviceListCallBack.deviceList((DeviceDetailListData.Response) msg.obj); + } else { + //失败 + getDeviceListCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + dealDeviceDetailList(handler, deviceListData); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + private void dealDeviceDetailList(LCBusinessHandler handler, DeviceListData deviceListData) throws BusinessException { + if (deviceListData == null) { + deviceListData = new DeviceListData(); + } + //成功返回值 + DeviceDetailListData.Response result = null; + //获取乐橙添加的设备 + DeviceDetailListData.Response deviceBaseDetailList = getDeviceDetailListFromCloud(false, deviceListData); + //乐橙返回 + if (deviceBaseDetailList.data != null && deviceBaseDetailList.data.deviceList != null && deviceBaseDetailList.data.deviceList.size() > 0) { + result = new DeviceDetailListData.Response(); + result.data = new DeviceDetailListData.ResponseData(); + result.data.count = deviceBaseDetailList.data.deviceList.size(); + result.data.deviceList = new ArrayList<>(); + for (DeviceDetailListData.ResponseData.DeviceListBean a : deviceBaseDetailList.data.deviceList) { + DeviceDetailListData.ResponseData.DeviceListBean b = new DeviceDetailListData.ResponseData.DeviceListBean(); + Gson gson = new Gson(); + b = gson.fromJson(gson.toJson(a), DeviceDetailListData.ResponseData.DeviceListBean.class); + b.deviceSource=2; + result.data.deviceList.add(b); + } + result.baseBindId = deviceBaseDetailList.baseBindId; + if (result.data.deviceList.size() >= pageSize) { + //单次已经达到8条不再拉取 + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, result).sendToTarget(); + return; + } else { + //单次没有达到8条 + deviceListData.data.limit = (8 - result.data.deviceList.size()) + ""; + } + } + //获取开放平台添加的设备 + DeviceDetailListData.Response deviceOpenDetailList = getDeviceDetailListFromCloud(true, deviceListData); + //开放平台返回 + if (deviceOpenDetailList.data != null && deviceOpenDetailList.data.deviceList != null && deviceOpenDetailList.data.deviceList.size() > 0) { + if (result == null) { + result = new DeviceDetailListData.Response(); + result.data = new DeviceDetailListData.ResponseData(); + result.data.count = deviceOpenDetailList.data.deviceList.size(); + result.data.deviceList = new ArrayList<>(); + for (DeviceDetailListData.ResponseData.DeviceListBean a : deviceOpenDetailList.data.deviceList) { + DeviceDetailListData.ResponseData.DeviceListBean b = new DeviceDetailListData.ResponseData.DeviceListBean(); + Gson gson = new Gson(); + b = gson.fromJson(gson.toJson(a), DeviceDetailListData.ResponseData.DeviceListBean.class); + b.deviceSource=1; + result.data.deviceList.add(b); + } + } else { + result.data.count = deviceOpenDetailList.data.count + result.data.count; + for (DeviceDetailListData.ResponseData.DeviceListBean a : deviceOpenDetailList.data.deviceList) { + DeviceDetailListData.ResponseData.DeviceListBean b = new DeviceDetailListData.ResponseData.DeviceListBean(); + Gson gson = new Gson(); + b = gson.fromJson(gson.toJson(a), DeviceDetailListData.ResponseData.DeviceListBean.class); + result.data.deviceList.add(b); + } + } + result.openBindId = deviceOpenDetailList.openBindId; + } + if (result == null) { + result = new DeviceDetailListData.Response(); + } + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, result).sendToTarget(); + } + + private DeviceDetailListData.Response getDeviceDetailListFromCloud(boolean isOpenPlatform, DeviceListData deviceListDat) throws BusinessException { + DeviceDetailListData.Response result = new DeviceDetailListData.Response(); + DeviceListData.Response deviceList = null; + //获取到设备基本信息列表 + if (isOpenPlatform) { + deviceList = DeviceInfoOpenApiManager.deviceOpenList(deviceListDat); + } else { + deviceList = DeviceInfoOpenApiManager.deviceBaseList(deviceListDat); + } + if (deviceList.data == null || deviceList.data.deviceList == null || deviceList.data.deviceList.size() == 0) { + return result; + } + //获取设备详情列表request参数封装 + DeviceDetailListData deviceDetailListData = new DeviceDetailListData(); + List deviceListBeans = new ArrayList<>(); + for (DeviceListData.ResponseData.DeviceListElement deviceListElement : deviceList.data.deviceList) { + DeviceDetailListData.RequestData.DeviceListBean deviceListBean = new DeviceDetailListData.RequestData.DeviceListBean(); + deviceListBean.deviceId = deviceListElement.deviceId; + StringBuilder stringBuilder=new StringBuilder(); + if (deviceListElement.channels.size()>0){ + for (DeviceListData.ResponseData.DeviceListElement.ChannelsElement channelsElement:deviceListElement.channels){ + stringBuilder.append(channelsElement.channelId).append(","); + } + deviceListBean.channelList=stringBuilder.substring(0,stringBuilder.length()-1); + } + deviceListBeans.add(deviceListBean); + } + deviceDetailListData.data.deviceList = deviceListBeans; + //获取设备详情列表 + if (isOpenPlatform) { + result = DeviceInfoOpenApiManager.deviceOpenDetailList(deviceDetailListData); + } else { + result = DeviceInfoOpenApiManager.deviceBaseDetailList(deviceDetailListData); + } + if (result == null) { + result = new DeviceDetailListData.Response(); + } + if (isOpenPlatform) { + result.openBindId = Long.parseLong(deviceList.data.deviceList.get(deviceList.data.deviceList.size() - 1).bindId); + } else { + result.baseBindId = Long.parseLong(deviceList.data.deviceList.get(deviceList.data.deviceList.size() - 1).bindId); + } + return result; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceLocalCacheDatabase.java b/app/src/main/java/com/common/openapi/DeviceLocalCacheDatabase.java new file mode 100644 index 0000000..8bdcc2b --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceLocalCacheDatabase.java @@ -0,0 +1,122 @@ +package com.common.openapi; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import com.common.openapi.entity.DeviceLocalCacheData; + +import java.util.ArrayList; +import java.util.List; + +public class DeviceLocalCacheDatabase extends SQLiteOpenHelper { + private static final String TAG = DeviceLocalCacheDatabase.class.getSimpleName(); + + private static final String DB_NAME = "device_local_cache"; + private static final String TABLE_NAME = "t_device_local_cache"; + + private static final String TABLE_CREATE_SQL = "create table " + TABLE_NAME + "(" + + "cache_id integer primary key autoincrement, " + + "device_id text, " + + "device_name text, " + + "channel_id text, " + + "channel_name text, " + + "pic_path text, " + + "creation_time integer, " + + "modify_time integer " + + ")"; + + private static final String[] TABLE_COLUMNS = { + "cache_id", + "device_id", + "device_name", + "channel_id", + "channel_name", + "pic_path", + "creation_time", + "modify_time" + }; + + public DeviceLocalCacheDatabase(Context context) { + super(context, DB_NAME, null, 1); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(TABLE_CREATE_SQL); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } + + public int addLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + SQLiteDatabase db = getWritableDatabase(); + ContentValues v = new ContentValues(); + v.put("device_id", deviceLocalCacheData.getDeviceId()); + v.put("device_name", deviceLocalCacheData.getDeviceName()); + v.put("channel_id", deviceLocalCacheData.getChannelId()); + v.put("channel_name", deviceLocalCacheData.getChannelName()); + v.put("pic_path", deviceLocalCacheData.getPicPath()); + v.put("creation_time", System.currentTimeMillis()); + v.put("modify_time", System.currentTimeMillis()); + long rowid = db.insert(TABLE_NAME, null, v); + if (rowid != -1) { + return 1; + } + return 0; + } + + public int updateLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + ContentValues v = new ContentValues(); + v.put("pic_path", deviceLocalCacheData.getPicPath()); + v.put("modify_time", System.currentTimeMillis()); + SQLiteDatabase db = getWritableDatabase(); + int ret = db.update(TABLE_NAME, v, "cache_id=?", new String[]{String.valueOf(deviceLocalCacheData.getCacheId())}); + if (ret > 0) { + return 1; + } + return 0; + } + + public DeviceLocalCacheData findLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + StringBuilder selectionBuilder = new StringBuilder(); + List selectionArgs = new ArrayList<>(); + boolean first = true; + if (deviceLocalCacheData.getDeviceId() != null) { + selectionBuilder.append(" device_id =? "); + selectionArgs.add(deviceLocalCacheData.getDeviceId()); + first = false; + } + if (deviceLocalCacheData.getChannelId() != null) { + if (!first) { + selectionBuilder.append(" and "); + } + selectionBuilder.append(" channel_id =? "); + selectionArgs.add(deviceLocalCacheData.getChannelId()); + } + SQLiteDatabase db = getReadableDatabase(); + try (Cursor c = db.query(TABLE_NAME, TABLE_COLUMNS, selectionBuilder.toString(), selectionArgs.toArray(new String[0]), null, null, null, "1")) { + if (c.moveToFirst()) { + return (buildLocalCacheFromCursor(c)); + } + } + return null; + } + + private DeviceLocalCacheData buildLocalCacheFromCursor(Cursor c) { + DeviceLocalCacheData deviceLocalCacheData = new DeviceLocalCacheData(); + deviceLocalCacheData.setCacheId(c.getInt(0)); + deviceLocalCacheData.setDeviceId(c.getString(1)); + deviceLocalCacheData.setDeviceName(c.getString(2)); + deviceLocalCacheData.setChannelId(c.getString(3)); + deviceLocalCacheData.setChannelName(c.getString(4)); + deviceLocalCacheData.setPicPath(c.getString(5)); + deviceLocalCacheData.setCreationTime(c.getLong(6)); + deviceLocalCacheData.setModifyTime(c.getLong(7)); + return deviceLocalCacheData; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceLocalCacheManager.java b/app/src/main/java/com/common/openapi/DeviceLocalCacheManager.java new file mode 100644 index 0000000..9022264 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceLocalCacheManager.java @@ -0,0 +1,43 @@ +package com.common.openapi; + +import android.content.Context; + +import com.common.openapi.entity.DeviceLocalCacheData; +import com.lechange.demo.tools.MediaPlayHelper; + +public class DeviceLocalCacheManager { + + private DeviceLocalCacheDatabase deviceLocalCacheDatabase; + + public void init(Context context) { + deviceLocalCacheDatabase = new DeviceLocalCacheDatabase(context); + } + + public int addLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + DeviceLocalCacheData find = deviceLocalCacheDatabase.findLocalCache(deviceLocalCacheData); + if (find == null) { + int add = deviceLocalCacheDatabase.addLocalCache(deviceLocalCacheData); + return add; + } else { + deviceLocalCacheData.setCacheId(find.getCacheId()); + int update = deviceLocalCacheDatabase.updateLocalCache(deviceLocalCacheData); + //删除之前缓存文件 + MediaPlayHelper.delete(find.getPicPath()); + return update; + } + } + + public DeviceLocalCacheData findLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + DeviceLocalCacheData find = deviceLocalCacheDatabase.findLocalCache(deviceLocalCacheData); + return find; + } + + public int updateLocalCache(DeviceLocalCacheData deviceLocalCacheData) { + DeviceLocalCacheData find = deviceLocalCacheDatabase.findLocalCache(deviceLocalCacheData); + if (find == null) { + return 0; + } + int update = deviceLocalCacheDatabase.updateLocalCache(find); + return update; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceLocalCacheService.java b/app/src/main/java/com/common/openapi/DeviceLocalCacheService.java new file mode 100644 index 0000000..54152b4 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceLocalCacheService.java @@ -0,0 +1,69 @@ +package com.common.openapi; + +import android.os.Message; + +import com.common.openapi.entity.DeviceLocalCacheData; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessRunnable; +import com.mm.android.deviceaddmodule.mobilecommon.base.LCBusinessHandler; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.BusinessErrorTip; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.HandleMessageCode; + +public class DeviceLocalCacheService { + + /** + * 添加设备缓存信息 + * @param localCacheData + */ + public void addLocalCache(final DeviceLocalCacheData localCacheData) { + new BusinessRunnable(null) { + @Override + public void doBusiness() throws BusinessException { + try { + DeviceLocalCacheManager deviceLocalCacheManager = ClassInstanceManager.newInstance().getDeviceLocalCacheManager(); + deviceLocalCacheManager.addLocalCache(localCacheData); + } catch (Throwable e) { + throw e; + } + } + }; + } + + /** + * 获取设备缓存信息 + * @param localCacheData + * @param deviceCacheCallBack + */ + public void findLocalCache(final DeviceLocalCacheData localCacheData, final IGetDeviceInfoCallBack.IDeviceCacheCallBack deviceCacheCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceCacheCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceCacheCallBack.deviceCache((DeviceLocalCacheData) msg.obj); + } else { + //失败 + deviceCacheCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + DeviceLocalCacheData localCache = ClassInstanceManager.newInstance().getDeviceLocalCacheManager().findLocalCache(localCacheData); + if (localCache != null) { + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, localCache).sendToTarget(); + } else { + throw new BusinessException("null point"); + } + } catch (Throwable e) { + throw e; + } + } + }; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceRecordService.java b/app/src/main/java/com/common/openapi/DeviceRecordService.java new file mode 100644 index 0000000..d83bb64 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceRecordService.java @@ -0,0 +1,204 @@ +package com.common.openapi; + +import android.os.Message; + +import com.common.openapi.entity.CloudRecordsData; +import com.common.openapi.entity.ControlMovePTZData; +import com.common.openapi.entity.DeleteCloudRecordsData; +import com.common.openapi.entity.LocalRecordsData; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessRunnable; +import com.mm.android.deviceaddmodule.mobilecommon.base.LCBusinessHandler; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.BusinessErrorTip; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.HandleMessageCode; + +public class DeviceRecordService { + + /** + * 倒序查询设备云录像片段 + * + * @param cloudRecordsData + * @param cloudRecordCallBack + */ + public void getCloudRecords(final CloudRecordsData cloudRecordsData, final IGetDeviceInfoCallBack.IDeviceCloudRecordCallBack cloudRecordCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (cloudRecordCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + cloudRecordCallBack.deviceCloudRecord((CloudRecordsData.Response) msg.obj); + } else { + //失败 + cloudRecordCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + CloudRecordsData.Response response = DeviceInfoOpenApiManager.getCloudRecords(cloudRecordsData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 查询设备设备录像片段 + * + * @param localRecordsData + * @param deviceLocalRecordCallBack + */ + public void queryLocalRecords(final LocalRecordsData localRecordsData, final IGetDeviceInfoCallBack.IDeviceLocalRecordCallBack deviceLocalRecordCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceLocalRecordCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceLocalRecordCallBack.deviceLocalRecord((LocalRecordsData.Response) msg.obj); + } else { + //失败 + deviceLocalRecordCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + LocalRecordsData.Response response = DeviceInfoOpenApiManager.queryLocalRecords(localRecordsData); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + public void queryCloudUse(final String deviceId, final String channelId, final IGetDeviceInfoCallBack.ICommon iCommon){ + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (iCommon == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + iCommon.onCommonBack(msg.obj); + } else { + //失败 + iCommon.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + int response = DeviceInfoOpenApiManager.queryCloudUse(deviceId,channelId); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + public void querySDUse(final String deviceId, final IGetDeviceInfoCallBack.ICommon iCommon){ + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (iCommon == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + iCommon.onCommonBack(msg.obj); + } else { + //失败 + iCommon.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + String response = DeviceInfoOpenApiManager.querySDState(deviceId); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 云台移动控制接口(V2版本) + * + * @param controlMovePTZData + */ + public void controlMovePTZ(final ControlMovePTZData controlMovePTZData) { + new BusinessRunnable(new LCBusinessHandler() { + + @Override + public void handleBusiness(Message msg) { + } + }) { + @Override + public void doBusiness() throws BusinessException { + try { + DeviceInfoOpenApiManager.controlMovePTZ(controlMovePTZData); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + /** + * 删除设备云录像片段 + * + * @param deleteCloudRecordsData + * @param deviceDeleteRecordCallBack + */ + public void deleteCloudRecords(final DeleteCloudRecordsData deleteCloudRecordsData, final IGetDeviceInfoCallBack.IDeviceDeleteRecordCallBack deviceDeleteRecordCallBack) { + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (deviceDeleteRecordCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + deviceDeleteRecordCallBack.deleteDeviceRecord(); + } else { + //失败 + deviceDeleteRecordCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + for (String id : deleteCloudRecordsData.data.recordRegionIds) { + DeviceInfoOpenApiManager.deleteCloudRecords(id); + } + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, null).sendToTarget(); + } catch (BusinessException e) { + throw e; + } + } + }; + } +} diff --git a/app/src/main/java/com/common/openapi/DeviceSubAccountListService.java b/app/src/main/java/com/common/openapi/DeviceSubAccountListService.java new file mode 100644 index 0000000..45530a2 --- /dev/null +++ b/app/src/main/java/com/common/openapi/DeviceSubAccountListService.java @@ -0,0 +1,83 @@ +package com.common.openapi; + +import android.os.Handler; +import android.os.Message; + +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.SubAccountDeviceData; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessException; +import com.mm.android.deviceaddmodule.mobilecommon.AppConsume.BusinessRunnable; +import com.mm.android.deviceaddmodule.mobilecommon.base.LCBusinessHandler; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.BusinessErrorTip; +import com.mm.android.deviceaddmodule.mobilecommon.businesstip.HandleMessageCode; + +public class DeviceSubAccountListService { + public static final int pageSize=10; + + public void getDeviceListSubAccount(final int pageNo, final String openid, final IGetDeviceInfoCallBack.ISubAccountDevice getDeviceListCallBack){ + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (getDeviceListCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + getDeviceListCallBack.DeviceList((SubAccountDeviceData.Response) msg.obj); + } else { + //失败 + getDeviceListCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + dealSubAccountDeviceList(handler,pageNo,openid); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + private void dealSubAccountDeviceList(Handler handler,int pageNo,String openid)throws BusinessException { + SubAccountDeviceData.Response response= DeviceInfoOpenApiManager.getSubAccountDeviceListLight(pageNo,pageSize,openid); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } + + public void getSubAccountDeviceList(final int pageNo, final IGetDeviceInfoCallBack.ISubAccountDevice getDeviceListCallBack){ + final LCBusinessHandler handler = new LCBusinessHandler() { + @Override + public void handleBusiness(Message msg) { + if (getDeviceListCallBack == null) { + return; + } + if (msg.what == HandleMessageCode.HMC_SUCCESS) { + //成功 + getDeviceListCallBack.DeviceList(( DeviceDetailListData.Response) msg.obj); + } else { + //失败 + getDeviceListCallBack.onError(BusinessErrorTip.throwError(msg)); + } + } + }; + new BusinessRunnable(handler) { + @Override + public void doBusiness() throws BusinessException { + try { + getDeviceListAtSubAccount(handler,pageNo); + } catch (BusinessException e) { + throw e; + } + } + }; + } + + private void getDeviceListAtSubAccount(Handler handler,int pageNo)throws BusinessException { + DeviceDetailListData.Response response= DeviceInfoOpenApiManager.getSubAccountDeviceList(pageNo,pageSize); + handler.obtainMessage(HandleMessageCode.HMC_SUCCESS, response).sendToTarget(); + } + +} diff --git a/app/src/main/java/com/common/openapi/IGetDeviceInfoCallBack.java b/app/src/main/java/com/common/openapi/IGetDeviceInfoCallBack.java new file mode 100644 index 0000000..e752944 --- /dev/null +++ b/app/src/main/java/com/common/openapi/IGetDeviceInfoCallBack.java @@ -0,0 +1,218 @@ +package com.common.openapi; + +import com.common.openapi.entity.CloudRecordsData; +import com.common.openapi.entity.DeviceChannelInfoData; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceLocalCacheData; +import com.common.openapi.entity.DeviceVersionListData; +import com.common.openapi.entity.LocalRecordsData; +import com.mm.android.deviceaddmodule.device_wifi.CurWifiInfo; + +public interface IGetDeviceInfoCallBack { + public interface IDeviceListCallBack { + /** + * 成功获取到设备列表 + * + * @param responseData + */ + void deviceList(DeviceDetailListData.Response responseData); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceVersionCallBack { + /** + * 获取设备版本和可升级信息 + * + * @param responseData + */ + void deviceVersion(DeviceVersionListData.Response responseData); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IModifyDeviceCallBack { + /** + * 修改设备或通道名称成功 + * + * @param result + */ + void deviceModify(boolean result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IUnbindDeviceCallBack { + /** + * 解绑设备成功 + * + * @param result + */ + void unBindDevice(boolean result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceChannelInfoCallBack { + /** + * 单个设备通道的详细信息获取 + * + * @param result + */ + void deviceChannelInfo(DeviceChannelInfoData.Response result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceAlarmStatusCallBack { + /** + * 设置动检开关 + * + * @param result + */ + void deviceAlarmStatus(boolean result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceUpdateCallBack { + /** + * 设备升级 + * + * @param result + */ + void deviceUpdate(boolean result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceCloudRecordCallBack { + /** + * 倒序查询设备云录像片段 + * + * @param result + */ + void deviceCloudRecord(CloudRecordsData.Response result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceLocalRecordCallBack { + /** + * 查询设备设备录像片段 + * + * @param result + */ + void deviceLocalRecord(LocalRecordsData.Response result); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceDeleteRecordCallBack { + /** + * 删除设备云录像片段 + */ + void deleteDeviceRecord(); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceCacheCallBack { + /** + * 获取设备缓存信息 + */ + void deviceCache(DeviceLocalCacheData deviceLocalCacheData); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IDeviceCurrentWifiInfoCallBack { + /** + * 设备当前连接热点信息 + */ + void deviceCurrentWifiInfo(CurWifiInfo curWifiInfo); + + /** + * 错误回调 + * + * @param throwable + */ + void onError(Throwable throwable); + } + + public interface IModifyDeviceName { + /** + * 设备修改之后的名字 + */ + void deviceName(String newName); + } + + public interface ISubAccountDevice{ + void DeviceList(T response); + + void onError(Throwable throwable); + } + + public interface ICommon{ + void onCommonBack(T response); + void onError(Throwable throwable); + } + + + +} diff --git a/app/src/main/java/com/common/openapi/MethodConst.java b/app/src/main/java/com/common/openapi/MethodConst.java new file mode 100644 index 0000000..10e26b6 --- /dev/null +++ b/app/src/main/java/com/common/openapi/MethodConst.java @@ -0,0 +1,54 @@ +package com.common.openapi; + +public class MethodConst { + //分页获取乐橙app添加或分享的设备通道基本信息 + public static String METHOD_DEVICE_BASE_LIST = "deviceBaseList"; + //分页获取开放平台添加设备的通道基本信息 + public static String METHOD_DEVICE_OPEN_LIST = "deviceOpenList"; + //批量根据设备序列号、通道号列表和配件号列表,获取设备的详细信息 + public static String METHOD_DEVICE_OPEN_DETAIL_LIST = "deviceOpenDetailList"; + //批量根据设备序列号、通道号列表和配件号列表,获取乐橙app添加或分享的设备的详细信息 + public static String METHOD_DEVICE_BASE_DETAIL_LIST = "deviceBaseDetailList"; + //解绑设备 + public static String METHOD_DEVICE_UN_BIND = "unBindDevice"; + //获取设备版本和可升级信息 + public static String METHOD_DEVICE_VERSION_LIST = "deviceVersionList"; + //修改设备或通道名称 + public static String METHOD_DEVICE_MODIFY_NAME = "modifyDeviceName"; + //单个设备通道的详细信息获取 + public static String METHOD_DEVICE_CHANNEL_INFO = "bindDeviceChannelInfo"; + //设置动检开关 + public static String METHOD_DEVICE_MODIFY_ALARM_STATUS = "modifyDeviceAlarmStatus"; + //设备升级 + public static String METHOD_DEVICE_UPDATE = "upgradeDevice"; + //倒序查询设备云录像片段 + public static String METHOD_GET_CLOUND_RECORDS = "getCloudRecords"; + //查询设备设备录像片段 + public static String METHOD_QUERY_LOCAL_RECORD = "queryLocalRecords"; + //云台移动控制接口(V2版本) + public static String METHOD_CONTROL_MOVE_PTZ = "controlMovePTZ"; + //查询设备云录像片 + public static String METHOD_QUERY_CLOUND_RECORDS = "queryCloudRecords"; + //删除设备云录像片段 + public static String METHOD_DELETE_CLOUND_RECORDS = "deleteCloudRecords"; + + public static String LIST_SUB_ACCOUNT_DEVICE = "listSubAccountDevice"; + + public static String SUB_ACCOUNT_DEVICE_LIST = "subAccountDeviceList"; + + public static String DELETE_DEVICE_PERMISSION = "deleteDevicePermission"; + + public static String SD_STATUE_QUERY = "deviceSdcardStatus"; + public static String GET_DEVICE_CLOUD = "getDeviceCloud"; + + + + public interface ParamConst { + public String deviceDetail = "deviceDetail"; + public String recordType = "recordType"; + public String recordData = "recordsData"; + public int recordTypeLocal = 2; + public int recordTypeCloud = 1; + public String fromList = "list"; + } +} diff --git a/app/src/main/java/com/common/openapi/entity/CloudRecordsData.java b/app/src/main/java/com/common/openapi/entity/CloudRecordsData.java new file mode 100644 index 0000000..121d14e --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/CloudRecordsData.java @@ -0,0 +1,48 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.List; + +public class CloudRecordsData implements Serializable { + public CloudRecordsData.RequestData data = new CloudRecordsData.RequestData(); + + public static class Response { + public CloudRecordsData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), CloudRecordsData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public List records; + + public static class RecordsBean implements Serializable { + public String recordId; + public String deviceId; + public String channelId; + public String beginTime; + public String endTime; + public String size; + public String thumbUrl; + public int encryptMode; + public String recordRegionId; + public String type; + } + } + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId = "0"; + public String beginTime; + public String endTime; + public long nextRecordId=-1; + public long count; + public String queryRange; + } +} diff --git a/app/src/main/java/com/common/openapi/entity/ControlMovePTZData.java b/app/src/main/java/com/common/openapi/entity/ControlMovePTZData.java new file mode 100644 index 0000000..279c92f --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/ControlMovePTZData.java @@ -0,0 +1,16 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class ControlMovePTZData implements Serializable { + public ControlMovePTZData.RequestData data = new ControlMovePTZData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId = "0"; + //0-上,1-下,2-左,3-右,4-左上,5-左下,6-右上,7-右下,8-放大,9-缩小,10-停止 + public String operation; + public long duration; + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeleteCloudRecordsData.java b/app/src/main/java/com/common/openapi/entity/DeleteCloudRecordsData.java new file mode 100644 index 0000000..6a0b988 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeleteCloudRecordsData.java @@ -0,0 +1,14 @@ +package com.common.openapi.entity; + +import java.io.Serializable; +import java.util.List; + +public class DeleteCloudRecordsData implements Serializable { + public DeleteCloudRecordsData.RequestData data = new DeleteCloudRecordsData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public List recordRegionIds; + + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceAlarmStatusData.java b/app/src/main/java/com/common/openapi/entity/DeviceAlarmStatusData.java new file mode 100644 index 0000000..d40b166 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceAlarmStatusData.java @@ -0,0 +1,15 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class DeviceAlarmStatusData implements Serializable { + public DeviceAlarmStatusData.RequestData data = new DeviceAlarmStatusData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId="0"; + public boolean enable; + } + +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceChannelInfoData.java b/app/src/main/java/com/common/openapi/entity/DeviceChannelInfoData.java new file mode 100644 index 0000000..e0b822e --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceChannelInfoData.java @@ -0,0 +1,39 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; + +public class DeviceChannelInfoData implements Serializable { + public DeviceChannelInfoData.RequestData data = new DeviceChannelInfoData.RequestData(); + + public static class Response { + public DeviceChannelInfoData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), DeviceChannelInfoData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public String deviceId; + public int alarmStatus; + public int channelId; + public String channelName; + public String channelOnline; + public String channelPicUrl; + public String shareStatus; + public String shareFunctions; + public String csStatus; + public String channelAbility; + } + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId="0"; + } + +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceDetailListData.java b/app/src/main/java/com/common/openapi/entity/DeviceDetailListData.java new file mode 100644 index 0000000..b3d588a --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceDetailListData.java @@ -0,0 +1,478 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class DeviceDetailListData implements Serializable { + public DeviceDetailListData.RequestData data = new DeviceDetailListData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public List deviceList; + + @Override + public String toString() { + return "RequestData{" + + "token='" + token + '\'' + + ", deviceList=" + deviceList + + '}'; + } + + public static class DeviceListBean implements Serializable { + public String deviceId; + public String channelList; + public String apList; + + @Override + public String toString() { + return "DeviceListBean{" + + "deviceId='" + deviceId + '\'' + + ", channelList='" + channelList + '\'' + + ", apList='" + apList + '\'' + + '}'; + } + } + } + + public static class Response { + public DeviceDetailListData.ResponseData data; + public long baseBindId = -1; + public long openBindId = -1; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), DeviceDetailListData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public int count; + + public List deviceList; + + @Override + public String toString() { + return "ResponseData{" + + "count=" + count + + ", deviceList=" + deviceList + + '}'; + } + + public List getDeviceList() { + if (deviceList == null) { + return new ArrayList<>(); + } + return deviceList; + } + + public void setDeviceList(List deviceList) { + this.deviceList = deviceList; + } + + public static class DeviceListBean implements Serializable { + public String deviceId; + public String id; + public String status; + public String deviceModel; + public String catalog; + public String brand; + public String version; + public String name; + public String ability; + public String accessType; + public int checkedChannel; + public String playToken; + public int encryptMode; + public String channelNum; + public String permission; + public String addressId; + public String deviceType; + //1:开放平台添加 2:乐橙App添加 + public int deviceSource; + public List channels = new ArrayList<>(); + public List aplist; + + @Override + public String toString() { + return "DeviceListBean{" + + "deviceId='" + deviceId + '\'' + + ", status='" + status + '\'' + + ", deviceModel='" + deviceModel + '\'' + + ", catalog='" + catalog + '\'' + + ", brand='" + brand + '\'' + + ", version='" + version + '\'' + + ", name='" + name + '\'' + + ", ability='" + ability + '\'' + + ", accessType='" + accessType + '\'' + + ", checkedChannel=" + checkedChannel + + ", channelNum=" + channelNum + + ", playToken='" + playToken + '\'' + + ", deviceSource=" + deviceSource + + ", channels=" + channels + + ", aplist=" + aplist + + '}'; + } + + public String getAddressId() { + return addressId == null ? "" : addressId; + } + + public void setAddressId(String addressId) { + this.addressId = addressId == null ? "" : addressId; + } + + public String getDeviceType() { + return deviceType == null ? "" : deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType == null ? "" : deviceType; + } + + public String getId() { + return id == null ? "" : id; + } + + public void setId(String id) { + this.id = id == null ? "" : id; + } + + public String getDeviceId() { + return deviceId == null ? "" : deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId == null ? "" : deviceId; + } + + public String getStatus() { + return status == null ? "" : status; + } + + public void setStatus(String status) { + this.status = status == null ? "" : status; + } + + public String getDeviceModel() { + return deviceModel == null ? "" : deviceModel; + } + + public void setDeviceModel(String deviceModel) { + this.deviceModel = deviceModel == null ? "" : deviceModel; + } + + public String getCatalog() { + return catalog == null ? "" : catalog; + } + + public void setCatalog(String catalog) { + this.catalog = catalog == null ? "" : catalog; + } + + public String getBrand() { + return brand == null ? "" : brand; + } + + public void setBrand(String brand) { + this.brand = brand == null ? "" : brand; + } + + public String getVersion() { + return version == null ? "" : version; + } + + public void setVersion(String version) { + this.version = version == null ? "" : version; + } + + public String getName() { + return name == null ? "" : name; + } + + public void setName(String name) { + this.name = name == null ? "" : name; + } + + public String getAbility() { + return ability == null ? "" : ability; + } + + public void setAbility(String ability) { + this.ability = ability == null ? "" : ability; + } + + public String getAccessType() { + return accessType == null ? "" : accessType; + } + + public void setAccessType(String accessType) { + this.accessType = accessType == null ? "" : accessType; + } + + public int getCheckedChannel() { + return checkedChannel; + } + + public void setCheckedChannel(int checkedChannel) { + this.checkedChannel = checkedChannel; + } + + public String getPlayToken() { + return playToken == null ? "" : playToken; + } + + public void setPlayToken(String playToken) { + this.playToken = playToken == null ? "" : playToken; + } + + public int getEncryptMode() { + return encryptMode; + } + + public void setEncryptMode(int encryptMode) { + this.encryptMode = encryptMode; + } + + public String getChannelNum() { + return channelNum == null ? "" : channelNum; + } + + public void setChannelNum(String channelNum) { + this.channelNum = channelNum == null ? "" : channelNum; + } + + public String getPermission() { + return permission == null ? "" : permission; + } + + public void setPermission(String permission) { + this.permission = permission == null ? "" : permission; + } + + public int getDeviceSource() { + return deviceSource; + } + + public void setDeviceSource(int deviceSource) { + this.deviceSource = deviceSource; + } + + public List getChannels() { + if (channels == null) { + return new ArrayList<>(); + } + return channels; + } + + public void setChannels(List channels) { + this.channels = channels; + } + + public List getAplist() { + if (aplist == null) { + return new ArrayList<>(); + } + return aplist; + } + + public void setAplist(List aplist) { + this.aplist = aplist; + } + + public static class ChannelsBean implements Serializable { + public String channelId; + public String deviceId; + public String channelName; + public String ability; + public String status; + public String picUrl; + public String remindStatus; + public String cameraStatus; + public String storageStrategyStatus; + public String shareStatus; + public String shareFunctions; + public String permission; +// public List resolutions = new ArrayList<>(); + + @Override + public String toString() { + return "ChannelsBean{" + + "channelId='" + channelId + '\'' + + ", deviceId='" + deviceId + '\'' + + ", channelName='" + channelName + '\'' + + ", ability='" + ability + '\'' + + ", status='" + status + '\'' + + ", picUrl='" + picUrl + '\'' + + ", remindStatus='" + remindStatus + '\'' + + ", cameraStatus='" + cameraStatus + '\'' + + ", storageStrategyStatus='" + storageStrategyStatus + '\'' + + ", shareStatus='" + shareStatus + '\'' + + ", shareFunctions='" + shareFunctions + '\'' + + ", permission='" + permission + '\'' + + '}'; + } + + public String getChannelId() { + return channelId == null ? "" : channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId == null ? "" : channelId; + } + + public String getDeviceId() { + return deviceId == null ? "" : deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId == null ? "" : deviceId; + } + + public String getChannelName() { + return channelName == null ? "" : channelName; + } + + public void setChannelName(String channelName) { + this.channelName = channelName == null ? "" : channelName; + } + + public String getAbility() { + return ability == null ? "" : ability; + } + + public void setAbility(String ability) { + this.ability = ability == null ? "" : ability; + } + + public String getStatus() { + return status == null ? "" : status; + } + + public void setStatus(String status) { + this.status = status == null ? "" : status; + } + + public String getPicUrl() { + return picUrl == null ? "" : picUrl; + } + + public void setPicUrl(String picUrl) { + this.picUrl = picUrl == null ? "" : picUrl; + } + + public String getRemindStatus() { + return remindStatus == null ? "" : remindStatus; + } + + public void setRemindStatus(String remindStatus) { + this.remindStatus = remindStatus == null ? "" : remindStatus; + } + + public String getCameraStatus() { + return cameraStatus == null ? "" : cameraStatus; + } + + public void setCameraStatus(String cameraStatus) { + this.cameraStatus = cameraStatus == null ? "" : cameraStatus; + } + + public String getStorageStrategyStatus() { + return storageStrategyStatus == null ? "" : storageStrategyStatus; + } + + public void setStorageStrategyStatus(String storageStrategyStatus) { + this.storageStrategyStatus = storageStrategyStatus == null ? "" : storageStrategyStatus; + } + + public String getShareStatus() { + return shareStatus == null ? "" : shareStatus; + } + + public void setShareStatus(String shareStatus) { + this.shareStatus = shareStatus == null ? "" : shareStatus; + } + + public String getShareFunctions() { + return shareFunctions == null ? "" : shareFunctions; + } + + public void setShareFunctions(String shareFunctions) { + this.shareFunctions = shareFunctions == null ? "" : shareFunctions; + } + + public String getPermission() { + return permission == null ? "" : permission; + } + + public void setPermission(String permission) { + this.permission = permission == null ? "" : permission; + } + + /*public List getResolutions() { + if (resolutions == null) { + return new ArrayList<>(); + } + return resolutions; + } + + public void setResolutions(List resolutions) { + this.resolutions = resolutions; + }*/ + + public static class ResolutionBean implements Serializable { + public String name; + public int imageSize; + public int streamType; + + public ResolutionBean(String name, int imageSize, int streamType) { + this.name = name; + this.imageSize = imageSize; + this.streamType = streamType; + } + + @Override + public String toString() { + return "ResolutionBean{" + + "name='" + name + '\'' + + ", imageSize=" + imageSize + + ", streamType=" + streamType + + '}'; + } + } + } + + + public static class AplistBean implements Serializable { + public String apId; + public String apName; + public String apType; + public String apModel; + public String ioType; + public String apVersion; + public String apStatus; + public String apEnable; + public String apCapacity; + + @Override + public String toString() { + return "AplistBean{" + + "apId='" + apId + '\'' + + ", apName='" + apName + '\'' + + ", apType='" + apType + '\'' + + ", apModel='" + apModel + '\'' + + ", ioType='" + ioType + '\'' + + ", apVersion='" + apVersion + '\'' + + ", apStatus='" + apStatus + '\'' + + ", apEnable='" + apEnable + '\'' + + ", apCapacity='" + apCapacity + '\'' + + '}'; + } + } + } + } + +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceListData.java b/app/src/main/java/com/common/openapi/entity/DeviceListData.java new file mode 100644 index 0000000..1cf2d97 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceListData.java @@ -0,0 +1,100 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.List; + +public class DeviceListData implements Serializable{ + public DeviceListData.RequestData data = new DeviceListData.RequestData(); + + public static class Response { + public DeviceListData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), DeviceListData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public String count; + public List deviceList; + + @Override + public String toString() { + return "ResponseData{" + + "count='" + count + '\'' + + ", deviceList=" + deviceList + + '}'; + } + + public static class DeviceListElement implements Serializable { + public String bindId; + public String deviceId; + public List channels; + public List aplist; + + @Override + public String toString() { + return "DeviceListElement{" + + "bindId='" + bindId + '\'' + + ", deviceId='" + deviceId + '\'' + + ", channels=" + channels + + ", aplist=" + aplist + + '}'; + } + + public static class ChannelsElement implements Serializable { + public String channelName; + public String channelId; + + @Override + public String toString() { + return "ChannelsElement{" + + "channelName='" + channelName + '\'' + + ", channelId='" + channelId + '\'' + + '}'; + } + } + + public static class AplistElement implements Serializable { + public String apId; + public String apName; + public String apType; + + @Override + public String toString() { + return "AplistElement{" + + "apId='" + apId + '\'' + + ", apName='" + apName + '\'' + + ", apType='" + apType + '\'' + + '}'; + } + } + } + + } + + public static class RequestData implements Serializable { + public String token; + public String limit="8"; + public String type="bindAndShare"; + public String needApInfo="false"; + public long baseBindId=-1; + public long openBindId=-1; + + @Override + public String toString() { + return "RequestData{" + + "token='" + token + '\'' + + ", limit='" + limit + '\'' + + ", type='" + type + '\'' + + ", needApInfo='" + needApInfo + '\'' + + ", baseBindId=" + baseBindId + + ", openBindId=" + openBindId + + '}'; + } + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceLocalCacheData.java b/app/src/main/java/com/common/openapi/entity/DeviceLocalCacheData.java new file mode 100644 index 0000000..72b2585 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceLocalCacheData.java @@ -0,0 +1,70 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class DeviceLocalCacheData implements Serializable { + private long cacheId; + private String deviceId; + private String deviceName; + private String channelId; + private String channelName; + private String picPath; + private long creationTime; + private long modifyTime; + + public long getCacheId() { + return cacheId; + } + + public void setCacheId(long cacheId) { + this.cacheId = cacheId; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public String getChannelName() { + return channelName; + } + + public void setChannelName(String channelName) { + this.channelName = channelName; + } + + public String getPicPath() { + return picPath; + } + + public void setPicPath(String picPath) { + this.picPath = picPath; + } + + public void setCreationTime(long creationTime) { + this.creationTime = creationTime; + } + + public void setModifyTime(long modifyTime) { + this.modifyTime = modifyTime; + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceModifyNameData.java b/app/src/main/java/com/common/openapi/entity/DeviceModifyNameData.java new file mode 100644 index 0000000..cd8d993 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceModifyNameData.java @@ -0,0 +1,46 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class DeviceModifyNameData implements Serializable { + public DeviceModifyNameData.RequestData data = new DeviceModifyNameData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId; + public String name; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceUnBindData.java b/app/src/main/java/com/common/openapi/entity/DeviceUnBindData.java new file mode 100644 index 0000000..8af1dc8 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceUnBindData.java @@ -0,0 +1,13 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class DeviceUnBindData implements Serializable { + public DeviceUnBindData.RequestData data = new DeviceUnBindData.RequestData(); + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + + } +} diff --git a/app/src/main/java/com/common/openapi/entity/DeviceVersionListData.java b/app/src/main/java/com/common/openapi/entity/DeviceVersionListData.java new file mode 100644 index 0000000..8e5221f --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/DeviceVersionListData.java @@ -0,0 +1,124 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.List; + +public class DeviceVersionListData implements Serializable { + public DeviceVersionListData.RequestData data = new DeviceVersionListData.RequestData(); + + public static class Response { + public DeviceVersionListData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), DeviceVersionListData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public String count; + public List deviceVersionList; + + public String getCount() { + return count; + } + + public void setCount(String count) { + this.count = count; + } + + public static class DeviceVersionListBean implements Serializable { + public boolean canBeUpgrade; + public String deviceId; + public String version; + public UpgradeInfoBean upgradeInfo; + + public boolean isCanBeUpgrade() { + return canBeUpgrade; + } + + public void setCanBeUpgrade(boolean canBeUpgrade) { + this.canBeUpgrade = canBeUpgrade; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public UpgradeInfoBean getUpgradeInfo() { + return upgradeInfo; + } + + public void setUpgradeInfo(UpgradeInfoBean upgradeInfo) { + this.upgradeInfo = upgradeInfo; + } + + public static class UpgradeInfoBean implements Serializable { + public String version; + public String description; + public String packageUrl; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getPackageUrl() { + return packageUrl; + } + + public void setPackageUrl(String packageUrl) { + this.packageUrl = packageUrl; + } + } + } + } + + public static class RequestData implements Serializable { + public String token; + public String deviceIds; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getDeviceIds() { + return deviceIds; + } + + public void setDeviceIds(String deviceIds) { + this.deviceIds = deviceIds; + } + } + +} diff --git a/app/src/main/java/com/common/openapi/entity/LocalRecordsData.java b/app/src/main/java/com/common/openapi/entity/LocalRecordsData.java new file mode 100644 index 0000000..a7d1650 --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/LocalRecordsData.java @@ -0,0 +1,44 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.List; + +public class LocalRecordsData implements Serializable { + public LocalRecordsData.RequestData data = new LocalRecordsData.RequestData(); + + public static class Response { + public LocalRecordsData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), LocalRecordsData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public List records; + + public static class RecordsBean implements Serializable { + public String recordId; + public long fileLength; + public String channelID; + public String beginTime; + public String endTime; + public String type; + } + } + + public static class RequestData implements Serializable { + public String token; + public String deviceId; + public String channelId = "0"; + public String beginTime; + public String endTime; + public String type; + public String queryRange; + + } +} diff --git a/app/src/main/java/com/common/openapi/entity/RecordListData.java b/app/src/main/java/com/common/openapi/entity/RecordListData.java new file mode 100644 index 0000000..e0ad44d --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/RecordListData.java @@ -0,0 +1,12 @@ +package com.common.openapi.entity; + +import com.lechange.demo.adapter.DeviceInnerRecordListAdapter; + +import java.io.Serializable; +import java.util.List; + +public class RecordListData implements Serializable { + public String period; + public List recordsData; + public DeviceInnerRecordListAdapter deviceInnerRecordListAdapters; +} diff --git a/app/src/main/java/com/common/openapi/entity/RecordsData.java b/app/src/main/java/com/common/openapi/entity/RecordsData.java new file mode 100644 index 0000000..e1c52ff --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/RecordsData.java @@ -0,0 +1,52 @@ +package com.common.openapi.entity; + +import java.io.Serializable; + +public class RecordsData implements Serializable { + //0 云录像 1设备录像 + public int recordType; + //通用字段 + public String recordId; + public String beginTime; + public String endTime; + public String type; + public boolean check; + //设备录像 + public long fileLength; + public String channelID; + //云录像 + public String deviceId; + public String channelId; + public String size; + public String thumbUrl; + public int encryptMode; + public String recordRegionId; + + public static RecordsData parseCloudData(CloudRecordsData.ResponseData.RecordsBean recordsBean){ + RecordsData recordsData=new RecordsData(); + recordsData.recordType=0; + recordsData.recordId=recordsBean.recordId; + recordsData.beginTime=recordsBean.beginTime; + recordsData.endTime=recordsBean.endTime; + recordsData.type=recordsBean.type; + recordsData.deviceId=recordsBean.deviceId; + recordsData.channelId=recordsBean.channelId; + recordsData.size=recordsBean.size; + recordsData.thumbUrl=recordsBean.thumbUrl; + recordsData.encryptMode=recordsBean.encryptMode; + recordsData.recordRegionId=recordsBean.recordRegionId; + return recordsData; + } + + public static RecordsData parseLocalData(LocalRecordsData.ResponseData.RecordsBean recordsBean){ + RecordsData recordsData=new RecordsData(); + recordsData.recordType=1; + recordsData.recordId=recordsBean.recordId; + recordsData.beginTime=recordsBean.beginTime; + recordsData.endTime=recordsBean.endTime; + recordsData.type=recordsBean.type; + recordsData.fileLength=recordsBean.fileLength; + recordsData.channelID=recordsBean.channelID; + return recordsData; + } +} diff --git a/app/src/main/java/com/common/openapi/entity/SubAccountDeviceData.java b/app/src/main/java/com/common/openapi/entity/SubAccountDeviceData.java new file mode 100644 index 0000000..5effb7b --- /dev/null +++ b/app/src/main/java/com/common/openapi/entity/SubAccountDeviceData.java @@ -0,0 +1,37 @@ +package com.common.openapi.entity; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; + +import java.io.Serializable; +import java.util.List; + +public class SubAccountDeviceData implements Serializable { + + public static class Response { + public SubAccountDeviceData.ResponseData data; + + public void parseData(JsonObject json) { + Gson gson = new Gson(); + this.data = gson.fromJson(json.toString(), SubAccountDeviceData.ResponseData.class); + } + } + + public static class ResponseData implements Serializable { + public int pageNo; + public int pageSize; + public int total; + List deviceLists; + + public static class DeviceList implements Serializable{ + public String deviceId; + public String permission; + List channelLists; + } + + public static class ChannelList implements Serializable{ + public String channelId; + public String permission; + } + } +} diff --git a/app/src/main/java/com/ds/remote/Device.java b/app/src/main/java/com/ds/remote/Device.java new file mode 100644 index 0000000..a60baf6 --- /dev/null +++ b/app/src/main/java/com/ds/remote/Device.java @@ -0,0 +1,241 @@ +package com.ds.remote; + +import android.content.Context; +import android.content.res.AssetManager; + +public class Device { + + //设备号定义 + public static enum DEVICE_TYPE { //设备类型 + C_AUX_DEVICE, //国外 + C_DVB_DEVICE, //国内DVB + C_STB_DEVICE, //国外机顶盒 + C_ATV_DEVICE, //国内TV,或东南亚TV + C_CTV_DEVICE, //国外TV + C_DVD_DEVICE, //国外DVD + C_ARC_DEVICE // + } + + //每个设备的最大码组数定义 + public static int C_AUX_GROUP_MAX = 501; + public static int C_DVB_GROUP_MAX = 372; + public static int C_STB_GROUP_MAX = 213; + public static int C_ATV_GROUP_MAX = 550; + public static int C_CTV_GROUP_MAX = 360; + public static int C_DVD_GROUP_MAX = 315; + public static int C_ARC_GROUP_MAX = 1000; + + //通信命令定义 + public static int CMD_URC_INDEX = 0x01; //发送 URC 的设备号、码组号、键值给IRIC,并启动IRIC发送内部码 + public static int CMD_ARC_INDEX = 0x02; //发送 ARC 的码组号、空调状态变量给IRIC,并启动IRIC发送内部空调码 + public static int CMD_URC_FID = 0x03; //发送 URC 的数据文件号和键值给IRIC,并启动IRIC从MPU读取数据并发送红外码 + public static int CMD_ARC_FID = 0x04; //发送 ARC 的数据文件号和空调状态变量给IRIC,并启动IRIC从MPU读取数据并发送红外码 + public static int CMD_FILE_DATA = 0x05; //将在数据文件中读到的数据发送给IRIC(与IRIC向MPU发送的命令CMD_READ_FILE对应) + public static int CMD_LEN_START = 0x06; //发送 学习命令给IRIC,并启动IRIC进入学习状态(与IRIC向MPU发送学习数据的命令CMD_LEN_DATA对应) + public static int CMD_LEN_DATA = 0x07; //发送 LRC数据给IRIC,并启动IRIC发送该数据(与IRIC向MPU发送学习数据的命令CMD_LEN_DATA相同) + //public static int CMD_READ_FILE = 0x80 //发送读数据文件命令给MPU,MPU根据文件号FILEID,偏移地址ADDR_OFS,需要读取的数据个数DataCnt,将数据取出后发给IRIC + public static int CMD_ARC_VAR = 0x0A; //发送 检测IRIC程序版本命令给IRIC,并启动IRIC将版本号发给MPU(与IRIC向MPU发送版本信息的命令CMD_IRIC_VER相同) + public static int CMD_IRIC_VER = 0x08; //IRIC将修正后的空调状态变量发给MPU,MPU收到后覆盖原来的空调状态变量(与MPU向IRIC发送空调命令CMD_ARC_FID,CMD_ARC_INDEX对应) + public static int CMD_ARC_LEN_START = 0x0c; //空调学习命令 + public static int CMD_ARC_LEN_DATA = 0x0d; //发空调学习数据命令 + + + // + public static int ADR_VAR_LEN = 14; + + /************** + * 学习返回状态 + ****************************************/ + public static int NO_LEARN_DATA = 0; + //public static int LEN_FLAS = 0xff + public static int LEN_DOING = 0x01; + public static int LEN_OK = 0x02; + public static int LEN_ERROR = 0x03; + + + //================================================================================================ + /* 空调变量数组 ADR_VAR[]说明 */ + public static int ADR_VAR_START = 0x00; //空调变量的存放位置(需要根据程序修改) + public static int ADR_MODE = 0; //模式------------》变化范围"0~4"对应模式详见"模式常量"定义 + public static int ADR_TMP = 1; //温度------------》变化范围"0~16"对应温度"16~32" + public static int ADR_FANLEV = 2; //风量------------》变化范围"0~3"对应风量"自动,低,中,高" + public static int ADR_FANDIR = 3; //风向------------》按自动风向键清0,按手动风向键加1(在1~8之间变化)(用于自动风向和手动风向数据在同一位置) + public static int ADR_AFANDIR = 4; //自动风向----》按自动风向键改变(在0~8之间变化),按手动风向键不变(用于自动风向和手动风向数据在不同位置) + public static int ADR_MFANDIR = 5; //手动风向----》按手动风向键改变(在0~8之间变化),按自动风向键不变(用于自动风向和手动风向数据在不同位置,或只有一个风向键的时候) + public static int ADR_CKHOUR = 6; //时钟小时 + public static int ADR_TIMEON = 7; //定开时间(小时)----》变化范围"0~12"对应定开时间"0~12"小时(只要用于定开定关数据在不同位置的时候) + public static int ADR_TIMEOFF = 8; //定关时间(小时)----》变化范围"0~12"对应定关时间"0~12"小时(只要用于定开定关数据在不同位置的时候) + public static int ADR_KEYVAL = 9; //键值------------》详见"按键常量"定义,空键:0FFH + public static int ADR_SYSFLAG = 10; //功能标志---》详见"功能标志"常量定义 + public static int ADR_TMSTATE7 = 11; //定时状态(7种),详见"定时状态常量(7态)" + public static int ADR_TMSTATE3 = 12; //定时状态(3种),详见"定时状态常量(3态)" + //ADR_TM_MIN EQU 13 //定时分钟 + public static int ADR_CKMIN = 13; //时钟分钟 + //#define ADR_TMON_10MINS 14 //定时开分钟 + //#define ADR_TMOFF_10MINS 15 //定时关分钟 + + + /*ADR_SYSFLAG(功能标志)常量定义*/ + public static int SYSFLAG_POWER = 0x01; //00000001B //开关机标志----》开关=1,关机=0 + public static int ADSF_POWER = 0; //开关机标志位置 + public static int SYSFLAG_SLEEP = 0x02; //00000010B //睡眠标志--------》睡眠开=1,睡眠关=0 + public static int ADSF_SLEEP = 1; //睡眠标志位置 + public static int SYSFLAG_HEAT = 0x04; //00000100B //电辅热标志----》电辅热开=1,电辅热关=0 + public static int ADSF_HEAT = 2; //电辅热标志位置 + public static int SYSFLAG_TIME = 0x08; //00001000B //定时标志-------》 有定时= 1,没有定时 = 0 + public static int ADSF_TIME = 3; //定时标志位置 + public static int SYSFLAG_STRONG = 0x10; //00010000B //强力标志-------》 强力开= 1,强力关 = 0 + public static int ADSF_STRONG = 4; //强力标志位置 + public static int SYSFLAG_LIGHT = 0x20; //00100000B //灯光标志-------》 灯光开= 1,灯光关 = 0 + public static int ADSF_LIGHT = 5; //灯光标志位置 + public static int SYSFLAG_AIRCLEAR = 0x40; //01000000B //空清/净化/健康标志-------》 空清/净化/健康开= 1,空清/净化/健康关 = 0 + public static int ADSF_AIRCLEAR = 6; //空清/净化/健康标志位置 + public static int SYSFLAG_ECONOMIC = 0x80; //10000000B //经济标志-------》 经济开= 1,经济关 = 0 + public static int ADSF_ECONOMIC = 7; //经济标志位置 + + //返回值 + public static int SEND_CODE = 0x01; //按键有发送发码命令 + public static int SEND_END = 0x11; //发码结束 + + public static int LENTIMEOUT = 0x80; + public static int UPDATE_ARC_DISP = 0xF0; //Tony 添加:用户ARC屏幕更新 + + + public static String urc_excode_file = "urc_excode.Bin"; + public static String arc_excode_file = "arc_excode.bin"; + + + //操作 + public static enum OPERATION { + HB_IOCTL_INIT, //初始化,应用程序打开时,调用此函数 + HB_IOCTL_TIMER100, //定时器100ms到时,调用此函数 + HB_IOCTL_TIMER500, //RTC定时器500ms + HB_IOCTL_CREATE_IRDevice, //新建红外设备(收藏红外设备时调用) + //建立对应红外设备 数据 + //TV(设备类型),品牌,码组索引,学习数据 + //ARC:空调相关变量 + HB_IOCTL_Delete_Device, //删除红外设备(删除收藏记录时调用) + HB_IOCTL_KeyDn, //设备按键按下,调用此函数发码 + HB_IOCTL_KeyUp, + //序根据当前设备值,红外设备号,调用对应文件中对应数据,查表或运算后发码 + HB_IOCTL_Change_Device, // 更改设备类型, + //应用层改变设备类型,红外设备,品牌,或者码组时,需要调用此函数更新红外系统内部变量 + HB_IOCTL_IRRX_BEGIN, //程序发码给HB1682 ,启动学习; 具体查询学习是否完成,在定时器中处理; + HB_IOCTL_ARC_IRRX, //启动空调码学习 + HB_IOCTL_IRRX_END, // 在学习过程中,用户可以取消学习,则应用层需要调用此函数终止学习; + HB_IOCTL_Send_LenCode, //发送URC学习的数据 + HB_IOCTL_Send_ArcLenCode, //发送ARC学习码 + HB_IOCTL_RX_ICVER, //读取IC 程序版本 + HB_IOCTL_RX_PRO, //串口接收数据处理 + HB_IOCTL_SEND_Search, //搜索发码 + } //ev_ioctl_e + + //--------------------------------------------------------- + public static int m_group; //码组 + public static int m_device; //设备类型 + public static int m_keyval; //键值 + public static int m_arc_group; //空调码组 + public static int m_arc_group_1; //空调码组1 + public static int m_arc_group_2; //空调码组2 + public static int m_arc_group_3; //空调码组3 + + public static DEVICE_TYPE m_device_type; //当前设备类型(这个是类型,m_device是序号) + public static boolean b_learn_mode; //是否在学习模式 + public static boolean b_recognition_mode; //是否在自动识别模式 + + public static int m_favorite_id; //收藏夹ID + + //用于传递数据 + public static DEVICE_TYPE tmp_device_type; //临时设备类型 + public static String tmp_brand; //临时品牌 + public static String tmp_group_list; //临时码组列表 + public static boolean tmp_force_exit; //强制退出页面 + + + public static String get_title(Context context, DEVICE_TYPE device_type) { + if (device_type == DEVICE_TYPE.C_ATV_DEVICE) { + return Language.get(context, "atv"); + } else if (device_type == DEVICE_TYPE.C_STB_DEVICE) { + return Language.get(context, "stb"); + } else if (device_type == DEVICE_TYPE.C_ARC_DEVICE) { + return Language.get(context, "air"); + } else if (device_type == DEVICE_TYPE.C_AUX_DEVICE) { + return Language.get(context, "aux"); + } else if (device_type == DEVICE_TYPE.C_CTV_DEVICE) { + return Language.get(context, "ctv"); + } else if (device_type == DEVICE_TYPE.C_DVB_DEVICE) { + return Language.get(context, "dvb"); + } else if (device_type == DEVICE_TYPE.C_DVD_DEVICE) { + return Language.get(context, "dvd"); + } + return ""; + } + + public static String get_title(Context context, int device_type) { + if (device_type == DEVICE_TYPE.C_ATV_DEVICE.ordinal()) { + return Language.get(context, "atv"); + } else if (device_type == DEVICE_TYPE.C_STB_DEVICE.ordinal()) { + return Language.get(context, "stb"); + } else if (device_type == DEVICE_TYPE.C_ARC_DEVICE.ordinal()) { + return Language.get(context, "air"); + } else if (device_type == DEVICE_TYPE.C_AUX_DEVICE.ordinal()) { + return Language.get(context, "aux"); + } else if (device_type == DEVICE_TYPE.C_CTV_DEVICE.ordinal()) { + return Language.get(context, "ctv"); + } else if (device_type == DEVICE_TYPE.C_DVB_DEVICE.ordinal()) { + return Language.get(context, "dvb"); + } else if (device_type == DEVICE_TYPE.C_DVD_DEVICE.ordinal()) { + return Language.get(context, "dvd"); + } + return ""; + } + + public static tagSerialPortRx get_RemoteRxData() { + short[] rx = new short[3]; + rx = Device.HBioctlGetRemoteRxData(); + tagSerialPortRx RemoteRxData = new tagSerialPortRx(); + // RemoteRxData.RxBuf = BytesUtil.hexStringToBytes("168cd02333000011012c026500250021002500c504250000002500ffffffffffffffffffffffff0122211122222222222222121222212122123122121222222212222222222222211114000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d4c08"); + // RemoteRxData.RxBuf = BytesUtil.hexStringToBytes("2333000011012c026500250021002500c504250000002500ffffffffffffffffffffffff0122211122222222222222121222212122123122121222222212222222222222211114000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d"); + RemoteRxData.RemoteCMD = (byte) rx[0]; + RemoteRxData.wRxLen = rx[1]; + RemoteRxData.wRxPos = rx[2]; + return RemoteRxData; + } + + public static DEVICE_TYPE get_default_device_type() { + if (Public.group_library == Public.GROUP_LIBRARY.america) { + return Public.DEFAULT_DEVICE_TYPE_AMERICA; + } else { + return Public.DEFAULT_DEVICE_TYPE_ASIA; + } + } + + public static void set_default_device() { + Device.m_device = get_default_device_type().ordinal(); + Device.m_group = 0; + Device.m_arc_group = 0; + Device.m_arc_group_1 = 0; + Device.m_arc_group_2 = 0; + Device.m_arc_group_3 = 0; + Device.m_favorite_id = 0; + } + + // TODO: 2017/7/3 + public native static int HBioctlGetArcGroupNum(int[] GroupNumber); + + public native static int HBioctl(int cmd, Object arg); + + public native static byte[] HBioctlGetAdrVar(); + + public native static int HBioctlSetAdrVar(Object arg); + + public native static byte[] HBioctlGetArDispData(); + + public native static short[] HBioctlGetRemoteRxData(); + + public native static int HBFILEOpen(AssetManager ass, String filename, int type); + + public native static int HBFILEClose(); +} + + diff --git a/app/src/main/java/com/ds/remote/Language.java b/app/src/main/java/com/ds/remote/Language.java new file mode 100644 index 0000000..ec959ae --- /dev/null +++ b/app/src/main/java/com/ds/remote/Language.java @@ -0,0 +1,12 @@ +package com.ds.remote; + +import android.content.Context; +import android.content.res.Resources; + +public class Language { + public static String get(Context context, String lang) { + Public.LANGUAGE l = Settings.get_language(context); + Resources res = context.getResources(); + return ""; + } +} diff --git a/app/src/main/java/com/ds/remote/Public.java b/app/src/main/java/com/ds/remote/Public.java new file mode 100644 index 0000000..769b012 --- /dev/null +++ b/app/src/main/java/com/ds/remote/Public.java @@ -0,0 +1,178 @@ +package com.ds.remote; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.util.Log; + +import java.util.Calendar; + +public class Public { + //串口服务 + public static SerialPortService serial_port_service; + //串口名称 + //public static final String ComDefaultName = "/dev/s3c2410_serial3"; //Android 开发板靠边第一个串口 + public static final String ComDefaultName = "/dev/ttyS1"; //Android 开发板靠边第一个串口 + private static String ComName; + //串口波特率 + public static final int ComBaudrate = 19200; + + //数据库 + public static final String db_name = "remote.sqlite"; + public static final String table_name_favorite = "favorite"; + public static final String table_name_learn_code = "learn_code"; + + //Message + public static final int MESSAGE_LEARN_BUTTON = 1; //更新学习的按钮 + public static final int MESSAGE_UPDATE_ARC_DISPLAY = 2; //更新arc显示 + public static final int MESSAGE_START_LEARN = 3; //开始学习 + public static final int MESSAGE_LEARN_TIMEOUT = 4; //学习超时 + public static final int MESSAGE_CHANGE_GROUP = 5; //变换码组 + public static final int MESSAGE_LEARN_SUCCEEDED = 6; //学习成功 + public static final int MESSAGE_LEARN_FAILED = 7; //学习失败 + public static final int MESSAGE_ON_RECEIVED = 8; //串口接收数据 + public static final int MESSAGE_SHOW_SIGNAL_FALG = 9; //显示发码标志 + public static final int MESSAGE_HIDE_SIGNAL_FALG = 10; //隐藏发码标志 + public static final int MESSAGE_AUTO_RECOGNITION = 11; //空调学习 + public static final int MESSAGE_RECOGNITION_TIMEOUT = 12; //识别超时 + public static final int MESSAGE_RECOGNITION_SUCCEEDED = 13; //识别超时 + public static final int MESSAGE_RECOGNITION_FAILED = 14; //学习失败 + + //常量 + public static final int REQUEST_LEARN = 0x01; + public static final int REQUEST_RECOGNITION = 0x02; + public static final int REQUEST_GROUP = 0x03; + + //码库 + public static enum GROUP_LIBRARY { + asia, //亚洲 + america //美洲/欧洲 + } + + //语言 + public static enum LANGUAGE { + simple_chinese, //中文 + english //英文 + } + + public static GROUP_LIBRARY group_library; + public static LANGUAGE language; + + + //设置 + public static final String PREFS_NAME = "HbgRemote.Prefs"; + public static final String SETTING_GROUP_LIBRARY = "SETTING_GROUP_LIBRARY"; + public static final String SETTING_LANGUAGE = "SETTING_LANGUAGE"; + + //默认:亚洲码库,中文界面 + public static final GROUP_LIBRARY DEFAULT_GROUP_LIBRARY = GROUP_LIBRARY.asia; + public static final LANGUAGE DEFAULT_LANGUAGE = LANGUAGE.simple_chinese; + + public static final String SETTING_FAVORITE_ID = "SETTING_FAVORITE_ID"; + public static final String SETTING_LAST_DEVICE = "SETTING_DEVICE"; + public static final String SETTING_LAST_GROUP = "SETTING_LAST_DEIVCE"; + public static final String SETTING_IS_FIRST = "SETTING_IS_FIRST"; + + //默认设备 + public static final Device.DEVICE_TYPE DEFAULT_DEVICE_TYPE_ASIA = Device.DEVICE_TYPE.C_ATV_DEVICE; + public static final Device.DEVICE_TYPE DEFAULT_DEVICE_TYPE_AMERICA = Device.DEVICE_TYPE.C_CTV_DEVICE; + + public static boolean b_require_reload; //是否需要重新加载页面 + + + ////////////////////////// + public static void ShowAlert(String title, String msg, Context context) { + new AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(title) + .setMessage(msg) + .setCancelable(false) + .setNegativeButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }) + .show(); + } + + public static void ShowInfo(String title, String msg, Context context) { + new AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_info) + .setTitle(title) + .setMessage(msg) + .setCancelable(false) + .setNegativeButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }) + .show(); + } + + public static String get_date() { + int mYear; + int mMonth; + int mDay; + + final Calendar c = Calendar.getInstance(); + + mYear = c.get(Calendar.YEAR); + mMonth = c.get(Calendar.MONTH) + 1; + mDay = c.get(Calendar.DAY_OF_MONTH); + + String result = String.format("%04d-%02d-%02d", mYear, mMonth, mDay); + return result; + } + + public static String get_date_time() { + int mYear; + int mMonth; + int mDay; + int mHour; + int mMinute; + int mSecond; + + final Calendar c = Calendar.getInstance(); + + mYear = c.get(Calendar.YEAR); + mMonth = c.get(Calendar.MONTH) + 1; + mDay = c.get(Calendar.DAY_OF_MONTH); + mHour = c.get(Calendar.HOUR_OF_DAY); + mMinute = c.get(Calendar.MINUTE); + mSecond = c.get(Calendar.SECOND); + + String result = String.format("%04d-%02d-%02d %02d:%02d:%02d", + mYear, mMonth, mDay, mHour, mMinute, mSecond); + return result; + } + + public static int get_current_hour() { + final Calendar c = Calendar.getInstance(); + return c.get(Calendar.HOUR_OF_DAY); + } + + public static int get_current_minute() { + final Calendar c = Calendar.getInstance(); + return c.get(Calendar.MINUTE); + } + + public static void debug(byte[] buf, int len) { + StringBuilder str = new StringBuilder(); + for (int i=0; i 0) { + // Send the obtained bytes to the UI Activity + mHandler.obtainMessage(Public.MESSAGE_ON_RECEIVED, size, -1, buffer).sendToTarget(); + } + } catch (IOException e) { + e.printStackTrace(); + return; + } + } + } + } + + +} diff --git a/app/src/main/java/com/ds/remote/Settings.java b/app/src/main/java/com/ds/remote/Settings.java new file mode 100644 index 0000000..f17ccf5 --- /dev/null +++ b/app/src/main/java/com/ds/remote/Settings.java @@ -0,0 +1,97 @@ +package com.ds.remote; + +import android.content.Context; +import android.content.SharedPreferences; + +public class Settings { + public static Public.GROUP_LIBRARY get_group_library(Context context) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + int lang = settings.getInt(Public.SETTING_GROUP_LIBRARY, Public.DEFAULT_GROUP_LIBRARY.ordinal()); + if (lang == 0) { + return Public.GROUP_LIBRARY.asia; + } else { + return Public.GROUP_LIBRARY.america; + } + } + + public static Public.LANGUAGE get_language(Context context) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + int lang = settings.getInt(Public.SETTING_LANGUAGE, Public.DEFAULT_GROUP_LIBRARY.ordinal()); + if (lang == 0) { + return Public.LANGUAGE.simple_chinese; + } else { + return Public.LANGUAGE.english; + } + } + + public static Remote get_last_device(Context context) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + Remote remote = new Remote(); + int first = settings.getInt(Public.SETTING_IS_FIRST, 0); + if (first == 0) { + remote.favorite_id = 0; + remote.device = Device.get_default_device_type().ordinal(); + remote.group = 0; + set_last_device(context, remote); + } else { + remote.favorite_id = settings.getInt(Public.SETTING_FAVORITE_ID, 0); + remote.device = settings.getInt(Public.SETTING_LAST_DEVICE, 0); + remote.group = settings.getInt(Public.SETTING_LAST_GROUP, 0); + } + return remote; + } + + public static void set_group_library(Context context, Public.GROUP_LIBRARY gl) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(Public.SETTING_GROUP_LIBRARY, gl.ordinal()); + editor.commit(); + + } + + public static void set_language(Context context, Public.LANGUAGE lang) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(Public.SETTING_LANGUAGE, lang.ordinal()); + editor.commit(); + } + + public static void set_last_device(Context context, Remote ld) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(Public.SETTING_IS_FIRST, 0x1234); + editor.putInt(Public.SETTING_FAVORITE_ID, ld.favorite_id); + editor.putInt(Public.SETTING_LAST_DEVICE, ld.device); + editor.putInt(Public.SETTING_LAST_GROUP, ld.group); + editor.commit(); + } + + public static void delete_all_settings(Context context) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + settings.edit().clear().commit(); + } + + public static void set_adr_var(Context context, int favorite_id, String adr_var) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + String key = String.format("ADR_VAR_:%d", favorite_id); + editor.putString(key, adr_var); + editor.commit(); + } + + public static String get_adr_var(Context context, int favorite_id) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + String key = String.format("ADR_VAR_:%d", favorite_id); + String var = settings.getString(key, ""); + return var; + } + + public static void delete_adr_var(Context context, int favorite_id) { + SharedPreferences settings = context.getSharedPreferences(Public.PREFS_NAME, 0); + SharedPreferences.Editor editor = settings.edit(); + String key = String.format("ADR_VAR_:%d", favorite_id); + editor.putString(key, ""); //清空,就等于删掉了 + editor.commit(); + } + +} diff --git a/app/src/main/java/com/ds/remote/tagSerialPortRx.java b/app/src/main/java/com/ds/remote/tagSerialPortRx.java new file mode 100644 index 0000000..ac080a4 --- /dev/null +++ b/app/src/main/java/com/ds/remote/tagSerialPortRx.java @@ -0,0 +1,17 @@ +package com.ds.remote; + +public class tagSerialPortRx { + byte RemoteCMD; + public byte RxDone; + public byte[] RxBuf; + public short wRxPos; + public short wRxLen; + + public tagSerialPortRx() { + RxBuf = new byte[256]; + RemoteCMD = 0; + RxDone = 0; + wRxPos = 0; + wRxLen = 0; + } +} diff --git a/app/src/main/java/com/ds/remote/type_CUR_group.java b/app/src/main/java/com/ds/remote/type_CUR_group.java new file mode 100644 index 0000000..d78c3a3 --- /dev/null +++ b/app/src/main/java/com/ds/remote/type_CUR_group.java @@ -0,0 +1,11 @@ +package com.ds.remote; + +public class type_CUR_group { + public short group_aux; + public short group_dvb; + public short group_stb; + public short group_atv; + public short group_ctv; + public short group_dvd; + public short group_arc; +} diff --git a/app/src/main/java/com/ds/remote/type_updatatime.java b/app/src/main/java/com/ds/remote/type_updatatime.java new file mode 100644 index 0000000..1c51a27 --- /dev/null +++ b/app/src/main/java/com/ds/remote/type_updatatime.java @@ -0,0 +1,7 @@ +package com.ds.remote; + +public class type_updatatime { + public short arc_group; + public byte clk_hour; + public byte clk_min; // +} diff --git a/app/src/main/java/com/lechange/demo/adapter/DeviceInnerRecordListAdapter.java b/app/src/main/java/com/lechange/demo/adapter/DeviceInnerRecordListAdapter.java new file mode 100644 index 0000000..50af6a7 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/adapter/DeviceInnerRecordListAdapter.java @@ -0,0 +1,103 @@ +package com.lechange.demo.adapter; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.common.openapi.entity.RecordsData; +import com.lechange.demo.tools.DateHelper; +import com.lechange.demo.tools.ImageHelper; +import com.yonsz.z1.R; + +import java.util.List; + +public class DeviceInnerRecordListAdapter extends RecyclerView.Adapter { + private Context mContext; + private List recordsData; + + public DeviceInnerRecordListAdapter(Context mContext, List recordsData) { + this.mContext = mContext; + this.recordsData = recordsData; + } + + @NonNull + @Override + public DeviceInnerRecordListHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_record, parent, false); + return new DeviceInnerRecordListAdapter.DeviceInnerRecordListHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull final DeviceInnerRecordListHolder holder, final int position) { + long time = DateHelper.string2Date(recordsData.get(position).endTime).getTime() - DateHelper.string2Date(recordsData.get(position).beginTime).getTime(); + holder.tvTimeM.setText(recordsData.get(position).beginTime.substring(11)); + holder.tvTimeS.setText(time / 1000 + "s"); + if (recordsData.get(position).recordType == 0) { + try { + ImageHelper.loadCacheImage(recordsData.get(position).thumbUrl, recordsData.get(position).deviceId, recordsData.get(position).deviceId, position, new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + try { + if (recordsData.get(msg.arg1).thumbUrl.hashCode() == msg.what && msg.obj != null) { + holder.ivBg.setImageDrawable((Drawable) msg.obj); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + holder.ivCheck.setVisibility(recordsData.get(position).check ? View.VISIBLE : View.GONE); + } + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (editClickListener != null) { + editClickListener.edit(position); + } + } + }); + } + + @Override + public int getItemCount() { + return recordsData == null ? 0 : recordsData.size(); + } + + class DeviceInnerRecordListHolder extends RecyclerView.ViewHolder { + + ImageView ivBg; + TextView tvTimeS; + TextView tvTimeM; + ImageView ivCheck; + + public DeviceInnerRecordListHolder(View itemView) { + super(itemView); + ivBg = itemView.findViewById(R.id.iv_bg); + ivCheck = itemView.findViewById(R.id.iv_check); + tvTimeS = itemView.findViewById(R.id.tv_time_s); + tvTimeM = itemView.findViewById(R.id.tv_time_m); + } + } + + private EditClickListener editClickListener; + + public interface EditClickListener { + void edit(int innerPosition); + } + + public void setEditClickListener(EditClickListener editClickListener) { + this.editClickListener = editClickListener; + } +} diff --git a/app/src/main/java/com/lechange/demo/adapter/DeviceRecordListAdapter.java b/app/src/main/java/com/lechange/demo/adapter/DeviceRecordListAdapter.java new file mode 100644 index 0000000..65f45c3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/adapter/DeviceRecordListAdapter.java @@ -0,0 +1,77 @@ +package com.lechange.demo.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.common.openapi.entity.RecordListData; +import com.yonsz.z1.R; + +import java.util.List; + +public class DeviceRecordListAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List recordListDataList; + + public DeviceRecordListAdapter(Context mContext, List recordListDataList) { + this.mContext = mContext; + this.recordListDataList = recordListDataList; + } + + @NonNull + @Override + public DeviceListHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_record_list, parent, false); + return new DeviceRecordListAdapter.DeviceListHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull DeviceListHolder holder, final int position) { + holder.tvTime.setText(recordListDataList.get(position).period); + GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 4); + holder.rcvRecord.setLayoutManager(gridLayoutManager); + DeviceInnerRecordListAdapter deviceInnerRecordListAdapter = new DeviceInnerRecordListAdapter(mContext, recordListDataList.get(position).recordsData); + deviceInnerRecordListAdapter.setEditClickListener(new DeviceInnerRecordListAdapter.EditClickListener() { + @Override + public void edit(int innerPosition) { + if (editClickListener != null) { + editClickListener.edit(position,innerPosition); + } + } + }); + holder.rcvRecord.setAdapter(deviceInnerRecordListAdapter); + } + + @Override + public int getItemCount() { + return recordListDataList == null ? 0 : recordListDataList.size(); + } + + class DeviceListHolder extends RecyclerView.ViewHolder { + + RecyclerView rcvRecord; + TextView tvTime; + + public DeviceListHolder(View itemView) { + super(itemView); + rcvRecord = itemView.findViewById(R.id.rcv_record); + tvTime = itemView.findViewById(R.id.tv_time); + } + } + + private EditClickListener editClickListener; + + public interface EditClickListener { + void edit(int outPosition, int innerPosition); + } + + public void setEditClickListener(EditClickListener editClickListener) { + this.editClickListener = editClickListener; + } +} diff --git a/app/src/main/java/com/lechange/demo/adapter/MediaPlayRecordAdapter.java b/app/src/main/java/com/lechange/demo/adapter/MediaPlayRecordAdapter.java new file mode 100644 index 0000000..b8ce372 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/adapter/MediaPlayRecordAdapter.java @@ -0,0 +1,126 @@ +package com.lechange.demo.adapter; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.common.openapi.entity.RecordsData; +import com.lechange.demo.tools.ImageHelper; +import com.yonsz.z1.R; + +import java.util.List; + +public class MediaPlayRecordAdapter extends RecyclerView.Adapter { + private List recordsBeanList; + private Context context; + + public MediaPlayRecordAdapter(List recordsBeanList, Context context) { + this.recordsBeanList = recordsBeanList; + this.context = context; + } + + @NonNull + @Override + public MediaPlayHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(context).inflate(R.layout.item_media_play_record, parent, false); + return new MediaPlayRecordAdapter.MediaPlayHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull final MediaPlayHolder holder, final int position) { + if (position == recordsBeanList.size()) { + holder.tvLoadingMore.setVisibility(View.VISIBLE); + holder.tvLoadingMore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (loadMoreClickListener != null) { + loadMoreClickListener.loadMore(); + } + } + }); + } else { + String time = recordsBeanList.get(position).beginTime.substring(11); + holder.tvTime.setText(time); + if (recordsBeanList.get(position).recordType == 0) { + //云录像 + holder.tvLoadingMore.setVisibility(View.GONE); + try { + ImageHelper.loadCacheImage(recordsBeanList.get(position).thumbUrl, recordsBeanList.get(position).deviceId, recordsBeanList.get(position).deviceId, position, new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + try { + if (recordsBeanList.get(msg.arg1).thumbUrl.hashCode() == msg.what && msg.obj != null) { + holder.ivImg.setImageDrawable((Drawable) msg.obj); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + //设备录像 + holder.tvLoadingMore.setVisibility(View.GONE); + holder.ivImg.setImageDrawable(context.getDrawable(R.mipmap.lc_demo_default_bg)); + } + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onItemClickListener != null) { + onItemClickListener.click(recordsBeanList.get(position).recordType, position); + } + } + }); + } + } + + @Override + public int getItemCount() { + return recordsBeanList == null ? 0 : (recordsBeanList.size() == 6 ? 7 : (recordsBeanList.size() + 1)); + } + + class MediaPlayHolder extends RecyclerView.ViewHolder { + ImageView ivImg; + TextView tvTime; + TextView tvLoadingMore; + + public MediaPlayHolder(View itemView) { + super(itemView); + ivImg = itemView.findViewById(R.id.iv_img); + tvTime = itemView.findViewById(R.id.tv_time); + tvLoadingMore = itemView.findViewById(R.id.tv_loadingmore); + } + } + + private LoadMoreClickListener loadMoreClickListener; + + public interface LoadMoreClickListener { + void loadMore(); + } + + public void setLoadMoreClickListener(LoadMoreClickListener loadMoreClickListener) { + this.loadMoreClickListener = loadMoreClickListener; + } + + + private OnItemClickListener onItemClickListener; + + public interface OnItemClickListener { + void click(int recordType, int position); + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + } +} diff --git a/app/src/main/java/com/lechange/demo/adapter/PixelListAdapter.java b/app/src/main/java/com/lechange/demo/adapter/PixelListAdapter.java new file mode 100644 index 0000000..4de6c26 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/adapter/PixelListAdapter.java @@ -0,0 +1,75 @@ +package com.lechange.demo.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.common.openapi.entity.DeviceDetailListData; +import com.lechange.demo.view.LcPopupWindow; +import com.yonsz.z1.R; + +import java.util.List; + +public class PixelListAdapter extends RecyclerView.Adapter implements View.OnClickListener { + + + private Context mContext; + private List mPixelList; + private LcPopupWindow.onRecyclerViewItemClickListener mItemClickListener; + private RecyclerView mRecycleView; + + + public PixelListAdapter(Context context, List pixelList) { + this.mContext = context; + this.mPixelList = pixelList; + } + + + public void setOnItemClickListener(LcPopupWindow.onRecyclerViewItemClickListener onRecyclerViewItemClickListener) { + this.mItemClickListener = onRecyclerViewItemClickListener; + } + + + @NonNull + @Override + public PixelHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + mRecycleView = (RecyclerView) parent; + View inflate = LayoutInflater.from(mContext).inflate(R.layout.item_pixel_list, parent, false); + inflate.setOnClickListener(this); + return new PixelHolder(inflate); + } + + @Override + public void onBindViewHolder(@NonNull PixelHolder holder, int position) { + holder.tvPixel.setText(mPixelList.get(position).name); + } + + @Override + public int getItemCount() { + return mPixelList!=null?mPixelList.size():0; + } + + @Override + public void onClick(View view) { + int childAdapterPosition = mRecycleView.getChildAdapterPosition(view); + if(mItemClickListener!=null){ + mItemClickListener.onItemClick(mRecycleView,view,childAdapterPosition, + mPixelList.get(childAdapterPosition).name,mPixelList.get(childAdapterPosition).imageSize,mPixelList.get(childAdapterPosition).streamType); + } + } + + class PixelHolder extends RecyclerView.ViewHolder{ + + public TextView tvPixel; + + public PixelHolder(View itemView) { + super(itemView); + tvPixel = itemView.findViewById(R.id.tv_pixel); + } + } + +} diff --git a/app/src/main/java/com/lechange/demo/business/Business.java b/app/src/main/java/com/lechange/demo/business/Business.java new file mode 100644 index 0000000..8ce826e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/Business.java @@ -0,0 +1,1905 @@ +package com.lechange.demo.business; + +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; + +import com.lechange.demo.business.entity.AlarmMessageInfo; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.entity.ChannelPTZInfo; +import com.lechange.demo.business.entity.ChannelPTZInfo.Direction; +import com.lechange.demo.business.entity.ChannelPTZInfo.Duration; +import com.lechange.demo.business.entity.ChannelPTZInfo.Operation; +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.business.entity.RecordInfo.RecordEventType; +import com.lechange.demo.business.util.OpenApiHelper; +import com.lechange.demo.business.util.TaskPoolHelper; +import com.lechange.demo.business.util.TaskPoolHelper.RunnableTask; +import com.lechange.demo.business.util.TimeHelper; +import com.lechange.opensdk.api.LCOpenSDK_Api; +import com.lechange.opensdk.api.bean.BeAuthDeviceList; +import com.lechange.opensdk.api.bean.BindDevice; +import com.lechange.opensdk.api.bean.BindDeviceInfo; +import com.lechange.opensdk.api.bean.BreathingLightStatus; +import com.lechange.opensdk.api.bean.CheckDeviceBindOrNot; +import com.lechange.opensdk.api.bean.ControlDeviceWifi; +import com.lechange.opensdk.api.bean.ControlPTZ; +import com.lechange.opensdk.api.bean.CurrentDeviceWifi; +import com.lechange.opensdk.api.bean.DeleteAlarmMessage; +import com.lechange.opensdk.api.bean.DeviceAlarmPlan; +import com.lechange.opensdk.api.bean.DeviceAlarmPlan.ResponseData.RulesElement; +import com.lechange.opensdk.api.bean.DeviceList; +import com.lechange.opensdk.api.bean.DeviceList.Response; +import com.lechange.opensdk.api.bean.DeviceList.ResponseData.DevicesElement; +import com.lechange.opensdk.api.bean.DeviceOnline; +import com.lechange.opensdk.api.bean.FrameReverseStatus; +import com.lechange.opensdk.api.bean.GetAlarmMessage; +import com.lechange.opensdk.api.bean.GetAlarmMessage.ResponseData.AlarmsElement; +import com.lechange.opensdk.api.bean.ModifyBreathingLight; +import com.lechange.opensdk.api.bean.ModifyDeviceAlarmPlan; +import com.lechange.opensdk.api.bean.ModifyDeviceAlarmStatus; +import com.lechange.opensdk.api.bean.ModifyDevicePwd; +import com.lechange.opensdk.api.bean.ModifyFrameReverseStatus; +import com.lechange.opensdk.api.bean.QueryCloudRecordNum; +import com.lechange.opensdk.api.bean.QueryCloudRecords; +import com.lechange.opensdk.api.bean.QueryCloudRecords.ResponseData.RecordsElement; +import com.lechange.opensdk.api.bean.QueryLocalRecordNum; +import com.lechange.opensdk.api.bean.QueryLocalRecords; +import com.lechange.opensdk.api.bean.RecoverSDCard; +import com.lechange.opensdk.api.bean.SetStorageStrategy; +import com.lechange.opensdk.api.bean.ShareDeviceList; +import com.lechange.opensdk.api.bean.UnBindDevice; +import com.lechange.opensdk.api.bean.UnBindDeviceInfo; +import com.lechange.opensdk.api.bean.UpgradeDevice; +import com.lechange.opensdk.api.bean.WifiAround; +import com.lechange.opensdk.api.client.BaseRequest; +import com.lechange.opensdk.api.client.BaseResponse; +import com.lechange.opensdk.device.LCOpenSDK_DeviceInit; +import com.lechange.opensdk.media.DeviceInitInfo; +import com.lechange.opensdk.media.LCOpenSDK_LoginManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Business { + + public static final boolean isOversea = false; + // hls,rtsp等相关底层库的错误码解析 + public static final int RESULT_SOURCE_OPENAPI = 99; // 在播放过程中rest请求回调类型 + public final static String tag = "Business"; + // 码流超时时间 + public final static int DMS_TIMEOUT = 60 * 1000; + private List mChannelInfoList = new ArrayList(); // 由于demo,不考虑多线程操作问题 + private List mSharedChannelInfoList = new ArrayList(); // 由于demo,不考虑多线程操作问题 + private List mBeAuthChannelInfoList = new ArrayList(); // 由于demo,不考虑多线程操作问题 + private List mRecordInfoList = new ArrayList(); // 由于demo,不考虑多线程操作问题 + private List mAllRecordInfoList = new ArrayList(); // 由于demo,不考虑多线程操作问题 + private List mAlarmMessageInfoList = new ArrayList(); + private String mHost; + private String mAppId; + private String mAppSecret; + private String mToken = ""; // userToken或accessToken + + public static Business getInstance() { + return Instance.instance; + } + + public boolean isOversea() { + return isOversea; + } + + /** + * 设备能力集转换 + * + * @param strAbility + * @return + */ + public static int StringToAbility(String strAbility) { + int ability = 0; + if (strAbility == null) { + return ability; + } + + if (strAbility.contains("WLAN")) { + ability |= ChannelInfo.Ability.WLAN; + } + if (strAbility.contains("AlarmPIR")) { + ability |= ChannelInfo.Ability.AlarmPIR; + } + if (strAbility.contains("AudioTalk")) { + ability |= ChannelInfo.Ability.AudioTalk; + } + if (strAbility.contains("VVP2P")) { + ability |= ChannelInfo.Ability.VVP2P; + } + if (strAbility.contains("PTZ") || strAbility.contains("PT")) { + ability |= ChannelInfo.Ability.PTZ; + } + if (strAbility.contains("HSEncrypt")) { + ability |= ChannelInfo.Ability.HSEncrypt; + } + if (strAbility.contains("CloudStorage")) { + ability |= ChannelInfo.Ability.CloudStorage; + } + if (strAbility.contains("RTSV1")) { + ability |= ChannelInfo.Ability.SUPPORT_DHHTTP_LIVE; + } + if (strAbility.contains("PBSV1")) { + ability |= ChannelInfo.Ability.SUPPORT_DHHTTP_PLAYBACK; + } + if (strAbility.contains("TCM")) { + ability |= ChannelInfo.Ability.TCM; + } + return ability; + } + + /** + * 初始化client对象,配置client参数 + * + * @return + */ + public boolean init(String appid, String appsecret, String host) { + // 设置乐橙服务地址 + LCOpenSDK_Api.setHost(host); + mAppId = appid; + mAppSecret = appsecret; + mHost = host; + + // bInit = true; + Log.d(tag, "Init OK"); + // } + return true; + } + + /** + * 发送网络请求,并对请求结果的错误码进行处理 + * + * @param req + * @return + */ + private RetObject request(BaseRequest req) { + return request(req, 15 * 1000); + } + + // private boolean bInit = false; + + /** + * 发送网络请求,并对请求结果的错误码进行处理 + * + * @param req + * @param timeOut 访问dms接口时,超时时间设置长一点 + * @return + * @throws Exception + */ + private RetObject request(BaseRequest req, int timeOut) { + // T t = LCOpenSDK_Api.request(req, timeOut); + RetObject retObject = new RetObject(); + BaseResponse t = null; + try { + t = LCOpenSDK_Api.request(req, timeOut); + // Log.d(tag, req.getBody()); + + if (t.getCode() == HttpCode.SC_OK) { + // 请求成功,则看服务器处理错误 + if (!t.getApiRetCode().equals("0")) + retObject.mErrorCode = 2; // 业务错误 + retObject.mMsg = "business errorcode: " + t.getApiRetCode() + + ", error msg: " + t.getApiRetMsg(); + } else { + retObject.mErrorCode = 1; // http错误 + retObject.mMsg = "HTTP errorcode: " + t.getCode() + + ", error msg: " + t.getDesc(); + } + } catch (Exception e) { + // if timeout,return; + e.printStackTrace(); + retObject.mErrorCode = -1000; + retObject.mMsg = "inner errorcode : -1000, error msg: " + + e.getMessage(); + Log.d(tag, req.getBody() + retObject.mMsg); + } + retObject.resp = t; + return retObject; + } + + public String getHost() { + return mHost; + } + + public String getToken() { + return mToken; + } + + public void setToken(String mToken) { + this.mToken = mToken; + } + + /** + * 管理员登陆设备 + */ + public void adminlogin(final Handler handler) { + // 请求AccessToken 以开发者手机号 + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + // AccessToken req = new AccessToken(); + // req.data.phone = ""; // 唯一标记一类app + // //AccessToken.Response resp= null; + // RetObject retObject = null; + // retObject = request(req); + // //将标示符和返回体发送给handle处理 + // //retobject.resp = resp; + // if(retObject.resp != null && ((AccessToken.Response)retObject.resp).data != null) + // handler.obtainMessage(retObject.mErrorCode, ((AccessToken.Response)retObject.resp).data.accessToken).sendToTarget(); + + // 实现一个443连接供上层参考 + // 3.0.1不需要管理员账号,在此屏蔽 + OpenApiHelper.getAccessToken(mHost, "", mAppId, mAppSecret, handler); + } + }); + } + + /** + * 获取验证码 + * + * @param phoneNumber + * @param mAppid + * @param mAppSecret + * @param handler + * @param context + */ + public void getUserSms(final String phoneNumber, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // 实现一个443连接供上层参考 + OpenApiHelper.userBindSms(mHost, phoneNumber, mAppId, + mAppSecret, handler); + } + }); + + } + + /** + * 验证验证码 + * + * @param phoneNumber + * @param smsCode + * @param handler + * @param context + */ + public void checkUserSms(final String phoneNumber, final String smsCode, + final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // 实现一个443连接供上层参考 + OpenApiHelper.userBind(mHost, phoneNumber, mAppId, mAppSecret, + smsCode, handler); + } + }); + } + + /** + * 用户登陆设备 + */ + public void userlogin(final String phoneNumber, final Handler handler) { + // 请求usersToken 以开发者手机号 + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // 实现一个443连接供上层参考 + OpenApiHelper.getUserToken(mHost, phoneNumber, mAppId, + mAppSecret, handler); + } + }); + } + + /** + * 从检索出的设备列表中查找制定设备通道 + * + * @param id + * @return + */ + public ChannelInfo getChannel(String id) { + + for (ChannelInfo chl : mChannelInfoList) { + if (chl.getUuid().equals(id)) { + return chl; + } + } + for (ChannelInfo chl : mSharedChannelInfoList) { + if (chl.getUuid().equals(id)) { + return chl; + } + } + for (ChannelInfo chl : mBeAuthChannelInfoList) { + if (chl.getUuid().equals(id)) { + return chl; + } + } + return null; + } + + /** + * 获取用户下面所有设备通道列表 + * + * @param handler + */ + public void getChannelList(final Handler handler) { + mChannelInfoList.clear(); // 清数据 + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + DeviceList req = new DeviceList(); + // req.data.filter = new ArrayList(); // + // 过滤条件,可指定获取特定设备序列号的设备信息,我们这获取用户所有设备,无过滤条件。 + req.data.token = mToken; // token + req.data.queryRange = "1-10"; + DeviceList.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (Response) retObject.resp; + mChannelInfoList.clear(); // 防止list崩溃 + if (resp != null && resp.data != null + && resp.data.devices != null) + for (DevicesElement devElement : resp.data.devices) { + List list = devicesElementToResult( + devElement, null); + mChannelInfoList.addAll(list); + } + retObject.resp = mChannelInfoList; + // 解析设备列表信息 + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + } + }); + } + + /** + * 获取分享设备列表 + * + * @param handler + */ + public void getSharedDeviceList(final Handler handler) { + + mSharedChannelInfoList.clear(); // 清数据 + TaskPoolHelper.addTask(new RunnableTask("Shared") { + @Override + public void run() { + // TODO Auto-generated method stub + + ShareDeviceList req = new ShareDeviceList(); + req.data.queryRange = "1-10"; + req.data.token = mToken; + + ShareDeviceList.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (ShareDeviceList.Response) retObject.resp; + mSharedChannelInfoList.clear(); // 防止list崩溃 + if (resp != null && resp.data != null + && resp.data.devices != null) { + for (ShareDeviceList.ResponseData.DevicesElement devElement : resp.data.devices) { + List list = devicesElementToResult(null, + devElement); + mSharedChannelInfoList.addAll(list); + } + + } + + retObject.resp = mSharedChannelInfoList; + + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + + } + }); + } + + /** + * 获取授权设备列表 + * + * @param handler + */ + public void getBeAuthDeviceList(final Handler handler) { + + mBeAuthChannelInfoList.clear(); // 清数据 + TaskPoolHelper.addTask(new RunnableTask("BeAuth") { + @Override + public void run() { + // TODO Auto-generated method stub + + BeAuthDeviceList req = new BeAuthDeviceList(); + req.data.queryRange = "1-10"; + req.data.token = mToken; + + BeAuthDeviceList.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (BeAuthDeviceList.Response) retObject.resp; + mBeAuthChannelInfoList.clear(); // 防止list崩溃 + // list = null; + if (resp != null && resp.data != null + && resp.data.devices != null) { + + // list = new ArrayList(); + for (BeAuthDeviceList.ResponseData.DevicesElement devElement : resp.data.devices) { + ChannelInfo channelInfo = devicesElementToResult(devElement); + // List list.add(channelInfo); + mBeAuthChannelInfoList.add(channelInfo); + } + } + retObject.resp = mBeAuthChannelInfoList; + + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + + } + }); + } + + /** + * 获取用户设备信息 + * + * @param handler + */ + public void getDeviceInfo(final String chnlId, final Handler handler) { + + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + BindDeviceInfo req = new BindDeviceInfo(); + + req.data.token = mToken; // token + req.data.deviceId = chl.getDeviceCode(); + BindDeviceInfo.Response resp = null; + + RetObject retObject = null; + retObject = request(req); + resp = (BindDeviceInfo.Response) retObject.resp; + + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "getDeviceInfo faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null || resp.data.channels == null) { + Log.d(tag, "getDeviceInfo success data is null"); + } + Bundle bundle = new Bundle(); + bundle.putInt("alarmStatus", + resp.data.channels.get(0).alarmStatus); + // bundle.putInt("alarmStatus", 0); + bundle.putInt("cloudStatus", + resp.data.channels.get(0).csStatus); + bundle.putBoolean("canBeUpgrade", resp.data.canBeUpgrade); + // todo:其他信息解析请见OpenAPI 平台sdk文档 + handler.obtainMessage(0, bundle).sendToTarget(); // 发送成功消息到界面 + } + } + + }); + } + + private ChannelInfo devicesElementToResult( + BeAuthDeviceList.ResponseData.DevicesElement beAuthDevElement) { + ChannelInfo chnlInfo = new ChannelInfo(); + // 解析分享设备通道列表 + if (beAuthDevElement != null) { + + chnlInfo.setDeviceCode(beAuthDevElement.deviceId); + chnlInfo.setDeviceModel(beAuthDevElement.deviceModel); + chnlInfo.setEncryptMode(beAuthDevElement.encryptMode); + chnlInfo.setIndex(beAuthDevElement.channelId); + chnlInfo.setName(beAuthDevElement.channelName + "[beAuth]"); + chnlInfo.setBackgroudImgURL(beAuthDevElement.channelPicUrl); + chnlInfo.setCloudMealStates(beAuthDevElement.csStatus); + // chnlInfo.setAlarmStatus(beAuthDevElement.alarmStatus); + // // 是否为云台设备 + // if ((chnlElement.channelAbility != null + // && chnlElement.channelAbility.contains("PTZ")) + // || devElement.ability.contains("PTZ")) { + // chnlInfo.setType(ChannelType.PtzCamera); + // } + // else { + // chnlInfo.setType(ChannelType.Camera); + // } + // 是否支持加密 + chnlInfo.setEncryptMode(beAuthDevElement.encryptMode); + // 设置设备能力集 + chnlInfo.setAbility(StringToAbility(beAuthDevElement.ability)); + + // 设备与通道同时在线,通道才算在线 + if (beAuthDevElement.channelOnline) + switch (beAuthDevElement.status) { + case 0: + chnlInfo.setState(ChannelInfo.ChannelState.Offline); + break; + case 1: + chnlInfo.setState(ChannelInfo.ChannelState.Online); + break; + case 3: + chnlInfo.setState(ChannelInfo.ChannelState.Upgrade); + break; + } + + } + + return chnlInfo; + + } + + /** + * 一个设备下面有多个通道,目前demo不需要太多设备信息,故没有解析设备信息,但设备信息解析可参照下面代码,或者参照OpenAPI sdk文档。 + * + * @param devElement + * @return + */ + private List devicesElementToResult( + DeviceList.ResponseData.DevicesElement devElement, + ShareDeviceList.ResponseData.DevicesElement shareDevElement) { + + List channelList = new ArrayList(); + + // 解析绑定通道列表 + if (devElement != null && devElement.channels != null) { + for (DeviceList.ResponseData.DevicesElement.ChannelsElement chnlElement : devElement.channels) { + ChannelInfo chnlInfo = new ChannelInfo(); + chnlInfo.setDeviceCode(devElement.deviceId); + chnlInfo.setDeviceModel(devElement.deviceModel); + chnlInfo.setEncryptMode(devElement.encryptMode); + chnlInfo.setIndex(chnlElement.channelId); + chnlInfo.setName(chnlElement.channelName); + chnlInfo.setBackgroudImgURL(chnlElement.channelPicUrl); + chnlInfo.setCloudMealStates(chnlElement.csStatus); + // chnlInfo.setAlarmStatus(chnlElement.alarmStatus); + // // 是否为云台设备 + // if ((chnlElement.channelAbility != null + // && chnlElement.channelAbility.contains("PTZ")) + // || devElement.ability.contains("PTZ")) { + // chnlInfo.setType(ChannelType.PtzCamera); + // } + // else { + // chnlInfo.setType(ChannelType.Camera); + // } + // 是否支持加密 + if (devElement.ability.contains("HSEncrypt")) { + chnlInfo.setEncrypt(1); + } else { + chnlInfo.setEncrypt(0); + } + // 设置设备能力集 + chnlInfo.setAbility(StringToAbility(devElement.ability) | StringToAbility(chnlElement.channelAbility)); + + // 设备与通道同时在线,通道才算在线 + if (chnlElement.channelOnline) + switch (devElement.status) { + case 0: + chnlInfo.setState(ChannelInfo.ChannelState.Offline); + break; + case 1: + chnlInfo.setState(ChannelInfo.ChannelState.Online); + break; + case 3: + chnlInfo.setState(ChannelInfo.ChannelState.Upgrade); + break; + } + channelList.add(chnlInfo); + } + } + + // 解析分享设备通道列表 + if (shareDevElement != null && shareDevElement.channels != null) { + for (ShareDeviceList.ResponseData.DevicesElement.ChannelsElement chnlElement : shareDevElement.channels) { + ChannelInfo chnlInfo = new ChannelInfo(); + chnlInfo.setDeviceCode(shareDevElement.deviceId); + chnlInfo.setDeviceModel(shareDevElement.deviceModel); + chnlInfo.setEncryptMode(shareDevElement.encryptMode); + chnlInfo.setIndex(chnlElement.channelId); + chnlInfo.setName(chnlElement.channelName + "[shared]"); + chnlInfo.setBackgroudImgURL(chnlElement.channelPicUrl); + // chnlInfo.setAlarmStatus(chnlElement.alarmStatus); + // // 是否为云台设备 + // if ((chnlElement.channelAbility != null + // && chnlElement.channelAbility.contains("PTZ")) + // || devElement.ability.contains("PTZ")) { + // chnlInfo.setType(ChannelType.PtzCamera); + // } + // else { + // chnlInfo.setType(ChannelType.Camera); + // } + // 是否支持加密 + if (shareDevElement.ability.contains("HSEncrypt")) { + chnlInfo.setEncrypt(1); + } else { + chnlInfo.setEncrypt(0); + } + // 设置设备能力集 + chnlInfo.setAbility(StringToAbility(shareDevElement.ability)); + + // 设备与通道同时在线,通道才算在线 + if (chnlElement.channelOnline) + switch (shareDevElement.status) { + case 0: + chnlInfo.setState(ChannelInfo.ChannelState.Offline); + break; + case 1: + chnlInfo.setState(ChannelInfo.ChannelState.Online); + break; + case 3: + chnlInfo.setState(ChannelInfo.ChannelState.Upgrade); + break; + } + channelList.add(chnlInfo); + } + } + return channelList; + } + + public void checkBindOrNot(final String deviceId, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + CheckDeviceBindOrNot req = new CheckDeviceBindOrNot(); + req.data.token = mToken; + req.data.deviceId = deviceId; // 设备id。 + // CheckDeviceBindOrNot.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 将标示符和返回体发送给handle处理 + // retobject.resp = resp; + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); + } + }); + } + + /** + * 设备在线状态 + * + * @param deviceId + * @param handler + */ + public void checkOnline(final String deviceId, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + DeviceOnline req = new DeviceOnline(); + req.data.token = mToken; + req.data.deviceId = deviceId; // 设备id。 + RetObject retObject = null; + retObject = request(req); + + // 将标示符和返回体发送给handle处理 + // retobject.resp = resp; + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); + } + }); + } + + public void unBindDeviceInfo(final String deviceID, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + UnBindDeviceInfo req = new UnBindDeviceInfo(); + req.data.token = mToken; + req.data.deviceId = deviceID; // 设备id。 + RetObject retObject = null; + retObject = request(req); + UnBindDeviceInfo.Response resp = (UnBindDeviceInfo.Response) retObject.resp; + if (resp.data == null || resp.data.ability == null) { + Log.e(tag, "unBindDeviceInfo response data is null"); + handler.obtainMessage(1000, "unBindDeviceInfo response data is null").sendToTarget(); + return; + } + + retObject.resp = resp.data.ability; + // 将标示符和返回体发送给handle处理 + handler.obtainMessage(retObject.mErrorCode, retObject.resp).sendToTarget(); + + } + }); + } + + /** + * 为账号绑定设备 + * + * @param deviceID 序列号 + * @param handler + */ + public void bindDevice(final String deviceID, final String key, + final Handler handler) { + bindDevice(deviceID, key, key, handler); + } + + public void bindDevice(final String deviceID, final String code, + final String key, final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + BindDevice req = new BindDevice(); + req.data.token = mToken; + req.data.deviceId = deviceID; + req.data.code = code; + + // BindDevice.Response resp = null; + RetObject retObject = null; + retObject = request(req, 5 * 1000); + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); + } + }); + } + + /** + * 为账号解绑设备 + * + * @param deleteCloudRecords 是否删除云录像 + * @param deviceID 序列号 + * @param handler + */ + public void unBindDevice(final String deviceID, final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + UnBindDevice req = new UnBindDevice(); + req.data.token = mToken; + req.data.deviceId = deviceID; + // UnBindDevice.Response resp = null; + RetObject retObject = null; + retObject = request(req, 15 * 1000); + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); + } + }); + } + + // 网络周边 + public void getWifiStatus(final String ssid, final String deviceID, + final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + WifiAround req = new WifiAround(); + req.data.token = mToken; + req.data.deviceId = deviceID; + // WifiAround.Response resp = null; + RetObject retObject = null; + retObject = request(req, 45 * 1000); + System.out.println("SSID:" + ssid); + + // 解析数据 + if (retObject.mErrorCode == 0) { + // get device wifilist + for (WifiAround.ResponseData.WLanElement element : ((WifiAround.Response) retObject.resp).data.wLan) { + if (element.ssid.equals(ssid)) { + System.out.println("obtainMessage:" + element.ssid); + retObject.resp = element.bssid; + } + } + } + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送消息到界面 + } + }); + } + + // 连接网络 + public void connectWifi(final String token, final String BSSID, final String ssid, + final String password, final String deviceID, final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + ControlDeviceWifi req = new ControlDeviceWifi(); + req.data.token = token; + req.data.password = password; + req.data.linkEnable = true; + req.data.ssid = ssid; + req.data.deviceId = deviceID; + req.data.bssid = BSSID; + // ControlDeviceWifi.Response resp = null; + System.out.println(ssid + "--" + password + "--" + deviceID + "--" + token); + RetObject retObject = null; + retObject = request(req, 45 * 1000); // dms timeout + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送消息到界面 + } + }); + } + + public void setAlarmPlanConfig(final String deviceID, + final String optional, final List rules, + final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + ModifyDeviceAlarmPlan req = new ModifyDeviceAlarmPlan(); + req.data.deviceId = deviceID; + req.data.channelId = optional; + + // System.out.println("channels.get(0).rules.size:"+channels.get(0).rules.size()); + for (RulesElement ele : rules) { + System.out.println(ele.beginTime); + System.out.println(ele.endTime); + System.out.println(ele.period); + } + RetObject retObject = null; + retObject = request(req); + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + } + }); + + } + + /** + * 查询报警计划配置 + * + * @param deviceID 设备id + * @param optional 通道id + * @param handler 回调 + */ + public void getAlarmPlanConfig(final String deviceID, + final String optional, final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + DeviceAlarmPlan req = new DeviceAlarmPlan(); + req.data.deviceId = deviceID; // 过滤条件,可指定获取特定设备序列号的设备信息。 + req.data.channelId = optional; // 通道id + DeviceAlarmPlan.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + if (resp == null || resp.data == null) { + // throw new + // BusinessException(BusinessErrorCode.BEC_COMMON_NULL_POINT); + } + + resp = (DeviceAlarmPlan.Response) retObject.resp; + // 如果设备在线 + if (resp.data != null) { + retObject.resp = resp.data.rules; + } + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送消息到界面 + } + }); + + } + + public void AsynControlPtz(String id, ChannelPTZInfo ptz, + final Handler handler) { + // TODO Auto-generated method stub + String operation = ""; + String duration = null; + int v = 0; + int h = 0; + double z = 1.0d; + if (ptz.getOperation() == Operation.Move) { + operation = "move"; + if (ptz.getDuration() == Duration.Forever) { + duration = "last"; + } else if (ptz.getDuration() == Duration.Long) { + duration = "last"; + } else if (ptz.getDuration() == Duration.Generral) { + duration = "500"; + } else if (ptz.getDuration() == Duration.Short) { + duration = "200"; + } + + if (ptz.getDirection() == Direction.Left) { + h = -5; + } else if (ptz.getDirection() == Direction.Right) { + h = 5; + } else if (ptz.getDirection() == Direction.Up) { + v = 5; + } else if (ptz.getDirection() == Direction.Down) { + v = -5; + } else if (ptz.getDirection() == Direction.ZoomIn) { + z = 0.5d; + } else if (ptz.getDirection() == Direction.ZoomOut) { + z = 1.5d; + } + + } else if (ptz.getOperation() == Operation.Locate) { + operation = "locate"; + } else if (ptz.getOperation() == Operation.Stop) { + operation = "move"; // stop 为自定义事件,协议为 operation设置move vhz的值设置0,0,1 + duration = "100"; // 随意填写 以防设备出错 + v = 0; + h = 0; + z = 1.0d; + } + + final ChannelInfo chl = getChannel(id); + if (chl == null) { + Log.d(tag, "chl is null"); + return; + } + + final ControlPTZ req = new ControlPTZ(); + req.data.token = mToken; + req.data.operation = operation; + req.data.v = v; + req.data.duration = duration; + req.data.h = h; + req.data.z = z; + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.deviceId = chl.getDeviceCode(); + + Log.d(tag, "id=" + id + "devId=" + chl.getDeviceCode()); + + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // ControlPTZ.Response resp = null; + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送消息到界面 + } + }); + + } + + /** + * 查询通道下的录像总数 + * + * @param chnlId + * @param chnl + * @param startTime + * @param endTime + * @param startIndex + * @param endIndex + * @param handler - + */ + public void queryRecordNum(String chnlId, final String startTime, + final String endTime, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + QueryLocalRecordNum req = new QueryLocalRecordNum(); + req.data.token = mToken; + req.data.beginTime = startTime; + // req.data.type = "All"; 默认为all + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.endTime = endTime; + req.data.deviceId = chl.getDeviceCode(); + Log.d(tag, "strStartTime:" + startTime + "strEndTime:" + + endTime); + + RetObject retObject = null; + retObject = request(req, DMS_TIMEOUT); + QueryLocalRecordNum.Response resp = (QueryLocalRecordNum.Response) retObject.resp; + + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "QueryLocalRecordNum faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null) { + Log.d(tag, "QueryLocalRecordNum success data is null"); + } + // todo:其他信息解析请见OpenAPI 平台sdk文档 + handler.obtainMessage( + 0, + resp.data.recordNum, 1).sendToTarget(); + // resp.data.recordNum > 99 ? 99 : resp.data.recordNum, 1).sendToTarget(); // 发送成功消息到界面 + } + } + }); + } + + /** + * 查询通道下的录像列表 + * + * @param chnlId + * @param chnl + * @param startTime + * @param endTime + * @param startIndex + * @param endIndex + * @param handler + */ + public void queryRecordList(String chnlId, final String startTime, + final String endTime, int startIndex, int endIndex, + final Handler handler) { + mRecordInfoList.clear(); // 清数据 + + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + //加个判断大于99个不能查 + if (endIndex - startIndex >= 60) { + startIndex = endIndex - 60; + } + final String strNneed = String.valueOf(startIndex) + "-" + + String.valueOf(endIndex); // 需要录像的条数,从那条记录到那一条,demo只读取前面5条,不查询完所有录像 + + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + + QueryLocalRecords req = new QueryLocalRecords(); + req.data.token = mToken; + req.data.beginTime = startTime; + // req.data.type = "All"; 默认为all + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.queryRange = strNneed; + req.data.endTime = endTime; + req.data.deviceId = chl.getDeviceCode(); + Log.d(tag, "strStartTime:" + startTime + "strEndTime:" + + endTime); + + RetObject retObject = null; + retObject = request(req); + QueryLocalRecords.Response resp = (QueryLocalRecords.Response) retObject.resp; + + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "QueryRecordList faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null || resp.data.records == null) { + Log.d(tag, "queryRecordList success data is null"); + handler.obtainMessage(-1, "respone data is null").sendToTarget(); + } + + for (QueryLocalRecords.ResponseData.RecordsElement element : resp.data.records) { + RecordInfo info = new RecordInfo(); + info.setDeviceId(chl.getDeviceCode()); + info.setChnlUuid(chl.getUuid()); + long dateStart = TimeHelper.getTimeStamp(element.beginTime); + info.setStartTime(dateStart); + long dateEnd = TimeHelper.getTimeStamp(element.endTime); + info.setEndTime(dateEnd); + info.setDeviceKey(chl.getEncryptKey()); + info.setRecordID(element.recordId); + info.setFileLength(element.fileLength); + if (element.type.equals("Event")) + info.setEventType(RecordEventType.Event); + else if (element.type.equals("All")) + info.setEventType(RecordEventType.All); + else if (element.type.equals("Manual")) + info.setEventType(RecordEventType.Manual); + mRecordInfoList.add(info); + mAllRecordInfoList.add(info); + } + Collections.reverse(mRecordInfoList);// 反序 临时使用下 + // todo:其他信息解析请见OpenAPI 平台sdk文档 + handler.obtainMessage(0, mRecordInfoList).sendToTarget(); // 发送成功消息到界面 + } + } + }); + } + + /** + * 查询通道下的云录像总数 + * + * @param chnlId + * @param startTime + * @param endTime + * @param startIndex + * @param endIndex + * @param handler + */ + public void queryCloudRecordNum(String chnlId, final String startTime, + final String endTime, final Handler handler) { + + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + // + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + QueryCloudRecordNum req = new QueryCloudRecordNum(); + req.data.token = mToken; + req.data.beginTime = startTime; + req.data.endTime = endTime; + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.deviceId = chl.getDeviceCode(); + Log.d(tag, "startTime:" + req.data.beginTime + "endTime:" + + req.data.endTime + "channelId:" + req.data.channelId + + "deviceId:" + chl.getDeviceCode()); + + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + QueryCloudRecordNum.Response resp = (QueryCloudRecordNum.Response) retObject.resp; + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "QueryCloudRecordNum faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null) { + Log.d(tag, "QueryCloudRecordNum success data is null"); + } + // todo:其他信息解析请见OpenAPI 平台sdk文档 + handler.obtainMessage( + 0, + resp.data.recordNum, + resp.data.recordNum > 10 ? resp.data.recordNum - 9 + : 1).sendToTarget(); // 发送成功消息到界面 + } + } + }); + } + + /** + * 查询通道下的云录像列表 + * + * @param chnlId + * @param startTime + * @param endTime + * @param startIndex + * @param endIndex + * @param handler + */ + public void queryCloudRecordList(String chnlId, final String startTime, + final String endTime, int startIndex, int endIndex, + final Handler handler) { + mRecordInfoList.clear(); // 清数据 + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + + final String strNneed = String.valueOf(startIndex) + "-" + + String.valueOf(endIndex); // 需要录像的条数,从那条记录到那一条,demo只读取前面10条,不查询完所有录像 + // + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + QueryCloudRecords req = new QueryCloudRecords(); + req.data.token = mToken; + req.data.beginTime = startTime; + req.data.endTime = endTime; + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.queryRange = strNneed; + req.data.deviceId = chl.getDeviceCode(); + Log.d(tag, "startTime:" + req.data.beginTime + "endTime:" + + req.data.endTime + "channelId:" + req.data.channelId + + "deviceId:" + chl.getDeviceCode() + "strNneed:" + + strNneed); + + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + QueryCloudRecords.Response resp = (QueryCloudRecords.Response) retObject.resp; + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "queryCloudRecordList faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null || resp.data.records == null) { + Log.d(tag, "queryRecordList success data is null"); + } + + for (RecordsElement element : resp.data.records) { + RecordInfo info = new RecordInfo(); + info.setChnlUuid(chl.getUuid()); + + String dateStart = element.beginTime; + // dateStart *= 1000; + info.setStartTime(TimeHelper.getTimeStamp(dateStart)); + String dateEnd = element.endTime; + // dateEnd *= 1000; + info.setEndTime(TimeHelper.getTimeStamp(dateEnd)); + info.setDeviceKey(chl.getEncryptKey()); + info.setRecordID(element.recordId); + info.setBackgroudImgUrl(element.thumbUrl); + info.setDeviceId(element.deviceId); + info.setType(RecordInfo.RecordType.PublicCloud); + if (element.size.length() > 0) { + info.setFileLength(Long.parseLong(element.size)); + } else { // easy4ip设备size字段为“” + info.setFileLength(0); + } + mRecordInfoList.add(info); + } + Collections.reverse(mRecordInfoList);// 反序 临时使用下 + // todo:其他信息解析请见OpenAPI 平台sdk文档 + handler.obtainMessage(0, mRecordInfoList).sendToTarget(); // 发送成功消息到界面 + } + } + }); + } + + /** + * 获取设备动检计划 + * + * @param chnlId + * @param handler + */ + public void getAlarmStatus(final String chnlId, final Handler handler) { + + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + DeviceAlarmPlan req = new DeviceAlarmPlan(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + + DeviceAlarmPlan.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (DeviceAlarmPlan.Response) retObject.resp; + + if (retObject.mErrorCode != 0) { + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + int arg1 = resp.data.rules.get(0).enable == true ? 1 : 0; + handler.obtainMessage(0, arg1, 0).sendToTarget(); + + } + + } + }); + } + + /** + * 改变设备的动检开关 + * + * @param enable + * @param channelId + * @param deviceId + */ + public void modifyAlarmStatus(final boolean enable, final String chnlId, + final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + ModifyDeviceAlarmStatus req = new ModifyDeviceAlarmStatus(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.enable = enable; + + ModifyDeviceAlarmStatus.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + public void setStorageStartegy(final String enable, final String chnlId, + final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + SetStorageStrategy req = new SetStorageStrategy(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.status = enable; + + SetStorageStrategy.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + /** + * recoverSDCard 请求初始化SD卡 + */ + public void recoverSDCard(final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + RecoverSDCard req = new RecoverSDCard(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + + RecoverSDCard.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + /** + * frameReverseStatus 获取设备翻转状态 + */ + public void frameReverseStatus(final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + FrameReverseStatus req = new FrameReverseStatus(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + + FrameReverseStatus.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (FrameReverseStatus.Response) retObject.resp; + if (retObject.mErrorCode != 0) { + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + int arg1 = 0; + if (resp.data.direction.toString().equals("reverse")) { + arg1 = 1; + } else { + arg1 = 0; + } + handler.obtainMessage(0, arg1, 0).sendToTarget(); + + } + + } + }); + } + + /** + * modifyFrameReverseStatus 设置设备翻转状态 + */ + public void modifyFrameReverseStatus(final String state, final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + ModifyFrameReverseStatus req = new ModifyFrameReverseStatus(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.direction = state; + + ModifyFrameReverseStatus.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + /** + * modifyBreathingLight 获取呼吸灯状态 + */ + public void breathingLightStatus(final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + BreathingLightStatus req = new BreathingLightStatus(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + + BreathingLightStatus.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (BreathingLightStatus.Response) retObject.resp; + if (retObject.mErrorCode != 0) { + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + int arg1; + if (resp.data.status.toString().equals("on")) { + arg1 = 1; + } else { + arg1 = 0; + } + handler.obtainMessage(0, arg1, 0).sendToTarget(); + + } + + } + }); + } + + /** + * modifyBreathingLight 设置呼吸灯开关 + */ + public void modifyBreathingLight(final String state, final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + ModifyBreathingLight req = new ModifyBreathingLight(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + req.data.status = state; + + ModifyBreathingLight.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + /** + * modifyBreathingLight 获取呼吸灯状态 + */ + public void currentDeviceWifi(final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + CurrentDeviceWifi req = new CurrentDeviceWifi(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + + CurrentDeviceWifi.Response resp = null; + RetObject retObject = null; + retObject = request(req); + resp = (CurrentDeviceWifi.Response) retObject.resp; + if (retObject.mErrorCode != 0) { + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + String ssid = resp.data.ssid; + handler.obtainMessage(0, ssid).sendToTarget(); + } + + } + }); + } + + /** + * 升级设备 + * + * @param chnlId + * @param handler + */ + + public void upgradeDevice(final String chnlId, final Handler handler) { + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // TODO Auto-generated method stub + UpgradeDevice req = new UpgradeDevice(); + req.data.token = mToken; + req.data.deviceId = chl.getDeviceCode(); + + UpgradeDevice.Response resp = null; + RetObject retObject = null; + retObject = request(req); + + // 网络请求失败 + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + + } + }); + } + + /** + * 查询报警消息列表 + * + * @param chnlId + * @param deviceId + * @param startTime + * @param endTime + * @param count + * @param handler + */ + public void queryAlarmMessageList(String chnlId, final String startTime, + final String endTime, final int count, final Handler handler) { + mAlarmMessageInfoList.clear(); + final ChannelInfo chl = getChannel(chnlId); + if (chl == null) { + return; + } + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + GetAlarmMessage req = new GetAlarmMessage(); + req.data.token = mToken; + req.data.beginTime = startTime; + req.data.endTime = endTime; + req.data.channelId = String.valueOf(chl.getIndex()); + req.data.count = "" + count; + req.data.deviceId = chl.getDeviceCode(); + Log.d(tag, "startTime:" + req.data.beginTime + "endTime:" + + req.data.endTime + "channelId:" + req.data.channelId + + "deviceId:" + chl.getDeviceCode()); + + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + GetAlarmMessage.Response resp = (GetAlarmMessage.Response) retObject.resp; + // 网络请求失败 + if (retObject.mErrorCode != 0) { + Log.d(tag, "queryAlarmMessageList faied " + retObject.mMsg); + handler.obtainMessage(retObject.mErrorCode).sendToTarget(); + } else { + if (resp.data == null || resp.data.alarms == null) { + Log.d(tag, "query Alarm Message success data is null"); + } + + for (AlarmsElement element : resp.data.alarms) { + AlarmMessageInfo info = new AlarmMessageInfo(); + info.setChnlUuid(chl.getUuid()); + info.setAlarmId(element.alarmId); + info.setType(element.type); + info.setDeviceId(element.deviceId); + info.setDeviceKey(chl.getEncryptKey()); + info.setName(element.name); + // 暂不支持缩略图 + if (element.picurlArray.size() > 0) + info.setPicUrl(element.picurlArray.get(0)); + info.setThumbUrl(element.thumbUrl); + info.setLocalDate(element.localDate); + + info.setTime(element.time); + mAlarmMessageInfoList.add(info); + } + + // todo:其他信息解析请见RestAPI 平台sdk文档 + handler.obtainMessage(0, mAlarmMessageInfoList) + .sendToTarget(); // 发送成功消息到界面 + } + } + }); + } + + /** + * 删除报警消息 + * + * @param indexId + * @param handler + */ + public void deleteAlarmMessage(final AlarmMessageInfo info, + final Handler handler) { + + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + DeleteAlarmMessage req = new DeleteAlarmMessage(); + req.data.token = mToken; + req.data.indexId = info.getAlarmId(); + Log.d(tag, "indexId" + info.getAlarmId()); + + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + DeleteAlarmMessage.Response resp = (DeleteAlarmMessage.Response) retObject.resp; + + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + } + + }); + } + + /** + * 检索已查询出来的录像对象 + * + * @param id + * @return + */ + public RecordInfo getRecord(String id) { + // TODO Auto-generated method stub + for (RecordInfo red : mRecordInfoList) { + if (red.getId().equals(id)) { + return red; + } + } + return null; + } + + public RecordInfo getAllRecord(String id) { + // TODO Auto-generated method stub + for (RecordInfo red : mAllRecordInfoList) { + if (red.getId().equals(id)) { + return red; + } + } + return null; + } + + /** + * 设备密码校验 + * + * @param deviceId + * @param pwd + * @return + */ + public int checkPwdValidity(String deviceId, String pwd) { + // return LCOpenSDK_DeviceInit.getInstance().checkPwdValidity(mToken, deviceId, pwd); + return 1; + } + + /** + * 设备初始化 + * + * @param deviceId + * @param pwd + * @param timeout + * @return + */ + public void searchDevice(final String deviceId, final int timeout, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + + int ret = -1; + String msg = ""; + DeviceInitInfo deviceInitInfo = LCOpenSDK_DeviceInit.getInstance().searchDeviceInitInfo(deviceId, timeout); + if (deviceInitInfo != null) { + if (deviceInitInfo.mStatus == 0) { // 不支持初始化操作 + ret = 0; + msg = "device not support init"; + } else if (deviceInitInfo.mStatus == 1) { // 未初始化 + ret = 1; + msg = "device not init yet"; + } else if (deviceInitInfo.mStatus == 2) { // 已初始化 + ret = 2; + msg = "device already init"; + } else { + ret = -2; + msg = "device not found"; + } + } else { + ret = -1; + msg = "StartSearchDevices failed"; + } + + handler.obtainMessage(ret, deviceInitInfo).sendToTarget(); + + } + }); + + } + + /** + * 修改设备密码 + * + * @param deviceId + * @param oldPwd + * @param newPwd + * @param handler + */ + public void modifyDevicePwd(final String deviceId, final String oldPwd, + final String newPwd, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + + @Override + public void run() { + // if (0 != checkPwdValidity(deviceId, oldPwd)) { + // RetObject retObject = new RetObject(); + // retObject.mErrorCode = -1; + // retObject.mMsg = "checkPwdValidity failed"; + // handler.obtainMessage(retObject.mErrorCode, retObject) + // .sendToTarget(); // 发送成功消息到界面 + // return; + // } + + ModifyDevicePwd req = new ModifyDevicePwd(); + req.data.token = mToken; + req.data.deviceId = deviceId; + req.data.oldPwd = oldPwd; + req.data.newPwd = newPwd; + + RetObject retObject = null; + retObject = request(req); // 码流请求超时时间长一些 + ModifyDevicePwd.Response resp = (ModifyDevicePwd.Response) retObject.resp; + + handler.obtainMessage(retObject.mErrorCode, retObject) + .sendToTarget(); // 发送成功消息到界面 + } + + }); + } + + public void initDevice(final String mac, final String key, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + int ret = LCOpenSDK_DeviceInit.getInstance().initDevice(mac, key); + String msg = ""; + if (ret == 0) { + msg = "Init success"; + } else if (ret == -1) { + msg = "input param is empty"; + } else {//ret = error code + msg = "InitDevAccount failed"; + } + + handler.obtainMessage(ret, msg).sendToTarget(); + } + }); + } + + public void initDeviceByIP(final String mac, final String ip, final String key, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + int ret = LCOpenSDK_DeviceInit.getInstance().initDeviceByIP(mac, ip, key); + String msg = ""; + if (ret == 0) { + msg = "Init success"; + } else if (ret == -1) { + msg = "input param is empty"; + } else {//ret = error code + msg = "InitDevAccountByIP failed"; + } + + handler.obtainMessage(ret, msg).sendToTarget(); + } + }); + } + + public void addDevices(final String devicesJsonStr, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + // TODO Auto-generated method stub + int ret = LCOpenSDK_LoginManager.addDevices(mToken, devicesJsonStr); + String msg = ""; + if (ret == 1) + msg = "addDevices success"; + else if (ret == -1) + msg = "init server failed"; + else + msg = "addDevices failed"; + + handler.obtainMessage(ret, msg).sendToTarget(); + } + }); + } + + private static class Instance { + static Business instance = new Business(); + } + + public static class CloudStorageCode { + public static final String HLS_DOWNLOAD_FAILD = "0"; // 下载失败 + public static final String HLS_DOWNLOAD_BEGIN = "1"; // 开始下载 + public static final String HLS_DOWNLOAD_END = "2"; // 下载结束 + public static final String HLS_SEEK_SUCCESS = "3"; // 定位成功 + public static final String HLS_SEEK_FAILD = "4"; // 定位失败 + // public static final String HLS_ABORT_DONE = "5"; + // public static final String HLS_RESUME_DONE = "6"; + public static final String HLS_KEY_ERROR = "11"; // 秘钥错误 + } + + public static class LocalDownloadCode { + public static final String RTSP_DOWNLOAD_FRAME_ERROR = "0"; + public static final String RTSP_DOWNLOAD_TEARDOWN = "1"; + public static final String RTSP_DOWNLOAD_AUTHORIZATION_FAIL = "3"; + public static final String RTSP_DOWNLOAD_BEGIN = "4"; + public static final String RTSP_DOWNLOAD_OVER = "5"; + public static final String RTSP_DOWNLOAD_PAUSE = "6"; + public static final String RTSP_DOWNLOAD_KEY_MISMATH = "7"; + } + + public static class PlayerResultCode { + public static final String STATE_PACKET_FRAME_ERROR = "0"; // 组帧失败 + public static final String STATE_RTSP_TEARDOWN_ERROR = "1"; // 内部要求关闭,如连接断开等 + public static final String STATE_RTSP_DESCRIBE_READY = "2"; // 会话已经收到Describe响应 + public static final String STATE_RTSP_AUTHORIZATION_FAIL = "3"; // RTSP鉴权失败 + public static final String STATE_RTSP_PLAY_READY = "4"; // 收到PLAY响应 + // public static final String STATE_RTSP_FILE_PLAY_OVER = "5"; // + // 录像文件回放正常结束 + public static final String STATE_RTSP_KEY_MISMATCH = "7"; + } + + public static class RetObject { + public int mErrorCode = 0; // 错误码表示符 -1:返回体为null,0:成功,1:http错误, 2:业务错误 + public String mMsg; + public Object resp; + } + + public final class HttpCode { + public static final int SC_OK = 200;// OK + // (API调用成功,但是具体返回结果,由content中的code和desc描述) + public static final int Bad_Request = 400;// Bad Request (API格式错误,无返回内容) + public static final int Unauthorized = 401;// Unauthorized + // (用户名密码认证失败,无返回内容) + public static final int Forbidden = 403;// Forbidden (认证成功但是无权限,无返回内容) + public static final int Not_Found = 404;// Not Found (请求的URI错误,无返回内容) + public static final int Precondition_Failed = 412;// Precondition Failed + // (先决条件失败,无返回内容。通常是由于客户端所带的x-hs-date时间与服务器时间相差过大。) + public static final int Internal_Server_Error = 500;// Internal Server + // Error + // (服务器内部错误,无返回内容) + public static final int Service_Unavailable = 503;// Service Unavailable + // (服务不可用,无返回内容。这种情况一般是因为接口调用超出频率限制。) + } + +} diff --git a/app/src/main/java/com/lechange/demo/business/entity/AlarmMessageInfo.java b/app/src/main/java/com/lechange/demo/business/entity/AlarmMessageInfo.java new file mode 100644 index 0000000..607fef2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/entity/AlarmMessageInfo.java @@ -0,0 +1,114 @@ +package com.lechange.demo.business.entity; + + +public class AlarmMessageInfo { + + private String chnlUuid; // 通道的uuid + + /** [long]消息ID */ + private long alarmId; + + /** [int]报警类型 */ + private int type; + + /** 设备或通道的名称 */ + private String name = ""; + + /** ***LLLJHHDF */ + private String thumbUrl = ""; + private String picUrl = ""; + + /** 报警时设备本地时间,格式如2014-12-12 12:12:12 */ + private String localDate = ""; + + private String deviceId; //设备ID + private String deviceKey; //设备秘钥 + + /** [long]报警时间UNIX时间戳秒 */ + private long time; + + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public long getAlarmId() { + return alarmId; + } + + public void setAlarmId(long alarmId) { + this.alarmId = alarmId; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPicUrl() { + return picUrl; + } + + public void setPicUrl(String picUrl) { + this.picUrl = picUrl; + } + + public String getThumbUrl() { + return thumbUrl; + } + + public void setThumbUrl(String thumbUrl) { + this.thumbUrl = thumbUrl; + } + + public String getLocalDate() { + return localDate; + } + + public void setLocalDate(String localDate) { + this.localDate = localDate; + } + + + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getChnlUuid() { + return chnlUuid; + } + + public void setChnlUuid(String chnlUuid) { + this.chnlUuid = chnlUuid; + } + + public String getDeviceKey() { + return deviceKey; + } + + public void setDeviceKey(String deviceKey) { + this.deviceKey = deviceKey; + } + + +} diff --git a/app/src/main/java/com/lechange/demo/business/entity/ChannelInfo.java b/app/src/main/java/com/lechange/demo/business/entity/ChannelInfo.java new file mode 100644 index 0000000..4cc878b --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/entity/ChannelInfo.java @@ -0,0 +1,175 @@ +package com.lechange.demo.business.entity; + +import com.tuya.sdk.blelib.channel.ChannelState; + +import java.util.UUID; + +public class ChannelInfo { + + private String id = UUID.randomUUID().toString(); + private int index; // 通道索引 + private String name; // 通道名称 + private ChannelState state; // 通道状态 + private String backgroudImgURL; // 背景图URL + private String deviceCode; // 关联的设备id + private String deviceModel; // 关联的设备型号 + private String encryptKey; // 秘钥的key + private String deviceName; // 设备名称 + private String deviceType; // 设备类型 + private int encryptMode; // 秘钥模式:0-默认模式,1-自定义模式 + private int encrypt; // 是否支持加密 + private int ability; + private int cloudMealStates; //云套餐状态 + private int alarmStatus; //动检计划状态 + + public String getDeviceType() { + return deviceType == null ? "" : deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public String getDeviceName() { + return deviceName == null ? "" : deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public ChannelState getState() { + return state; + } + + public void setState(ChannelState state) { + this.state = state; + } + + public String getUuid() { + return id; + } + + public String getId() { + return id == null ? "" : id; + } + + public void setId(String id) { + this.id = id; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getName() { + return name == null ? "" : name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBackgroudImgURL() { + return backgroudImgURL == null ? "" : backgroudImgURL; + } + + public void setBackgroudImgURL(String backgroudImgURL) { + this.backgroudImgURL = backgroudImgURL; + } + + public String getDeviceCode() { + return deviceCode == null ? "" : deviceCode; + } + + public void setDeviceCode(String deviceCode) { + this.deviceCode = deviceCode; + } + + public String getDeviceModel() { + return deviceModel == null ? "" : deviceModel; + } + + public void setDeviceModel(String deviceModel) { + this.deviceModel = deviceModel; + } + + public String getEncryptKey() { + return encryptKey == null ? "" : encryptKey; + } + + public void setEncryptKey(String encryptKey) { + this.encryptKey = encryptKey; + } + + public int getEncryptMode() { + return encryptMode; + } + + public void setEncryptMode(int encryptMode) { + this.encryptMode = encryptMode; + } + + public int getEncrypt() { + return encrypt; + } + + public void setEncrypt(int encrypt) { + this.encrypt = encrypt; + } + + public int getAbility() { + return ability; + } + + public void setAbility(int ability) { + this.ability = ability; + } + + public int getCloudMealStates() { + return cloudMealStates; + } + + public void setCloudMealStates(int cloudMealStates) { + this.cloudMealStates = cloudMealStates; + } + + public int getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(int alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public enum ChannelState { + Online, // 在线 + Offline, // 离线 + Upgrade, // 升级中 + } + + /** + * 设备能力集合 + * + * @author 23930 + */ + public class Ability { + public static final int WLAN = 1; // 设备支持接入无线局域网 + public static final int AlarmPIR = 2;// 设备支持人体红外报警 + public static final int AlarmMD = 4; // 设备支持动检报警 + public static final int AudioTalk = 8; // 设备支持语音对讲 + public static final int VVP2P = 16; // 设备支持威威网络P2P服务 + public static final int DHP2P = 32; // 设备支持大华P2P服务 + public static final int PTZ = 64; //设备支持云台操作 + public static final int HSEncrypt = 128; // 设备支持华视微讯码流加密 + public static final int CloudStorage = 256; // 设备支持华视微讯平台云存储 + public static final int SUPPORT_DHHTTP_LIVE = 512; //支持私有协议直播 + public static final int SUPPORT_DHHTTP_PLAYBACK = 1024; //支持私有协议回放 + public static final int SUPPORT_DHHTTP_TALK = 2048; //支持私有协议对讲 + public static final int TCM = 4096; //设备支持TCM能力 + } +} diff --git a/app/src/main/java/com/lechange/demo/business/entity/ChannelPTZInfo.java b/app/src/main/java/com/lechange/demo/business/entity/ChannelPTZInfo.java new file mode 100644 index 0000000..4b637d6 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/entity/ChannelPTZInfo.java @@ -0,0 +1,91 @@ +package com.lechange.demo.business.entity; +/** + * 文件描述:package com.android.business.entity; + * 功能说明: + * 版权申明: + * @author ding_qili + * @version 2015-6-17下午3:29:12 + */ + +public class ChannelPTZInfo { + + public enum Operation{ + Move,//移动 + Locate,//定位 + Stop;//立即停止! + } + + + public enum Duration{//持续多久 + Forever,//永远 + Long,//长 + Generral,//普通 + Short;//短 + } + + public enum Direction{//方向 + Left, + Right, + Up, + Down, + ZoomIn, + ZoomOut; + } + + public ChannelPTZInfo(Operation operation,Direction direction) { + this.operation = operation; + this.direction = direction; + } + + + + /** 操作行为;move表示移动,locate表示定位 */ + private Operation operation = Operation.Move; + /** + * 持续时间 + */ + private Duration duration = Duration.Generral; + /** + * 方向 + */ + private Direction direction = Direction.Left; + /** + * @return the operation + */ + public Operation getOperation() { + return operation; + } + /** + * @param operation the operation to set + */ + public void setOperation(Operation operation) { + this.operation = operation; + } + /** + * @return the duration + */ + public Duration getDuration() { + return duration; + } + /** + * @param duration the duration to set + */ + public void setDuration(Duration duration) { + this.duration = duration; + } + /** + * @return the direction + */ + public Direction getDirection() { + return direction; + } + /** + * @param direction the direction to set + */ + public void setDirection(Direction direction) { + this.direction = direction; + } + + + +} diff --git a/app/src/main/java/com/lechange/demo/business/entity/RecordInfo.java b/app/src/main/java/com/lechange/demo/business/entity/RecordInfo.java new file mode 100644 index 0000000..e567560 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/entity/RecordInfo.java @@ -0,0 +1,128 @@ +package com.lechange.demo.business.entity; + +import java.util.UUID; + +public class RecordInfo { + + public enum RecordType + { + DeviceLocal, // 设备本地录像 + PrivateCloud, // 私有云 + PublicCloud, // 公有云 + } + + public enum RecordEventType + { + All, // 所有录像 + Manual, // 手动录像 + Event, // 事件录像 + } + + private String id = UUID.randomUUID().toString(); + private RecordType type; // 录像类型 + private float fileLength; // 文件长度 + private float downLength = -1; // 已下载长度 + private long startTime; // 开始时间 + private long endTime; // 结束时间 + private String deviceId; //设备ID + private String deviceKey; + private String backgroudImgUrl; // 录像文件Url + private String chnlUuid; // 通道的uuid + private RecordEventType eventType; // 事件类型 + private String recordID; //录像ID + private String recordPath; //录像ID(设备录像) + private String recordRegionId; //新的录像ID + + + public String getRecordRegionId() { + return recordRegionId; + } + public void setRecordRegionId(String recordRegionId) { + this.recordRegionId = recordRegionId; + } + + + public String getDeviceId() { + return deviceId; + } + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + public String getDeviceKey() { + return deviceKey; + } + public void setDeviceKey(String deviceKey) { + this.deviceKey = deviceKey; + } + + public RecordType getType() { + return type; + } + public void setType(RecordType type) { + this.type = type; + } + public long getStartTime() { + return startTime; + } + public float getFileLength() { + return fileLength; + } + public void setFileLength(float fileLength) { + this.fileLength = fileLength; + } + public float getDownLength() { + return downLength; + } + public void setDownLength(float downLength) { + this.downLength = downLength; + } + public void setStartTime(long startTime) { + this.startTime = startTime; + } + public long getEndTime() { + return endTime; + } + public void setEndTime(long endTime) { + this.endTime = endTime; + } + public String getBackgroudImgUrl() { + return backgroudImgUrl; + } + public void setBackgroudImgUrl(String backgroudImgUrl) { + this.backgroudImgUrl = backgroudImgUrl; + } + public String getChnlUuid() { + return chnlUuid; + } + public void setChnlUuid(String chnlUuid) { + this.chnlUuid = chnlUuid; + } + public RecordEventType getEventType() { + return eventType; + } + public void setEventType(RecordEventType eventType) { + this.eventType = eventType; + } + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public void setRecordID(String id) { + this.recordID = id; + } + public String getRecordID() { + return this.recordID; + } + + public boolean isDownload() { + return downLength >= 0; + } + public String getRecordPath() { + return recordPath; + } + public void setRecordPath(String recordPath) { + this.recordPath = recordPath; + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/HttpUtils.java b/app/src/main/java/com/lechange/demo/business/util/HttpUtils.java new file mode 100644 index 0000000..9b32389 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/HttpUtils.java @@ -0,0 +1,227 @@ +package com.lechange.demo.business.util; + +import android.net.Uri; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * @author 31833 + * @version Version Time Description
+ * 1.0 2017/3/4 13:45 封装HTTP的相关请求 + */ + +public class HttpUtils { + + private static final String ALLOWED_URL_CHARS = "@#&=*+-_.,:!?()/~'%"; + + private static final String CHARSET = "UTF-8"; + + private static final int connectTimeout = 5 * 1000; + + private static final int readTimout = 10 * 1000; + + private static HttpUtils instance; + + private TrustManager[] trustAllCerts = {new TrustAllX509TrustManager()}; + + public static HttpUtils getInstance() { + if (instance == null) { + synchronized (HttpUtils.class) { + if (instance == null) { + instance = new HttpUtils(); + } + } + } + return instance; + } + + private HttpUtils() { + + try { + HttpsURLConnection.setDefaultHostnameVerifier(new NullhostNameVerifier()); + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpURLConnection.setFollowRedirects(true); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } + + public HttpURLConnection createConnection(String url) throws IOException { + + String encodeUrl = Uri.encode(url, ALLOWED_URL_CHARS); + HttpURLConnection conn = (HttpURLConnection) new URL(encodeUrl).openConnection(); + conn.setConnectTimeout(connectTimeout); + conn.setReadTimeout(readTimout); + + return conn; + } + + public InputStream getInputStream(String url) { + InputStream is = null; + + try { + HttpURLConnection conn = createConnection(url); + conn.setRequestMethod("GET"); + is = conn.getInputStream(); + } catch (Exception e) { + e.printStackTrace(); + } + return is; + } + + public String getString(String url) { + String result = null; + InputStream is = null; + BufferedReader br = null; + + try { + is = getInputStream(url); + br = new BufferedReader(new InputStreamReader(is, CHARSET)); + String line = null; + StringBuffer sb = new StringBuffer(); + + while ((line = br.readLine()) != null) { + sb.append(line); + } + result = sb.toString(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (br != null) { + br.close(); + } + } catch (IOException e) { + + } + + try { + if (is != null) { + is.close(); + } + } catch (IOException e) { + + } + + } + return result; + } + + public String postString(String url, String params) { + String result = null; + OutputStream os = null; + InputStream is = null; + BufferedReader br = null; + + try { + HttpURLConnection conn = createConnection(url); + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches(false); + + conn.setRequestProperty("Content_Type", "application/json;charset= " + CHARSET); + + if (params != null) { + os = conn.getOutputStream(); + DataOutputStream dos = new DataOutputStream(os); + dos.write(params.getBytes(CHARSET)); + dos.flush(); + dos.close(); + ; + } + + is = conn.getInputStream(); + br = new BufferedReader(new InputStreamReader(is, CHARSET)); + String line = null; + + StringBuffer sb = new StringBuffer(); + + while ((line = br.readLine()) != null) { + sb.append(line); + } + + result = sb.toString(); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (os != null) { + os.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + if (is != null) { + is.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + return result; + } + + + private boolean shouldBeProcessed(HttpURLConnection conn) throws IOException { + return conn.getResponseCode() == 200; + } + + private static class NullhostNameVerifier implements HostnameVerifier { + + public NullhostNameVerifier() { + + } + + @Override + public boolean verify(String host, SSLSession session) { + return true; + } + } + + private static class TrustAllX509TrustManager implements X509TrustManager { + + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/ImageHelper.java b/app/src/main/java/com/lechange/demo/business/util/ImageHelper.java new file mode 100644 index 0000000..7f4505e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/ImageHelper.java @@ -0,0 +1,209 @@ +package com.lechange.demo.business.util; + +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.BitmapFactory.Options; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.LruCache; + +import com.lechange.demo.business.util.TaskPoolHelper.RunnableTask; +import com.lechange.opensdk.utils.LCOpenSDK_Utils; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class ImageHelper { + + private final static String TAG = "ImageHelper"; + private static Options mDefaultOption; + //最近最少使用算法的缓存策略 + private static LruCache mImageCache = new LruCache(100); + + static{ + mDefaultOption = new Options(); + //demo里面为了降低使用内存,图片缩小了一倍 + mDefaultOption.inSampleSize = 2; + mDefaultOption.inPreferredConfig = Config.RGB_565; + } + + + + public static void loadRealImage(final String url, final Handler handler) { + downloadImage(url, "real", handler); + } + + /** + * 加载普通图片(缓存) + * @param url + * @param key + * @param handler + */ + public static void loadCacheImage(final String url, final Handler handler) { + String[] imageIDBuffer = url.split("[/?]"); + final String imageID = imageIDBuffer[imageIDBuffer.length - 2]; + Drawable drawable = mImageCache.get(imageID); + if(drawable != null){ + Message msg = new Message(); + msg.what = url.hashCode(); + msg.obj = drawable; + handler.handleMessage(msg); + } + else{ + downloadImage(url, imageID, handler); + } + } + + + + /** + * 加载加密图片(实时) + * @param url + * @param key + * @param handler + */ + public static void loadRealImage(final String url,String deviceId, String key, final Handler handler) { + downloadImage(url, "real",deviceId, key, handler); + } + + + /** + * 加载加密图片(缓存) + * @param url + * @param key + * @param handler + */ + public static void loadCacheImage(final String url,final String deviceId, String key, final Handler handler) { + String[] imageIDBuffer = url.split("[/?]"); + final String imageID = imageIDBuffer[imageIDBuffer.length - 2]; + Drawable drawable = mImageCache.get(imageID); + if(drawable != null){ + Message msg = new Message(); + msg.what = url.hashCode(); + msg.obj = drawable; + handler.handleMessage(msg); + } + else{ + downloadImage(url, imageID,deviceId, key, handler); + } + } + + + /** + * 下载普通图片任务 + * @param url + * @param imageID + * @param handler + */ + private static void downloadImage(final String url, final String imageID, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask(imageID) { + @Override + public void run() { + // TODO Auto-generated method stub + Drawable drawable = null; + try { + //创建一个url对象 + URL resurl = new URL(url); + //设置超时时间 + HttpURLConnection urlConn = (HttpURLConnection) resurl.openConnection(); + urlConn.setConnectTimeout(5000); + urlConn.setReadTimeout(5000); + //打开URL对应的资源输入流 + InputStream is= urlConn.getInputStream(); + //从InputStream流中解析出图片 + Bitmap bitmap = BitmapFactory.decodeStream(is, null, mDefaultOption); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + //加入缓存 + mImageCache.put(imageID, drawable); + //关闭输入流 + is.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + // 解析设备列表信息 + handler.obtainMessage(url.hashCode(), drawable).sendToTarget(); // 发送成功消息到界面 + } + }); + } + + /** + * 下载加密图片任务 + * @param url + * @param imageID + * @param key + * @param handler + */ + private static void downloadImage(final String url, final String imageID, final String deviceId,final String key, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask(imageID) { + @Override + public void run() { + // TODO Auto-generated method stub + Drawable drawable = null; + try { + //创建一个url对象 + URL resurl = new URL(url); + //设置超时时间 + HttpURLConnection urlConn = (HttpURLConnection) resurl.openConnection(); + urlConn.setConnectTimeout(5000); + urlConn.setReadTimeout(5000); + //打开URL对应的资源输入流 + InputStream is= urlConn.getInputStream(); + //从InputStream流中解析出图片 + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + byte[] buff = new byte[500]; + int rc = 0; + int length = 0; + while((rc = is.read(buff,0,500)) >0) + { + length += rc; + swapStream.write(buff,0,rc); + } + + byte[] srcBuf = swapStream.toByteArray(); + byte[] dstBuf = new byte[500000]; + int[] dstLen = new int[1]; + dstLen[0] = 500000; + Bitmap bitmap; //=null + switch(LCOpenSDK_Utils.decryptPic(srcBuf,length,deviceId,key,dstBuf,dstLen)){ + case 0: //解密成功 + bitmap = BitmapFactory.decodeByteArray(dstBuf, 0, dstLen[0], mDefaultOption); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + break; + case 3: //图片非加密 + bitmap = BitmapFactory.decodeByteArray(srcBuf, 0, length, mDefaultOption); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + break; + default: //解密失败 + break; + } + //加入缓存 + mImageCache.put(imageID, drawable); + //关闭输入流 + is.close(); + swapStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解析设备列表信息 + handler.obtainMessage(url.hashCode(), drawable).sendToTarget(); // 发送成功消息到界面 + } + }); + } + + public static void clear() { + TaskPoolHelper.clearTask(); + mImageCache.evictAll(); + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/MD5Helper.java b/app/src/main/java/com/lechange/demo/business/util/MD5Helper.java new file mode 100644 index 0000000..0f91ab3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/MD5Helper.java @@ -0,0 +1,91 @@ +package com.lechange.demo.business.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class MD5Helper +{ + private static byte[] hex = new byte[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + /** + * 对字符串进行MD5加密 + * @param rawString 要加密的字符串 + * @return MD5摘要码 + */ + public static String encode(String rawString) + { + String md5String = null; + + try + { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(rawString.getBytes()); + md5String = convertToHexString(md5.digest()); + } + catch (NoSuchAlgorithmException e) + { + e.printStackTrace(); + } + + if (null != md5String) + { + return md5String.toUpperCase(); + } + + return md5String; + } + + public static String encodeToLowerCase(String rawString){ + return encode(rawString).toLowerCase(); + } + + /** + * 对文件全文生成MD5摘要 + * @param file 要加密的文件 + * @return MD5摘要码 + */ + public static String getMD5(File file) { + FileInputStream fis = null; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + + fis = new FileInputStream(file); + byte[] buffer = new byte[2048]; + int length = -1; + while ((length = fis.read(buffer)) != -1) { + md.update(buffer, 0, length); + } + byte[] b = md.digest(); + return convertToHexString(b);//byteToHexString(b); + // 16位加密 + // return buf.toString().substring(8, 24); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } finally { + try { + fis.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + } + + private static String convertToHexString(byte[] digests) + { + byte[] md5String = new byte[digests.length * 2]; + + int index = 0; + for (byte digest : digests) + { + md5String[index] = hex[(digest >> 4) & 0x0F]; + md5String[index + 1] = hex[digest &0x0F]; + index += 2; + } + + return new String(md5String); + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/MediaPlayHelper.java b/app/src/main/java/com/lechange/demo/business/util/MediaPlayHelper.java new file mode 100644 index 0000000..b51fd22 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/MediaPlayHelper.java @@ -0,0 +1,132 @@ +package com.lechange.demo.business.util; + +import android.app.Activity; +import android.os.Environment; +import android.view.WindowManager; + +import java.io.File; +import java.text.SimpleDateFormat; + +public class MediaPlayHelper { + + private final static String ProjectName = "LechangeDemo"; + + public enum DHFilesType { + DHImage, + DHVideo + } + + + public static void setFullScreen(Activity activity) { + activity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + public static void quitFullScreen(Activity activity) { + final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); + attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); + activity.getWindow().setAttributes(attrs); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + + + + /** + * 创建文件路径 + * @param file + * @param filePath + * @return + */ + public static boolean createFilePath(File file, String filePath) { + int index = filePath.indexOf("/"); + if (index == -1) { + return false; + } + if (index == 0) { + filePath = filePath.substring(index + 1, filePath.length()); + index = filePath.indexOf("/"); + } + String path = filePath.substring(0, index); + File fPath; + if (file == null) { + fPath = new File(path); + } else { + fPath = new File(file.getPath() + "/" + path); + } + if (!fPath.exists()) { + if (!fPath.mkdir()) // SD卡已满无法在下载文件 + { + return false; + } + } + if (index < (filePath.length() - 1)) { + String exPath = filePath.substring(index + 1, filePath.length()); + createFilePath(fPath, exPath); + } + return true; + + } + + /** + * 生成抓图路径或录像存放路径 + * + */ + public static String getCaptureAndVideoPath(DHFilesType type, String cameraName) { + String path = null; + String picType = null; + java.util.Date now = new java.util.Date(); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + String sdPath = Environment.getExternalStorageDirectory().getPath(); + if(type == DHFilesType.DHImage){ + picType = "image"; + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + cameraName + ".jpg"; + } else{ + picType = "video"; + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + cameraName + ".mp4"; + } + createFilePath(null, path); + return path; + } + + /** + * 生成下载录像存放路径 + * + */ + public static String getDownloadVideoPath(int type, String recordID, long startTime) { + String path = null; + String sdPath = Environment.getExternalStorageDirectory().getPath(); + String picType = "download"; + picType += type==0 ? "_cloud" : "_remote"; + + java.util.Date now = new java.util.Date(startTime); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + recordID + ".mp4"; + createFilePath(null, path); + return path; + } + + /** + * 删除下载录像存放的录像 + * + */ + public static void deleteDownloadVideo(String recordID, long startTime) { + String path = null; + String sdPath = Environment.getExternalStorageDirectory().getPath(); + String picType = "download"; + java.util.Date now = new java.util.Date(startTime); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + recordID + ".mp4"; + + File soFile = new File(path); + if (soFile.exists()) { + soFile.delete(); + } + + } + +} diff --git a/app/src/main/java/com/lechange/demo/business/util/OpenApiHelper.java b/app/src/main/java/com/lechange/demo/business/util/OpenApiHelper.java new file mode 100644 index 0000000..553c16a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/OpenApiHelper.java @@ -0,0 +1,192 @@ +package com.lechange.demo.business.util; + +import android.os.Handler; +import android.util.Log; + +import org.json.JSONObject; + + +public class OpenApiHelper { + + public final static String tag = "OpenApiHelper"; + + + public static void getAccessToken(final String host, + final String phoneNumber, final String appid, + final String appsecret, final Handler handler) { + // 拼装url + String url = ""; + if (host.endsWith(":443")) { + url = "https://" + host + "/openapi/accessToken"; + } else { + url = "http://" + host + "/openapi/accessToken"; + } + Log.d(tag, url); + getToken(url, phoneNumber, appid, appsecret, handler); + } + + public static void getUserToken(final String host, + final String phoneNumber, final String appid, + final String appsecret, final Handler handler) { + // 拼装url + String url = ""; + if (host.endsWith(":443")) { + url = "https://" + host + "/openapi/userToken"; + } else { + url = "http://" + host + "/openapi/userToken"; + } + Log.d(tag, url); + getToken(url, phoneNumber, appid, appsecret, handler); + } + + public static void userBindSms(final String host, final String phoneNumber, + final String appid, final String appsecret, final Handler handler) { + String url = ""; + if (host.endsWith(":443")) { + url = "https://" + host + "/openapi/userBindSms"; + } else { + url = "http://" + host + "/openapi/userBindSms"; + } + Log.d(tag, url); + + int code = -1; + String result = null; + try { + JSONObject body = new JSONObject(); + String data = "{phone: \"" + phoneNumber + "\"}"; + body.put("params", new JSONObject(data)); + body.put("id", "1");// id号 随机值 + + body.put( + "system", + new JSONObject(SignHelper.getSystem(data, appid, appsecret, + "1.1"))); + + String response = HttpUtils.getInstance().postString(url, body.toString()); + + JSONObject res = new JSONObject((String) response); + if (res.getJSONObject("result").getString("code").equals("0")) { + code = 0; + result = res.getJSONObject("result").getString("msg"); + } else { + code = -1; + result = res.getJSONObject("result").getString("msg"); + + } + + } catch (Exception e) { + e.printStackTrace(); + result = e.getMessage(); + } + + handler.obtainMessage(code, result).sendToTarget(); + + } + + public static void userBind(final String host, final String phoneNumber, + final String appId, String appSecret, final String smsCode, + final Handler handler) { + String url = ""; + if (host.endsWith(":443")) { + url = "https://" + host + "/openapi/userBind"; + } else { + url = "http://" + host + "/openapi/userBind"; + } + Log.d(tag, url); + + + int code = -1; + String result = null; + try { + JSONObject body = new JSONObject(); + String data = "{phone: \"" + phoneNumber + "\",smsCode:\"" + smsCode + + "\"}"; + body.put("params", new JSONObject(data)); + body.put("id", "1");// id号 随机值 + body.put( + "system", + new JSONObject(SignHelper.getSystem(data, appId, appSecret, + "1.1"))); + + + String response = HttpUtils.getInstance().postString(url, body.toString()); + Log.d("Uriah", "response" + response); + JSONObject res = new JSONObject((String) response); + if (res.getJSONObject("result").getString("code").equals("0")) { + code = 0; + result = res.getJSONObject("result").getString("msg"); + } else { + code = -1; + result = res.getJSONObject("result").getString("msg"); + + } + + } catch (Exception e) { + e.printStackTrace(); + result = e.getMessage(); + } + + handler.obtainMessage(code, result).sendToTarget(); + } + + private static void getToken(final String host, final String phoneNumber, + final String appid, final String appsecret, final Handler handler) { + + int code = -1; + String result = null; + try { + JSONObject body = new JSONObject(); + String data = "{phone:\"" + phoneNumber + "\"}"; + body.put("params", new JSONObject(data)); + body.put("id", "1");// id号 随机值 + body.put( + "system", + new JSONObject(SignHelper.getSystem(data, appid, appsecret, + "1.1"))); + + String response = HttpUtils.getInstance().postString(host, body.toString()); + + if(response != null){ + JSONObject res = new JSONObject((String) response); + if (res.getJSONObject("result").getString("code").equals("0")) { + code = 0; + if (res.getJSONObject("result").getJSONObject("data") + .has("accessToken")) { + result = res.getJSONObject("result") + .getJSONObject("data") + .getString("accessToken"); + } else { + result = res.getJSONObject("result") + .getJSONObject("data") + .getString("userToken"); + } + } else { + code = -1; + result = res.getJSONObject("result").getString("msg"); + // 界面展示和业务需要 特殊处理 + if (res.getJSONObject("result").getString("code") + .equals("TK1004")) + code = 1; + if (res.getJSONObject("result").getString("code") + .equals("TK1006")) + code = 1; + + } + }else{ + code = -1; + result = "get Token failed,Response is null"; + } + + } catch (Exception e) { + e.printStackTrace(); + result = e.getMessage(); + } + + handler.obtainMessage(code, result).sendToTarget(); + + } + +} + + + diff --git a/app/src/main/java/com/lechange/demo/business/util/PermissionHelper.java b/app/src/main/java/com/lechange/demo/business/util/PermissionHelper.java new file mode 100644 index 0000000..2aba920 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/PermissionHelper.java @@ -0,0 +1,43 @@ +package com.lechange.demo.business.util; + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.support.v4.app.ActivityCompat; + +/** + * @author 31833 + * @version Version Time Description
+ * 1.0 2017/4/27 15:42 运行时权限申请帮助类 + */ + +public class PermissionHelper { + + private static boolean isHasPermission(Context context, String permission){ + + if(Build.VERSION.SDK_INT < 23) { + return true; + } + + return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; + + } + + + public static void requestPermission(Activity activity, String[] permissions) { + boolean flag = true; + + for (String permission : permissions) { + if(isHasPermission(activity,permission)){ + flag = false; + break; + } + continue; + } + + if(flag) { + ActivityCompat.requestPermissions(activity, permissions, permissions.length); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/SignHelper.java b/app/src/main/java/com/lechange/demo/business/util/SignHelper.java new file mode 100644 index 0000000..28a829f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/SignHelper.java @@ -0,0 +1,84 @@ +package com.lechange.demo.business.util; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +public class SignHelper { + public static String getSystem(String data, String appId, String appSecret, String sysVersion){ + StringBuffer sign = new StringBuffer(); + try { + JSONObject params = new JSONObject(data); + Iterator it = params.keys(); + List keyList = new ArrayList(); + while(it.hasNext()){ + keyList.add(it.next().toString()); + } + Collections.sort(keyList); + for(String key : keyList){ + sign.append("").append(key).append(":").append(params.get(key).toString()).append(","); + } + //System.out.println(sign); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String time = Long.toString(System.currentTimeMillis()/1000); + String nonce = randomString(32); + sign.append("time").append(":").append(time).append(","); + sign.append("nonce").append(":").append(nonce).append(","); + sign.append("appSecret").append(":").append(appSecret); + //System.out.println(sign); + JSONObject system = new JSONObject(); + try { + system.put("ver", sysVersion); + system.put("sign", md5Hex(sign.toString())); + system.put("appId", appId); + system.put("time", time); + system.put("nonce", nonce); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return system.toString(); + } + + public static String md5Hex(String str) { + try { + byte hash[] = MessageDigest.getInstance("MD5").digest(str.getBytes()); + StringBuilder hex = new StringBuilder(hash.length * 2); + for (byte b : hash) { + if ((b & 0xFF) < 0x10) { + hex.append("0"); + } + hex.append(Integer.toHexString(b & 0xFF)); + } + return hex.toString(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + final static String VEC = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + private static Random rand; + public static String randomString(int length) { + if (rand == null) { + rand = new Random(System.currentTimeMillis()); + } + String ret = ""; + for (int i = 0; i < length; i++) { + ret = ret + VEC.charAt(rand.nextInt(VEC.length())); + } + return ret; + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/TaskPoolHelper.java b/app/src/main/java/com/lechange/demo/business/util/TaskPoolHelper.java new file mode 100644 index 0000000..8f5aa65 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/TaskPoolHelper.java @@ -0,0 +1,102 @@ +package com.lechange.demo.business.util; + +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.locks.LockSupport; + +public class TaskPoolHelper { + private final static String TAG = "TaskPoolHelper"; + + /** + * 构造具备过滤的task + */ + public static abstract class RunnableTask implements Runnable{ + public String mTaskID; + + public RunnableTask(String taskID){ + this.mTaskID = taskID; + } + } + + //private static ExecutorService mPool = Executors.newFixedThreadPool(3); + //队列属性的task + private static ArrayBlockingQueue mQueueTask = new ArrayBlockingQueue(50); + private static List mFilteTask = new ArrayList(); + private static Thread mQueueThread; + + //实时属性的task + private static RunnableTask mRealTask; //=null + private static Thread mRealThread; + + static { + mQueueThread = new Thread() { + @Override + public void run() { + // TODO Auto-generated method stub + super.run(); + while (true) { + try { + //自带阻塞光环 + RunnableTask task = mQueueTask.take(); + task.run(); + mFilteTask.remove(task.mTaskID); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + }; + mQueueThread.start(); + + mRealThread = new Thread() { + @Override + public void run() { + // TODO Auto-generated method stub + super.run(); + while (true) { + if (mRealTask == null) { + LockSupport.park(); + } else { + RunnableTask task = mRealTask; + mRealTask = null; + task.run(); + } + } + } + }; + mRealThread.start(); + } + + + public static void addTask(RunnableTask task) { + //过滤 + if (task.mTaskID.equals("real")) { + mRealTask = task; + LockSupport.unpark(mRealThread); + return; + } + if (mFilteTask.contains(task.mTaskID)) { + return; + } + + try { + mQueueTask.add(task); + mFilteTask.add(task.mTaskID); + } catch(IllegalStateException e) { + Log.w(TAG, e.getMessage()); + mQueueTask.clear(); + mFilteTask.clear(); + } + } + + + public static void clearTask(){ + mQueueTask.clear(); + mFilteTask.clear(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/business/util/TimeHelper.java b/app/src/main/java/com/lechange/demo/business/util/TimeHelper.java new file mode 100644 index 0000000..0d2b00c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/TimeHelper.java @@ -0,0 +1,44 @@ +package com.lechange.demo.business.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class TimeHelper { + + public static String getDateHMS(long time) { + SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); + Date date = new Date(time); + String strdate = format.format(date); + return strdate;// 2012-10-03 23:41:31 + } + + public static String getTimeHMS(long time) { + SimpleDateFormat format1 = new SimpleDateFormat("HH:mm:ss"); + Date date = new Date(time); + String date1 = format1.format(date); + return date1;// 2012-10-03 23:41:31 + } + + public static String getDateEN(long time) { + SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = new Date(time); + String date1 = format1.format(date); + return date1;// 2012-10-03 23:41:31 + } + + public static long getTimeStamp(String time) { + SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = null; + try { + date = format1.parse(time); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (date == null) { + return -1; + } + return date.getTime(); + } +} diff --git a/app/src/main/java/com/lechange/demo/business/util/WifiManagerUtil.java b/app/src/main/java/com/lechange/demo/business/util/WifiManagerUtil.java new file mode 100644 index 0000000..a87941f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/business/util/WifiManagerUtil.java @@ -0,0 +1,379 @@ +package com.lechange.demo.business.util; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.DhcpInfo; +import android.net.NetworkInfo; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; + +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +public class WifiManagerUtil { + private WifiManager mWifiManager; + private WifiInfo mWifiInfo; + private List mWifiList; + private List mWifiConfiguration; + private WifiManager.WifiLock mWifiLock; + private static int WIFI_TYPE_NO_PASSWORD = 1; + private static int WIFI_TYPE_WEP = 2; + private static int WIFI_TYPE_WPA = 3; + + @SuppressLint("MissingPermission") + public WifiManagerUtil(Context context) { + this.mWifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); + this.mWifiInfo = this.mWifiManager.getConnectionInfo(); + } + + @SuppressLint("MissingPermission") + public void openWifi() { + if (!this.mWifiManager.isWifiEnabled()) { + this.mWifiManager.setWifiEnabled(true); + } + + } + + @SuppressLint("MissingPermission") + public void closeWifi() { + if (this.mWifiManager.isWifiEnabled()) { + this.mWifiManager.setWifiEnabled(false); + } + + } + + public boolean isWifi5G(Context context) { + int freq = 0; + if (Build.VERSION.SDK_INT > 21) { + freq = this.mWifiInfo.getFrequency(); + } else { + String ssid = this.mWifiInfo.getSSID(); + if (ssid != null && ssid.length() > 2) { + String ssidTemp = ssid.substring(1, ssid.length() - 1); + @SuppressLint("MissingPermission") + List scanResults = this.mWifiManager.getScanResults(); + Iterator var6 = scanResults.iterator(); + + while(var6.hasNext()) { + ScanResult scanResult = (ScanResult)var6.next(); + if (scanResult.SSID.equals(ssidTemp)) { + freq = scanResult.frequency; + break; + } + } + } + } + + return freq > 4900 && freq < 5900; + } + + @SuppressLint("MissingPermission") + public int checkState() { + return this.mWifiManager.getWifiState(); + } + + public void acquireWifiLock() { + this.mWifiLock.acquire(); + } + + public void releaseWifiLock() { + if (this.mWifiLock.isHeld()) { + this.mWifiLock.acquire(); + } + + } + + public void creatWifiLock() { + this.mWifiLock = this.mWifiManager.createWifiLock("Test"); + } + + public List getConfiguration() { + return this.mWifiConfiguration; + } + + @SuppressLint("MissingPermission") + public void connectConfiguration(int index) { + if (index <= this.mWifiConfiguration.size()) { + this.mWifiManager.enableNetwork(((WifiConfiguration)this.mWifiConfiguration.get(index)).networkId, true); + } + } + + @SuppressLint("MissingPermission") + public void startScan() { + this.mWifiManager.startScan(); + this.mWifiList = this.mWifiManager.getScanResults(); + this.mWifiConfiguration = this.mWifiManager.getConfiguredNetworks(); + } + + public List getWifiList() { + return this.mWifiList; + } + + public StringBuilder lookUpScan() { + StringBuilder stringBuilder = new StringBuilder(); + + for(int i = 0; i < this.mWifiList.size(); ++i) { + stringBuilder.append("Index_" + (new Integer(i + 1)).toString() + ":"); + stringBuilder.append(((ScanResult)this.mWifiList.get(i)).toString()); + stringBuilder.append("/n"); + } + + return stringBuilder; + } + + public String getMacAddress() { + return this.mWifiInfo == null ? "NULL" : this.mWifiInfo.getMacAddress(); + } + + public String getBSSID() { + return this.mWifiInfo == null ? "NULL" : this.mWifiInfo.getBSSID(); + } + + public int getIPAddress() { + return this.mWifiInfo == null ? 0 : this.mWifiInfo.getIpAddress(); + } + + public int getNetworkId() { + return this.mWifiInfo == null ? 0 : this.mWifiInfo.getNetworkId(); + } + + public String getWifiInfo() { + return this.mWifiInfo == null ? "NULL" : this.mWifiInfo.toString(); + } + + @SuppressLint("MissingPermission") + public boolean addNetwork(WifiConfiguration wcg) { + int wcgID = this.mWifiManager.addNetwork(wcg); + return this.mWifiManager.enableNetwork(wcgID, true); + } + + @SuppressLint("MissingPermission") + public void disconnectWifi(int netId) { + this.mWifiManager.disableNetwork(netId); + this.mWifiManager.disconnect(); + } + + @SuppressLint("MissingPermission") + public WifiConfiguration createWifiInfo(String SSID, String Password, int Type) { + WifiConfiguration config = new WifiConfiguration(); + config.allowedAuthAlgorithms.clear(); + config.allowedGroupCiphers.clear(); + config.allowedKeyManagement.clear(); + config.allowedPairwiseCiphers.clear(); + config.allowedProtocols.clear(); + config.SSID = "\"" + SSID + "\""; + WifiConfiguration tempConfig = this.IsExsits(SSID); + if (tempConfig != null) { + this.mWifiManager.removeNetwork(tempConfig.networkId); + } + + if (Type == WIFI_TYPE_NO_PASSWORD) { + config.wepKeys[0] = "\"\""; + config.allowedKeyManagement.set(0); + config.wepTxKeyIndex = 0; + } + + if (Type == WIFI_TYPE_WEP) { + config.hiddenSSID = true; + config.wepKeys[0] = "\"" + Password + "\""; + config.allowedAuthAlgorithms.set(1); + config.allowedGroupCiphers.set(3); + config.allowedGroupCiphers.set(2); + config.allowedGroupCiphers.set(0); + config.allowedGroupCiphers.set(1); + config.allowedKeyManagement.set(0); + config.wepTxKeyIndex = 0; + } + + if (Type == WIFI_TYPE_WPA) { + config.preSharedKey = "\"" + Password + "\""; + config.hiddenSSID = true; + config.allowedAuthAlgorithms.set(0); + config.allowedGroupCiphers.set(2); + config.allowedKeyManagement.set(1); + config.allowedPairwiseCiphers.set(1); + config.allowedGroupCiphers.set(3); + config.allowedPairwiseCiphers.set(2); + config.status = 2; + } + + return config; + } + + @SuppressLint("MissingPermission") + private WifiConfiguration IsExsits(String SSID) { + List existingConfigs = this.mWifiManager.getConfiguredNetworks(); + if (existingConfigs == null) { + return null; + } else { + Iterator var3 = existingConfigs.iterator(); + + WifiConfiguration existingConfig; + do { + if (!var3.hasNext()) { + return null; + } + + existingConfig = (WifiConfiguration)var3.next(); + } while(!existingConfig.SSID.equals("\"" + SSID + "\"")); + + return existingConfig; + } + } + @SuppressLint("MissingPermission") + public boolean connectWifi(String SSID, String passWord) { + if (Build.VERSION.SDK_INT >= 23) { + WifiConfiguration tempConfig = this.IsExsits(SSID); + if (tempConfig != null) { + return this.mWifiManager.enableNetwork(tempConfig.networkId, true); + } + } + + return this.addNetwork(this.createWifiInfo(SSID, passWord, WIFI_TYPE_NO_PASSWORD)); + } + @SuppressLint("MissingPermission") + public String getGatewayIp() { + DhcpInfo dhcpInfo = this.mWifiManager.getDhcpInfo(); + if (dhcpInfo != null) { + long gatewayIps = (long)dhcpInfo.gateway; + return this.long2ip(gatewayIps); + } else { + return ""; + } + } + + public String long2ip(long ip) { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(String.valueOf((int)(ip & 255L))); + stringBuffer.append('.'); + stringBuffer.append(String.valueOf((int)(ip >> 8 & 255L))); + stringBuffer.append('.'); + stringBuffer.append(String.valueOf((int)(ip >> 16 & 255L))); + stringBuffer.append('.'); + stringBuffer.append(String.valueOf((int)(ip >> 24 & 255L))); + return stringBuffer.toString(); + } + + @SuppressLint("MissingPermission") + public WifiInfo getCurrentWifiInfo() { + this.mWifiInfo = this.mWifiManager.getConnectionInfo(); + return this.mWifiInfo; + } + @SuppressLint("MissingPermission") + public boolean isWifi(Context context) { + ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivity == null) { + return false; + } else { + NetworkInfo curNetwork = connectivity.getActiveNetworkInfo(); + if (curNetwork != null && curNetwork.getType() == ConnectivityManager.TYPE_WIFI) { + return true; + } + } + return false; + } + + public int getWifiEncryption(String capabilities) { + int encryption = 255; + String cap = capabilities.toUpperCase(Locale.US); + if (cap.indexOf("WPA2") != -1) { + if (cap.indexOf("WPA2-PSK-TKIP") != -1) { + encryption = 6; + } else if (cap.indexOf("WPA2-PSK-AES") != -1) { + encryption = 7; + } else if (cap.indexOf("WPA2-TKIP") != -1) { + encryption = 10; + } else if (cap.indexOf("WPA2-AES") != -1) { + encryption = 11; + } else if (cap.indexOf("WPA2-PSK-CCMP") != -1) { + encryption = 12; + } + } else if (cap.indexOf("WPA") != -1) { + if (cap.indexOf("WPA-PSK-TKIP") != -1) { + encryption = 4; + } else if (cap.indexOf("WPA-PSK-CCMP") != -1) { + encryption = 5; + } else if (cap.indexOf("WPA-TKIP") != -1) { + encryption = 8; + } else if (cap.indexOf("WPA-CCMP") != -1) { + encryption = 9; + } + } else if (cap.indexOf("WEP") != -1) { + if (cap.indexOf("WEP_Open") != -1) { + encryption = 2; + } else if (cap.indexOf("WEP_Shared") != -1) { + encryption = 3; + } + } else { + encryption = 255; + } + + return encryption; + } + + public ScanResult getScanResult() { + ScanResult scanResult = null; + if (this.mWifiManager == null) { + return null; + } else { + this.getCurrentWifiInfo(); + if (this.mWifiInfo.getSSID() != null) { + try { + if (this.mWifiList == null) { + this.startScan(); + } + + if (this.mWifiList == null) { + return null; + } + + Iterator var2 = this.mWifiList.iterator(); + + while(var2.hasNext()) { + ScanResult s = (ScanResult)var2.next(); + if (s.SSID.replaceAll("\"", "").equals(this.mWifiInfo.getSSID().replaceAll("\"", ""))) { + scanResult = s; + break; + } + } + } catch (Exception var4) { + return null; + } + } + + return scanResult; + } + } + + public boolean isNoPasswordWifi() { + ScanResult scanResult = this.getScanResult(); + if (scanResult == null) { + return false; + } else { + int encypt = this.getWifiEncryption(scanResult.capabilities); + return encypt == 2 || encypt == 255; + } + } + + public String getDoorbellSSID(String deviceSn) { + return "Doorbell-" + deviceSn; + } + + public boolean isConnectedDoorbellHot(String deviceSn) { + WifiInfo wifiInfo = this.getCurrentWifiInfo(); + if (wifiInfo == null) { + return false; + } else { + String ssid = this.getDoorbellSSID(deviceSn); + ssid = "\"" + ssid + "\""; + return wifiInfo.getSSID().equals(ssid); + } + } + + +} diff --git a/app/src/main/java/com/lechange/demo/common/CommonTitle.java b/app/src/main/java/com/lechange/demo/common/CommonTitle.java new file mode 100644 index 0000000..d884e4a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/CommonTitle.java @@ -0,0 +1,264 @@ +package com.lechange.demo.common; + + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yonsz.z1.R; + +/** + * 工具类使用说明:左按钮,中间按钮,右按钮,均支持图片和文字背景二选一,左右按钮默认支持图片,中间按钮默认支持文字 + * xml使用注意:需要在xml文件中设置宽高和背景色 + * + */ +public class CommonTitle extends RelativeLayout +{ + /** + * 左侧按钮ID + */ + public static final int ID_LEFT = 0; + + /** + * 右侧按钮ID + */ + public static final int ID_RIGHT = 1; + + /** + * 中间按钮ID, 暂时不加监听器 + */ + public static final int ID_CENTER = 2; + + /** + * 左侧按钮 + */ + private ImageView mTitleLeft; + + + /** + * 右侧按钮 + */ + private ImageView mTitleRight; + + + /** + * 文字标题 + */ + private TextView mTitleCenter; + + /** + * 点击监听 + */ + private OnTitleClickListener mListener; + + private View mBottom; + + /** + * 默认隐藏左2和右2的按钮 ,创建一个新的实例CommonTitle. + * @param context + * @param attrs + */ + public CommonTitle(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.widget_common_title, this); + initView(); + setListeners(); + } + + private void initView() { + mBottom = findViewById(R.id.bottom_line); + mTitleLeft = (ImageView) findViewById(R.id.title_left); + mTitleRight = (ImageView) findViewById(R.id.title_right); + + mTitleCenter = (TextView) findViewById(R.id.title_center); + mTitleCenter.setTextColor(getResources().getColor(R.color.title_color_center)); + mTitleCenter.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.text_size_large)); + } + + private void setListeners() { + mTitleLeft.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_LEFT); + } + + } + }); + + + mTitleRight.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_RIGHT); + } + + } + }); + } + + /** + * 初始化参数,按钮均可支持图片或者文字背景 + * + * @param leftResId 左按钮 + * @param rightResId 右按钮 + * @param centerResId 中间text + * + */ + + public void initView(int leftResId, int rightResId, int centerResId) { + setTitleLeftView(leftResId); + setTitleRightView(rightResId); + setTitleCenterView(centerResId, 0, 0); + } + + + public TextView getTextViewCenter() { + return mTitleCenter; + } + + + /** + *

+ * 设置按钮是否可用 + *

+ */ + public void setTitleEnabled(boolean enabled, int id) { + View v = findView(id); + if (v != null) { + v.setEnabled(enabled); + } + } + + private View findView(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeft; + case ID_RIGHT: + return mTitleRight; + case ID_CENTER: + return mTitleCenter; + default: + return null; + } + } + + public void setTitleLeftView(int resId) { + setTitleLeft(resId); + } + + public void setTitleRightView(int resId) { + setTitleRight(resId); + } + + public void setTitleCenterView(int resId, int colorId, int textSizeDimenId) { + setTitleCenter(resId); + setTextColorCenter(colorId); + setTextSizeCenter(textSizeDimenId); + } + + + /** + * 设置左边按钮图片 + * @param leftResId + */ + private void setTitleLeft(int leftResId) { + if (leftResId != 0) { + if (mTitleLeft != null && mTitleLeft.getVisibility() != View.VISIBLE) + mTitleLeft.setVisibility(VISIBLE); + mTitleLeft.setImageResource(leftResId); + }else { + if (mTitleLeft != null) + mTitleLeft.setVisibility(INVISIBLE); + } + } + + + /** + * 设置右边按钮图片 + * @param rightResId + */ + private void setTitleRight(int rightResId) { + if (rightResId != 0) { + if (mTitleRight != null && mTitleRight.getVisibility() != View.VISIBLE) + mTitleRight.setVisibility(VISIBLE); + mTitleRight.setImageResource(rightResId); + }else { + if (mTitleRight != null) + mTitleRight.setVisibility(INVISIBLE); + } + } + + + /** + * 设置中间按钮文字 + * @param centerResId + */ + private void setTitleCenter(int centerResId) { + if (centerResId != 0) { + if (mTitleCenter != null && mTitleCenter.getVisibility() != View.VISIBLE) + mTitleCenter.setVisibility(VISIBLE); + mTitleCenter.setText(centerResId); + }else { + if (mTitleCenter != null) + mTitleCenter.setVisibility(INVISIBLE); + } + } + + public void setTextColorCenter(int colorId) { + if (mTitleCenter != null) { + mTitleCenter.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.title_color_center)); + } + } + + + public void setTextSizeCenter(int textSizeDimenId) { + if (mTitleCenter != null) { + mTitleCenter.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_large)); + } + } + + public void setVisibleLeft(int flag) { + if (mTitleLeft != null) { + mTitleLeft.setVisibility(flag); + } + } + + + public void setVisibleRight(int flag) { + if (mTitleRight != null) { + mTitleRight.setVisibility(flag); + } + } + + + public void setVisibleCenter(int flag) { + if (mTitleCenter != null) { + mTitleCenter.setVisibility(flag); + } + } + + public void setVisibleBottom(int flag) { + if (mBottom != null) { + mBottom.setVisibility(flag); + } + } + + public void setOnTitleClickListener(OnTitleClickListener listener) { + mListener = listener; + } + + public interface OnTitleClickListener { + public void onCommonTitleClick(int id); + } +} diff --git a/app/src/main/java/com/lechange/demo/common/DatePicker.java b/app/src/main/java/com/lechange/demo/common/DatePicker.java new file mode 100644 index 0000000..6789eb6 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/DatePicker.java @@ -0,0 +1,254 @@ +package com.lechange.demo.common; + + +import android.annotation.SuppressLint; +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AnticipateOvershootInterpolator; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.lechange.demo.common.datepicker.AbstractWheel; +import com.lechange.demo.common.datepicker.OnWheelChangedListener; +import com.lechange.demo.common.datepicker.adapters.NumericWheelAdapter; +import com.yonsz.z1.R; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + + +@SuppressLint("SimpleDateFormat") +public class DatePicker extends LinearLayout { + private static final String TAG = "LCDatePicker"; + + public static final int ID_LEFT = 0; + public static final int ID_RIGHT = 1; + + private OnTimeClickListener mListener; + + private AbstractWheel mYearWheel; //滚轮-年 + private AbstractWheel mMonthWheel; //滚轮-月 + private AbstractWheel mDayWheel; //滚轮-日 + + private Button mCancel; //取消按钮(左边按钮) + private TextView mNotice; //提示信息(中间文本) + private Button mSearch; //搜索按钮(右边按钮) + + private Date mMinDate; //拾取器的最小日期 ,默认为当前时间往前50年 + private Date mMaxDate; //拾取器的最大日期,默认为当前时间往后50年 + private String mCurrentYear; //拾取器当前选中的年-yyyy + private String mCurrentMonth; //拾取器当前选中的月-MM + private String mCurrentDay; //拾取器当前选中的日-dd + + public DatePicker(Context context){ + super(context); + LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.widget_common_datepicker, this); + init(); + resetWheels(); + + } + + public DatePicker(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.widget_common_datepicker, this); + init(); + resetWheels(); + } + + /** + * 设置时间拾取器可选时间范围 + *

+ * @author 16552 2016年2月29日 上午9:44:34 + * @param minDate + * @param maxDate + */ + public void setMinMaxDate(Date minDate, Date maxDate) { + this.mMinDate = minDate; + this.mMaxDate = maxDate; + resetWheels(); + } + + + /** + * 设置按钮文本 + * @param leftText + * @param centerText + * @param rightText + */ + public void setText(String leftText,String centerText,String rightText){ + + mCancel.setText(leftText); + mNotice.setText(centerText); + mSearch.setText(rightText); + } + /** + * 获取时间拾取器当前选中的时间 + *

+ * @author 16552 2016年2月29日 上午9:44:18 + * @return + */ + public Date getSelectedDate() { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); + Log.d("Business",mCurrentYear + mCurrentMonth + mCurrentDay); + Date selectedDate = null; + try { + selectedDate = dateFormat.parse(mCurrentYear + mCurrentMonth + mCurrentDay ); + } catch (ParseException e) { + e.printStackTrace(); + Log.e(TAG, "getEndTime parse daile -> " + mCurrentYear + mCurrentMonth + mCurrentDay ); + } + return selectedDate == null ? new Date() : selectedDate; + } + + private void init() { + Date currentDate = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(currentDate); + calendar.add(Calendar.YEAR, 50); + mMaxDate = calendar.getTime(); + calendar.add(Calendar.YEAR, -100); + mMinDate = calendar.getTime(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + String dateString = sdf.format(currentDate); + mCurrentYear = dateString.substring(0, 4); + mCurrentMonth = dateString.substring(4, 6); + mCurrentDay = dateString.substring(6, 8); + + + mYearWheel = (AbstractWheel) findViewById(R.id.year_wheel); + mMonthWheel = (AbstractWheel) findViewById(R.id.month_wheel); + mDayWheel = (AbstractWheel) findViewById(R.id.day_wheel); + + mCancel = (Button) findViewById(R.id.cancel); + mNotice = (TextView) findViewById(R.id.notice); + mSearch = (Button) findViewById(R.id.search); + + mCancel.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View arg0) { + if(mListener != null) { + mListener.onCommonTimeClick(ID_LEFT); + } + + } + }); + + mSearch.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View arg0) { + if(mListener != null) { + mListener.onCommonTimeClick(ID_RIGHT); + } + + + } + }); + + } + + private void resetWheels() { + + + + + if(mYearWheel == null) + { + Log.d("tag","mYearWheel is null"); + } + mYearWheel.setViewAdapter(new NumericWheelAdapter(getContext(), mMinDate.getYear() + 1900, mMaxDate.getYear() + 1900, "%04d")); + mYearWheel.setCyclic(false); + mYearWheel.setInterpolator(new AnticipateOvershootInterpolator()); + mYearWheel.addChangingListener(new OnWheelChangedListener() { + + @Override + public void onChanged(AbstractWheel wheel, int oldValue, int newValue) { + String format = "%04d"; + mCurrentYear = String.format(format, newValue + (mMinDate.getYear() + 1900)); + resetDayWheelAdapter(); + } + }); + mYearWheel.setCurrentItem(Integer.valueOf(mCurrentYear) - (mMinDate.getYear() + 1900)); + + int thisMonth = Integer.valueOf(mCurrentMonth); + mMonthWheel.setViewAdapter(new NumericWheelAdapter(getContext(), 1,12, "%02d")); + mMonthWheel.setCyclic(true); + mMonthWheel.setInterpolator(new AnticipateOvershootInterpolator()); + mMonthWheel.addChangingListener(new OnWheelChangedListener() { + + @Override + public void onChanged(AbstractWheel wheel, int oldValue, int newValue) { + String format = "%02d"; + mCurrentMonth = String.format(format, newValue + 1); + resetDayWheelAdapter(); + } + }); + mMonthWheel.setCurrentItem(thisMonth - 1); + + resetDayWheelAdapter(); + + } + + + /** + * 使用 mCurrentYear 和 mCurrentMonth 计算并重设 mDayWheel + */ + private void resetDayWheelAdapter() { + + int thisDay = Integer.valueOf(mCurrentDay); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM"); + Calendar cal = Calendar.getInstance(); + Date month = null; + try { + month = dateFormat.parse(mCurrentYear + mCurrentMonth); + } catch (ParseException e) { + e.printStackTrace(); + Log.e(TAG, "dateFormat.parse daile -> " + mCurrentYear + mCurrentMonth); + } + if (month != null){ + cal.setTime(month); + }else { + cal.setTime(new Date()); + } + int maxDays = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + + mDayWheel.setViewAdapter(new NumericWheelAdapter(getContext(), 1, maxDays, "%02d")); + mDayWheel.setCyclic(true); + mDayWheel.setInterpolator(new AnticipateOvershootInterpolator()); + mDayWheel.addChangingListener(new OnWheelChangedListener() { + + @Override + public void onChanged(AbstractWheel wheel, int oldValue, int newValue) { + String format = "%02d"; + mCurrentDay = String.format(format, newValue + 1); + } + }); + + if(thisDay > maxDays){ + mDayWheel.setCurrentItem(maxDays - 1); + }else { + mDayWheel.setCurrentItem(thisDay - 1); + } + + } + + public void setOnTimeClickListener(OnTimeClickListener listener){ + + mListener = listener; + } + + public interface OnTimeClickListener{ + + public void onCommonTimeClick(int id); + } +} diff --git a/app/src/main/java/com/lechange/demo/common/ProgressDialog.java b/app/src/main/java/com/lechange/demo/common/ProgressDialog.java new file mode 100644 index 0000000..9dc0780 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/ProgressDialog.java @@ -0,0 +1,116 @@ +package com.lechange.demo.common; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import java.util.concurrent.locks.LockSupport; + + +/** + * 多个ProgressDialog映射一个线程,通过mThreadDialog字段标识 + * @author 31554 + * + */ +public class ProgressDialog extends TextView{ + + private static Thread mUIThread; + private static ProgressDialog mThreadDialog; + + private static StringBuilder mMsg; + private static int mMsgIndex; + private static Handler mHandler; + static { + mHandler = new Handler(){ + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + //Log.d("ProgressDialog", "======" + mMsg.toString()); + if (mThreadDialog != null) { + mThreadDialog.setText(mMsg.toString()); + } + } + }; + mUIThread = new Thread() { + @Override + public void run() { + super.run(); + while (true) { + if (mThreadDialog != null) { + if(mMsgIndex >= 4){ + mMsgIndex = 0; + mMsg.setLength(mMsg.length() - 8); + } + mMsg.append(" ."); + mMsgIndex++; + mHandler.obtainMessage().sendToTarget(); + try { + Thread.sleep(1000); + } catch (Exception e) { + // InterruptedException + e.printStackTrace(); + } + } else + LockSupport.park(); + } + } + }; + mUIThread.start(); + } + + //构造 + public ProgressDialog(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public ProgressDialog(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ProgressDialog(Context context) { + super(context); + } + + public void setStart(String msg){ + //Log.d("111", this + "=====start " + mThreadDialog + " : " + this); + mMsgIndex = 0; + mMsg = new StringBuilder(msg); + if (mThreadDialog == null || mThreadDialog.hashCode() != this.hashCode()) { + mHandler.post(new Runnable() { + @Override + public void run() { + setVisibility(View.VISIBLE); + setText(mMsg); + } + }); + mThreadDialog = this; + LockSupport.unpark(mUIThread); + } + } + + public void setStop(){ + //Log.d("111", "=====stop " + mThreadDialog + " : " + this); + mHandler.post(new Runnable() { + @Override + public void run() { + setVisibility(View.GONE); + } + }); + if (mThreadDialog != null && mThreadDialog.hashCode() == this.hashCode()) { + mThreadDialog = null; + } + } + +} + + +//mUIThread.interrupt(); +//try { +// mUIThread.join(); +//} catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +//} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/common/RecoderSeekBar.java b/app/src/main/java/com/lechange/demo/common/RecoderSeekBar.java new file mode 100644 index 0000000..8e888cc --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/RecoderSeekBar.java @@ -0,0 +1,33 @@ +package com.lechange.demo.common; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.SeekBar; + +public class RecoderSeekBar extends SeekBar{ + + private boolean canTouchAble = true; + + public RecoderSeekBar(Context context,AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + public RecoderSeekBar(Context context, + AttributeSet attrs) { + super(context, attrs); + } + public RecoderSeekBar(Context context) { + super(context); + } + @Override + public boolean onTouchEvent(MotionEvent event) { + if(!canTouchAble){ + return true; + } + return super.onTouchEvent(event); + } + + public void setCanTouchAble(boolean canTouchAble){ + this.canTouchAble = canTouchAble; + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheel.java b/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheel.java new file mode 100644 index 0000000..366cc52 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheel.java @@ -0,0 +1,889 @@ +package com.lechange.demo.common.datepicker; + + + +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Interpolator; +import android.widget.LinearLayout; + +import com.lechange.demo.common.datepicker.adapters.WheelViewAdapter; +import com.yonsz.z1.R; + +import java.util.LinkedList; +import java.util.List; + + +/** + * Abstract spinner spinnerwheel view + * This class should be subclassed. + * + * @author Yuri Kanivets + * @author Dimitri Fedorov + */ +public abstract class AbstractWheel extends View { + + private static int itemID = -1; + + @SuppressWarnings("unused") + private final String LOG_TAG = AbstractWheel.class.getName() + " #" + (++itemID); + + //---------------------------------- + // Default properties values + //---------------------------------- + + /** Default count of visible items */ + private static final int DEF_VISIBLE_ITEMS = 4; + private static final boolean DEF_IS_CYCLIC = false; + + //---------------------------------- + // Class properties + //---------------------------------- + + protected int mCurrentItemIdx = 0; + + // Count of visible items + protected int mVisibleItems; + // Should all items be visible + protected boolean mIsAllVisible; + + protected boolean mIsCyclic; + + // Scrolling + protected WheelScroller mScroller; + protected boolean mIsScrollingPerformed; + protected int mScrollingOffset; + + // Items layout + protected LinearLayout mItemsLayout; + + // The number of first item in layout + protected int mFirstItemIdx; + + // View adapter + protected WheelViewAdapter mViewAdapter; + + protected int mLayoutHeight; + protected int mLayoutWidth; + + // Recycle + private WheelRecycler mRecycler = new WheelRecycler(this); + + // Listeners + private List changingListeners = new LinkedList(); + private List scrollingListeners = new LinkedList(); + private List clickingListeners = new LinkedList(); + + //XXX: I don't like listeners the way as they are now. -df + + // Adapter listener + private DataSetObserver mDataObserver; + + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Create a new AbstractWheel instance + * + * @param context the application environment. + * @param attrs a collection of attributes. + * @param defStyle The default style to apply to this view. + */ + public AbstractWheel(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs); + initAttributes(attrs, defStyle); + initData(context); + } + + //-------------------------------------------------------------------------- + // + // Initiating data and assets at start up + // + //-------------------------------------------------------------------------- + + /** + * Initiates data and parameters from styles + * + * @param attrs a collection of attributes. + * @param defStyle The default style to apply to this view. + */ + protected void initAttributes(AttributeSet attrs, int defStyle) { + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AbstractWheelView, defStyle, 0); + mVisibleItems = a.getInt(R.styleable.AbstractWheelView_visibleItems, DEF_VISIBLE_ITEMS); + mIsAllVisible = a.getBoolean(R.styleable.AbstractWheelView_isAllVisible, false); + mIsCyclic = a.getBoolean(R.styleable.AbstractWheelView_isCyclic, DEF_IS_CYCLIC); + + a.recycle(); + } + + /** + * Initiates data + * + * @param context the context + */ + protected void initData(Context context) { + + mDataObserver = new DataSetObserver() { + @Override + public void onChanged() { + invalidateItemsLayout(false); + } + + @Override + public void onInvalidated() { + invalidateItemsLayout(true); + } + }; + + // creating new scroller + mScroller = createScroller(new WheelScroller.ScrollingListener() { + + public void onStarted() { + mIsScrollingPerformed = true; + notifyScrollingListenersAboutStart(); + onScrollStarted(); + } + + public void onTouch() { + onScrollTouched(); + } + + public void onTouchUp() { + if (!mIsScrollingPerformed) + onScrollTouchedUp(); // if scrolling IS performed, whe should use onFinished instead + } + + public void onScroll(int distance) { + doScroll(distance); + + int dimension = getBaseDimension(); + if (mScrollingOffset > dimension) { + mScrollingOffset = dimension; + mScroller.stopScrolling(); + } else if (mScrollingOffset < - dimension) { + mScrollingOffset = - dimension; + mScroller.stopScrolling(); + } + } + + public void onFinished() { + if (mIsScrollingPerformed) { + notifyScrollingListenersAboutEnd(); + mIsScrollingPerformed = false; + onScrollFinished(); + } + + mScrollingOffset = 0; + invalidate(); + } + + public void onJustify() { + if (Math.abs(mScrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) { + mScroller.scroll(mScrollingOffset, 0); + } + } + }); + } + + @Override + public Parcelable onSaveInstanceState() { + //begin boilerplate code that allows parent classes to save state + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + //end + + ss.currentItem = this.getCurrentItem(); + + return ss; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + //begin boilerplate code so parent classes can restore state + if(!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + final SavedState ss = (SavedState)state; + super.onRestoreInstanceState(ss.getSuperState()); + //end + + mCurrentItemIdx = ss.currentItem; + + // dirty hack to re-draw child items correctly + postDelayed(new Runnable() { + @Override + public void run() { + invalidateItemsLayout(false); + } + }, 100); + } + + static class SavedState extends BaseSavedState { + int currentItem; + + SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + this.currentItem = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(this.currentItem); + } + + //required field that makes Parcelables from a Parcel + public static final Creator CREATOR = + new Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + abstract protected void recreateAssets(int width, int height); + + abstract public void removeBitmap(); + + //-------------------------------------------------------------------------- + // + // Scroller operations + // + //-------------------------------------------------------------------------- + + /** + * Creates scroller appropriate for specific wheel implementation. + * + * @param scrollingListener listener to be passed to the scroller + * @return Initialized scroller to be used + */ + abstract protected WheelScroller createScroller(WheelScroller.ScrollingListener scrollingListener); + + /* These methods are not abstract, as we may want to override only some of them */ + protected void onScrollStarted() {} + protected void onScrollTouched() {} + protected void onScrollTouchedUp() {} + protected void onScrollFinished() {} + + /** + * Stops scrolling + */ + public void stopScrolling() { + mScroller.stopScrolling(); + } + + /** + * Set the the specified scrolling interpolator + * @param interpolator the interpolator + */ + public void setInterpolator(Interpolator interpolator) { + mScroller.setInterpolator(interpolator); + } + + /** + * Scroll the spinnerwheel + * @param itemsToScroll items to scroll + * @param time scrolling duration + */ + public void scroll(int itemsToScroll, int time) { + int distance = itemsToScroll * getItemDimension() - mScrollingOffset; + onScrollTouched(); // we have to emulate touch when scrolling spinnerwheel programmatically to light up stuff + mScroller.scroll(distance, time); + } + + /** + * Scrolls the spinnerwheel + * @param delta the scrolling value + */ + private void doScroll(int delta) { + mScrollingOffset += delta; + + int itemDimension = getItemDimension(); + int count = mScrollingOffset / itemDimension; + + int pos = mCurrentItemIdx - count; + int itemCount = mViewAdapter.getItemsCount(); + + int fixPos = mScrollingOffset % itemDimension; + if (Math.abs(fixPos) <= itemDimension / 2) { + fixPos = 0; + } + if (mIsCyclic && itemCount > 0) { + if (fixPos > 0) { + pos--; + count++; + } else if (fixPos < 0) { + pos++; + count--; + } + // fix position by rotating + while (pos < 0) { + pos += itemCount; + } + pos %= itemCount; + } else { + if (pos < 0) { + count = mCurrentItemIdx; + pos = 0; + } else if (pos >= itemCount) { + count = mCurrentItemIdx - itemCount + 1; + pos = itemCount - 1; + } else if (pos > 0 && fixPos > 0) { + pos--; + count++; + } else if (pos < itemCount - 1 && fixPos < 0) { + pos++; + count--; + } + } + + int offset = mScrollingOffset; + if (pos != mCurrentItemIdx) { + setCurrentItem(pos, false); + } else { + invalidate(); + } + + // update offset + int baseDimension = getBaseDimension(); + mScrollingOffset = offset - count * itemDimension; + if (mScrollingOffset > baseDimension) { + mScrollingOffset = mScrollingOffset % baseDimension + baseDimension; + } + } + + //-------------------------------------------------------------------------- + // + // Base measurements + // + //-------------------------------------------------------------------------- + + /** + * Returns base dimension of the spinnerwheel 鈥�width for horizontal spinnerwheel, height for vertical + * + * @return width or height of the spinnerwheel + */ + abstract protected int getBaseDimension(); + + /** + * Returns base dimension of base item 鈥�width for horizontal spinnerwheel, height for vertical + * + * @return width or height of base item + */ + abstract protected int getItemDimension(); + + /** + * Processes MotionEvent and returns relevant position 鈥�x for horizontal spinnerwheel, y for vertical + * + * @param event MotionEvent to be processed + * @return relevant position of the MotionEvent + */ + abstract protected float getMotionEventPosition(MotionEvent event); + + + //-------------------------------------------------------------------------- + // + // Layout creation and measurement operations + // + //-------------------------------------------------------------------------- + + /** + * Creates item layouts if necessary + */ + abstract protected void createItemsLayout(); + + /** + * Sets layout width and height + */ + abstract protected void doItemsLayout(); + + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (changed) { + int w = r - l; + int h = b - t; + doItemsLayout(); + if (mLayoutWidth != w || mLayoutHeight != h) { + recreateAssets(getMeasuredWidth(), getMeasuredHeight()); + } + mLayoutWidth = w; + mLayoutHeight = h; + } + } + + /** + * Invalidates items layout + * + * @param clearCaches if true then cached views will be cleared + */ + public void invalidateItemsLayout(boolean clearCaches) { + if (clearCaches) { + mRecycler.clearAll(); + if (mItemsLayout != null) { + mItemsLayout.removeAllViews(); + } + mScrollingOffset = 0; + } else if (mItemsLayout != null) { + // cache all items + mRecycler.recycleItems(mItemsLayout, mFirstItemIdx, new ItemsRange()); + } + invalidate(); + } + + + //-------------------------------------------------------------------------- + // + // Getters and setters + // + //-------------------------------------------------------------------------- + + /** + * Gets count of visible items + * + * @return the count of visible items + */ + public int getVisibleItems() { + return mVisibleItems; + } + + /** + * Sets the desired count of visible items. + * Actual amount of visible items depends on spinnerwheel layout parameters. + * To apply changes and rebuild view call measure(). + * + * @param count the desired count for visible items + */ + public void setVisibleItems(int count) { + mVisibleItems = count; + } + + /** + * Sets all items to have no dim and makes them visible + * @param isAllVisible + */ + public void setAllItemsVisible(boolean isAllVisible){ + mIsAllVisible = isAllVisible; + invalidateItemsLayout(false); + } + + /** + * Gets view adapter + * @return the view adapter + */ + public WheelViewAdapter getViewAdapter() { + return mViewAdapter; + } + + + /** + * Sets view adapter. Usually new adapters contain different views, so + * it needs to rebuild view by calling measure(). + * + * @param viewAdapter the view adapter + */ + public void setViewAdapter(WheelViewAdapter viewAdapter) { + if (this.mViewAdapter != null) { + this.mViewAdapter.unregisterDataSetObserver(mDataObserver); + } + this.mViewAdapter = viewAdapter; + if (this.mViewAdapter != null) { + this.mViewAdapter.registerDataSetObserver(mDataObserver); + } + invalidateItemsLayout(true); + } + + /** + * Gets current value + * + * @return the current value + */ + public int getCurrentItem() { + return mCurrentItemIdx; + } + + /** + * Sets the current item. Does nothing when index is wrong. + * + * @param index the item index + * @param animated the animation flag + */ + public void setCurrentItem(int index, boolean animated) { + if (mViewAdapter == null || mViewAdapter.getItemsCount() == 0) { + return; // throw? + } + + int itemCount = mViewAdapter.getItemsCount(); + if (index < 0 || index >= itemCount) { + if (mIsCyclic) { + while (index < 0) { + index += itemCount; + } + index %= itemCount; + } else{ + return; // throw? + } + } + if (index != mCurrentItemIdx) { + if (animated) { + int itemsToScroll = index - mCurrentItemIdx; + if (mIsCyclic) { + int scroll = itemCount + Math.min(index, mCurrentItemIdx) - Math.max(index, mCurrentItemIdx); + if (scroll < Math.abs(itemsToScroll)) { + itemsToScroll = itemsToScroll < 0 ? scroll : -scroll; + } + } + scroll(itemsToScroll, 0); + } else { + mScrollingOffset = 0; + final int old = mCurrentItemIdx; + mCurrentItemIdx = index; + notifyChangingListeners(old, mCurrentItemIdx); + invalidate(); + } + } + } + + /** + * Sets the current item w/o animation. Does nothing when index is wrong. + * + * @param index the item index + */ + public void setCurrentItem(int index) { + setCurrentItem(index, false); + } + + /** + * Tests if spinnerwheel is cyclic. That means before the 1st item there is shown the last one + * @return true if spinnerwheel is cyclic + */ + public boolean isCyclic() { + return mIsCyclic; + } + + /** + * Set spinnerwheel cyclic flag + * @param isCyclic the flag to set + */ + public void setCyclic(boolean isCyclic) { + this.mIsCyclic = isCyclic; + invalidateItemsLayout(false); + } + + + //-------------------------------------------------------------------------- + // + // Listener operations + // + //-------------------------------------------------------------------------- + + /** + * Adds spinnerwheel changing listener + * @param listener the listener + */ + public void addChangingListener(OnWheelChangedListener listener) { + changingListeners.add(listener); + } + + /** + * Removes spinnerwheel changing listener + * @param listener the listener + */ + public void removeChangingListener(OnWheelChangedListener listener) { + changingListeners.remove(listener); + } + + /** + * Notifies changing listeners + * @param oldValue the old spinnerwheel value + * @param newValue the new spinnerwheel value + */ + protected void notifyChangingListeners(int oldValue, int newValue) { + for (OnWheelChangedListener listener : changingListeners) { + listener.onChanged(this, oldValue, newValue); + } + } + + /** + * Adds spinnerwheel scrolling listener + * @param listener the listener + */ + public void addScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.add(listener); + } + + /** + * Removes spinnerwheel scrolling listener + * @param listener the listener + */ + public void removeScrollingListener(OnWheelScrollListener listener) { + scrollingListeners.remove(listener); + } + + /** + * Notifies listeners about starting scrolling + */ + protected void notifyScrollingListenersAboutStart() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingStarted(this); + } + } + + /** + * Notifies listeners about ending scrolling + */ + protected void notifyScrollingListenersAboutEnd() { + for (OnWheelScrollListener listener : scrollingListeners) { + listener.onScrollingFinished(this); + } + } + + /** + * Adds spinnerwheel clicking listener + * @param listener the listener + */ + public void addClickingListener(OnWheelClickedListener listener) { + clickingListeners.add(listener); + } + + /** + * Removes spinnerwheel clicking listener + * @param listener the listener + */ + public void removeClickingListener(OnWheelClickedListener listener) { + clickingListeners.remove(listener); + } + + /** + * Notifies listeners about clicking + * @param item clicked item + */ + protected void notifyClickListenersAboutClick(int item) { + for (OnWheelClickedListener listener : clickingListeners) { + listener.onItemClicked(this, item); + } + } + + + //-------------------------------------------------------------------------- + // + // Rebuilding items + // + //-------------------------------------------------------------------------- + + /** + * Rebuilds spinnerwheel items if necessary. Caches all unused items. + * + * @return true if items are rebuilt + */ + protected boolean rebuildItems() { + boolean updated; + ItemsRange range = getItemsRange(); + + if (mItemsLayout != null) { + int first = mRecycler.recycleItems(mItemsLayout, mFirstItemIdx, range); + updated = mFirstItemIdx != first; + mFirstItemIdx = first; + } else { + createItemsLayout(); + updated = true; + } + + if (!updated) { + updated = mFirstItemIdx != range.getFirst() || mItemsLayout.getChildCount() != range.getCount(); + } + + if (mFirstItemIdx > range.getFirst() && mFirstItemIdx <= range.getLast()) { + for (int i = mFirstItemIdx - 1; i >= range.getFirst(); i--) { + if (!addItemView(i, true)) { + break; + } + mFirstItemIdx = i; + } + } else { + mFirstItemIdx = range.getFirst(); + } + + int first = mFirstItemIdx; + for (int i = mItemsLayout.getChildCount(); i < range.getCount(); i++) { + if (!addItemView(mFirstItemIdx + i, false) && mItemsLayout.getChildCount() == 0) { + first++; + } + } + mFirstItemIdx = first; + + return updated; + } + + //---------------------------------- + // ItemsRange operations + //---------------------------------- + + /** + * Calculates range for spinnerwheel items + * @return the items range + */ + private ItemsRange getItemsRange() { + if (mIsAllVisible) { + int baseDimension = getBaseDimension(); + int itemDimension = getItemDimension(); + if (itemDimension != 0) + mVisibleItems = baseDimension / itemDimension + 1; + } + + int start = mCurrentItemIdx - mVisibleItems / 2; + int end = start + mVisibleItems - (mVisibleItems % 2 == 0 ? 0 : 1); + if (mScrollingOffset != 0) { + if (mScrollingOffset > 0) { + start--; + } else { + end++; + } + } + if (!isCyclic()) { + if (start < 0) + start = 0; + if (end > mViewAdapter.getItemsCount()) + end = mViewAdapter.getItemsCount(); + } + return new ItemsRange(start, end - start + 1); + } + + /** + * Checks whether item index is valid + * @param index the item index + * @return true if item index is not out of bounds or the spinnerwheel is cyclic + */ + protected boolean isValidItemIndex(int index) { + return (mViewAdapter != null) && (mViewAdapter.getItemsCount() > 0) && + (mIsCyclic || (index >= 0 && index < mViewAdapter.getItemsCount())); + } + + //---------------------------------- + // Operations with item view + //---------------------------------- + + /** + * Adds view for item to items layout + * @param index the item index + * @param first the flag indicates if view should be first + * @return true if corresponding item exists and is added + */ + private boolean addItemView(int index, boolean first) { + View view = getItemView(index); + if (view != null) { + if (first) { + mItemsLayout.addView(view, 0); + } else { + mItemsLayout.addView(view); + } + return true; + } + return false; + } + + /** + * Returns view for specified item + * @param index the item index + * @return item view or empty view if index is out of bounds + */ + private View getItemView(int index) { + if (mViewAdapter == null || mViewAdapter.getItemsCount() == 0) { + return null; + } + int count = mViewAdapter.getItemsCount(); + if (!isValidItemIndex(index)) { + return mViewAdapter.getEmptyItem( mRecycler.getEmptyItem(), mItemsLayout); + } else { + while (index < 0) { + index = count + index; + } + } + index %= count; + return mViewAdapter.getItem(index, mRecycler.getItem(), mItemsLayout); + } + + + //-------------------------------------------------------------------------- + // + // Intercepting and processing touch event + // + //-------------------------------------------------------------------------- + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled() || getViewAdapter() == null) { + return true; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + if (getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + break; + + case MotionEvent.ACTION_UP: + if (!mIsScrollingPerformed) { + int distance = (int) getMotionEventPosition(event) - getBaseDimension() / 2; + if (distance > 0) { + distance += getItemDimension() / 2; + } else { + distance -= getItemDimension() / 2; + } + int items = distance / getItemDimension(); + if (items != 0 && isValidItemIndex(mCurrentItemIdx + items)) { + notifyClickListenersAboutClick(mCurrentItemIdx + items); + } + } + break; + } + return mScroller.onTouchEvent(event); + } + +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheelView.java b/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheelView.java new file mode 100644 index 0000000..c8494eb --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/AbstractWheelView.java @@ -0,0 +1,325 @@ +package com.lechange.demo.common.datepicker; + + + +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; + +import com.yonsz.z1.R; + +/** + * Abstract spinner spinnerwheel view. + * This class should be subclassed. + * + * @author Yuri Kanivets + * @author Dimitri Fedorov + */ +public abstract class AbstractWheelView extends AbstractWheel { + + private static int itemID = -1; + + @SuppressWarnings("unused") + private final String LOG_TAG = AbstractWheelView.class.getName() + " #" + (++itemID); + + //---------------------------------- + // Default properties values + //---------------------------------- + + protected static final int DEF_ITEMS_DIMMED_ALPHA = 50; // 60 in ICS + + protected static final int DEF_SELECTION_DIVIDER_ACTIVE_ALPHA = 70; + + protected static final int DEF_SELECTION_DIVIDER_DIMMED_ALPHA = 70; + + protected static final int DEF_ITEM_OFFSET_PERCENT = 10; + + protected static final int DEF_ITEM_PADDING = 10; + + protected static final int DEF_SELECTION_DIVIDER_SIZE = 2; + + //---------------------------------- + // Class properties + //---------------------------------- + + // configurable properties + + /** The alpha of the selector spinnerwheel when it is dimmed. */ + protected int mItemsDimmedAlpha; + + /** The alpha of separators spinnerwheel when they are shown. */ + protected int mSelectionDividerActiveAlpha; + + /** The alpha of separators when they are is dimmed. */ + protected int mSelectionDividerDimmedAlpha; + + /** Top and bottom items offset */ + protected int mItemOffsetPercent; + + /** Left and right padding value */ + protected int mItemsPadding; + + /** Divider for showing item to be selected while scrolling */ + protected Drawable mSelectionDivider; + + // the rest + + /** + * The {@link Paint} for drawing the selector. + */ + protected Paint mSelectorWheelPaint; + + /** + * The {@link Paint} for drawing the separators. + */ + protected Paint mSeparatorsPaint; + + /** + * {@link com.nineoldandroids.animation.Animator} for dimming the selector spinnerwheel. + */ + protected Animator mDimSelectorWheelAnimator; + + /** + * {@link com.nineoldandroids.animation.Animator} for dimming the selector spinnerwheel. + */ + protected Animator mDimSeparatorsAnimator; + + /** + * The property for setting the selector paint. + */ + protected static final String PROPERTY_SELECTOR_PAINT_COEFF = "selectorPaintCoeff"; + + /** + * The property for setting the separators paint. + */ + protected static final String PROPERTY_SEPARATORS_PAINT_ALPHA = "separatorsPaintAlpha"; + + + protected Bitmap mSpinBitmap; +// protected Bitmap mSeparatorsBitmap; + + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + public AbstractWheelView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + //-------------------------------------------------------------------------- + // + // Initiating assets and setters for paints + // + //-------------------------------------------------------------------------- + + @Override + protected void initAttributes(AttributeSet attrs, int defStyle) { + super.initAttributes(attrs, defStyle); + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AbstractWheelView, defStyle, 0); + mItemsDimmedAlpha = a.getInt(R.styleable.AbstractWheelView_itemsDimmedAlpha, DEF_ITEMS_DIMMED_ALPHA); + mSelectionDividerActiveAlpha = a.getInt(R.styleable.AbstractWheelView_selectionDividerActiveAlpha, DEF_SELECTION_DIVIDER_ACTIVE_ALPHA); + mSelectionDividerDimmedAlpha = a.getInt(R.styleable.AbstractWheelView_selectionDividerDimmedAlpha, DEF_SELECTION_DIVIDER_DIMMED_ALPHA); + mItemOffsetPercent = a.getInt(R.styleable.AbstractWheelView_itemOffsetPercent, DEF_ITEM_OFFSET_PERCENT); + mItemsPadding = a.getDimensionPixelSize(R.styleable.AbstractWheelView_itemsPadding, DEF_ITEM_PADDING); + mSelectionDivider = a.getDrawable(R.styleable.AbstractWheelView_selectionDivider); + a.recycle(); + } + + @Override + protected void initData(Context context) { + super.initData(context); + + // creating animators + mDimSelectorWheelAnimator = ObjectAnimator.ofFloat(this, PROPERTY_SELECTOR_PAINT_COEFF, 1, 0); + + mDimSeparatorsAnimator = ObjectAnimator.ofInt(this, PROPERTY_SEPARATORS_PAINT_ALPHA, + mSelectionDividerActiveAlpha, mSelectionDividerDimmedAlpha + ); + + // creating paints + mSeparatorsPaint = new Paint(); + mSeparatorsPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + mSeparatorsPaint.setAlpha(mSelectionDividerDimmedAlpha); + + mSelectorWheelPaint = new Paint(); + mSelectorWheelPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + } + + /** + * Recreates assets (like bitmaps) when layout size has been changed + * + * @param width New spinnerwheel width + * @param height New spinnerwheel height + */ + @Override + protected void recreateAssets(int width, int height) { + if(mSpinBitmap == null){ + mSpinBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + } + +// if(mSeparatorsBitmap == null){ +// mSeparatorsBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); +// } + setSelectorPaintCoeff(0); + } + + /** + * Sets the alpha of the {@link Paint} for drawing separators + * spinnerwheel. + * @param alpha alpha value from 0 to 255 + */ + @SuppressWarnings("unused") // Called via reflection + public void setSeparatorsPaintAlpha(int alpha) { + mSeparatorsPaint.setAlpha(alpha); + invalidate(); + } + + @Override + public void removeBitmap(){ + if(mSpinBitmap != null && !mSpinBitmap.isRecycled()){ + mSpinBitmap.recycle(); + mSpinBitmap = null; + } +// +// if(mSeparatorsBitmap != null && !mSeparatorsBitmap.isRecycled()){ +// mSeparatorsBitmap.recycle(); +// mSeparatorsBitmap = null; +// } + } + + /** + * Sets the coeff of the {@link Paint} for drawing + * the selector spinnerwheel. + * + * @param coeff Coefficient from 0 (selector is passive) to 1 (selector is active) + */ + abstract public void setSelectorPaintCoeff(float coeff); + + + //-------------------------------------------------------------------------- + // + // Processing scroller events + // + //-------------------------------------------------------------------------- + + @Override + protected void onScrollTouched() { + mDimSelectorWheelAnimator.cancel(); + mDimSeparatorsAnimator.cancel(); + setSelectorPaintCoeff(1); + setSeparatorsPaintAlpha(mSelectionDividerActiveAlpha); + } + + @Override + protected void onScrollTouchedUp() { + super.onScrollTouchedUp(); + fadeSelectorWheel(750); + lightSeparators(750); + } + + @Override + protected void onScrollFinished() { + fadeSelectorWheel(500); + lightSeparators(500); + } + + //---------------------------------- + // Animating components + //---------------------------------- + + /** + * Fade the selector spinnerwheel via an animation. + * + * @param animationDuration The duration of the animation. + */ + private void fadeSelectorWheel(long animationDuration) { + mDimSelectorWheelAnimator.setDuration(animationDuration); + mDimSelectorWheelAnimator.start(); + } + + /** + * Fade the selector spinnerwheel via an animation. + * + * @param animationDuration The duration of the animation. + */ + private void lightSeparators(long animationDuration) { + mDimSeparatorsAnimator.setDuration(animationDuration); + mDimSeparatorsAnimator.start(); + } + + + //-------------------------------------------------------------------------- + // + // Layout measuring + // + //-------------------------------------------------------------------------- + + /** + * Perform layout measurements + */ + abstract protected void measureLayout(); + + + //-------------------------------------------------------------------------- + // + // Drawing stuff + // + //-------------------------------------------------------------------------- + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (mViewAdapter != null && mViewAdapter.getItemsCount() > 0) { + if (rebuildItems()) { + measureLayout(); + } + doItemsLayout(); + drawItems(canvas); + } + } + + /** + * Draws items on specified canvas + * + * @param canvas the canvas for drawing + */ + abstract protected void drawItems(Canvas canvas); +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/ItemsRange.java b/app/src/main/java/com/lechange/demo/common/datepicker/ItemsRange.java new file mode 100644 index 0000000..fcf49b8 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/ItemsRange.java @@ -0,0 +1,86 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + + /** + * Range for visible items. + */ + public class ItemsRange { + // First item number + private int first; + + // Items count + private int count; + + /** + * Default constructor. Creates an empty range + */ + public ItemsRange() { + this(0, 0); + } + + /** + * Constructor + * @param first the number of first item + * @param count the count of items + */ + public ItemsRange(int first, int count) { + this.first = first; + this.count = count; + } + + /** + * Gets number of first item + * @return the number of the first item + */ + public int getFirst() { + return first; + } + + /** + * Gets number of last item + * @return the number of last item + */ + public int getLast() { + return getFirst() + getCount() - 1; + } + + /** + * Get items count + * @return the count of items + */ + public int getCount() { + return count; + } + + /** + * Tests whether item is contained by range + * @param index the item number + * @return true if item is contained + */ + public boolean contains(int index) { + return index >= getFirst() && index <= getLast(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelChangedListener.java b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelChangedListener.java new file mode 100644 index 0000000..b40b6ec --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelChangedListener.java @@ -0,0 +1,43 @@ +package com.lechange.demo.common.datepicker; + +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/** + * Wheel changed listener interface. + *

The onChanged() method is called whenever current spinnerwheel positions is changed: + *

  • New Wheel position is set + *
  • Wheel view is scrolled + */ +public interface OnWheelChangedListener { + /** + * Callback method to be invoked when current item changed + * @param wheel the spinnerwheel view whose state has changed + * @param oldValue the old value of current item + * @param newValue the new value of current item + */ + void onChanged(AbstractWheel wheel, int oldValue, int newValue); +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelClickedListener.java b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelClickedListener.java new file mode 100644 index 0000000..4d599e9 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelClickedListener.java @@ -0,0 +1,42 @@ +package com.lechange.demo.common.datepicker; + +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +/** + * Wheel clicked listener interface. + *

    The onItemClicked() method is called whenever a spinnerwheel item is clicked + *

  • New Wheel position is set + *
  • Wheel view is scrolled + */ +public interface OnWheelClickedListener { + /** + * Callback method to be invoked when current item clicked + * @param wheel the spinnerwheel view + * @param itemIndex the index of clicked item + */ + void onItemClicked(AbstractWheel wheel, int itemIndex); +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelScrollListener.java b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelScrollListener.java new file mode 100644 index 0000000..f7805cb --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/OnWheelScrollListener.java @@ -0,0 +1,42 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + +/** + * Wheel scrolled listener interface. + */ +public interface OnWheelScrollListener { + /** + * Callback method to be invoked when scrolling started. + * @param wheel the spinnerwheel view whose state has changed. + */ + void onScrollingStarted(AbstractWheel wheel); + + /** + * Callback method to be invoked when scrolling ended. + * @param wheel the spinnerwheel view whose state has changed. + */ + void onScrollingFinished(AbstractWheel wheel); +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalScroller.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalScroller.java new file mode 100644 index 0000000..c9e1c03 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalScroller.java @@ -0,0 +1,72 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + +import android.content.Context; +import android.view.MotionEvent; + +public class WheelHorizontalScroller extends WheelScroller { + + /** + * Constructor + * + * @param context + * the current context + * @param listener + * the scrolling listener + */ + public WheelHorizontalScroller(Context context, ScrollingListener listener) { + super(context, listener); + } + + @Override + protected int getCurrentScrollerPosition() { + return scroller.getCurrX(); + } + + @Override + protected int getFinalScrollerPosition() { + return scroller.getFinalX(); + } + + @Override + protected float getMotionEventPosition(MotionEvent event) { + // should be overriden + return event.getX(); + } + + @Override + protected void scrollerStartScroll(int distance, int time) { + scroller.startScroll(0, 0, distance, 0, time); + } + + @Override + protected void scrollerFling(int position, int velocityX, int velocityY) { + final int maxPosition = 0x7FFFFFFF; + final int minPosition = -maxPosition; + scroller.fling(position, 0, -velocityX, 0, minPosition, maxPosition, 0, + 0); + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalView.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalView.java new file mode 100644 index 0000000..e9eeda3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelHorizontalView.java @@ -0,0 +1,371 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.LinearLayout; + +import com.yonsz.z1.R; + +/** + * Spinner wheel horizontal view. + * + * @author Yuri Kanivets + * @author Dimitri Fedorov + */ +public class WheelHorizontalView extends AbstractWheelView { + + private static int itemID = -1; + + @SuppressWarnings("unused") + private final String LOG_TAG = WheelVerticalView.class.getName() + " #" + (++itemID); + + /** + * The width of the selection divider. + */ + protected int mSelectionDividerWidth; + + // Item width + private int itemWidth = 0; + + //-------------------------------------------------------------------------- + // + // Constructors + // + //-------------------------------------------------------------------------- + + /** + * Create a new wheel horizontal view. + * + * @param context The application environment. + */ + public WheelHorizontalView(Context context) { + this(context, null); + } + + /** + * Create a new wheel horizontal view. + * + * @param context The application environment. + * @param attrs A collection of attributes. + */ + public WheelHorizontalView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.abstractWheelViewStyle); + } + + /** + * Create a new wheel horizontal view. + * + * @param context the application environment. + * @param attrs a collection of attributes. + * @param defStyle The default style to apply to this view. + */ + public WheelHorizontalView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + + //-------------------------------------------------------------------------- + // + // Initiating assets and setter for selector paint + // + //-------------------------------------------------------------------------- + + @Override + protected void initAttributes(AttributeSet attrs, int defStyle) { + super.initAttributes(attrs, defStyle); + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WheelHorizontalView, defStyle, 0); + mSelectionDividerWidth = a.getDimensionPixelSize(R.styleable.WheelHorizontalView_selectionDividerWidth, DEF_SELECTION_DIVIDER_SIZE); + a.recycle(); + } + + @Override + public void setSelectorPaintCoeff(float coeff) { + if (mItemsDimmedAlpha >= 100) + return; + + LinearGradient shader; + + int w = getMeasuredWidth(); + int iw = getItemDimension(); + float p1 = (1 - iw/(float) w)/2; + float p2 = (1 + iw/(float) w)/2; + float z = mItemsDimmedAlpha * (1 - coeff); + float c1f = z + 255 * coeff; + + if (mVisibleItems == 2) { + int c1 = Math.round( c1f ) << 24; + int c2 = Math.round( z ) << 24; + int[] colors = {c2, c1, 0xff000000, 0xff000000, c1, c2}; + float[] positions = { 0, p1, p1, p2, p2, 1}; + shader = new LinearGradient(0, 0, w, 0, colors, positions, Shader.TileMode.CLAMP); + } else { + float p3 = (1 - iw*3/(float) w)/2; + float p4 = (1 + iw*3/(float) w)/2; + + float s = 255 * p3/p1; + float c3f = s * coeff ; // here goes some optimized stuff + float c2f = z + c3f; + + int c1 = Math.round( c1f ) << 24; + int c2 = Math.round( c2f ) << 24; + int c3 = Math.round( c3f ) << 24; + + int[] colors = { c2, c2, c2, c2, 0xff000000, 0xff000000, c2, c2, c2, c2 }; + float[] positions = { 0, p3, p3, p1, p1, p2, p2, p4, p4, 1 }; + shader = new LinearGradient(0, 0, w, 0, colors, positions, Shader.TileMode.CLAMP); + } + mSelectorWheelPaint.setShader(shader); + invalidate(); + } + + + //-------------------------------------------------------------------------- + // + // Scroller-specific methods + // + //-------------------------------------------------------------------------- + + @Override + protected WheelScroller createScroller(WheelScroller.ScrollingListener scrollingListener) { + return new WheelHorizontalScroller(getContext(), scrollingListener); + } + + @Override + protected float getMotionEventPosition(MotionEvent event) { + return event.getX(); + } + + + //-------------------------------------------------------------------------- + // + // Base measurements + // + //-------------------------------------------------------------------------- + + @Override + protected int getBaseDimension() { + return getWidth(); + } + + /** + * Returns height of spinnerwheel item + * @return the item width + */ + @Override + protected int getItemDimension() { + if (itemWidth != 0) { + return itemWidth; + } + + if (mItemsLayout != null && mItemsLayout.getChildAt(0) != null) { + itemWidth = mItemsLayout.getChildAt(0).getMeasuredWidth(); + return itemWidth; + } + + return getBaseDimension() / mVisibleItems; + } + + //-------------------------------------------------------------------------- + // + // Debugging stuff + // + //-------------------------------------------------------------------------- + + + @Override + protected void onScrollTouchedUp() { + super.onScrollTouchedUp(); + int cnt = mItemsLayout.getChildCount(); + View itm; + Log.e(LOG_TAG, " ----- layout: " + mItemsLayout.getMeasuredWidth() + mItemsLayout.getMeasuredHeight()); + Log.e(LOG_TAG, " -------- dumping " + cnt + " items"); + for (int i = 0; i < cnt; i++) { + itm = mItemsLayout.getChildAt(i); + Log.e(LOG_TAG, " item #" + i + ": " + itm.getWidth() + "x" + itm.getHeight()); + itm.forceLayout(); // forcing layout without re-rendering parent + } + Log.e(LOG_TAG, " ---------- dumping finished "); + } + + + //-------------------------------------------------------------------------- + // + // Layout creation and measurement operations + // + //-------------------------------------------------------------------------- + + /** + * Creates item layouts if necessary + */ + @Override + protected void createItemsLayout() { + if (mItemsLayout == null) { + mItemsLayout = new LinearLayout(getContext()); + mItemsLayout.setOrientation(LinearLayout.HORIZONTAL); + } + } + + @Override + protected void doItemsLayout() { + mItemsLayout.layout(0, 0, getMeasuredWidth(), getMeasuredHeight() - 2 * mItemsPadding); + } + + @Override + protected void measureLayout() { + mItemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + // XXX: Locating bug + mItemsLayout.measure( + View.MeasureSpec.makeMeasureSpec(getWidth() + getItemDimension(), View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(getHeight(), View.MeasureSpec.AT_MOST)); + } + + //XXX: Most likely, measurements of mItemsLayout or/and its children are done inconrrectly. + // Investigate and fix it + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = View.MeasureSpec.getMode(widthMeasureSpec); + int heightMode = View.MeasureSpec.getMode(heightMeasureSpec); + int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); + int heightSize = View.MeasureSpec.getSize(heightMeasureSpec); + + rebuildItems(); // rebuilding before measuring + + int height = calculateLayoutHeight(heightSize, heightMode); + + int width; + if (widthMode == View.MeasureSpec.EXACTLY) { + width = widthSize; + } else { + width = Math.max( + getItemDimension() * (mVisibleItems - mItemOffsetPercent / 100), + getSuggestedMinimumWidth() + ); + + if (widthMode == View.MeasureSpec.AT_MOST) { + width = Math.min(width, widthSize); + } + } + setMeasuredDimension(width, height); + } + + + /** + * Calculates control height and creates text layouts + * @param heightSize the input layout height + * @param mode the layout mode + * @return the calculated control height + */ + private int calculateLayoutHeight(int heightSize, int mode) { + mItemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + mItemsLayout.measure( + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.UNSPECIFIED) + ); + int height = mItemsLayout.getMeasuredHeight(); + + if (mode == View.MeasureSpec.EXACTLY) { + height = heightSize; + } else { + height += 2 * mItemsPadding; + + // Check against our minimum width + height = Math.max(height, getSuggestedMinimumHeight()); + + if (mode == View.MeasureSpec.AT_MOST && heightSize < height) { + height = heightSize; + } + } + // forcing recalculating + mItemsLayout.measure( + // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(400, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height - 2 * mItemsPadding, View.MeasureSpec.EXACTLY) + ); + + return height; + } + + + //-------------------------------------------------------------------------- + // + // Drawing items + // + //-------------------------------------------------------------------------- + + @Override + protected void drawItems(Canvas canvas) { + canvas.save(); + int w = getMeasuredWidth(); + int h = getMeasuredHeight(); + int iw = getItemDimension(); + + // resetting intermediate bitmap and recreating canvases + mSpinBitmap.eraseColor(0); + Canvas c = new Canvas(mSpinBitmap); + Canvas cSpin = new Canvas(mSpinBitmap); + + int left = (mCurrentItemIdx - mFirstItemIdx) * iw + (iw - getWidth()) / 2; + c.translate(- left + mScrollingOffset, mItemsPadding); + mItemsLayout.draw(c); + +// mSeparatorsBitmap.eraseColor(0); + Canvas cSeparators = new Canvas(mSpinBitmap); + + if (mSelectionDivider != null) { + // draw the top divider + int leftOfLeftDivider = (getWidth() - iw - mSelectionDividerWidth) / 2; + int rightOfLeftDivider = leftOfLeftDivider + mSelectionDividerWidth; + mSelectionDivider.setBounds(leftOfLeftDivider, 0, rightOfLeftDivider, getHeight()); + mSelectionDivider.draw(cSeparators); + + // draw the bottom divider + int leftOfRightDivider = leftOfLeftDivider + iw; + int rightOfRightDivider = rightOfLeftDivider + iw; + mSelectionDivider.setBounds(leftOfRightDivider, 0, rightOfRightDivider, getHeight()); + mSelectionDivider.draw(cSeparators); + } + + cSpin.drawRect(0, 0, w, h, mSelectorWheelPaint); + cSeparators.drawRect(0, 0, w, h, mSeparatorsPaint); + + canvas.drawBitmap(mSpinBitmap, 0, 0, null); + canvas.drawBitmap(mSpinBitmap, 0, 0, null); + canvas.restore(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelRecycler.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelRecycler.java new file mode 100644 index 0000000..ddd36e8 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelRecycler.java @@ -0,0 +1,163 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + +import android.view.View; +import android.widget.LinearLayout; + +import java.util.LinkedList; +import java.util.List; + +/** + * Recycle stored spinnerwheel items to reuse. + */ +public class WheelRecycler { + + + @SuppressWarnings("unused") + private static final String LOG_TAG = WheelRecycler.class.getName(); + + // Cached items + private List items; + + // Cached empty items + private List emptyItems; + + // Wheel view + private AbstractWheel wheel; + + /** + * Constructor + * @param wheel the spinnerwheel view + */ + public WheelRecycler(AbstractWheel wheel) { + this.wheel = wheel; + } + + /** + * Recycles items from specified layout. + * There are saved only items not included to specified range. + * All the cached items are removed from original layout. + * + * @param layout the layout containing items to be cached + * @param firstItem the number of first item in layout + * @param range the range of current spinnerwheel items + * @return the new value of first item number + */ + public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) { + int index = firstItem; + for (int i = 0; i < layout.getChildCount();) { + if (!range.contains(index)) { + recycleView(layout.getChildAt(i), index); + layout.removeViewAt(i); + if (i == 0) { // first item + firstItem++; + } + } else { + i++; // go to next item + } + index++; + } + return firstItem; + } + + /** + * Gets item view + * @return the cached view + */ + public View getItem() { + return getCachedView(items); + } + + /** + * Gets empty item view + * @return the cached empty view + */ + public View getEmptyItem() { + return getCachedView(emptyItems); + } + + /** + * Clears all views + */ + public void clearAll() { + if (items != null) { + items.clear(); + } + if (emptyItems != null) { + emptyItems.clear(); + } + } + + /** + * Adds view to specified cache. Creates a cache list if it is null. + * @param view the view to be cached + * @param cache the cache list + * @return the cache list + */ + private List addView(View view, List cache) { + if (cache == null) { + cache = new LinkedList(); + } + + cache.add(view); + return cache; + } + + /** + * Adds view to cache. Determines view type (item view or empty one) by index. + * @param view the view to be cached + * @param index the index of view + */ + private void recycleView(View view, int index) { + int count = wheel.getViewAdapter().getItemsCount(); + + if ((index < 0 || index >= count) && !wheel.isCyclic()) { + // empty view + emptyItems = addView(view, emptyItems); + } else { + while (index < 0) { + index = count + index; + } + index %= count; + items = addView(view, items); + } + } + + /** + * Gets view from specified cache. + * @param cache the cache + * @return the first view from cache. + */ + private View getCachedView(List cache) { + if (cache != null && cache.size() > 0) { + View view = cache.get(0); + cache.remove(0); + return view; + } + return null; + } + +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelScroller.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelScroller.java new file mode 100644 index 0000000..cd2a20f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelScroller.java @@ -0,0 +1,281 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.view.GestureDetector; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.MotionEvent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * Scroller class handles scrolling events and updates the spinnerwheel + */ +public abstract class WheelScroller { + /** + * Scrolling listener interface + */ + public interface ScrollingListener { + /** + * Scrolling callback called when scrolling is performed. + * @param distance the distance to scroll + */ + void onScroll(int distance); + + /** + * This callback is invoked when scroller has been touched + */ + void onTouch(); + + /** + * This callback is invoked when touch is up + */ + void onTouchUp(); + + /** + * Starting callback called when scrolling is started + */ + void onStarted(); + + /** + * Finishing callback called after justifying + */ + void onFinished(); + + /** + * Justifying callback called to justify a view when scrolling is ended + */ + void onJustify(); + } + + /** Scrolling duration */ + private static final int SCROLLING_DURATION = 400; + + /** Minimum delta for scrolling */ + public static final int MIN_DELTA_FOR_SCROLLING = 1; + + // Listener + private ScrollingListener listener; + + // Context + private Context context; + + // Scrolling + private GestureDetector gestureDetector; + protected Scroller scroller; + private int lastScrollPosition; + private float lastTouchedPosition; + private boolean isScrollingPerformed; + + /** + * Constructor + * @param context the current context + * @param listener the scrolling listener + */ + public WheelScroller(Context context, ScrollingListener listener) { + gestureDetector = new GestureDetector(context, new SimpleOnGestureListener() { + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + // Do scrolling in onTouchEvent() since onScroll() are not call immediately + // when user touch and move the spinnerwheel + return true; + } + + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + lastScrollPosition = 0; + scrollerFling(lastScrollPosition, (int) velocityX, (int) velocityY); + setNextMessage(MESSAGE_SCROLL); + return true; + } + + // public boolean onDown(MotionEvent motionEvent); + + }); + gestureDetector.setIsLongpressEnabled(false); + + scroller = new Scroller(context); + + this.listener = listener; + this.context = context; + } + + /** + * Set the the specified scrolling interpolator + * @param interpolator the interpolator + */ + public void setInterpolator(Interpolator interpolator) { + scroller.forceFinished(true); + scroller = new Scroller(context, interpolator); + } + + /** + * Scroll the spinnerwheel + * @param distance the scrolling distance + * @param time the scrolling duration + */ + public void scroll(int distance, int time) { + scroller.forceFinished(true); + lastScrollPosition = 0; + scrollerStartScroll(distance, time != 0 ? time : SCROLLING_DURATION); + setNextMessage(MESSAGE_SCROLL); + startScrolling(); + } + + /** + * Stops scrolling + */ + public void stopScrolling() { + scroller.forceFinished(true); + } + + /** + * Handles Touch event + * @param event the motion event + * @return + */ + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + + case MotionEvent.ACTION_DOWN: + lastTouchedPosition = getMotionEventPosition(event); + scroller.forceFinished(true); + clearMessages(); + listener.onTouch(); + break; + + case MotionEvent.ACTION_UP: + if (scroller.isFinished()) + listener.onTouchUp(); + break; + + + case MotionEvent.ACTION_MOVE: + // perform scrolling + int distance = (int)(getMotionEventPosition(event) - lastTouchedPosition); + if (distance != 0) { + startScrolling(); + listener.onScroll(distance); + lastTouchedPosition = getMotionEventPosition(event); + } + break; + } + + if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) { + justify(); + } + + return true; + } + + + // Messages + private final int MESSAGE_SCROLL = 0; + private final int MESSAGE_JUSTIFY = 1; + + /** + * Set next message to queue. Clears queue before. + * + * @param message the message to set + */ + private void setNextMessage(int message) { + clearMessages(); + animationHandler.sendEmptyMessage(message); + } + + /** + * Clears messages from queue + */ + private void clearMessages() { + animationHandler.removeMessages(MESSAGE_SCROLL); + animationHandler.removeMessages(MESSAGE_JUSTIFY); + } + + // animation handler + private Handler animationHandler = new Handler() { + public void handleMessage(Message msg) { + scroller.computeScrollOffset(); + int currPosition = getCurrentScrollerPosition(); + int delta = lastScrollPosition - currPosition; + lastScrollPosition = currPosition; + if (delta != 0) { + listener.onScroll(delta); + } + + // scrolling is not finished when it comes to final Y + // so, finish it manually + if (Math.abs(currPosition - getFinalScrollerPosition()) < MIN_DELTA_FOR_SCROLLING) { + // currPosition = getFinalScrollerPosition(); + scroller.forceFinished(true); + } + if (!scroller.isFinished()) { + animationHandler.sendEmptyMessage(msg.what); + } else if (msg.what == MESSAGE_SCROLL) { + justify(); + } else { + finishScrolling(); + } + } + }; + + /** + * Justifies spinnerwheel + */ + private void justify() { + listener.onJustify(); + setNextMessage(MESSAGE_JUSTIFY); + } + + /** + * Starts scrolling + */ + private void startScrolling() { + if (!isScrollingPerformed) { + isScrollingPerformed = true; + listener.onStarted(); + } + } + + /** + * Finishes scrolling + */ + protected void finishScrolling() { + if (isScrollingPerformed) { + listener.onFinished(); + isScrollingPerformed = false; + } + } + + protected abstract int getCurrentScrollerPosition(); + + protected abstract int getFinalScrollerPosition(); + + protected abstract float getMotionEventPosition(MotionEvent event); + + protected abstract void scrollerStartScroll(int distance, int time); + + protected abstract void scrollerFling(int position, int velocityX, int velocityY); +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalScroller.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalScroller.java new file mode 100644 index 0000000..ce8ad81 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalScroller.java @@ -0,0 +1,71 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + +import android.content.Context; +import android.view.MotionEvent; + +/** + * Scroller class handles scrolling events and updates the + */ +public class WheelVerticalScroller extends WheelScroller { + + /** + * Constructor + * @param context the current context + * @param listener the scrolling listener + */ + public WheelVerticalScroller(Context context, ScrollingListener listener) { + super(context, listener); + } + + @Override + protected int getCurrentScrollerPosition() { + return scroller.getCurrY(); + } + + @Override + protected int getFinalScrollerPosition() { + return scroller.getFinalY(); + } + + @Override + protected float getMotionEventPosition(MotionEvent event) { + // should be overriden + return event.getY(); + } + + @Override + protected void scrollerStartScroll(int distance, int time) { + scroller.startScroll(0, 0, 0, distance, time); + } + + @Override + protected void scrollerFling(int position, int velocityX, int velocityY) { + final int maxPosition = 0x7FFFFFFF; + final int minPosition = -maxPosition; + scroller.fling(0, position, 0, -velocityY, 0, 0, minPosition, maxPosition); + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalView.java b/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalView.java new file mode 100644 index 0000000..ba0669a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/WheelVerticalView.java @@ -0,0 +1,344 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.LinearLayout; + +import com.yonsz.z1.R; + +/** + * Spinner wheel vertical view. + * + * @author Yuri Kanivets + * @author Dimitri Fedorov + */ +public class WheelVerticalView extends AbstractWheelView { + + private static int itemID = -1; + + @SuppressWarnings("unused") + private final String LOG_TAG = WheelVerticalView.class.getName() + " #" + (++itemID); + + /** + * The height of the selection divider. + */ + protected int mSelectionDividerHeight; + + // Cached item height + private int mItemHeight = 0; + + //-------------------------------------------------------------------------- + // + // Constructors + // + //-------------------------------------------------------------------------- + + /** + * Create a new wheel vertical view. + * + * @param context The application environment. + */ + public WheelVerticalView(Context context) { + this(context, null); + } + + /** + * Create a new wheel vertical view. + * + * @param context The application environment. + * @param attrs A collection of attributes. + */ + public WheelVerticalView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.abstractWheelViewStyle); + } + + /** + * Create a new wheel vertical view. + * + * @param context the application environment. + * @param attrs a collection of attributes. + * @param defStyle The default style to apply to this view. + */ + public WheelVerticalView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + + //-------------------------------------------------------------------------- + // + // Initiating assets and setter for selector paint + // + //-------------------------------------------------------------------------- + + @Override + protected void initAttributes(AttributeSet attrs, int defStyle) { + super.initAttributes(attrs, defStyle); + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WheelVerticalView, defStyle, 0); + mSelectionDividerHeight = a.getDimensionPixelSize(R.styleable.WheelVerticalView_selectionDividerHeight, DEF_SELECTION_DIVIDER_SIZE); + a.recycle(); + } + + @Override + public void setSelectorPaintCoeff(float coeff) { + LinearGradient shader; + + int h = getMeasuredHeight(); + int ih = getItemDimension(); + float p1 = (1 - ih/(float) h)/2; + float p2 = (1 + ih/(float) h)/2; + float z = mItemsDimmedAlpha * (1 - coeff); + float c1f = z + 255 * coeff; + + if (mVisibleItems == 2) { + int c1 = Math.round( c1f ) << 24; + int c2 = Math.round( z ) << 24; + int[] colors = {c2, c1, 0xff000000, 0xff000000, c1, c2}; + float[] positions = { 0, p1, p1, p2, p2, 1}; + shader = new LinearGradient(0, 0, 0, h, colors, positions, Shader.TileMode.CLAMP); + } else { + float p3 = (1 - ih*3/(float) h)/2; + float p4 = (1 + ih*3/(float) h)/2; + + float s = 255 * p3/p1; + float c3f = s * coeff ; // here goes some optimized stuff + float c2f = z + c3f; + + int c1 = Math.round( c1f ) << 24; + int c2 = Math.round( c2f ) << 24; + int c3 = Math.round( c3f ) << 24; + + int[] colors = {0, c3, c2, c1, 0xff000000, 0xff000000, c1, c2, c3, 0}; + float[] positions = {0, p3, p3, p1, p1, p2, p2, p4, p4, 1}; + shader = new LinearGradient(0, 0, 0, h, colors, positions, Shader.TileMode.CLAMP); + } + mSelectorWheelPaint.setShader(shader); + invalidate(); + } + + + //-------------------------------------------------------------------------- + // + // Scroller-specific methods + // + //-------------------------------------------------------------------------- + + @Override + protected WheelScroller createScroller(WheelScroller.ScrollingListener scrollingListener) { + return new WheelVerticalScroller(getContext(), scrollingListener); + } + + @Override + protected float getMotionEventPosition(MotionEvent event) { + return event.getY(); + } + + //-------------------------------------------------------------------------- + // + // Base measurements + // + //-------------------------------------------------------------------------- + + @Override + protected int getBaseDimension() { + return getHeight(); + } + + /** + * Returns height of the spinnerwheel + * @return the item height + */ + @Override + protected int getItemDimension() { + if (mItemHeight != 0) { + return mItemHeight; + } + + if (mItemsLayout != null && mItemsLayout.getChildAt(0) != null) { + mItemHeight = mItemsLayout.getChildAt(0).getMeasuredHeight(); + return mItemHeight; + } + + return getBaseDimension() / mVisibleItems; + } + + //-------------------------------------------------------------------------- + // + // Layout creation and measurement operations + // + //-------------------------------------------------------------------------- + + /** + * Creates item layout if necessary + */ + @Override + protected void createItemsLayout() { + if (mItemsLayout == null) { + mItemsLayout = new LinearLayout(getContext()); + mItemsLayout.setOrientation(LinearLayout.VERTICAL); + } + } + + @Override + protected void doItemsLayout() { + mItemsLayout.layout(0, 0, getMeasuredWidth() - 2 * mItemsPadding, getMeasuredHeight()); + } + + + @Override + protected void measureLayout() { + mItemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + + mItemsLayout.measure( + View.MeasureSpec.makeMeasureSpec(getWidth() - 2 * mItemsPadding, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) + ); + + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + int widthMode = View.MeasureSpec.getMode(widthMeasureSpec); + int heightMode = View.MeasureSpec.getMode(heightMeasureSpec); + int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); + int heightSize = View.MeasureSpec.getSize(heightMeasureSpec); + + rebuildItems(); // rebuilding before measuring + + int width = calculateLayoutWidth(widthSize, widthMode); + + int height; + if (heightMode == View.MeasureSpec.EXACTLY) { + height = heightSize; + } else { + height = Math.max( + getItemDimension() * (mVisibleItems - mItemOffsetPercent / 100), + getSuggestedMinimumHeight() + ); + + if (heightMode == View.MeasureSpec.AT_MOST) { + height = Math.min(height, heightSize); + } + } + setMeasuredDimension(width, height); + } + + /** + * Calculates control width + * @param widthSize the input layout width + * @param mode the layout mode + * @return the calculated control width + */ + private int calculateLayoutWidth(int widthSize, int mode) { + mItemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + mItemsLayout.measure( + View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) + ); + int width = mItemsLayout.getMeasuredWidth(); + + if (mode == View.MeasureSpec.EXACTLY) { + width = widthSize; + } else { + width += 2 * mItemsPadding; + + // Check against our minimum width + width = Math.max(width, getSuggestedMinimumWidth()); + + if (mode == View.MeasureSpec.AT_MOST && widthSize < width) { + width = widthSize; + } + } + + // forcing recalculating + mItemsLayout.measure( + View.MeasureSpec.makeMeasureSpec(width - 2 * mItemsPadding, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) + ); + + return width; + } + + + //-------------------------------------------------------------------------- + // + // Drawing items + // + //-------------------------------------------------------------------------- + + @Override + protected void drawItems(Canvas canvas) { + canvas.save(); + int w = getMeasuredWidth(); + int h = getMeasuredHeight(); + int ih = getItemDimension(); + + // resetting intermediate bitmap and recreating canvases + mSpinBitmap.eraseColor(0); + Canvas c = new Canvas(mSpinBitmap); + Canvas cSpin = new Canvas(mSpinBitmap); + + int top = (mCurrentItemIdx - mFirstItemIdx) * ih + (ih - getHeight()) / 2; + c.translate(mItemsPadding, - top + mScrollingOffset); + mItemsLayout.draw(c); + +// mSeparatorsBitmap.eraseColor(0); + Canvas cSeparators = new Canvas(mSpinBitmap); + + if (mSelectionDivider != null) { + // draw the top divider + int topOfTopDivider = (getHeight() - ih - mSelectionDividerHeight) / 2; + int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; + mSelectionDivider.setBounds(0, topOfTopDivider, w, bottomOfTopDivider); + mSelectionDivider.draw(cSeparators); + + // draw the bottom divider + int topOfBottomDivider = topOfTopDivider + ih; + int bottomOfBottomDivider = bottomOfTopDivider + ih; + mSelectionDivider.setBounds(0, topOfBottomDivider, w, bottomOfBottomDivider); + mSelectionDivider.draw(cSeparators); + } + + cSpin.drawRect(0, 0, w, h, mSelectorWheelPaint); + cSeparators.drawRect(0, 0, w, h, mSeparatorsPaint); + + canvas.drawBitmap(mSpinBitmap, 0, 0, null); + canvas.drawBitmap(mSpinBitmap, 0, 0, null); + canvas.restore(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelAdapter.java b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelAdapter.java new file mode 100644 index 0000000..be3dafc --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelAdapter.java @@ -0,0 +1,82 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +import java.util.LinkedList; +import java.util.List; + +/** + * Abstract Wheel adapter. + */ +public abstract class AbstractWheelAdapter implements WheelViewAdapter { + // Observers + private List datasetObservers; + + @Override + public View getEmptyItem(View convertView, ViewGroup parent) { + return null; + } + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + if (datasetObservers == null) { + datasetObservers = new LinkedList(); + } + datasetObservers.add(observer); + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + if (datasetObservers != null) { + datasetObservers.remove(observer); + } + } + + /** + * Notifies observers about data changing + */ + protected void notifyDataChangedEvent() { + if (datasetObservers != null) { + for (DataSetObserver observer : datasetObservers) { + observer.onChanged(); + } + } + } + + /** + * Notifies observers about invalidating data + */ + protected void notifyDataInvalidatedEvent() { + if (datasetObservers != null) { + for (DataSetObserver observer : datasetObservers) { + observer.onInvalidated(); + } + } + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelTextAdapter.java b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelTextAdapter.java new file mode 100644 index 0000000..4864a34 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/AbstractWheelTextAdapter.java @@ -0,0 +1,289 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.lechange.demo.common.datepicker.adapters; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +/** + * Abstract spinnerwheel adapter provides common functionality for adapters. + */ +public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter { + + /** Text view resource. Used as a default view for adapter. */ + public static final int TEXT_VIEW_ITEM_RESOURCE = -1; + + /** No resource constant. */ + protected static final int NO_RESOURCE = 0; + + /** Default text color */ + public static final int DEFAULT_TEXT_COLOR = 0xFF101010; + + /** Default text color */ + public static final int LABEL_COLOR = 0xFF700070; + + /** Default text size */ + public static final int DEFAULT_TEXT_SIZE = 24; + + /// Custom text typeface + private Typeface textTypeface; + + // Text settings + private int textColor = DEFAULT_TEXT_COLOR; + private int textSize = DEFAULT_TEXT_SIZE; + + // Current context + protected Context context; + // Layout inflater + protected LayoutInflater inflater; + + // Items resources + protected int itemResourceId; + protected int itemTextResourceId; + + // Empty items resources + protected int emptyItemResourceId; + + + /** + * Constructor + * @param context the current context + */ + protected AbstractWheelTextAdapter(Context context) { + this(context, TEXT_VIEW_ITEM_RESOURCE); + } + + /** + * Constructor + * @param context the current context + * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views + */ + protected AbstractWheelTextAdapter(Context context, int itemResource) { + this(context, itemResource, NO_RESOURCE); + } + + /** + * Constructor + * @param context the current context + * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views + * @param itemTextResource the resource ID for a text view in the item layout + */ + protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) { + this.context = context; + itemResourceId = itemResource; + itemTextResourceId = itemTextResource; + + inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + /** + * Gets text color + * @return the text color + */ + public int getTextColor() { + return textColor; + } + + /** + * Sets text color + * @param textColor the text color to set + */ + public void setTextColor(int textColor) { + this.textColor = textColor; + } + + /** + * Sets text typeface + * @param typeface typeface to set + */ + public void setTextTypeface(Typeface typeface) { + this.textTypeface = typeface; + } + + /** + * Gets text size + * @return the text size + */ + public int getTextSize() { + return textSize; + } + + /** + * Sets text size + * @param textSize the text size to set + */ + public void setTextSize(int textSize) { + this.textSize = textSize; + } + + /** + * Gets resource Id for items views + * @return the item resource Id + */ + public int getItemResource() { + return itemResourceId; + } + + /** + * Sets resource Id for items views + * @param itemResourceId the resource Id to set + */ + public void setItemResource(int itemResourceId) { + this.itemResourceId = itemResourceId; + } + + /** + * Gets resource Id for text view in item layout + * @return the item text resource Id + */ + public int getItemTextResource() { + return itemTextResourceId; + } + + /** + * Sets resource Id for text view in item layout + * @param itemTextResourceId the item text resource Id to set + */ + public void setItemTextResource(int itemTextResourceId) { + this.itemTextResourceId = itemTextResourceId; + } + + /** + * Gets resource Id for empty items views + * @return the empty item resource Id + */ + public int getEmptyItemResource() { + return emptyItemResourceId; + } + + /** + * Sets resource Id for empty items views + * @param emptyItemResourceId the empty item resource Id to set + */ + public void setEmptyItemResource(int emptyItemResourceId) { + this.emptyItemResourceId = emptyItemResourceId; + } + + /** + * Returns text for specified item + * @param index the item index + * @return the text of specified items + */ + protected abstract CharSequence getItemText(int index); + + @Override + public View getItem(int index, View convertView, ViewGroup parent) { + if (index >= 0 && index < getItemsCount()) { + if (convertView == null) { + convertView = getView(itemResourceId, parent); + } + TextView textView = getTextView(convertView, itemTextResourceId); + if (textView != null) { + CharSequence text = getItemText(index); + if (text == null) { + text = ""; + } + textView.setText(text); + configureTextView(textView); + } + return convertView; + } + return null; + } + + @Override + public View getEmptyItem(View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = getView(emptyItemResourceId, parent); + } + if (convertView instanceof TextView) { + configureTextView((TextView)convertView); + } + + return convertView; + } + + /** + * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views. + * @param view the text view to be configured + */ + protected void configureTextView(TextView view) { + if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) { + view.setTextColor(textColor); + view.setGravity(Gravity.CENTER); + view.setTextSize(textSize); + view.setLines(1); + } + if (textTypeface != null) { + view.setTypeface(textTypeface); + } else { + view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); + } + } + + /** + * Loads a text view from view + * @param view the text view or layout containing it + * @param textResource the text resource Id in layout + * @return the loaded text view + */ + private TextView getTextView(View view, int textResource) { + TextView text = null; + try { + if (textResource == NO_RESOURCE && view instanceof TextView) { + text = (TextView) view; + } else if (textResource != NO_RESOURCE) { + text = (TextView) view.findViewById(textResource); + } + } catch (ClassCastException e) { + Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView"); + throw new IllegalStateException( + "AbstractWheelAdapter requires the resource ID to be a TextView", e); + } + + return text; + } + + /** + * Loads view from resources + * @param resource the resource Id + * @return the loaded view or null if resource is not set + */ + private View getView(int resource, ViewGroup parent) { + switch (resource) { + case NO_RESOURCE: + return null; + case TEXT_VIEW_ITEM_RESOURCE: + return new TextView(context); + default: + return inflater.inflate(resource, parent, false); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/adapters/ArrayWheelAdapter.java b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/ArrayWheelAdapter.java new file mode 100644 index 0000000..54ff65c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/ArrayWheelAdapter.java @@ -0,0 +1,70 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.lechange.demo.common.datepicker.adapters; + +import android.content.Context; + +/** + * The simple Array spinnerwheel adapter + * + * @param + * the element type + */ +public class ArrayWheelAdapter extends AbstractWheelTextAdapter { + + // items + private T items[]; + + /** + * Constructor + * + * @param context + * the current context + * @param items + * the items + */ + public ArrayWheelAdapter(Context context, T items[]) { + super(context); + + // setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE); + this.items = items; + } + + @Override + public CharSequence getItemText(int index) { + if (index >= 0 && index < items.length) { + T item = items[index]; + if (item instanceof CharSequence) { + return (CharSequence) item; + } + return item.toString(); + } + return null; + } + + @Override + public int getItemsCount() { + return items.length; + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/adapters/NumericWheelAdapter.java b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/NumericWheelAdapter.java new file mode 100644 index 0000000..1afe288 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/NumericWheelAdapter.java @@ -0,0 +1,106 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker.adapters; + +import android.content.Context; + +/** + * Numeric Wheel adapter. + */ +public class NumericWheelAdapter extends AbstractWheelTextAdapter { + + /** The default min value */ + public static final int DEFAULT_MAX_VALUE = 9; + + /** The default max value */ + private static final int DEFAULT_MIN_VALUE = 0; + + // Values + private int minValue; + private int maxValue; + + // format + private String format; + + /** + * Constructor + * + * @param context + * the current context + */ + public NumericWheelAdapter(Context context) { + this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE); + } + + /** + * Constructor + * + * @param context + * the current context + * @param minValue + * the spinnerwheel min value + * @param maxValue + * the spinnerwheel max value + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue) { + this(context, minValue, maxValue, null); + } + + /** + * Constructor + * + * @param context + * the current context + * @param minValue + * the spinnerwheel min value + * @param maxValue + * the spinnerwheel max value + * @param format + * the format string + */ + public NumericWheelAdapter(Context context, int minValue, int maxValue, + String format) { + super(context); + + this.minValue = minValue; + this.maxValue = maxValue; + this.format = format; + } + + @Override + public CharSequence getItemText(int index) { + if (index >= 0 && index < getItemsCount()) { + int value = minValue + index; + return format != null ? String.format(format, value) : Integer + .toString(value); + } + return null; + } + + @Override + public int getItemsCount() { + return maxValue - minValue + 1; + } +} diff --git a/app/src/main/java/com/lechange/demo/common/datepicker/adapters/WheelViewAdapter.java b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/WheelViewAdapter.java new file mode 100644 index 0000000..297095d --- /dev/null +++ b/app/src/main/java/com/lechange/demo/common/datepicker/adapters/WheelViewAdapter.java @@ -0,0 +1,72 @@ +/* + * android-spinnerwheel + * https://github.com/ai212983/android-spinnerwheel + * + * based on + * + * Android Wheel Control. + * https://code.google.com/p/android-wheel/ + * + * Copyright 2011 Yuri Kanivets + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.common.datepicker.adapters; + +import android.database.DataSetObserver; +import android.view.View; +import android.view.ViewGroup; + +/** + * Wheel items adapter interface + */ +public interface WheelViewAdapter { + /** + * Gets items count + * @return the count of spinnerwheel items + */ + public int getItemsCount(); + + /** + * Get a View that displays the data at the specified position in the data set + * + * @param index the item index + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the spinnerwheel item View + */ + public View getItem(int index, View convertView, ViewGroup parent); + + /** + * Get a View that displays an empty spinnerwheel item placed before the first or after + * the last spinnerwheel item. + * + * @param convertView the old view to reuse if possible + * @param parent the parent that this view will eventually be attached to + * @return the empty item View + */ + public View getEmptyItem(View convertView, ViewGroup parent); + + /** + * Register an observer that is called when changes happen to the data used by this adapter. + * @param observer the observer to be registered + */ + public void registerDataSetObserver(DataSetObserver observer); + + /** + * Unregister an observer that has previously been registered + * @param observer the observer to be unregistered + */ + void unregisterDataSetObserver(DataSetObserver observer); +} diff --git a/app/src/main/java/com/lechange/demo/dialog/DeviceUpdateDialog.java b/app/src/main/java/com/lechange/demo/dialog/DeviceUpdateDialog.java new file mode 100644 index 0000000..c6c3e1c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/dialog/DeviceUpdateDialog.java @@ -0,0 +1,59 @@ +package com.lechange.demo.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import com.yonsz.z1.R; + + +public class DeviceUpdateDialog extends Dialog { + private TextView tv_title; + private TextView tv_msg; + private TextView btn_ok; + private TextView btn_cancel; + + public DeviceUpdateDialog(Context context) { + super(context, R.style.sign_dialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_device_update); + tv_title = findViewById(R.id.tv_title); + tv_msg = findViewById(R.id.tv_msg); + btn_ok = findViewById(R.id.btn_ok); + btn_cancel = findViewById(R.id.btn_cancel); + btn_ok.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mOnOkClickLisenter != null) { + mOnOkClickLisenter.OnOK(); + } + dismiss(); + + } + }); + btn_cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dismiss(); + + } + }); + } + + public interface OnOkClickLisenter { + void OnOK(); + } + + private OnOkClickLisenter mOnOkClickLisenter; + + public void setOnOkClickLisenter(OnOkClickLisenter lisenter) { + this.mOnOkClickLisenter = lisenter; + } + +} diff --git a/app/src/main/java/com/lechange/demo/dialog/EncryptKeyInputDialog.java b/app/src/main/java/com/lechange/demo/dialog/EncryptKeyInputDialog.java new file mode 100644 index 0000000..b5fa4a1 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/dialog/EncryptKeyInputDialog.java @@ -0,0 +1,72 @@ +package com.lechange.demo.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.mm.android.deviceaddmodule.mobilecommon.widget.ClearEditText; +import com.yonsz.z1.R; + +public class EncryptKeyInputDialog extends Dialog { + + private TextView tvTitle; + private ClearEditText encryptKey; + private TextView tvCancel; + private TextView tvSure; + private OnClick onClick; + + public EncryptKeyInputDialog(Context context) { + super(context, R.style.custom_dialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_encryptkey_input); + setCanceledOnTouchOutside(false); + initView(); + } + + public void setText(String content){ + tvTitle.setText(content); + } + + + private void initView() { + tvTitle = findViewById(R.id.tv_title); + encryptKey = findViewById(R.id.encrypt_key); + tvCancel = findViewById(R.id.tv_cancel); + tvSure = findViewById(R.id.tv_sure); + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismissLoading(); + } + }); + tvSure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String key = encryptKey.getText().toString().trim(); + if (onClick != null && !TextUtils.isEmpty(key)) { + onClick.onSure(key); + dismissLoading(); + } + } + }); + } + + public void dismissLoading() { + dismiss(); + } + + public interface OnClick { + void onSure(String txt); + } + + public void setOnClick(OnClick onClick) { + this.onClick = onClick; + } +} diff --git a/app/src/main/java/com/lechange/demo/dialog/LoadingDialog.java b/app/src/main/java/com/lechange/demo/dialog/LoadingDialog.java new file mode 100644 index 0000000..7cb11b1 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/dialog/LoadingDialog.java @@ -0,0 +1,35 @@ +package com.lechange.demo.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.widget.ProgressBar; + +import com.yonsz.z1.R; + + +public class LoadingDialog extends Dialog { + ProgressBar av_anim; + + public LoadingDialog(Context context) { + super(context, R.style.custom_dialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_loading_view); + setCanceledOnTouchOutside(false); + initView(); + } + + private void initView() { + av_anim = (ProgressBar) findViewById(R.id.av_anim); + } + + public void dismissLoading() { + av_anim.setVisibility(View.GONE); + dismiss(); + } +} diff --git a/app/src/main/java/com/lechange/demo/dialog/PasswordDialog.java b/app/src/main/java/com/lechange/demo/dialog/PasswordDialog.java new file mode 100644 index 0000000..7d7b158 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/dialog/PasswordDialog.java @@ -0,0 +1,148 @@ +package com.lechange.demo.dialog; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; + +import com.lechange.demo.listener.PasswordSetListener; +import com.yonsz.z1.R; + +public class PasswordDialog extends DialogFragment { + + + private PasswordSetListener mListener; + // private EditText mEditText; + private EditText editText1; + + private int currentType = -1; //1 表示设备密码 2表示wifi密码 设备初始化的密码 + + @Override + public void setStyle(int style, int theme) { + super.setStyle(style, theme); + } + + @Override + public void dismiss() { + super.dismiss(); + } + + @Override + public void setCancelable(boolean cancelable) { + super.setCancelable(cancelable); + } + + @Override + public boolean isCancelable() { + return super.isCancelable(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + } + + @Override + public void onDetach() { + super.onDetach(); + } + + /** + * 注释原因:wifi密码从设备添加页面携带过来,不再从密码框输入中获取 + * + * @param savedInstanceState + */ + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// mEditText = new EditText(getActivity()); + editText1 = new EditText(getActivity()); +// mEditText.setHint(getResources().getString(R.string.please_input_connect_wifi_password)); + editText1.setHint(getResources().getString(R.string.please_input_init_password)); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage("请输入密码"); + LinearLayout linearLayout = new LinearLayout(getActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); +// linearLayout.addView(mEditText); + linearLayout.addView(editText1); + builder.setView(linearLayout); + if (currentType == 1) { + editText1.setHint(getResources().getString(R.string.please_input_init_password)); + editText1.setVisibility(View.VISIBLE); + } else if (currentType == 2) { + editText1.setHint(getResources().getString(R.string.please_input_init_password_old)); + editText1.setVisibility(View.VISIBLE); + } else { + editText1.setVisibility(View.GONE); + } + + builder.setPositiveButton(getResources().getString(R.string.dialog_positive), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (null != mListener) { + if (currentType == 1 || currentType == 2) { +// mListener.onSaveSuccess(mEditText.getText().toString(),editText1.getText().toString()); + mListener.onSaveSuccess(editText1.getText().toString()); + } else { +// mListener.onWifiPassWord(mEditText.getText().toString(),editText1.getText().toString()); + mListener.onWifiPassWord(editText1.getText().toString()); + } + } + } + }); + builder.setNegativeButton(getResources().getString(R.string.dialog_negative), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dismiss(); + } + }); + builder.setCancelable(false); + AlertDialog alertDialog = builder.create(); + return alertDialog; + } + + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onStart() { + super.onStart(); + } + + @Override + public void onStop() { + super.onStop(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + } + + + public void setListener(PasswordSetListener listener) { + this.mListener = listener; + + } + + + public void setCurrentType(int currentType) { + this.currentType = currentType; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/handler/ActivityHandler.java b/app/src/main/java/com/lechange/demo/handler/ActivityHandler.java new file mode 100644 index 0000000..c14d377 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/handler/ActivityHandler.java @@ -0,0 +1,25 @@ +package com.lechange.demo.handler; + +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.FragmentActivity; + +import java.lang.ref.WeakReference; + +public abstract class ActivityHandler extends Handler { + private WeakReference mActivity; + public ActivityHandler(FragmentActivity activity){ + super(); + this.mActivity = new WeakReference(activity); + } + public abstract void handleMsg(Message msg); + @Override + public void handleMessage(Message msg) { + FragmentActivity activity = mActivity.get(); + if(activity == null){ + return; + } + handleMsg(msg); + super.handleMessage(msg); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/listener/PasswordSetListener.java b/app/src/main/java/com/lechange/demo/listener/PasswordSetListener.java new file mode 100644 index 0000000..aecc5af --- /dev/null +++ b/app/src/main/java/com/lechange/demo/listener/PasswordSetListener.java @@ -0,0 +1,6 @@ +package com.lechange.demo.listener; + +public interface PasswordSetListener { + void onSaveSuccess(String psw1); + void onWifiPassWord(String psw1); +} diff --git a/app/src/main/java/com/lechange/demo/listview/DevicelistActivity.java b/app/src/main/java/com/lechange/demo/listview/DevicelistActivity.java new file mode 100644 index 0000000..08d2280 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/listview/DevicelistActivity.java @@ -0,0 +1,498 @@ +package com.lechange.demo.listview; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.Toast; + +import com.lechange.common.log.Logger; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.RetObject; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.common.CommonTitle; +import com.lechange.demo.common.CommonTitle.OnTitleClickListener; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.manager.DeviceAddActivity; +import com.yonsz.z1.R; + +import java.util.ArrayList; +import java.util.List; + +public class DevicelistActivity extends Activity { + private final String tag = "MainActivity"; + private ListView mListview; + private CommonTitle mCommonTitle; + private ProgressDialog mProgressDialog; //请求加载使用 + private List mChannelInfoList; + private ChannelAdapter mChnlAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_device_list); + + //绘制标题 + mCommonTitle = (CommonTitle) findViewById(R.id.title); + mCommonTitle.initView(R.drawable.title_btn_back, R.drawable.title_btn_deviceadd, R.string.devices_name); + + mCommonTitle.setOnTitleClickListener(new OnTitleClickListener() { + @Override + public void onCommonTitleClick(int id) { + // TODO Auto-generated method stub + switch (id) { + case CommonTitle.ID_LEFT: + finish(); + break; + case CommonTitle.ID_RIGHT: + Intent intent = new Intent(DevicelistActivity.this, DeviceAddActivity.class); + Log.d(tag, "LcnDeviceAddActivity"); + startActivityForResult(intent, 0); + break; + default: + break; + } + } + }); + + //开启请求加载控件 + mProgressDialog = (ProgressDialog) this.findViewById(R.id.query_load); + mProgressDialog.setStart(getString(R.string.common_loading)); + + //绘制list + mListview = (ListView) this.findViewById(R.id.list_devices); + mChnlAdapter = new ChannelAdapter(this); + mListview.setAdapter(mChnlAdapter); + + // 初始化数据 + loadChannelList(); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (resultCode) { //resultCode为回传的标记 + case RESULT_OK: + loadChannelList(); + mChnlAdapter.notifyDataSetChanged(); + mProgressDialog.setStart(getString(R.string.common_loading)); + //Toast.makeText(DevicelistActivity.this, "刷新完成", Toast.LENGTH_SHORT).show(); + break; + default: + break; + } + } + + private void loadChannelList() { + + mChannelInfoList = new ArrayList(); + + + // 初始化数据 + Business.getInstance().getChannelList(new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + Business.RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0) { + mChannelInfoList.addAll((List) retObject.resp); + // mChannelInfoList = (List) retObject.resp; + if (mChannelInfoList != null && mChannelInfoList.size() > 0) { + mChnlAdapter.notifyDataSetChanged(); + // addDevices(); + } else { + Toast.makeText(DevicelistActivity.this, R.string.toast_device_no_devices, Toast.LENGTH_LONG).show(); + } + } else { + Toast.makeText(DevicelistActivity.this, retObject.mMsg, Toast.LENGTH_LONG).show(); + Logger.e(tag, retObject.mMsg); + } + } + }); + + //国内支持共享设备和授权设备 + if (!Business.getInstance().isOversea) { + Business.getInstance().getSharedDeviceList(new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + Business.RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0 && retObject.resp != null) { + mChannelInfoList.addAll((List) retObject.resp); + // mChannelInfoList = (List) retObject.resp; + if (mChannelInfoList != null && mChannelInfoList.size() > 0) { + mChnlAdapter.notifyDataSetChanged(); + } else { + Toast.makeText(DevicelistActivity.this, R.string.devices_no_shared_device, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(DevicelistActivity.this, retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + } + }); + System.out.println("devices"); + Business.getInstance().getBeAuthDeviceList(new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + Business.RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0 && retObject.resp != null) { + mChannelInfoList.addAll((List) retObject.resp); + // mChannelInfoList = (List) retObject.resp; + if (mChannelInfoList != null && mChannelInfoList.size() > 0) { + mChnlAdapter.notifyDataSetChanged(); + } else { + Toast.makeText(DevicelistActivity.this, R.string.devices_no_authorized_device, Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(DevicelistActivity.this, retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + } + }); + } + // try { + // Thread.sleep(50000); + // } catch (InterruptedException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + + // addDevices(); + } + + private void addDevices() { + for (int i = 0; i < mChannelInfoList.size(); i++) { + StringBuilder devicesJson = new StringBuilder(); + if (mChannelInfoList.size() > 0) { + ChannelInfo c = mChannelInfoList.get(i); + devicesJson.append("[{\"Sn\":\"" + c.getDeviceCode() + "\","); + devicesJson.append("\"Port\":554,"); + devicesJson.append("\"User\":\"\","); + devicesJson.append("\"Pwd\":\"\","); + devicesJson.append("\"Type\":1}]"); + + Business.getInstance().addDevices(devicesJson.toString(), new Handler() { + @Override + public void handleMessage(Message msg) { + Toast.makeText(DevicelistActivity.this, (String) msg.obj, Toast.LENGTH_LONG).show(); + } + }); + } + } + + } + + static class ViewHolder { + /*TextView mChannelName; + ImageView mDelete; + RelativeLayout mBgDevice; + ImageView mLiveVideo; + ImageView mLocalVideo; + ImageView mCloudVideo; + ImageView mMessage; + ImageView mSetting; + LinearLayout mListShade; + ChannelInfo mInfo;*/ + } + + private class ChannelAdapter extends BaseAdapter { + private LayoutInflater mInflater; + + public ChannelAdapter(Context context) { + mInflater = LayoutInflater.from(context); + } + + @Override + public int getCount() { + return mChannelInfoList != null ? mChannelInfoList.size() : 0; + } + + @Override + public ChannelInfo getItem(int position) { + return mChannelInfoList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + private void unBindDevice(final ChannelInfo info) { + Business.getInstance().unBindDevice(info.getDeviceCode(), new Handler() { + @Override + public void handleMessage(Message msg) { + RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0) { + Toast.makeText(getApplicationContext(), R.string.toast_device_delete_success, Toast.LENGTH_SHORT).show(); + mChannelInfoList.remove(info); + mChnlAdapter.notifyDataSetChanged(); + } else { + Toast.makeText(getApplicationContext(), retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + + } + }); + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + final ViewHolder holder; + + /*if (convertView == null) { + convertView = mInflater.inflate(R.layout.activity_device_list_item, null); + holder = new ViewHolder(); + holder.mChannelName = (TextView) convertView.findViewById(R.id.list_channel_name); + holder.mDelete = (ImageView) convertView.findViewById(R.id.list_device_delete); + holder.mBgDevice = (RelativeLayout) convertView.findViewById(R.id.list_bg_device); + holder.mLiveVideo = (ImageView) convertView.findViewById(R.id.list_device_livevideo); + holder.mLocalVideo = (ImageView) convertView.findViewById(R.id.list_device_localvideo); + holder.mCloudVideo = (ImageView) convertView.findViewById(R.id.list_device_cloudvideo); + holder.mMessage = (ImageView) convertView.findViewById(R.id.list_device_message); + holder.mSetting = (ImageView) convertView.findViewById(R.id.list_device_setting); + holder.mListShade = (LinearLayout) convertView.findViewById(R.id.list_shade); + + //设置监听 + holder.mDelete.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // TODO Auto-generated method stub + DialogInterface.OnClickListener dialogOnclicListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case Dialog.BUTTON_POSITIVE: + unBindDevice(holder.mInfo); + break; + case Dialog.BUTTON_NEGATIVE: + break; + case Dialog.BUTTON_NEUTRAL: + break; + } + } + }; + //dialog参数设置 + AlertDialog.Builder builder = new AlertDialog.Builder(DevicelistActivity.this); //先得到构造器 + builder.setTitle(R.string.devices_delete_dialog_title); //设置标题 + builder.setMessage(R.string.devices_delete_dialog_message); //设置内容 + builder.setPositiveButton(R.string.dialog_positive, dialogOnclicListener); + builder.setNegativeButton(R.string.dialog_negative, dialogOnclicListener); + builder.create().show(); + } + }); + + holder.mListShade.setVisibility(View.GONE); + + holder.mLiveVideo.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // 启动实时视频 + final EditText et = new EditText(DevicelistActivity.this); + if (holder.mInfo.getEncryptMode() == 1 && holder.mInfo.getEncryptKey() == null) { + new AlertDialog.Builder(DevicelistActivity.this).setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info).setView(et) + .setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + holder.mInfo.setEncryptKey(et.getText().toString()); + Intent intent = new Intent(DevicelistActivity.this, MediaPlayActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_ONLINE); + intent.putExtra("MEDIA_TITLE", R.string.live_play_name); + DevicelistActivity.this.startActivityForResult(intent, 0); + } + }) + .setNegativeButton(R.string.dialog_negative, null).show(); + } else { + Intent intent = new Intent(DevicelistActivity.this, MediaPlayActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_ONLINE); + intent.putExtra("MEDIA_TITLE", R.string.live_play_name); + DevicelistActivity.this.startActivityForResult(intent, 0); + } + } + }); + holder.mLocalVideo.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // 启动本地录像 + final EditText et = new EditText(DevicelistActivity.this); + if (holder.mInfo.getEncryptMode() == 1 && holder.mInfo.getEncryptKey() == null) { + new AlertDialog.Builder(DevicelistActivity.this).setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info).setView(et) + .setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + holder.mInfo.setEncryptKey(et.getText().toString()); + Intent intent = new Intent(DevicelistActivity.this, RecordListActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent.putExtra("MEDIA_TITLE", R.string.local_records_name); + DevicelistActivity.this.startActivity(intent); + } + }) + .setNegativeButton(R.string.dialog_negative, null).show(); + } else { + Intent intent = new Intent(DevicelistActivity.this, RecordListActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent.putExtra("MEDIA_TITLE", R.string.local_records_name); + DevicelistActivity.this.startActivity(intent); + } + } + }); + holder.mCloudVideo.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // 启动云录像 + final EditText et = new EditText(DevicelistActivity.this); + if (holder.mInfo.getEncryptMode() == 1 && holder.mInfo.getEncryptKey() == null) { + new AlertDialog.Builder(DevicelistActivity.this).setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info).setView(et) + .setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + holder.mInfo.setEncryptKey(et.getText().toString()); + Intent intent = new Intent(DevicelistActivity.this, RecordListActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("MEDIA_TITLE", R.string.cloud_records_name); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD); + DevicelistActivity.this.startActivity(intent); + } + }) + .setNegativeButton(R.string.dialog_negative, null).show(); + } else { + Intent intent = new Intent(DevicelistActivity.this, RecordListActivity.class); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("MEDIA_TITLE", R.string.cloud_records_name); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD); + DevicelistActivity.this.startActivity(intent); + } + } + }); + holder.mMessage.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // TODO Auto-generated method stub + // 启动报警图片 + final EditText et = new EditText(DevicelistActivity.this); + if (holder.mInfo.getEncryptMode() == 1 && holder.mInfo.getEncryptKey() == null) { + new AlertDialog.Builder(DevicelistActivity.this).setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info).setView(et) + .setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + holder.mInfo.setEncryptKey(et.getText().toString()); + Intent intent = new Intent(DevicelistActivity.this, AlarmMessageActivity.class); + intent.putExtra("sn", holder.mInfo.getDeviceCode()); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("index", holder.mInfo.getIndex()); + DevicelistActivity.this.startActivity(intent); + System.out.println("DeviceCode" + holder.mInfo.getDeviceCode()); + } + }) + .setNegativeButton(R.string.dialog_negative, null).show(); + } else { + Intent intent = new Intent(DevicelistActivity.this, AlarmMessageActivity.class); + intent.putExtra("sn", holder.mInfo.getDeviceCode()); + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("index", holder.mInfo.getIndex()); + DevicelistActivity.this.startActivity(intent); + System.out.println("DeviceCode" + holder.mInfo.getDeviceCode()); + } + } + }); + //设备操作 + holder.mSetting.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // 启动设备管理 + Intent intent = new Intent(DevicelistActivity.this, DeviceSetActivity.class); + + intent.putExtra("UUID", holder.mInfo.getUuid()); + intent.putExtra("alarmPlanStatus", holder.mInfo.getAlarmStatus()); + intent.putExtra("cloudMealStatus", holder.mInfo.getCloudMealStates()); + + + DevicelistActivity.this.startActivity(intent); + System.out.println("DeviceCode" + holder.mInfo.getDeviceCode()); + } + }); + //屏蔽监听 + holder.mListShade.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionevent) { + // TODO Auto-generated method stub + return true; + } + }); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + //修改数据信息(含加密标识符) + holder.mInfo = getItem(position); + //Log.d(tag, "index : " + position); + // holder.mChannelName.setText(holder.mInfo.getDeviceCode() + "-" + holder.mInfo.getIndex()); + if (holder.mInfo.getEncryptMode() == 1) { + holder.mChannelName.setText(holder.mInfo.getName() + " - Encrypt"); + } else { + holder.mChannelName.setText(holder.mInfo.getName()); + } + + //加载背景图片 + holder.mBgDevice.setBackgroundResource(R.drawable.list_bg_device); + if (holder.mInfo.getBackgroudImgURL() != null && holder.mInfo.getBackgroudImgURL().length() > 0) { + //下载 注:由于有些请求的图片是经过加密处理的,所以需要使用带有解密功能的接口,默认密码为设备序列号 + ImageHelper.loadCacheImage(holder.mInfo.getBackgroudImgURL(), holder.mInfo.getDeviceCode(), holder.mInfo.getDeviceCode(), new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + if (holder.mInfo.getBackgroudImgURL().hashCode() == msg.what && msg.obj != null) { + holder.mBgDevice.setBackgroundDrawable((Drawable) msg.obj); + } + } + }); + } + + //"在线" : "离线" + if (holder.mInfo.getState() == ChannelInfo.ChannelState.Online) { + holder.mListShade.setVisibility(View.GONE); + } else { + holder.mListShade.setVisibility(View.VISIBLE); + } + + //是否自定义加密,效率不高 + if (holder.mInfo.getEncryptMode() == 1 && holder.mInfo.getEncryptKey() == null) { + holder.mLiveVideo.setAlpha(128); + holder.mLocalVideo.setAlpha(128); + holder.mCloudVideo.setAlpha(128); + holder.mMessage.setAlpha(128); + } else { + holder.mLiveVideo.setAlpha(255); + holder.mLocalVideo.setAlpha(255); + holder.mCloudVideo.setAlpha(255); + holder.mMessage.setAlpha(255); + }*/ + + return convertView; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/BaseDecoration.java b/app/src/main/java/com/lechange/demo/localvideo/BaseDecoration.java new file mode 100644 index 0000000..8b048a2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/BaseDecoration.java @@ -0,0 +1,475 @@ +package com.lechange.demo.localvideo; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.ColorInt; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.util.SparseIntArray; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +import com.gavin.com.library.BuildConfig; +import com.gavin.com.library.ClickInfo; +import com.gavin.com.library.listener.OnGroupClickListener; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Administrator on 2019/3/15. + */ + +public abstract class BaseDecoration extends RecyclerView.ItemDecoration { + // TODO: 2018/4/13 加载更新后闪动 + + protected OnGroupClickListener mOnGroupClickListener; + /** + * 记录每个头部和悬浮头部的坐标信息【用于点击事件】 + * 位置由子类添加 + */ + protected HashMap stickyHeaderPosArray = new HashMap<>(); + /** + * group背景色,默认透明 + */ + @ColorInt + int mGroupBackground = Color.parseColor("#48BDFF"); + /** + * 悬浮栏高度 + */ + int mGroupHeight = 120; + /** + * 分割线颜色,默认灰色 + */ + @ColorInt + int mDivideColor = Color.parseColor("#CCCCCC"); + /** + * 分割线宽度 + */ + int mDivideHeight = 0; + /** + * RecyclerView头部数量 + * 最小为0 + */ + int mHeaderCount; + Paint mDividePaint; + /** + * 缓存分组第一个item的position + */ + private SparseIntArray firstInGroupCash = new SparseIntArray(100); + /** + * down事件在顶部悬浮栏中 + */ + private boolean mDownInHeader; + private GestureDetector gestureDetector; + private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() { + @Override + public boolean onDown(MotionEvent e) { + return false; + } + + @Override + public void onShowPress(MotionEvent e) { + } + + @Override + public boolean onSingleTapUp(MotionEvent e) { + return onTouchEvent(e); + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + return false; + } + + @Override + public void onLongPress(MotionEvent e) { + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return false; + } + }; + + public BaseDecoration() { + mDividePaint = new Paint(); + mDividePaint.setColor(mDivideColor); + } + + /** + * 设置点击事件 + * + * @param listener + */ + protected void setOnGroupClickListener(OnGroupClickListener listener) { + this.mOnGroupClickListener = listener; + } + + /** + * 获取分组名 + * + * @param position position + * @return group + */ + abstract String getGroupName(int position); + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + RecyclerView.LayoutManager manager = parent.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + //网格布局 + int spanCount = ((GridLayoutManager) manager).getSpanCount(); + if (!isHeader(position)) { + if (isFirstLineInGroup(position, spanCount)) { + //为悬浮view预留空间 + outRect.top = mGroupHeight; + } else { + //为分割线预留空间 + outRect.top = mDivideHeight; + } + } + } else { + //其他的默认为线性布局 + //只有是同一组的第一个才显示悬浮栏 + if (!isHeader(position)) { + if (isFirstInGroup(position)) { + //为悬浮view预留空间 + outRect.top = mGroupHeight; + } else { + //为分割线预留空间 + outRect.top = mDivideHeight; + } + } + } + } + + /** + * 判断是不是组中的第一个位置 + * 根据前一个组名,判断当前是否为新的组 + * 当前为groupId为null时,则与上一个为同一组 + */ + protected boolean isFirstInGroup(int position) { + int realPosition = position - mHeaderCount; + if (realPosition < 0) { + //小于header数量,不是第一个 + return false; + } else if (realPosition == 0) { + //等于header数量,为第一个 + return true; + } + String preGroupId; + if (realPosition <= 0) { + preGroupId = null; + } else { + preGroupId = getGroupName(realPosition - 1); + } + String curGroupId = getGroupName(realPosition); + if (curGroupId == null) { + return false; + } + return !TextUtils.equals(preGroupId, curGroupId); + } + + /** + * 是否在RecyclerView处于第一个(header部分不算) + * + * @param position 总的position + * @param index RecyclerView中的Index + * @return + */ + protected boolean isFirstInRecyclerView(int position, int index) { + return position >= mHeaderCount && index == 0; + } + + /** + * 是否为Header + * + * @param position + * @return + */ + protected boolean isHeader(int position) { + return position < mHeaderCount; + } + + /** + * 判断是不是新组的第一行(GridLayoutManager使用) + * 利用当前行的第一个对比前一个组名,判断当前是否为新组的第一样 + */ + protected boolean isFirstLineInGroup(int position, int spanCount) { + int realPosition = position - mHeaderCount; + if (realPosition < 0) { + //小于header数量,不是第一个 + return false; + } else if (realPosition == 0) { + return true; + } + if (position <= 0) { + return true; + } else { + int posFirstInGroup = getFirstInGroupWithCash(position); + if (position - posFirstInGroup < spanCount) { + return true; + } else { + return false; + } + } + } + + /** + * 网格布局需要调用 + * + * @param recyclerView recyclerView + * @param gridLayoutManager gridLayoutManager + */ + public void resetSpan(RecyclerView recyclerView, GridLayoutManager gridLayoutManager) { + if (recyclerView == null) { + throw new NullPointerException("recyclerView not allow null"); + } + if (gridLayoutManager == null) { + throw new NullPointerException("gridLayoutManager not allow null"); + } + final int spanCount = gridLayoutManager.getSpanCount(); + //相当于weight + GridLayoutManager.SpanSizeLookup lookup = new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + int span; + int realPosition = position - mHeaderCount; + if (realPosition < 0) { + //小于header数量 + span = spanCount; + } else { + String curGroupId = getGroupName(position); + String nextGroupId; + try { + //防止外面没判断,导致越界 + nextGroupId = getGroupName(position + 1); + } catch (Exception e) { + nextGroupId = curGroupId; + } + if (!TextUtils.equals(curGroupId, nextGroupId)) { + //为本行的最后一个 + int posFirstInGroup = getFirstInGroupWithCash(position); + span = spanCount - (position - posFirstInGroup) % spanCount; + } else { + span = 1; + } + } + return span; + } + }; + gridLayoutManager.setSpanSizeLookup(lookup); + } + + /** + * RecyclerView onInterceptEvent中down事件调用,用于处理点击穿透问题 + * + * @param event + */ + public void onEventDown(MotionEvent event) { + if (event == null) { + mDownInHeader = false; + return; + } + mDownInHeader = event.getY() > 0 && event.getY() < mGroupHeight; + } + + /** + * RecyclerView onInterceptEvent中up事件调用,用于处理点击穿透问题 + * + * @param event + * @return + */ + public boolean onEventUp(MotionEvent event) { + if (mDownInHeader) { + float y = event.getY(); + boolean isInHeader = y > 0 && y < mGroupHeight; + if (isInHeader) { + return onTouchEvent(event); + } + } + return false; + } + + /** + * 得到当前分组第一个item的position + * + * @param position position + */ + protected int getFirstInGroupWithCash(int position) { + if (firstInGroupCash.get(position) == 0) { + int firstPosition = getFirstInGroup(position); + firstPosition = firstPosition > 0 ? firstPosition - mHeaderCount : firstPosition; + firstInGroupCash.put(position, firstPosition); + return firstPosition; + } else { + return firstInGroupCash.get(position); + } + } + + /** + * 得到当前分组第一个item的position + * + * @param position position + */ + private int getFirstInGroup(int position) { + if (position <= 0) { + return 0; + } else { + if (isFirstInGroup(position)) { + return position; + } else { + return getFirstInGroup(position - 1); + } + } + } + + /** + * 判断自己是否为group的最后一行 + * + * @param recyclerView recyclerView + * @param position position + * @return + */ + protected boolean isLastLineInGroup(RecyclerView recyclerView, int position) { + int realPosition = position - mHeaderCount; + if (realPosition < 0) { + return true; + } else { + String curGroupName = getGroupName(realPosition); + String nextGroupName; + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + //默认往下查找的数量 + int findCount = 1; + if (manager instanceof GridLayoutManager) { + int spanCount = ((GridLayoutManager) manager).getSpanCount(); + int firstPositionInGroup = getFirstInGroupWithCash(realPosition); + findCount = spanCount - (realPosition - firstPositionInGroup) % spanCount; + } + try { + nextGroupName = getGroupName(realPosition + findCount); + } catch (Exception e) { + nextGroupName = curGroupName; + } + if (nextGroupName == null) { + return false; + } + return !TextUtils.equals(curGroupName, nextGroupName); + } + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDrawOver(c, parent, state); + //点击事件处理 + if (gestureDetector == null) { + gestureDetector = new GestureDetector(parent.getContext(), gestureListener); + parent.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return gestureDetector.onTouchEvent(event); + } + }); + } + stickyHeaderPosArray.clear(); + } + + /** + * 点击事件调用 + * + * @param position position + */ + private void onGroupClick(int position, int viewId) { + if (mOnGroupClickListener != null) { + mOnGroupClickListener.onClick(position, viewId); + } + } + + /** + * 对touch事件处理,找到点击事件 + * + * @param e + * @return + */ + private boolean onTouchEvent(MotionEvent e) { + for (Map.Entry entry : stickyHeaderPosArray.entrySet()) { + + ClickInfo value = stickyHeaderPosArray.get(entry.getKey()); + float y = e.getY(); + float x = e.getX(); + if (value.mBottom - mGroupHeight <= y && y <= value.mBottom) { + //如果点击到分组头 + if (value.mDetailInfoList == null || value.mDetailInfoList.size() == 0) { + //没有子View的点击事件 + onGroupClick(entry.getKey(), value.mGroupId); + } else { + List list = value.mDetailInfoList; + boolean isChildViewClicked = false; + for (ClickInfo.DetailInfo detailInfo : list) { + if (detailInfo.top <= y && y <= detailInfo.bottom + && detailInfo.left <= x && detailInfo.right >= x) { + //当前view被点击 + onGroupClick(entry.getKey(), detailInfo.id); + isChildViewClicked = true; + break; + } + } + if (!isChildViewClicked) { + //点击范围不在带有id的子view中,则表示整个groupView被点击 + onGroupClick(entry.getKey(), value.mGroupId); + } + + } + return true; + } + } + return false; + } + + /** + * 绘制分割线 + * + * @param c + * @param parent + * @param childView + * @param position + * @param left + * @param right + */ + protected void drawDivide(Canvas c, RecyclerView parent, View childView, int position, int left, int right) { + if (mDivideHeight != 0 && !isHeader(position)) { + RecyclerView.LayoutManager manager = parent.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + int spanCount = ((GridLayoutManager) manager).getSpanCount(); + if (!isFirstLineInGroup(position, spanCount)) { + float bottom = childView.getTop() + parent.getPaddingTop(); + //高度小于顶部悬浮栏时,跳过绘制 + if (bottom >= mGroupHeight) { + c.drawRect(left, bottom - mDivideHeight, right, bottom, mDividePaint); + } + } + } else { + float bottom = childView.getTop(); + //高度小于顶部悬浮栏时,跳过绘制 + if (bottom >= mGroupHeight) { + c.drawRect(left, bottom - mDivideHeight, right, bottom, mDividePaint); + } + } + } + } + + protected void log(String content) { + if (BuildConfig.DEBUG) { + Log.i("StickDecoration", content); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/City.java b/app/src/main/java/com/lechange/demo/localvideo/City.java new file mode 100644 index 0000000..2df5c23 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/City.java @@ -0,0 +1,71 @@ +package com.lechange.demo.localvideo; + +/** + * Created by gavin + * Created date 17/5/24 + * Created log 市 + */ + +public class City { + /** + * 城市名 + */ + private String name; + /** + * 所属省份 + */ + private String province; + /** + * 省份icon + */ + private int icon; + + private boolean expanded = true; + + public City(String name, String province, int icon) { + this.name = name; + this.province = province; + this.icon = icon; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public int getIcon() { + return icon; + } + + public void setIcon(int icon) { + this.icon = icon; + } + + public boolean isExpanded() { + return expanded; + } + + public void setExpanded(boolean expanded) { + this.expanded = expanded; + } + + @Override + public String toString() { + return "City{" + + "name='" + name + '\'' + + ", province='" + province + '\'' + + ", icon=" + icon + + '}'; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/localvideo/CityUtil.java b/app/src/main/java/com/lechange/demo/localvideo/CityUtil.java new file mode 100644 index 0000000..dfb0aa9 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/CityUtil.java @@ -0,0 +1,79 @@ +package com.lechange.demo.localvideo; + + +import com.yonsz.z1.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Created by gavin + * Created date 17/5/31 + * Created log + */ + +public class CityUtil { + + private static final String[] CITYS = {"福建省", "安徽省", "浙江省", "江苏省"}; + + /** + * 获取城市名 + * + * @return + */ + public static List getCityList() { + List dataList = new ArrayList<>(); + final String FU_JIAN = CITYS[0]; + final int FU_JIAN_ICON = R.mipmap.city1; + dataList.add(new City("福州", FU_JIAN, FU_JIAN_ICON)); + dataList.add(new City("厦门", FU_JIAN, FU_JIAN_ICON)); + dataList.add(new City("泉州", FU_JIAN, FU_JIAN_ICON)); + dataList.add(new City("宁德", FU_JIAN, FU_JIAN_ICON)); + dataList.add(new City("漳州", FU_JIAN, FU_JIAN_ICON)); + final String AN_HUI = CITYS[1]; + final int AN_HUI_ICON = R.mipmap.city2; + dataList.add(new City("合肥", AN_HUI, AN_HUI_ICON)); + dataList.add(new City("芜湖", AN_HUI, AN_HUI_ICON)); + dataList.add(new City("蚌埠", AN_HUI, AN_HUI_ICON)); + final String ZHE_JIANG = CITYS[2]; + final int ZHE_JIANG_ICON = R.mipmap.city3; + dataList.add(new City("杭州", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("宁波", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("温州", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("嘉兴", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("绍兴", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("金华", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("湖州", ZHE_JIANG, ZHE_JIANG_ICON)); + dataList.add(new City("舟山", ZHE_JIANG, ZHE_JIANG_ICON)); + final String JIANG_SU = CITYS[3]; + final int JIANG_SU_ICOM = R.mipmap.city4; + dataList.add(new City("南京", JIANG_SU, JIANG_SU_ICOM)); + return dataList; + } + + + /** + * 获取城市名 + * + * @return + */ + public static List getRandomCityList() { + List dataList = new ArrayList<>(); + Random random = new Random(); + int provinceSize = random.nextInt(5) + 3; + for (int i = 0; i < provinceSize; i++) { + String province = getRandomCityName(); + int citySize = random.nextInt(3) + 1; + for (int j = 0; j < citySize; j++) { + dataList.add(new City(province + " : city " + j, province, R.mipmap.city4)); + } + } + return dataList; + } + + private static String getRandomCityName() { + Random random = new Random(); + return CITYS[random.nextInt(4)]; + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/MyRecyclerView.java b/app/src/main/java/com/lechange/demo/localvideo/MyRecyclerView.java new file mode 100644 index 0000000..5f0b1c0 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/MyRecyclerView.java @@ -0,0 +1,57 @@ +package com.lechange.demo.localvideo; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.gavin.com.library.BaseDecoration; + +/** + * Created by gavin + * date 2018/8/26 + */ +public class MyRecyclerView extends RecyclerView { + + private BaseDecoration mDecoration; + + public MyRecyclerView(Context context) { + super(context); + } + + public MyRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void addItemDecoration(ItemDecoration decor) { + if (decor != null && decor instanceof BaseDecoration) { + mDecoration = (BaseDecoration) decor; + } + super.addItemDecoration(decor); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (mDecoration != null) { + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + mDecoration.onEventDown(e); + break; + case MotionEvent.ACTION_UP: + if (mDecoration.onEventUp(e)) { + return true; + } + break; + default: + } + } + return super.onInterceptTouchEvent(e); + } +} + diff --git a/app/src/main/java/com/lechange/demo/localvideo/PowerfulStickyDecoration.java b/app/src/main/java/com/lechange/demo/localvideo/PowerfulStickyDecoration.java new file mode 100644 index 0000000..f4c6628 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/PowerfulStickyDecoration.java @@ -0,0 +1,331 @@ +package com.lechange.demo.localvideo; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.support.annotation.ColorInt; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import com.gavin.com.library.ClickInfo; +import com.gavin.com.library.cache.CacheUtil; +import com.gavin.com.library.listener.OnGroupClickListener; +import com.gavin.com.library.listener.PowerGroupListener; +import com.gavin.com.library.util.ViewUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2019/3/15. + */ + +public class PowerfulStickyDecoration extends BaseDecoration { + + private Paint mGroutPaint; + + /** + * 缓存图片 + */ + private CacheUtil mBitmapCache = new CacheUtil<>(); + + /** + * 缓存View + */ + private CacheUtil mHeadViewCache = new CacheUtil<>(); + + private PowerGroupListener mGroupListener; + + private PowerfulStickyDecoration(PowerGroupListener groupListener) { + super(); + this.mGroupListener = groupListener; + //设置悬浮栏的画笔---mGroutPaint + mGroutPaint = new Paint(); + } + + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDrawOver(c, parent, state); + //绘制 + int itemCount = state.getItemCount(); + int childCount = parent.getChildCount(); + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + + for (int i = 0; i < childCount; i++) { + View childView = parent.getChildAt(i); + int position = parent.getChildAdapterPosition(childView); + if (isFirstInGroup(position) || isFirstInRecyclerView(position, i)) { + int viewBottom = childView.getBottom(); + //top 决定当前顶部第一个悬浮Group的位置 + int bottom = Math.max(mGroupHeight, childView.getTop() + parent.getPaddingTop()); + if (position + 1 < itemCount) { + //下一组的第一个View接近头部 + if (isLastLineInGroup(parent, position) && viewBottom < bottom) { + bottom = viewBottom; + } + } + drawDecoration(c, position, left, right, bottom); + } else { + //绘制分割线 + drawDivide(c, parent, childView, position, left, right); + } + } + } + + /** + * 绘制悬浮框 + * + * @param c Canvas + * @param position position + * @param left left + * @param right right + * @param bottom bottom + */ + private void drawDecoration(Canvas c, int position, int left, int right, int bottom) { + c.drawRect(left, bottom - mGroupHeight, right, bottom, mGroutPaint); + //根据position获取View + View groupView; + int firstPositionInGroup = getFirstInGroupWithCash(position); + if (mHeadViewCache.get(firstPositionInGroup) == null) { + groupView = getGroupView(firstPositionInGroup); + if (groupView == null) { + return; + } + measureAndLayoutView(groupView, left, right); + mHeadViewCache.put(firstPositionInGroup, groupView); + } else { + groupView = mHeadViewCache.get(firstPositionInGroup); + } + Bitmap bitmap; + if (mBitmapCache.get(firstPositionInGroup) != null) { + bitmap = mBitmapCache.get(firstPositionInGroup); + } else { + bitmap = Bitmap.createBitmap(groupView.getDrawingCache()); + mBitmapCache.put(firstPositionInGroup, bitmap); + } + c.drawBitmap(bitmap, left, bottom - mGroupHeight, null); + if (mOnGroupClickListener != null) { + setClickInfo(groupView, left, bottom, position); + } + } + + /** + * 对view进行测量和布局 + * + * @param groupView groupView + * @param left left + * @param right right + */ + private void measureAndLayoutView(View groupView, int left, int right) { + groupView.setDrawingCacheEnabled(true); + //手动对view进行测量,指定groupView的高度、宽度 + ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(right, mGroupHeight); + groupView.setLayoutParams(layoutParams); + groupView.measure( + View.MeasureSpec.makeMeasureSpec(right, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(mGroupHeight, View.MeasureSpec.EXACTLY)); + groupView.layout(left, 0 - mGroupHeight, right, 0); + } + + /** + * 点击的位置信息 + * + * @param groupView + * @param parentBottom + * @param position + */ + private void setClickInfo(View groupView, int parentLeft, int parentBottom, int position) { + int parentTop = parentBottom - mGroupHeight; + List list = new ArrayList<>(); + List viewList = ViewUtil.getChildViewWithId(groupView); + for (View view : viewList) { + int top = view.getTop() + parentTop; + int bottom = view.getBottom() + parentTop; + int left = view.getLeft() + parentLeft; + int right = view.getRight() + parentLeft; + list.add(new ClickInfo.DetailInfo(view.getId(), left, right, top, bottom)); + } + ClickInfo clickInfo = new ClickInfo(parentBottom, list); + clickInfo.mGroupId = groupView.getId(); + stickyHeaderPosArray.put(position, clickInfo); + } + + /** + * 获取组名 + * + * @param position position + * @return 组名 + */ + @Override + String getGroupName(int position) { + if (mGroupListener != null) { + return mGroupListener.getGroupName(position); + } else { + return null; + } + } + + /** + * 获取组View + * + * @param position position + * @return 组名 + */ + private View getGroupView(int position) { + if (mGroupListener != null) { + return mGroupListener.getGroupView(position); + } else { + return null; + } + } + + /** + * 是否使用缓存 + * + * @param b b + */ + public void setCacheEnable(boolean b) { + mHeadViewCache.isCacheable(b); + } + + /** + * 清空缓存 + */ + public void clearCache() { + mHeadViewCache.clean(); + mBitmapCache.clean(); + } + + /** + * 通知重新绘制 + * 使用场景:网络图片加载后调用 + * + * @param recyclerView recyclerView + * @param position position + */ + public void notifyRedraw(RecyclerView recyclerView, View viewGroup, int position) { + viewGroup.setDrawingCacheEnabled(false); + int firstPositionInGroup = getFirstInGroupWithCash(position); + mBitmapCache.remove(firstPositionInGroup); + mHeadViewCache.remove(firstPositionInGroup); + int left = recyclerView.getPaddingLeft(); + int right = recyclerView.getWidth() - recyclerView.getPaddingRight(); + measureAndLayoutView(viewGroup, left, right); + mHeadViewCache.put(firstPositionInGroup, viewGroup); + recyclerView.invalidate(); + } + + public static class Builder { + PowerfulStickyDecoration mDecoration; + + private Builder(PowerGroupListener listener) { + mDecoration = new PowerfulStickyDecoration(listener); + } + + public static PowerfulStickyDecoration.Builder init(PowerGroupListener listener) { + return new PowerfulStickyDecoration.Builder(listener); + } + + /** + * 设置Group高度 + * + * @param groutHeight 高度 + * @return this + */ + public PowerfulStickyDecoration.Builder setGroupHeight(int groutHeight) { + mDecoration.mGroupHeight = groutHeight; + return this; + } + + + /** + * 设置Group背景 + * + * @param background 背景色 + */ + public PowerfulStickyDecoration.Builder setGroupBackground(@ColorInt int background) { + mDecoration.mGroupBackground = background; + mDecoration.mGroutPaint.setColor(mDecoration.mGroupBackground); + return this; + } + + /** + * 设置分割线高度 + * + * @param height 高度 + * @return this + */ + public PowerfulStickyDecoration.Builder setDivideHeight(int height) { + mDecoration.mDivideHeight = height; + return this; + } + + /** + * 设置分割线颜色 + * + * @param color color + * @return this + */ + public PowerfulStickyDecoration.Builder setDivideColor(@ColorInt int color) { + mDecoration.mDivideColor = color; + return this; + } + + /** + * 设置点击事件 + * + * @param listener 点击事件 + * @return this + */ + public PowerfulStickyDecoration.Builder setOnClickListener(OnGroupClickListener listener) { + mDecoration.setOnGroupClickListener(listener); + return this; + } + + /** + * 重置span + * + * @param recyclerView recyclerView + * @param gridLayoutManager gridLayoutManager + * @return this + */ + public PowerfulStickyDecoration.Builder resetSpan(RecyclerView recyclerView, GridLayoutManager gridLayoutManager) { + mDecoration.resetSpan(recyclerView, gridLayoutManager); + return this; + } + + /** + * 是否使用缓存 + * + * @param b + * @return + */ + public PowerfulStickyDecoration.Builder setCacheEnable(boolean b) { + mDecoration.setCacheEnable(b); + return this; + } + + /** + * 设置头部数量 + * 用于顶部Header不需要设置悬浮的情况(仅LinearLayoutManager) + * + * @param headerCount + * @return + */ + public PowerfulStickyDecoration.Builder setHeaderCount(int headerCount) { + if (headerCount >= 0) { + mDecoration.mHeaderCount = headerCount; + } + return this; + } + + public PowerfulStickyDecoration build() { + return mDecoration; + } + } + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/RecordListActivity.java b/app/src/main/java/com/lechange/demo/localvideo/RecordListActivity.java new file mode 100644 index 0000000..3f669cb --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/RecordListActivity.java @@ -0,0 +1,883 @@ +package com.lechange.demo.localvideo; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.media.MediaScannerConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.gavin.com.library.listener.OnGroupClickListener; +import com.gavin.com.library.listener.PowerGroupListener; +import com.lechange.common.log.Logger; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.CloudStorageCode; +import com.lechange.demo.business.Business.LocalDownloadCode; +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.business.util.ImageHelper; +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.business.util.TaskPoolHelper; +import com.lechange.demo.business.util.TimeHelper; +import com.lechange.demo.common.DatePicker; +import com.lechange.demo.common.DatePicker.OnTimeClickListener; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.localvideo.calendar.CalendarPopipWindow; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.opensdk.listener.LCOpenSDK_DownloadListener; +import com.lechange.opensdk.media.LCOpenSDK_Download; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.utils.DateTimeUitl; +import com.yonsz.z1.utils.DensityUtil; +import com.yonsz.z1.view.TitleView; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +public class RecordListActivity extends BaseActivity { + private final String tag = "RecordList"; + private TitleView mTitleView; + private RecyclerView mRv; + private ImageView iv_back; + private RadioButton rb_model_set, rb_model_time; + private RelativeLayout mFuntion; + private ListView mListview = null; + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + //不显示进度 + int firstIndex = mListview.getFirstVisiblePosition(); + int lastIndex = mListview.getLastVisiblePosition(); + for (int i = firstIndex; i <= lastIndex; i++) { + ViewHolder holder = (ViewHolder) mListview.getChildAt(i - firstIndex).getTag(); + //渲染下载更新 + ViewGroup.LayoutParams params = holder.mDownload_bg.getLayoutParams(); + if (holder.mInfo.isDownload()) { + if (holder.mInfo.getDownLength() > 0) { + if (holder.mInfo.getFileLength() > 0) + params.width = (int) (holder.mDownload_icon.getWidth() / (holder.mInfo.getFileLength() / holder.mInfo.getDownLength())); + else + params.width = 0; + } + } else { + params.width = 0; + holder.mDownload_icon.setText(R.string.download); + } + holder.mDownload_bg.setLayoutParams(params); + } + sendEmptyMessageDelayed(0, 1000); + } + + ; + }; //定时器,每500ms刷新一次, + private DatePicker mDatePicker; + private LinearLayout mViewContainer; // 放置DatePicker的容器 + private ProgressDialog mProgressDialog; //请求加载使用 + private RecrodListAdapter mRecordListAdapt; + private List mRecordList; + private String mChannelUUID = null; + private int mType; + private int mIndex = -1; //当前正在下载的索引号,目前仅支持单个下载,日后会扩展多个下载 + private PowerfulStickyDecoration decoration; + private List dataList = new ArrayList<>(); + private com.lechange.demo.localvideo.SimpleAdapter mAdapter; + private TextView mCalendarTv, tv_before_day, tv_last_day; + private boolean isChangeDate = false; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_record_list); + Intent intent = getIntent(); + mChannelUUID = intent.getStringExtra("UUID"); + mType = intent.getIntExtra("TYPE", 0); + Log.d(tag, mType + "::mChannelUUID:" + mChannelUUID); + initView(); + } + + private void initView() { + mTitleView = (TitleView) findViewById(R.id.title_local_video_list); + mTitleView.setHead("本地录像"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + mRv = (RecyclerView) findViewById(R.id.rv); + //绘制标题 + iv_back = (ImageView) findViewById(R.id.iv_back); + rb_model_set = (RadioButton) findViewById(R.id.rb_model_set); + rb_model_time = (RadioButton) findViewById(R.id.rb_model_time); + mFuntion = (RelativeLayout) findViewById(R.id.iv_funtion); + iv_back.setOnClickListener(this); + rb_model_set.setOnClickListener(this); + rb_model_time.setOnClickListener(this); + mFuntion.setOnClickListener(this); + + //日期控件 + mViewContainer = (LinearLayout) findViewById(R.id.timerContainer); + //开启请求加载控件 + mProgressDialog = (ProgressDialog) this.findViewById(R.id.query_load); + mProgressDialog.setStart(getString(R.string.common_loading)); + + //绘制list + mListview = (ListView) this.findViewById(R.id.list_records); + mRecordListAdapt = new RecrodListAdapter(this); + mListview.setAdapter(mRecordListAdapt); + + tv_before_day = (TextView) findViewById(R.id.tv_before_day); + tv_last_day = (TextView) findViewById(R.id.tv_last_day); + tv_before_day.setOnClickListener(this); + tv_last_day.setOnClickListener(this); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + mCalendarTv = (TextView) findViewById(R.id.tv_calendar); + mCalendarTv.setText(df.format(new Date())); + String startTime = df.format(new Date()) + " 00:00:00"; + String endTime = df.format(new Date()) + " 23:59:59"; + //初始化数据 + if (null != getIntent().getExtras().get("dateString")) { + String date = (String) getIntent().getExtras().get("dateString"); + if (mCalendarTv.getText().toString().compareTo(date) > 0) { + tv_last_day.setVisibility(View.VISIBLE); + } + mCalendarTv.setText(date); + startTime = date + " 00:00:00"; + endTime = date + " 23:59:59"; + } + loadRecrodList(startTime, endTime); + + //设置监听 + setItemClick(); + + //设置云录像下载监听 + if (mType == MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD) { + LCOpenSDK_Download.setListener(new CloudDownloadListener()); + } else { + LCOpenSDK_Download.setListener(new LocalDownloadListener()); + } + //开启定时刷新 + mHandler.obtainMessage().sendToTarget(); + + // setRecycleView(); + + mCalendarTv.setOnClickListener(this); + mCalendarTv.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + String s1 = s.toString(); + if (s1.equals(df.format(new Date())) || s1.compareTo(df.format(new Date())) > 0) { + tv_last_day.setVisibility(View.GONE); + } else { + tv_last_day.setVisibility(View.VISIBLE); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + private void setRecycleView() { + //模拟数据 + // dataList.addAll(CityUtil.getCityList()); + GridLayoutManager manager = new GridLayoutManager(this, 4); + // LinearLayoutManager manager = new LinearLayoutManager(this); + mRv.setLayoutManager(manager); + if (null != decoration) { + mRv.removeItemDecoration(decoration); + } + decoration = PowerfulStickyDecoration.Builder + .init(new PowerGroupListener() { + @Override + public String getGroupName(int position) { + //获取组名,用于判断是否是同一组 + if (dataList.size() > position) { + Log.i("TAG", "RecordListActivity getGroupName()" + String.valueOf(dataList.get(position).getStartTime())); + SimpleDateFormat sdf2 = new SimpleDateFormat("HH"); + Log.i("TAG", "RecordListActivity getGroupName()" + sdf2.format(dataList.get(position).getStartTime())); + return String.valueOf(sdf2.format(dataList.get(position).getStartTime()) + ":00"); + } + return null; + } + + @Override + public View getGroupView(int position) { + //获取自定定义的组View + if (dataList.size() > position) { + SimpleDateFormat sdf2 = new SimpleDateFormat("HH"); + final View view = getLayoutInflater().inflate(R.layout.city_group, null, true); + ((TextView) view.findViewById(R.id.tv)).setText(sdf2.format(dataList.get(position).getStartTime()) + ":00"); + ImageView imageView = (ImageView) view.findViewById(R.id.iv); + imageView.setImageResource(R.drawable.icon_style); + return view; + } else { + return null; + } + } + }) + .setCacheEnable(true) + .resetSpan(mRv, manager) + .setGroupHeight(DensityUtil.dip2px(RecordListActivity.this, 40)) + .setDivideHeight(0) + .setOnClickListener(new OnGroupClickListener() { + @Override + public void onClick(int position, int id) { + if (dataList.size() > position) { + /*//修改数据 + changeExpandedState(position); + City city = dataList.get(position); + //修改悬浮窗 + final View view = getLayoutInflater().inflate(R.layout.city_group, null, false); + ((TextView) view.findViewById(R.id.tv)).setText(dataList.get(position).getProvince()); + ImageView imageView = (ImageView) view.findViewById(R.id.iv); + imageView.setImageResource(dataList.get(position).getIcon()); + ImageView ivExpanded = (ImageView) view.findViewById(R.id.iv_expanded); + int rotation = city.isExpanded() ? 0 : 180; + ivExpanded.setRotation(rotation); + //修改数据后,刷新指定的悬浮窗 + decoration.notifyRedraw(mRv, view, position); + mAdapter.notifyDataSetChanged();*/ + } + } + }) + .build(); + //---------------- ------------- + mRv.addItemDecoration(decoration); + mRv.setVisibility(View.VISIBLE); + //------------- PowerfulStickyDecoration 使用部分 ---------------- + //下面是平时的RecyclerView操作 + mAdapter = new com.lechange.demo.localvideo.SimpleAdapter(this, dataList); + mRv.setAdapter(mAdapter); + } + + /** + * 修改数据 + * + * @param position + */ + private void changeExpandedState(int position) { + if (dataList.size() > position) { + RecordInfo city = dataList.get(position); + /*city.setExpanded(!city.isExpanded()); + position++; + if (dataList.size() > position) { + //下个是当前分组 + City city2 = dataList.get(position); + if (TextUtils.equals(city.getProvince(), city2.getProvince())) { + changeExpandedState(position); + } + }*/ + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + case R.id.rb_model_set: + + break; + case R.id.rb_model_time: + + break; + case R.id.iv_funtion: + //添加时间选择控件 + Log.d("Business", "Business" + mViewContainer.getChildCount()); + if (mViewContainer.getChildCount() > 0) { + return; + } + + // undo 添加datepicker + if (mDatePicker == null) { + mDatePicker = new DatePicker(getApplicationContext()); + initDatePicker(); + } + + LayoutParams lp = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); + mViewContainer.addView(mDatePicker, lp); + break; + case R.id.tv_calendar: + showCalendarBottom(mCalendarTv.getText().toString()); + break; + case R.id.tv_before_day: + String beforeFromTarget = DateTimeUitl.getBeforeFromTarget(mCalendarTv.getText().toString()); + mCalendarTv.setText(beforeFromTarget); + showChooseDateVideo(beforeFromTarget); + break; + case R.id.tv_last_day: + String futureFromTarget = DateTimeUitl.getFutureFromTarget(mCalendarTv.getText().toString()); + mCalendarTv.setText(futureFromTarget); + showChooseDateVideo(futureFromTarget); + break; + } + } + + private void showCalendarBottom(String date) { + View rootview = LayoutInflater.from(this).inflate(R.layout.fragment_media_record, null); + CalendarPopipWindow popupWindow = new CalendarPopipWindow(this, date.substring(0, 4) + "年" + date.substring(5, 7) + "月", new CalendarPopipWindow.OnCompleteListener() { + @Override + public void onComplete(String dayStr) { + showChooseDateVideo(dayStr); + mCalendarTv.setText(dayStr); + } + }); + popupWindow.showAtLocation(rootview, Gravity.BOTTOM, 0, 0); + } + + public void initDatePicker() { + if (mDatePicker == null) { + return; + } + + mDatePicker.setOnTimeClickListener(new OnTimeClickListener() { + @Override + public void onCommonTimeClick(int id) { + if (id == DatePicker.ID_LEFT) { // 点击左边 + mViewContainer.removeView(mDatePicker); + } else { // 点击右边 + // showChooseDateVideo(); + } + + } + }); + } + + private void showChooseDateVideo(String date) { + if (mIndex != -1) { + LCOpenSDK_Download.stopDownload(mIndex); //重新加载前停止下载 + MediaPlayHelper.deleteDownloadVideo(mRecordList.get(mIndex).getRecordID(), mRecordList.get(mIndex).getStartTime()); + //屏蔽操作 + mIndex = -1; + } + /*Date time = mDatePicker.getSelectedDate(); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + String date = df.format(date1);*/ + /*int year = Integer.parseInt(date1.substring(0, 4)); + int month = Integer.parseInt(date1.substring(5, 7)); + int day = Integer.parseInt(date1.substring(date1.indexOf("月") + 1, date1.indexOf("日"))); + String date = DateTimeUitl.formatDateFromInt(year, month, day);*/ + + String startTime = date + " 00:00:00"; + String endTime = date + " 23:59:59"; + + mViewContainer.removeView(mDatePicker); + isChangeDate = true; + loadRecrodList(startTime, endTime); + //清空屏幕 + if (mRecordList != null) + mRecordList.clear(); //清数据 临时使用 + mRecordListAdapt.notifyDataSetChanged(); + + RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.GONE); + RecordListActivity.this.findViewById(R.id.tv_records_novideo).setVisibility(View.GONE); + mProgressDialog.setStart(getString(R.string.common_loading)); + } + + public void setItemClick() { + //单个录像监听 + mListview.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterview, View view, int position, + long id) { + // TODO Auto-generated method stub + if (mIndex != -1) { + Toast.makeText(RecordListActivity.this, R.string.toast_recordlist_onlyone, Toast.LENGTH_SHORT).show(); + return; + } + Log.d(tag, "click:" + position + "-" + id + "ID:" + view.getId()); + Intent intent = new Intent(RecordListActivity.this, MediaPlayActivity.class); + switch (mType) { + case MediaPlayActivity.IS_VIDEO_REMOTE_RECORD: + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + break; + case MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD: + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD); + break; + default: + break; + } + intent.putExtra("ID", mRecordList.get(position).getId()); + intent.putExtra("MEDIA_TITLE", R.string.record_play_name); + RecordListActivity.this.startActivity(intent); + } + }); + } + + + public void loadRecrodList(final String startTime, final String endTime) { + switch (mType) { + case MediaPlayActivity.IS_VIDEO_REMOTE_RECORD: + //查询1天之内的后10条录像 + dataList.clear(); + Business.getInstance().queryRecordNum(mChannelUUID, startTime, + endTime, new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + mProgressDialog.setStop(); //关闭加载窗口 + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_query_failed) + msg.what, Toast.LENGTH_SHORT).show(); + } else if (msg.what == 0) { + if (msg.arg1 > 0) { + Business.getInstance().queryRecordList(mChannelUUID, startTime, + endTime, msg.arg2, msg.arg1, new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + if (msg.what != 0) { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_query_failed) + msg.obj, Toast.LENGTH_SHORT).show(); + } else { + // mRecordList = (List) msg.obj; + dataList.addAll((List) msg.obj); + if (dataList != null && dataList.size() > 0) { + Log.d(tag, "loadRecrodList mRecordList.size:" + dataList.size()); + Collections.reverse(dataList); + // mRecordListAdapt.notifyDataSetChanged(); + setRecycleView(); + } else { + mRv.setVisibility(View.GONE); + RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + RecordListActivity.this.findViewById(R.id.tv_records_novideo).setVisibility(View.VISIBLE); + //Toast.makeText(RecordListActivity.this, "没有录像", Toast.LENGTH_SHORT).show(); + } + } + } + }); + } else { + mRv.setVisibility(View.GONE); + mProgressDialog.setStop(); //关闭加载窗口 + RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + RecordListActivity.this.findViewById(R.id.tv_records_novideo).setVisibility(View.VISIBLE); + } + } + } + }); + break; + case MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD: + //查询1天之内的前10条录像 + Business.getInstance().queryCloudRecordNum(mChannelUUID, startTime, + endTime, new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + mProgressDialog.setStop(); //关闭加载窗口 + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_query_failed) + msg.what, Toast.LENGTH_SHORT).show(); + } else if (msg.what == 0) { + if (msg.arg1 > 0) { + Business.getInstance().queryCloudRecordList(mChannelUUID, startTime, + endTime, msg.arg2, msg.arg1, new Handler() { + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + if (msg.what != 0) { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_query_failed) + msg.arg1, Toast.LENGTH_SHORT).show(); + } else { + mRecordList = (List) msg.obj; + if (mRecordList != null && mRecordList.size() > 0) { + Log.d(tag, "loadRecrodList mRecordList.size:" + mRecordList.size() + mRecordList.toString()); + mRecordListAdapt.notifyDataSetChanged(); + } else { + RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + RecordListActivity.this.findViewById(R.id.tv_records_novideo).setVisibility(View.VISIBLE); + //Toast.makeText(RecordListActivity.this, "没有录像", Toast.LENGTH_SHORT).show(); + } + } + } + }); + } else { + mProgressDialog.setStop(); //关闭加载窗口 + RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + RecordListActivity.this.findViewById(R.id.tv_records_novideo).setVisibility(View.VISIBLE); + } + } + } + }); + break; + default: + break; + } + } + + @Override + public void onPause() { + // TODO Auto-generated method stub + super.onPause(); + if (mIndex != -1) { + LCOpenSDK_Download.stopDownload(mIndex); + MediaPlayHelper.deleteDownloadVideo(mRecordList.get(mIndex).getRecordID(), mRecordList.get(mIndex).getStartTime()); + mRecordList.get(mIndex).setDownLength(-1); + //屏蔽操作 + mIndex = -1; + } + } + + @Override + protected void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + TaskPoolHelper.clearTask(); + } + + @Override + public void callBackUiThread(Message msg) { + + } + + static class ViewHolder { + int mPosition; + RelativeLayout mBgVideo; + TextView mRecordTime; + RecordInfo mInfo; + FrameLayout mDownload; + View mDownload_bg; + TextView mDownload_icon; + } + + private class RecrodListAdapter extends BaseAdapter { + private LayoutInflater mInflater; + + public RecrodListAdapter(Context context) { + mInflater = LayoutInflater.from(context); + } + + @Override + public int getCount() { + return mRecordList != null ? mRecordList.size() : 0; + } + + @Override + public RecordInfo getItem(int position) { + return mRecordList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final ViewHolder holder; + + if (convertView == null) { + convertView = mInflater.inflate(R.layout.activity_record_list_item, null); + holder = new ViewHolder(); + holder.mBgVideo = (RelativeLayout) convertView.findViewById(R.id.list_bg_video); + holder.mRecordTime = (TextView) convertView.findViewById(R.id.list_record_time); + //云录像加载下载按钮 + // if (mType == MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD) { + holder.mDownload = (FrameLayout) convertView.findViewById(R.id.list_record_download); + holder.mDownload_bg = convertView.findViewById(R.id.record_download_bg); + holder.mDownload_icon = (TextView) convertView.findViewById(R.id.record_download_icon); + holder.mDownload.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + // TODO Auto-generated method stub + if (mIndex == -1 || mIndex == holder.mPosition) + if (holder.mDownload_icon.getText().toString().equals(getString(R.string.download))) { + //置为可以取消状态 + holder.mDownload_icon.setText(R.string.cancel); + holder.mInfo.setDownLength(0); + + String decryptKey = holder.mInfo.getDeviceKey() != null ? holder.mInfo.getDeviceKey() : holder.mInfo.getDeviceId(); + Logger.e("====decryptKey====", decryptKey); + if (mType == MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD) { + LCOpenSDK_Download.startDownload(holder.mPosition, + MediaPlayHelper.getDownloadVideoPath(0, String.valueOf(holder.mPosition), holder.mInfo.getStartTime()), + Business.getInstance().getToken(), + holder.mInfo.getRecordRegionId(), + holder.mInfo.getDeviceId(), + String.valueOf(0), + decryptKey, + 1000, + 5000); + } else { + LCOpenSDK_Download.startDownload(holder.mPosition, Business.getInstance().getToken(), + holder.mInfo.getDeviceId(), + MediaPlayHelper.getDownloadVideoPath(1, String.valueOf(holder.mPosition), holder.mInfo.getStartTime()), + holder.mInfo.getRecordID(), + decryptKey, + 0, //默认偏移为0 + 0, //mp4格式 + 16.0f); + } + //屏蔽操作 + mIndex = holder.mPosition; + } else { + //置为可以下载状态 + ViewGroup.LayoutParams params = holder.mDownload_bg.getLayoutParams(); + params.width = 0; + holder.mDownload_bg.setLayoutParams(params); + holder.mDownload_icon.setText(R.string.download); + holder.mInfo.setDownLength(-1); + LCOpenSDK_Download.stopDownload(holder.mPosition); + + //删除文件 + MediaPlayHelper.deleteDownloadVideo(String.valueOf(holder.mPosition), holder.mInfo.getStartTime()); + //屏蔽操作 + mIndex = -1; + } + else + Toast.makeText(RecordListActivity.this, R.string.toast_recordlist_onlyone, Toast.LENGTH_SHORT).show(); + } + }); + // } + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + //修改数据信息 + holder.mPosition = position; + holder.mInfo = getItem(position); + //Log.d(tag, "index : " + position); + + ViewGroup.LayoutParams params = holder.mDownload_bg.getLayoutParams(); + switch (mType) { + case MediaPlayActivity.IS_VIDEO_REMOTE_RECORD: + // 屏蔽平台返回的录像大小=0情况(easy4ip设备返回录像大小为0) + if (holder.mInfo.getFileLength() > 0) { + holder.mDownload.setVisibility(View.VISIBLE); + } else { + holder.mDownload.setVisibility(View.INVISIBLE); + } + + //渲染下载更新 + if (holder.mInfo.isDownload()) { + holder.mDownload_icon.setText(R.string.cancel); + if (holder.mInfo.getDownLength() > 0) { + params.width = (int) (holder.mDownload_icon.getWidth() / (holder.mInfo.getFileLength() / holder.mInfo.getDownLength())); + } else { + params.width = 0; + } + } else { + holder.mDownload_icon.setText(R.string.download); + params.width = 0; + } + holder.mDownload_bg.setLayoutParams(params); + + //加载背景图片,设备录像,不用解密 + holder.mBgVideo.setBackgroundResource(R.drawable.list_bg_video); + if (holder.mInfo.getBackgroudImgUrl() != null && holder.mInfo.getBackgroudImgUrl().length() > 0) { + //下载 + ImageHelper.loadCacheImage(holder.mInfo.getBackgroudImgUrl(), new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + if (holder.mInfo.getBackgroudImgUrl().hashCode() == msg.what && msg.obj != null) { + holder.mBgVideo.setBackgroundDrawable((Drawable) msg.obj); + } + } + }); + } + break; + case MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD: + // 屏蔽平台返回的录像大小=0情况(easy4ip设备返回录像大小为0) + if (holder.mInfo.getFileLength() > 0) { + holder.mDownload.setVisibility(View.VISIBLE); + } else { + holder.mDownload.setVisibility(View.INVISIBLE); + } + + //渲染下载更新 + if (holder.mInfo.isDownload()) { + holder.mDownload_icon.setText(R.string.cancel); + if (holder.mInfo.getDownLength() > 0) { + params.width = (int) (holder.mDownload_icon.getWidth() / (holder.mInfo.getFileLength() / holder.mInfo.getDownLength())); + } else { + params.width = 0; + } + } else { + holder.mDownload_icon.setText(R.string.download); + params.width = 0; + } + holder.mDownload_bg.setLayoutParams(params); + //加载背景图片,云录像,要解密 + holder.mBgVideo.setBackgroundResource(R.drawable.list_bg_device); + if (holder.mInfo.getBackgroudImgUrl() != null && holder.mInfo.getBackgroudImgUrl().length() > 0) { + //下载 + ImageHelper.loadCacheImage(holder.mInfo.getBackgroudImgUrl(), holder.mInfo.getDeviceId(), holder.mInfo.getDeviceKey() != null ? holder.mInfo.getDeviceKey() : holder.mInfo.getDeviceId(), new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + if (holder.mInfo.getBackgroudImgUrl().hashCode() == msg.what && msg.obj != null) { + holder.mBgVideo.setBackgroundDrawable((Drawable) msg.obj); + } + } + }); + } + break; + default: + break; + } + + //时间 + holder.mRecordTime.setText(TimeHelper.getDateHMS(holder.mInfo.getStartTime()) + "--" + TimeHelper.getDateHMS(holder.mInfo.getEndTime())); + + return convertView; + } + } + + private class CloudDownloadListener extends LCOpenSDK_DownloadListener { + @Override + public void onDownloadReceiveData(int index, int dataLen) { + // TODO Auto-generated method stub + if (mRecordList.size() != 0) { + RecordInfo info = mRecordList.get((int) index); + info.setDownLength(info.getDownLength() + dataLen); + Logger.d(tag, "downLen:" + info.getDownLength()); + } + } + + @Override + public void onDownloadState(final int index, String code, int Type) { + // TODO Auto-generated method stub + if (Type == Business.RESULT_SOURCE_OPENAPI + || code.equals(CloudStorageCode.HLS_DOWNLOAD_FAILD) + || code.equals(CloudStorageCode.HLS_SEEK_FAILD) + || code.equals(CloudStorageCode.HLS_KEY_ERROR)) { + //重置为可以下载状态 + mRecordList.get((int) index).setDownLength(-1); + if (mHandler != null) { + mHandler.post(new Runnable() { + public void run() { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_failed) + ",index : " + index, Toast.LENGTH_SHORT).show(); + } + }); + } + //删除下载到一半的文件 + MediaPlayHelper.deleteDownloadVideo(String.valueOf(index), mRecordList.get(index).getStartTime()); + //屏蔽操作 + mIndex = -1; + + } + if (code.equals(CloudStorageCode.HLS_DOWNLOAD_END)) { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_end) + ",index : " + index, Toast.LENGTH_SHORT).show(); + //重置为可以下载状态 + mRecordList.get((int) index).setDownLength(-1); + if (mHandler != null) { + mHandler.post(new Runnable() { + public void run() { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_end) + ",index : " + index, Toast.LENGTH_SHORT).show(); + } + }); + } + //通知图库刷新 + MediaScannerConnection.scanFile(RecordListActivity.this, + new String[]{MediaPlayHelper.getDownloadVideoPath(0, String.valueOf(index), mRecordList.get(index).getStartTime())}, null, null); + //屏蔽操作 + mIndex = -1; + } + } + } + + private class LocalDownloadListener extends LCOpenSDK_DownloadListener { + @Override + public void onDownloadReceiveData(int index, int dataLen) { + // TODO Auto-generated method stub + if (mRecordList.size() != 0) { + RecordInfo info = mRecordList.get((int) index); + info.setDownLength(info.getDownLength() + dataLen); + + Logger.d(tag, "downLen:" + info.getDownLength()); + } + } + + @Override + public void onDownloadState(final int index, String code, int Type) { + // TODO Auto-generated method stub + if (Type == Business.RESULT_SOURCE_OPENAPI + || code.equals(LocalDownloadCode.RTSP_DOWNLOAD_FRAME_ERROR) + || code.equals(LocalDownloadCode.RTSP_DOWNLOAD_TEARDOWN) + || code.equals(LocalDownloadCode.RTSP_DOWNLOAD_AUTHORIZATION_FAIL) + || code.equals(LocalDownloadCode.RTSP_DOWNLOAD_KEY_MISMATH)) { + //重置为可以下载状态 + mRecordList.get((int) index).setDownLength(-1); + if (mHandler != null) { + mHandler.post(new Runnable() { + public void run() { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_failed) + ",index : " + index, Toast.LENGTH_SHORT).show(); + } + }); + } + //删除下载到一半的文件 + MediaPlayHelper.deleteDownloadVideo(String.valueOf(index), mRecordList.get(index).getStartTime()); + //屏蔽操作 + mIndex = -1; + + } + if (code.equals(LocalDownloadCode.RTSP_DOWNLOAD_OVER)) { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_end) + ",index : " + index, Toast.LENGTH_SHORT).show(); + //重置为可以下载状态 + mRecordList.get((int) index).setDownLength(-1); + LCOpenSDK_Download.stopDownload(index); + if (mHandler != null) { + mHandler.post(new Runnable() { + public void run() { + Toast.makeText(RecordListActivity.this, getString(R.string.toast_recordlist_download_end) + ",index : " + index, Toast.LENGTH_SHORT).show(); + } + }); + } + //通知图库刷新 + MediaScannerConnection.scanFile(RecordListActivity.this, + new String[]{MediaPlayHelper.getDownloadVideoPath(1, String.valueOf(index), mRecordList.get(index).getStartTime())}, null, null); + //屏蔽操作 + mIndex = -1; + } + } + } + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/SimpleAdapter.java b/app/src/main/java/com/lechange/demo/localvideo/SimpleAdapter.java new file mode 100644 index 0000000..b877c28 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/SimpleAdapter.java @@ -0,0 +1,120 @@ +package com.lechange.demo.localvideo; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.demo.mediaplay.MediaPlayBackActivity; +import com.yonsz.z1.R; + +import java.text.SimpleDateFormat; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by gavin + * Created date 17/6/5 + * Created log + */ + +public class SimpleAdapter extends RecyclerView.Adapter { + private List mCities; + private Context mContext; + + public SimpleAdapter(Context context, List cities) { + mCities = cities; + mContext = context; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_city, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) { + ViewHolder holder = (ViewHolder) viewHolder; + if (mCities.size() > position) { + RecordInfo city = mCities.get(position); + holder.mIvCity.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(mContext, MediaPlayBackActivity.class); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent.putExtra("ID", mCities.get(position).getId()); + intent.putExtra("dateString", mCities.get(position).getStartTime()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.getApplicationContext().startActivity(intent); + } + }); + long startTime = city.getStartTime(); + long endTime = city.getEndTime(); + long l = endTime - startTime; + SimpleDateFormat sdf1 = new SimpleDateFormat("mm:ss"); + holder.mTvCity.setText(String.valueOf(sdf1.format(l))); + SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); + holder.mTvBrief.setText(String.valueOf(sdf2.format(startTime))); + /*if (city.isExpanded()) { + ViewGroup.LayoutParams layoutParams = holder.mLlBg.getLayoutParams(); + layoutParams.height = DensityUtil.dip2px(mContext, 100); + holder.mLlBg.setLayoutParams(layoutParams); + //holder.itemView.setVisibility(View.VISIBLE); + int i = position % 5 + 1; + if (i == 1) { + holder.mIvCity.setImageResource(R.mipmap.subject1); + holder.mLlBg.setBackgroundColor(mContext.getResources().getColor(R.color.bg1)); + } else if (i == 2) { + holder.mIvCity.setImageResource(R.mipmap.subject2); + holder.mLlBg.setBackgroundColor(mContext.getResources().getColor(R.color.bg2)); + } else if (i == 3) { + holder.mIvCity.setImageResource(R.mipmap.subject3); + holder.mLlBg.setBackgroundColor(mContext.getResources().getColor(R.color.bg3)); + } else if (i == 4) { + holder.mIvCity.setImageResource(R.mipmap.subject4); + holder.mLlBg.setBackgroundColor(mContext.getResources().getColor(R.color.bg4)); + } else { + holder.mIvCity.setImageResource(R.mipmap.subject5); + holder.mLlBg.setBackgroundColor(mContext.getResources().getColor(R.color.bg5)); + } + holder.mTvCity.setText(city.getName()); + } else { + ViewGroup.LayoutParams layoutParams = holder.mLlBg.getLayoutParams(); + layoutParams.height = DensityUtil.dip2px(mContext, 0); + holder.mLlBg.setLayoutParams(layoutParams); + //holder.itemView.setVisibility(View.GONE); + }*/ + } + } + + @Override + public int getItemCount() { + return mCities.size(); + } + + + static class ViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.iv_city) + ImageView mIvCity; + @BindView(R.id.tv_city) + TextView mTvCity; + @BindView(R.id.tv_brief) + TextView mTvBrief; + /*@BindView(R.id.ll_bg) + LinearLayout mLlBg;*/ + + ViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/TodayLocalAdapter.java b/app/src/main/java/com/lechange/demo/localvideo/TodayLocalAdapter.java new file mode 100644 index 0000000..1ea214d --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/TodayLocalAdapter.java @@ -0,0 +1,140 @@ +package com.lechange.demo.localvideo; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.mediaplay.MediaPlayBackActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.listener.OnRecyclerClickListener; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2019/2/27. + */ + +public class TodayLocalAdapter extends RecyclerView.Adapter { + + private List mOnLineRecordList = new ArrayList<>(); + private Context mContext; + private String uuid; + private OnRecyclerClickListener mOnItemClickListener; + + public TodayLocalAdapter(Context mContext, List mRecordInfos, String uuid) { + super(); + this.mContext = mContext; + this.mOnLineRecordList = mRecordInfos; + this.uuid = uuid; + } + + public void setmOnItemClickListener(OnRecyclerClickListener mOnItemClickListener) { + this.mOnItemClickListener = mOnItemClickListener; + } + + @Override + public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_local_video_item, + parent, false); + return new TodayLocalAdapter.MessageViewHolder(view); + } + + @Override + public void onBindViewHolder(TodayLocalAdapter.MessageViewHolder holder, int position) { + holder.setViews(position); + } + + @Override + public int getItemCount() { + if (mOnLineRecordList.size() < 5) { + return mOnLineRecordList != null ? mOnLineRecordList.size() + 1 : 0; + } else { + return mOnLineRecordList != null ? 6 : 0; + } + } + + @Override + public long getItemId(int position) { + return super.getItemId(position); + } + + class MessageViewHolder extends RecyclerView.ViewHolder { + /*private TextView mChannelName; + private ImageView mDelete;*/ + // private RelativeLayout mBgDevice; + private ImageView mLiveVideo; + /*private ImageView mLocalVideo; + private ImageView mCloudVideo; + private ImageView mMessage; + private ImageView mSetting;*/ + private LinearLayout mListShade; + private ChannelInfo mInfo; + private ImageView iv; + private TextView tv_more; + private TextView tv_start_time; + + public MessageViewHolder(View convertView) { + super(convertView); + /*mChannelName = (TextView) convertView.findViewById(R.id.list_channel_name); + mDelete = (ImageView) convertView.findViewById(R.id.list_device_delete);*/ + // mBgDevice = (RelativeLayout) convertView.findViewById(R.id.list_bg_device); + mLiveVideo = (ImageView) convertView.findViewById(R.id.list_device_livevideo); + /*mLocalVideo = (ImageView) convertView.findViewById(R.id.list_device_localvideo); + mCloudVideo = (ImageView) convertView.findViewById(R.id.list_device_cloudvideo); + mMessage = (ImageView) convertView.findViewById(R.id.list_device_message); + mSetting = (ImageView) convertView.findViewById(R.id.list_device_setting);*/ + mListShade = (LinearLayout) convertView.findViewById(R.id.list_shade); + iv = (ImageView) itemView.findViewById(R.id.imageView); + tv_more = (TextView) itemView.findViewById(R.id.tv_more); + tv_start_time = (TextView) itemView.findViewById(R.id.tv_start_time); + } + + public void setViews(final int position) { + //修改数据信息(含加密标识符) + if (position == mOnLineRecordList.size() || position == 5) { + iv.setVisibility(View.GONE); + } else { + iv.setVisibility(View.VISIBLE); + SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss"); + tv_start_time.setText(String.valueOf(sdf2.format(mOnLineRecordList.get(position).getStartTime()))); + } + iv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnItemClickListener != null) { + mOnItemClickListener.onClick(v, position); + } + /*Intent intent = new Intent(mContext, MediaPlayBackActivity.class); + if (TextUtils.isEmpty(mOnLineRecordList.get(position).getId())) { + return; + } + intent.putExtra("TYPE", MediaPlayBackActivity.IS_VIDEO_REMOTE_RECORD); + intent.putExtra("ID", mOnLineRecordList.get(position).getId()); + intent.putExtra("dateString", mOnLineRecordList.get(position).getStartTime()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.getApplicationContext().startActivity(intent);*/ + } + }); + tv_more.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent1 = new Intent(mContext, RecordListActivity.class); + intent1.putExtra("UUID", uuid); + intent1.putExtra("TYPE", MediaPlayBackActivity.IS_VIDEO_REMOTE_RECORD); + intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.getApplicationContext().startActivity(intent1); + } + }); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/calendar/CalendarPopipWindow.java b/app/src/main/java/com/lechange/demo/localvideo/calendar/CalendarPopipWindow.java new file mode 100644 index 0000000..07a9bd8 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/calendar/CalendarPopipWindow.java @@ -0,0 +1,136 @@ +package com.lechange.demo.localvideo.calendar; + +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; +import android.widget.Toast; + +import com.yonsz.z1.R; +import com.yonsz.z1.utils.DateTimeUitl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by Administrator on 2019/3/7. + */ + +public class CalendarPopipWindow extends PopupWindow { + private Context context; + private View contentView; + private CustomCalendar cal; + private String chooseDay; + private OnCompleteListener onCompleteListener; + + public CalendarPopipWindow(Context context, String chooseDay, OnCompleteListener onCompleteListener) { + super(context); + this.context = context; + this.chooseDay = chooseDay; + this.onCompleteListener = onCompleteListener; + init(); + } + + private void init() { + contentView = LayoutInflater.from(context).inflate(R.layout.pop_calendar, null); + cal = (CustomCalendar) contentView.findViewById(R.id.cal); + final List list = new ArrayList<>(); + cal.setRenwu(chooseDay, list); + cal.setOnClickListener(new CustomCalendar.onClickListener() { + @Override + public void onLeftRowClick() { + Toast.makeText(context, "点击减箭头", Toast.LENGTH_SHORT).show(); + cal.monthChange(-1); + new Thread() { + @Override + public void run() { + try { + Thread.sleep(1000); + /*runOnUiThread(new Runnable() { + @Override + public void run() { + cal.setRenwu(list); + } + });*/ + } catch (Exception e) { + } + } + }.start(); + } + + @Override + public void onRightRowClick() { + Toast.makeText(context, "点击加箭头", Toast.LENGTH_SHORT).show(); + cal.monthChange(1); + new Thread() { + @Override + public void run() { + try { + Thread.sleep(1000); + /*runOnUiThread(new Runnable() { + @Override + public void run() { + cal.setRenwu(list); + } + });*/ + } catch (Exception e) { + } + } + }.start(); + } + + @Override + public void onTitleClick(String monthStr, Date month) { + Toast.makeText(context, "点击了标题:" + monthStr, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onWeekClick(int weekIndex, String weekStr) { + Toast.makeText(context, "点击了星期:" + weekStr, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onDayClick(int day, String dayStr, DayFinish finish) { + Toast.makeText(context, "点击了日期:" + dayStr, Toast.LENGTH_SHORT).show(); + // Log.w("", "点击了日期:" + dayStr); + if (onCompleteListener != null) { + int year = Integer.parseInt(dayStr.substring(0, 4)); + int month = Integer.parseInt(dayStr.substring(5, 7)); + String date = DateTimeUitl.formatDateFromInt(year, month, day); + onCompleteListener.onComplete(date); + } + dismiss(); + } + }); + + setContentView(contentView); + this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); + this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + // 设置可触 + this.setFocusable(true); + this.setOutsideTouchable(true); + this.setTouchable(true); + ColorDrawable dw = new ColorDrawable(0x80000000); + this.setBackgroundDrawable(dw); + + this.setTouchInterceptor(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent event) { + //如果点击了popuWindow的外部,popuWindow也会消失 + if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { + dismiss(); + return true; + } + return false; + } + }); + } + + public interface OnCompleteListener { + void onComplete(String dayStr); + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/calendar/CustomCalendar.java b/app/src/main/java/com/lechange/demo/localvideo/calendar/CustomCalendar.java new file mode 100644 index 0000000..12712a3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/calendar/CustomCalendar.java @@ -0,0 +1,657 @@ +package com.lechange.demo.localvideo.calendar; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Paint; +import android.graphics.PathEffect; +import android.graphics.PointF; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +import com.yonsz.z1.R; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * author : openXu + * create at : 2017/1/3 9:56 + * blog : http://blog.csdn.net/xmxkf + * gitHub : https://github.com/openXu + * project : CustomCalendar + * class name : CustomCalendar + * version : 1.0 + * class describe:自定义日历控件 + */ +public class CustomCalendar extends View { + + private String TAG = "CustomCalendar"; + + /** + * 各部分背景 + */ + private int mBgMonth, mBgWeek, mBgDay, mBgPre; + /** + * 标题的颜色、大小 + */ + private int mTextColorMonth; + private float mTextSizeMonth; + private int mMonthRowL, mMonthRowR; + private float mMonthRowSpac; + private float mMonthSpac; + /** + * 星期的颜色、大小 + */ + private int mTextColorWeek, mSelectWeekTextColor; + private float mTextSizeWeek; + /** + * 日期文本的颜色、大小 + */ + private int mTextColorDay; + private float mTextSizeDay; + /** + * 任务次数文本的颜色、大小 + */ + private int mTextColorPreFinish, mTextColorPreUnFinish, mTextColorPreNull; + private float mTextSizePre; + /** + * 选中的文本的颜色 + */ + private int mSelectTextColor; + /** + * 选中背景 + */ + private int mSelectBg, mCurrentBg; + private float mSelectRadius, mCurrentBgStrokeWidth; + private float[] mCurrentBgDashPath; + + /** + * 行间距 + */ + private float mLineSpac; + /** + * 字体上下间距 + */ + private float mTextSpac; + + private Paint mPaint; + private Paint bgPaint; + + private float titleHeight, weekHeight, dayHeight, preHeight, oneHeight; + private int columnWidth; //每列宽度 + + private Date month; //当前的月份 + private boolean isCurrentMonth; //展示的月份是否是当前月 + private int currentDay, selectDay, lastSelectDay; //当前日期 、 选中的日期 、上一次选中的日期(避免造成重复回调请求) + + private int dayOfMonth; //月份天数 + private int firstIndex; //当月第一天位置索引 + private int todayWeekIndex;//今天是星期几 + private int firstLineNum, lastLineNum; //第一行、最后一行能展示多少日期 + private int lineNum; //日期行数 + private String[] WEEK_STR = new String[]{"日", "一", "二", "三", "四", "五", "六",}; + /** + * 绘制月份 + */ + private int rowLStart, rowRStart, rowWidth; + /****************************事件处理↓↓↓↓↓↓↓****************************/ + //焦点坐标 + private PointF focusPoint = new PointF(); + //控制事件是否响应 + private boolean responseWhenEnd = false; + /***********************接口API↓↓↓↓↓↓↓**************************/ + private Map map; + private onClickListener listener; + + public CustomCalendar(Context context) { + this(context, null); + } + + public CustomCalendar(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + //获取自定义属性的值 + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomCalendar, defStyleAttr, 0); + + mBgMonth = a.getColor(R.styleable.CustomCalendar_mBgMonth, Color.TRANSPARENT); + mBgWeek = a.getColor(R.styleable.CustomCalendar_mBgWeek, Color.TRANSPARENT); + mBgDay = a.getColor(R.styleable.CustomCalendar_mBgDay, Color.TRANSPARENT); + mBgPre = a.getColor(R.styleable.CustomCalendar_mBgPre, Color.TRANSPARENT); + + mMonthRowL = a.getResourceId(R.styleable.CustomCalendar_mMonthRowL, R.drawable.custom_calendar_row_left); + mMonthRowR = a.getResourceId(R.styleable.CustomCalendar_mMonthRowR, R.drawable.custom_calendar_row_right); + mMonthRowSpac = a.getDimension(R.styleable.CustomCalendar_mMonthRowSpac, 20); + mTextColorMonth = a.getColor(R.styleable.CustomCalendar_mTextColorMonth, Color.BLACK); + mTextSizeMonth = a.getDimension(R.styleable.CustomCalendar_mTextSizeMonth, 100); + mMonthSpac = a.getDimension(R.styleable.CustomCalendar_mMonthSpac, 20); + mTextColorWeek = a.getColor(R.styleable.CustomCalendar_mTextColorWeek, Color.BLACK); + mSelectWeekTextColor = a.getColor(R.styleable.CustomCalendar_mSelectWeekTextColor, Color.BLACK); + + mTextSizeWeek = a.getDimension(R.styleable.CustomCalendar_mTextSizeWeek, 70); + mTextColorDay = a.getColor(R.styleable.CustomCalendar_mTextColorDay, Color.GRAY); + mTextSizeDay = a.getDimension(R.styleable.CustomCalendar_mTextSizeDay, 70); + mTextColorPreFinish = a.getColor(R.styleable.CustomCalendar_mTextColorPreFinish, Color.BLUE); + mTextColorPreUnFinish = a.getColor(R.styleable.CustomCalendar_mTextColorPreUnFinish, Color.BLUE); + mTextColorPreNull = a.getColor(R.styleable.CustomCalendar_mTextColorPreNull, Color.BLUE); + mTextSizePre = a.getDimension(R.styleable.CustomCalendar_mTextSizePre, 0); + mSelectTextColor = a.getColor(R.styleable.CustomCalendar_mSelectTextColor, Color.YELLOW); + mCurrentBg = a.getColor(R.styleable.CustomCalendar_mCurrentBg, Color.GRAY); + try { + int dashPathId = a.getResourceId(R.styleable.CustomCalendar_mCurrentBgDashPath, R.array.customCalendar_currentDay_bg_DashPath); + int[] array = getResources().getIntArray(dashPathId); + mCurrentBgDashPath = new float[array.length]; + for (int i = 0; i < array.length; i++) { + mCurrentBgDashPath[i] = array[i]; + } + } catch (Exception e) { + e.printStackTrace(); + mCurrentBgDashPath = new float[]{2, 3, 2, 3}; + } + mSelectBg = a.getColor(R.styleable.CustomCalendar_mSelectBg, Color.YELLOW); + mSelectRadius = a.getDimension(R.styleable.CustomCalendar_mSelectRadius, 20); + mCurrentBgStrokeWidth = a.getDimension(R.styleable.CustomCalendar_mCurrentBgStrokeWidth, 5); + mLineSpac = a.getDimension(R.styleable.CustomCalendar_mLineSpac, 20); + mTextSpac = a.getDimension(R.styleable.CustomCalendar_mTextSpac, 20); + a.recycle(); //注意回收 + + initCompute(); + + } + + /** + * 计算相关常量,构造方法中调用 + */ + private void initCompute() { + mPaint = new Paint(); + bgPaint = new Paint(); + mPaint.setAntiAlias(true); //抗锯齿 + bgPaint.setAntiAlias(true); //抗锯齿 + + map = new HashMap<>(); + + //标题高度 + mPaint.setTextSize(mTextSizeMonth); + titleHeight = FontUtil.getFontHeight(mPaint) + 2 * mMonthSpac; + //星期高度 + mPaint.setTextSize(mTextSizeWeek); + weekHeight = FontUtil.getFontHeight(mPaint); + //日期高度 + mPaint.setTextSize(mTextSizeDay); + dayHeight = FontUtil.getFontHeight(mPaint); + //次数字体高度 + mPaint.setTextSize(mTextSizePre); + preHeight = FontUtil.getFontHeight(mPaint); + //每行高度 = 行间距 + 日期字体高度 + 字间距 + 次数字体高度 + oneHeight = mLineSpac + dayHeight + mTextSpac + preHeight; + + //默认当前月份 + String cDateStr = getMonthStr(new Date()); + // cDateStr = "2015年08月"; + setMonth(cDateStr); + } + + /** + * 设置月份 + */ + private void setMonth(String Month) { + //设置的月份(2017年01月) + month = str2Date(Month); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + //获取今天是多少号 + currentDay = calendar.get(Calendar.DAY_OF_MONTH); + todayWeekIndex = calendar.get(Calendar.DAY_OF_WEEK) - 1; + + Date cM = str2Date(getMonthStr(new Date())); + //判断是否为当月 + if (cM.getTime() == month.getTime()) { + isCurrentMonth = true; + selectDay = currentDay;//当月默认选中当前日 + } else { + isCurrentMonth = false; + selectDay = 0; + } + Log.d(TAG, "设置月份:" + month + " 今天" + currentDay + "号, 是否为当前月:" + isCurrentMonth); + calendar.setTime(month); + dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + //第一行1号显示在什么位置(星期几) + firstIndex = calendar.get(Calendar.DAY_OF_WEEK) - 1; + lineNum = 1; + //第一行能展示的天数 + firstLineNum = 7 - firstIndex; + lastLineNum = 0; + int shengyu = dayOfMonth - firstLineNum; + while (shengyu > 7) { + lineNum++; + shengyu -= 7; + } + if (shengyu > 0) { + lineNum++; + lastLineNum = shengyu; + } + Log.i(TAG, getMonthStr(month) + "一共有" + dayOfMonth + "天,第一天的索引是:" + firstIndex + " 有" + lineNum + + "行,第一行" + firstLineNum + "个,最后一行" + lastLineNum + "个"); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + //宽度 = 填充父窗体 + int widthSize = MeasureSpec.getSize(widthMeasureSpec); //获取宽的尺寸 + columnWidth = widthSize / 7; + //高度 = 标题高度 + 星期高度 + 日期行数*每行高度 + float height = titleHeight + weekHeight + (lineNum * oneHeight); + Log.v(TAG, "标题高度:" + titleHeight + " 星期高度:" + weekHeight + " 每行高度:" + oneHeight + + " 行数:" + lineNum + " \n控件高度:" + height); + setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), + (int) height); + + } + + @Override + protected void onDraw(Canvas canvas) { + drawMonth(canvas); + drawWeek(canvas); + drawDayAndPre(canvas); + } + + private void drawMonth(Canvas canvas) { + //背景 + bgPaint.setColor(mBgMonth); + RectF rect = new RectF(0, 0, getWidth(), titleHeight); + canvas.drawRect(rect, bgPaint); + //绘制月份 + mPaint.setTextSize(mTextSizeMonth); + mPaint.setColor(mTextColorMonth); + float textLen = FontUtil.getFontlength(mPaint, getMonthStr(month)); + float textStart = (getWidth() - textLen) / 2; + canvas.drawText(getMonthStr(month), textStart, + mMonthSpac + FontUtil.getFontLeading(mPaint), mPaint); + /*绘制左右箭头*/ + Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mMonthRowL); + int h = bitmap.getHeight(); + rowWidth = bitmap.getWidth(); + //float left, float top + rowLStart = (int) (textStart - 2 * mMonthRowSpac - rowWidth); + canvas.drawBitmap(bitmap, rowLStart + mMonthRowSpac, (titleHeight - h) / 2, new Paint()); + bitmap = BitmapFactory.decodeResource(getResources(), mMonthRowR); + rowRStart = (int) (textStart + textLen); + canvas.drawBitmap(bitmap, rowRStart + mMonthRowSpac, (titleHeight - h) / 2, new Paint()); + } + + /** + * 绘制绘制星期 + */ + private void drawWeek(Canvas canvas) { + //背景 + bgPaint.setColor(mBgWeek); + RectF rect = new RectF(0, titleHeight, getWidth(), titleHeight + weekHeight); + canvas.drawRect(rect, bgPaint); + //绘制星期:七天 + mPaint.setTextSize(mTextSizeWeek); + + for (int i = 0; i < WEEK_STR.length; i++) { + if (todayWeekIndex == i && isCurrentMonth) { + mPaint.setColor(mSelectWeekTextColor); + } else { + mPaint.setColor(mTextColorWeek); + } + int len = (int) FontUtil.getFontlength(mPaint, WEEK_STR[i]); + int x = i * columnWidth + (columnWidth - len) / 2; + canvas.drawText(WEEK_STR[i], x, titleHeight + FontUtil.getFontLeading(mPaint), mPaint); + } + } + + /** + * 绘制日期和次数 + */ + private void drawDayAndPre(Canvas canvas) { + //某行开始绘制的Y坐标,第一行开始的坐标为标题高度+星期部分高度 + float top = titleHeight + weekHeight; + //行 + for (int line = 0; line < lineNum; line++) { + if (line == 0) { + //第一行 + drawDayAndPre(canvas, top, firstLineNum, 0, firstIndex); + } else if (line == lineNum - 1) { + //最后一行 + top += oneHeight; + drawDayAndPre(canvas, top, lastLineNum, firstLineNum + (line - 1) * 7, 0); + } else { + //满行 + top += oneHeight; + drawDayAndPre(canvas, top, 7, firstLineNum + (line - 1) * 7, 0); + } + } + } + + /** + * 绘制某一行的日期 + * + * @param canvas + * @param top 顶部坐标 + * @param count 此行需要绘制的日期数量(不一定都是7天) + * @param overDay 已经绘制过的日期,从overDay+1开始绘制 + * @param startIndex 此行第一个日期的星期索引 + */ + private void drawDayAndPre(Canvas canvas, float top, + int count, int overDay, int startIndex) { + // Log.e(TAG, "总共"+dayOfMonth+"天 有"+lineNum+"行"+ " 已经画了"+overDay+"天,下面绘制:"+count+"天"); + //背景 + float topPre = top + mLineSpac + dayHeight; + bgPaint.setColor(mBgDay); + RectF rect = new RectF(0, top, getWidth(), topPre); + canvas.drawRect(rect, bgPaint); + + bgPaint.setColor(mBgPre); + rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + dayHeight); + canvas.drawRect(rect, bgPaint); + + mPaint.setTextSize(mTextSizeDay); + float dayTextLeading = FontUtil.getFontLeading(mPaint); + mPaint.setTextSize(mTextSizePre); + float preTextLeading = FontUtil.getFontLeading(mPaint); + // Log.v(TAG, "当前日期:"+currentDay+" 选择日期:"+selectDay+" 是否为当前月:"+isCurrentMonth); + for (int i = 0; i < count; i++) { + int left = (startIndex + i) * columnWidth; + int day = (overDay + i + 1); + + mPaint.setTextSize(mTextSizeDay); + + //如果是当前月,当天日期需要做处理 + if (isCurrentMonth && currentDay == day) { + mPaint.setColor(mTextColorDay); + bgPaint.setColor(mCurrentBg); + bgPaint.setStyle(Paint.Style.STROKE); //空心 + PathEffect effect = new DashPathEffect(mCurrentBgDashPath, 1); + bgPaint.setPathEffect(effect); //设置画笔曲线间隔 + bgPaint.setStrokeWidth(mCurrentBgStrokeWidth); //画笔宽度 + //绘制空心圆背景 + canvas.drawCircle(left + columnWidth / 2, top + mLineSpac + dayHeight / 2, + mSelectRadius - mCurrentBgStrokeWidth, bgPaint); + } + //绘制完后将画笔还原,避免脏笔 + bgPaint.setPathEffect(null); + bgPaint.setStrokeWidth(0); + bgPaint.setStyle(Paint.Style.FILL); + + //选中的日期,如果是本月,选中日期正好是当天日期,下面的背景会覆盖上面绘制的虚线背景 + if (selectDay == day) { + //选中的日期字体白色,橙色背景 + mPaint.setColor(mSelectTextColor); + bgPaint.setColor(mSelectBg); + //绘制橙色圆背景,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象; + canvas.drawCircle(left + columnWidth / 2, top + mLineSpac + dayHeight / 2, mSelectRadius, bgPaint); + } else { + mPaint.setColor(mTextColorDay); + } + + int len = (int) FontUtil.getFontlength(mPaint, day + ""); + int x = left + (columnWidth - len) / 2; + canvas.drawText(day + "", x, top + mLineSpac + dayTextLeading, mPaint); + + //绘制次数 + mPaint.setTextSize(mTextSizePre); + DayFinish finish = map.get(day); + String preStr = ""; + if (isCurrentMonth) { + if (day > currentDay) { + mPaint.setColor(mTextColorPreNull); + } else if (finish != null) { + //区分完成未完成 + if (finish.finish >= finish.all) { + mPaint.setColor(mTextColorPreFinish); + } else { + mPaint.setColor(mTextColorPreUnFinish); + } + preStr = finish.finish + "/" + finish.all; + + } else { + mPaint.setColor(mTextColorPreNull); + } + } else { + if (finish != null) { + //区分完成未完成 + if (finish.finish >= finish.all) { + mPaint.setColor(mTextColorPreFinish); + } else { + mPaint.setColor(mTextColorPreUnFinish); + } + preStr = finish.finish + "/" + finish.all; + + } else { + mPaint.setColor(mTextColorPreNull); + } + } + + len = (int) FontUtil.getFontlength(mPaint, preStr); + x = left + (columnWidth - len) / 2; + canvas.drawText(preStr, x, topPre + mTextSpac + preTextLeading, mPaint); + } + } + + /** + * 获取月份标题 + */ + private String getMonthStr(Date month) { + SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月"); + return df.format(month); + } + + private Date str2Date(String str) { + try { + SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月"); + return df.parse(str); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_DOWN: + focusPoint.set(event.getX(), event.getY()); + touchFocusMove(focusPoint, false); + break; + case MotionEvent.ACTION_MOVE: + focusPoint.set(event.getX(), event.getY()); + touchFocusMove(focusPoint, false); + break; + case MotionEvent.ACTION_OUTSIDE: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + focusPoint.set(event.getX(), event.getY()); + touchFocusMove(focusPoint, true); + break; + } + return true; + } + + /** + * 焦点滑动 + */ + public void touchFocusMove(final PointF point, boolean eventEnd) { + Log.e(TAG, "点击坐标:(" + point.x + " ," + point.y + "),事件是否结束:" + eventEnd); + /**标题和星期只有在事件结束后才响应*/ + if (point.y <= titleHeight) { + //事件在标题上 + if (eventEnd && listener != null) { + if (point.x >= rowLStart && point.x < (rowLStart + 2 * mMonthRowSpac + rowWidth)) { + Log.w(TAG, "点击左箭头"); + listener.onLeftRowClick(); + } else if (point.x > rowRStart && point.x < (rowRStart + 2 * mMonthRowSpac + rowWidth)) { + Log.w(TAG, "点击右箭头"); + listener.onRightRowClick(); + } else if (point.x > rowLStart && point.x < rowRStart) { + listener.onTitleClick(getMonthStr(month), month); + } + } + } else if (point.y <= (titleHeight + weekHeight)) { + //事件在星期部分 + if (eventEnd && listener != null) { + //根据X坐标找到具体的焦点日期 + int xIndex = (int) point.x / columnWidth; + Log.e(TAG, "列宽:" + columnWidth + " x坐标余数:" + (point.x / columnWidth)); + if ((point.x / columnWidth - xIndex) > 0) { + xIndex += 1; + } + if (listener != null) { + listener.onWeekClick(xIndex - 1, WEEK_STR[xIndex - 1]); + } + } + } else { + /**日期部分按下和滑动时重绘,只有在事件结束后才响应*/ + touchDay(point, eventEnd); + } + } + + /** + * 事件点在 日期区域 范围内 + */ + private void touchDay(final PointF point, boolean eventEnd) { + //根据Y坐标找到焦点行 + boolean availability = false; //事件是否有效 + //日期部分 + float top = titleHeight + weekHeight + oneHeight; + int foucsLine = 1; + while (foucsLine <= lineNum) { + if (top >= point.y) { + availability = true; + break; + } + top += oneHeight; + foucsLine++; + } + if (availability) { + //根据X坐标找到具体的焦点日期 + int xIndex = (int) point.x / columnWidth; + if ((point.x / columnWidth - xIndex) > 0) { + xIndex += 1; + } + // Log.e(TAG, "列宽:"+columnWidth+" x坐标余数:"+(point.x / columnWidth)); + if (xIndex <= 0) + xIndex = 1; //避免调到上一行最后一个日期 + if (xIndex > 7) + xIndex = 7; //避免调到下一行第一个日期 + // Log.e(TAG, "事件在日期部分,第"+foucsLine+"/"+lineNum+"行, "+xIndex+"列"); + if (foucsLine == 1) { + //第一行 + if (xIndex <= firstIndex) { + Log.e(TAG, "点到开始空位了"); + setSelectedDay(selectDay, true); + } else { + setSelectedDay(xIndex - firstIndex, eventEnd); + } + } else if (foucsLine == lineNum) { + //最后一行 + if (xIndex > lastLineNum) { + Log.e(TAG, "点到结尾空位了"); + setSelectedDay(selectDay, true); + } else { + setSelectedDay(firstLineNum + (foucsLine - 2) * 7 + xIndex, eventEnd); + } + } else { + setSelectedDay(firstLineNum + (foucsLine - 2) * 7 + xIndex, eventEnd); + } + } else { + //超出日期区域后,视为事件结束,响应最后一个选择日期的回调 + setSelectedDay(selectDay, true); + } + } + + /** + * 设置选中的日期 + */ + private void setSelectedDay(int day, boolean eventEnd) { + Log.w(TAG, "选中:" + day + " 事件是否结束" + eventEnd); + selectDay = day; + invalidate(); + if (listener != null && eventEnd && responseWhenEnd && lastSelectDay != selectDay) { + lastSelectDay = selectDay; + listener.onDayClick(selectDay, getMonthStr(month) + selectDay + "日", map.get(selectDay)); + } + responseWhenEnd = !eventEnd; + } + + /****************************事件处理↑↑↑↑↑↑↑****************************/ + + + @Override + public void invalidate() { + requestLayout(); + super.invalidate(); + } + + public void setRenwu(String month, List list) { + setMonth(month); + + if (list != null && list.size() > 0) { + map.clear(); + for (DayFinish finish : list) { + map.put(finish.day, finish); + } + } + invalidate(); + } + + public void setRenwu(List list) { + if (list != null && list.size() > 0) { + map.clear(); + for (DayFinish finish : list) { + map.put(finish.day, finish); + } + } + invalidate(); + } + + /** + * 月份增减 + */ + public void monthChange(int change) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(month); + calendar.add(Calendar.MONTH, change); + setMonth(getMonthStr(calendar.getTime())); + map.clear(); + invalidate(); + } + + public void setOnClickListener(onClickListener listener) { + this.listener = listener; + } + + interface onClickListener { + + public abstract void onLeftRowClick(); + + public abstract void onRightRowClick(); + + public abstract void onTitleClick(String monthStr, Date month); + + public abstract void onWeekClick(int weekIndex, String weekStr); + + public abstract void onDayClick(int day, String dayStr, DayFinish finish); + } + + + /***********************接口API↑↑↑↑↑↑↑**************************/ + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/calendar/DayFinish.java b/app/src/main/java/com/lechange/demo/localvideo/calendar/DayFinish.java new file mode 100644 index 0000000..66da3da --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/calendar/DayFinish.java @@ -0,0 +1,16 @@ +package com.lechange.demo.localvideo.calendar; + +/** + * Created by Administrator on 2019/3/7. + */ + +public class DayFinish { + int day; + int all; + int finish; + public DayFinish(int day, int finish, int all) { + this.day = day; + this.all = all; + this.finish = finish; + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/calendar/FontUtil.java b/app/src/main/java/com/lechange/demo/localvideo/calendar/FontUtil.java new file mode 100644 index 0000000..7da877c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/calendar/FontUtil.java @@ -0,0 +1,44 @@ +package com.lechange.demo.localvideo.calendar; + +import android.graphics.Paint; + +/** + * author : openXu + * create at : 2016/07/8 12:40 + * blog : http://blog.csdn.net/xmxkf + * gitHub : https://github.com/openXu + * project : StockChart + * class name : FontUtil + * version : 1.0 + * class describe:文字相关处理帮助类 + */ +public class FontUtil { + + /** + * @param paint + * @param str + * @return 返回指定笔和指定字符串的长度 + * @add yujiangtao 16/8/5 + */ + public static float getFontlength(Paint paint, String str) { + return paint.measureText(str); + } + /** + * @return 返回指定笔的文字高度 + * @add yujiangtao 16/8/5 + */ + public static float getFontHeight(Paint paint) { + Paint.FontMetrics fm = paint.getFontMetrics(); + return fm.descent - fm.ascent; + } + /** + * @return 返回指定笔离文字顶部的基准距离 + * @add yujiangtao 16/8/5 + */ + public static float getFontLeading(Paint paint) { + Paint.FontMetrics fm = paint.getFontMetrics(); + return fm.leading- fm.ascent; + } + + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/LayoutController.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/LayoutController.java new file mode 100644 index 0000000..d0f941d --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/LayoutController.java @@ -0,0 +1,83 @@ +package com.lechange.demo.localvideo.timeshaftbar; + +import android.content.Context; +import android.util.Log; + + +public class LayoutController { + protected int mWidth; + protected int mHeight; + + protected int mScrollPosition; + + protected int mContentLength = 0; + protected OverScroller mScroller; + protected int mPaddingLeft = 0; + protected int mPaddingRight = 0; + protected int mPaddingTop = 0; + + public LayoutController(Context context) { + mScroller = new OverScroller(context); + } + + public void setLayoutSize(int width,int height,int contentLength) { + mWidth = width; + mHeight = height; + mPaddingLeft = mWidth/2; + mPaddingRight = mWidth/2; + mContentLength = mPaddingLeft + contentLength + mPaddingRight; + } + public int getScrollLimit() { + int limit = mContentLength - mPaddingLeft - mPaddingRight; + return limit <= 0 ? 0 : limit; + } + //for scroll + public boolean computeScrollOffset() { + return mScroller.computeScrollOffset(); + } + public void forceFinished() { + mScroller.forceFinished(true); + mScroller.startScroll(mScroller.getCurrX(), mScroller.getCurrY(),0, 0 , 0); + } + public int getPosition() { + return mScroller.getCurrX(); + } + + + public int getPaddingLeft() { + return mPaddingLeft; + } + + public int getPaddingRight() { + return mPaddingRight; + } + + public void fling(int velocity, int min, int max) { + int currX = getPosition(); + mScroller.fling(currX, 0, velocity, 0, min, max, 0, 0,0,0); + } + // Returns the input value x clamped to the range [min, max]. + public static int clamp(int x, int min, int max) { + if (x > max) return max; + if (x < min) return min; + return x; + } + // Returns the distance that over the scroll limit. + public int startScroll(int distance, int min, int max) { + int currPosition = mScroller.getCurrX(); + int newPosition = clamp(currPosition + distance, min, max); + if (newPosition != currPosition) { + Log.d("LayoutController","currPosition = " + currPosition +" distance = "+distance); + mScroller.startScroll(currPosition,0, newPosition - currPosition,0, 0); + } + return distance - newPosition; + } + + public void setPosition(int postion) { + mScrollPosition = postion; + mScroller.startScroll(postion,mScroller.getCurrY(),0, 0 , 0); + } + public boolean isFinished() { + return mScroller.isFinished(); + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/OverScroller.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/OverScroller.java new file mode 100644 index 0000000..cb079cb --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/OverScroller.java @@ -0,0 +1,952 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.localvideo.timeshaftbar; + +import android.content.Context; +import android.hardware.SensorManager; +import android.view.ViewConfiguration; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + + +/** + * This class encapsulates scrolling with the ability to overshoot the bounds + * of a scrolling operation. This class is a drop-in replacement for + * {@link android.widget.Scroller} in most cases. + */ +public class OverScroller { + private int mMode; + + private final SplineOverScroller mScrollerX; + private final SplineOverScroller mScrollerY; + + private Interpolator mInterpolator; + + private final boolean mFlywheel; + + private static final int DEFAULT_DURATION = 250; + private static final int SCROLL_MODE = 0; + private static final int FLING_MODE = 1; + + /** + * Creates an OverScroller with a viscous fluid scroll interpolator and flywheel. + * @param context + */ + public OverScroller(Context context) { + this(context, null); + } + + /** + * Creates an OverScroller with flywheel enabled. + * @param context The context of this application. + * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will + * be used. + */ + public OverScroller(Context context, Interpolator interpolator) { + this(context, interpolator, true); + } + + /** + * Creates an OverScroller. + * @param context The context of this application. + * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will + * be used. + * @param flywheel If true, successive fling motions will keep on increasing scroll speed. + * @hide + */ + public OverScroller(Context context, Interpolator interpolator, boolean flywheel) { + mInterpolator = interpolator; + mFlywheel = flywheel; + mScrollerX = new SplineOverScroller(context); + mScrollerY = new SplineOverScroller(context); + } + + /** + * Creates an OverScroller with flywheel enabled. + * @param context The context of this application. + * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will + * be used. + * @param bounceCoefficientX A value between 0 and 1 that will determine the proportion of the + * velocity which is preserved in the bounce when the horizontal edge is reached. A null value + * means no bounce. This behavior is no longer supported and this coefficient has no effect. + * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction. This + * behavior is no longer supported and this coefficient has no effect. + * !deprecated Use {!link #OverScroller(Context, Interpolator, boolean)} instead. + */ + public OverScroller(Context context, Interpolator interpolator, + float bounceCoefficientX, float bounceCoefficientY) { + this(context, interpolator, true); + } + + /** + * Creates an OverScroller. + * @param context The context of this application. + * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will + * be used. + * @param bounceCoefficientX A value between 0 and 1 that will determine the proportion of the + * velocity which is preserved in the bounce when the horizontal edge is reached. A null value + * means no bounce. This behavior is no longer supported and this coefficient has no effect. + * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction. This + * behavior is no longer supported and this coefficient has no effect. + * @param flywheel If true, successive fling motions will keep on increasing scroll speed. + * !deprecated Use {!link OverScroller(Context, Interpolator, boolean)} instead. + */ + public OverScroller(Context context, Interpolator interpolator, + float bounceCoefficientX, float bounceCoefficientY, boolean flywheel) { + this(context, interpolator, flywheel); + } + + void setInterpolator(Interpolator interpolator) { + mInterpolator = interpolator; + } + + /** + * The amount of friction applied to flings. The default value + * is {@link ViewConfiguration#getScrollFriction}. + * + * @param friction A scalar dimension-less value representing the coefficient of + * friction. + */ + public final void setFriction(float friction) { + mScrollerX.setFriction(friction); + mScrollerY.setFriction(friction); + } + + /** + * + * Returns whether the scroller has finished scrolling. + * + * @return True if the scroller has finished scrolling, false otherwise. + */ + public final boolean isFinished() { + return mScrollerX.mFinished && mScrollerY.mFinished; + } + + /** + * Force the finished field to a particular value. Contrary to + * {@link #abortAnimation()}, forcing the animation to finished + * does NOT cause the scroller to move to the final x and y + * position. + * + * @param finished The new finished value. + */ + public final void forceFinished(boolean finished) { + mScrollerX.mFinished = mScrollerY.mFinished = finished; + } + + /** + * Returns the current X offset in the scroll. + * + * @return The new X offset as an absolute distance from the origin. + */ + public final int getCurrX() { + return mScrollerX.mCurrentPosition; + } + + /** + * Returns the current Y offset in the scroll. + * + * @return The new Y offset as an absolute distance from the origin. + */ + public final int getCurrY() { + return mScrollerY.mCurrentPosition; + } + + /** + * Returns the absolute value of the current velocity. + * + * @return The original velocity less the deceleration, norm of the X and Y velocity vector. + */ + public float getCurrVelocity() { + float squaredNorm = mScrollerX.mCurrVelocity * mScrollerX.mCurrVelocity; + squaredNorm += mScrollerY.mCurrVelocity * mScrollerY.mCurrVelocity; + return (float) Math.sqrt(squaredNorm); + } + + /** + * Returns the start X offset in the scroll. + * + * @return The start X offset as an absolute distance from the origin. + */ + public final int getStartX() { + return mScrollerX.mStart; + } + + /** + * Returns the start Y offset in the scroll. + * + * @return The start Y offset as an absolute distance from the origin. + */ + public final int getStartY() { + return mScrollerY.mStart; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final X offset as an absolute distance from the origin. + */ + public final int getFinalX() { + return mScrollerX.mFinal; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final Y offset as an absolute distance from the origin. + */ + public final int getFinalY() { + return mScrollerY.mFinal; + } + + /** + * Returns how long the scroll event will take, in milliseconds. + * + * @return The duration of the scroll in milliseconds. + * + * @hide Pending removal once nothing depends on it + * @deprecated OverScrollers don't necessarily have a fixed duration. + * This function will lie to the best of its ability. + */ + @Deprecated + public final int getDuration() { + return Math.max(mScrollerX.mDuration, mScrollerY.mDuration); + } + + /** + * Extend the scroll animation. This allows a running animation to scroll + * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. + * + * @param extend Additional time to scroll in milliseconds. + * @see #setFinalX(int) + * @see #setFinalY(int) + * + * @hide Pending removal once nothing depends on it + * @deprecated OverScrollers don't necessarily have a fixed duration. + * Instead of setting a new final position and extending + * the duration of an existing scroll, use startScroll + * to begin a new animation. + */ + @Deprecated + public void extendDuration(int extend) { + mScrollerX.extendDuration(extend); + mScrollerY.extendDuration(extend); + } + + /** + * Sets the final position (X) for this scroller. + * + * @param newX The new X offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalY(int) + * + * @hide Pending removal once nothing depends on it + * @deprecated OverScroller's final position may change during an animation. + * Instead of setting a new final position and extending + * the duration of an existing scroll, use startScroll + * to begin a new animation. + */ + @Deprecated + public void setFinalX(int newX) { + mScrollerX.setFinalPosition(newX); + } + + /** + * Sets the final position (Y) for this scroller. + * + * @param newY The new Y offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalX(int) + * + * @hide Pending removal once nothing depends on it + * @deprecated OverScroller's final position may change during an animation. + * Instead of setting a new final position and extending + * the duration of an existing scroll, use startScroll + * to begin a new animation. + */ + @Deprecated + public void setFinalY(int newY) { + mScrollerY.setFinalPosition(newY); + } + + /** + * Call this when you want to know the new location. If it returns true, the + * animation is not yet finished. + */ + public boolean computeScrollOffset() { + if (isFinished()) { + return false; + } + + switch (mMode) { + case SCROLL_MODE: + long time = AnimationUtils.currentAnimationTimeMillis(); + // Any scroller can be used for time, since they were started + // together in scroll mode. We use X here. + final long elapsedTime = time - mScrollerX.mStartTime; + + final int duration = mScrollerX.mDuration; + if (elapsedTime < duration) { + float q = (float) (elapsedTime) / duration; + + if (mInterpolator == null) { + q = Scroller.viscousFluid(q); + } else { + q = mInterpolator.getInterpolation(q); + } + + mScrollerX.updateScroll(q); + mScrollerY.updateScroll(q); + } else { + abortAnimation(); + } + break; + + case FLING_MODE: + if (!mScrollerX.mFinished) { + if (!mScrollerX.update()) { + if (!mScrollerX.continueWhenFinished()) { + mScrollerX.finish(); + } + } + } + + if (!mScrollerY.mFinished) { + if (!mScrollerY.update()) { + if (!mScrollerY.continueWhenFinished()) { + mScrollerY.finish(); + } + } + } + + break; + } + + return true; + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * The scroll will use the default value of 250 milliseconds for the + * duration. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + */ + public void startScroll(int startX, int startY, int dx, int dy) { + startScroll(startX, startY, dx, dy, DEFAULT_DURATION); + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + * @param duration Duration of the scroll in milliseconds. + */ + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + mMode = SCROLL_MODE; + mScrollerX.startScroll(startX, dx, duration); + mScrollerY.startScroll(startY, dy, duration); + } + + /** + * Call this when you want to 'spring back' into a valid coordinate range. + * + * @param startX Starting X coordinate + * @param startY Starting Y coordinate + * @param minX Minimum valid X value + * @param maxX Maximum valid X value + * @param minY Minimum valid Y value + * @param maxY Minimum valid Y value + * @return true if a springback was initiated, false if startX and startY were + * already within the valid range. + */ + public boolean springBack(int startX, int startY, int minX, int maxX, int minY, int maxY) { + mMode = FLING_MODE; + + // Make sure both methods are called. + final boolean spingbackX = mScrollerX.springback(startX, minX, maxX); + final boolean spingbackY = mScrollerY.springback(startY, minY, maxY); + return spingbackX || spingbackY; + } + + public void fling(int startX, int startY, int velocityX, int velocityY, + int minX, int maxX, int minY, int maxY) { + fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, 0, 0); + } + + /** + * Start scrolling based on a fling gesture. The distance traveled will + * depend on the initial velocity of the fling. + * + * @param startX Starting point of the scroll (X) + * @param startY Starting point of the scroll (Y) + * @param velocityX Initial velocity of the fling (X) measured in pixels per + * second. + * @param velocityY Initial velocity of the fling (Y) measured in pixels per + * second + * @param minX Minimum X value. The scroller will not scroll past this point + * unless overX > 0. If overfling is allowed, it will use minX as + * a springback boundary. + * @param maxX Maximum X value. The scroller will not scroll past this point + * unless overX > 0. If overfling is allowed, it will use maxX as + * a springback boundary. + * @param minY Minimum Y value. The scroller will not scroll past this point + * unless overY > 0. If overfling is allowed, it will use minY as + * a springback boundary. + * @param maxY Maximum Y value. The scroller will not scroll past this point + * unless overY > 0. If overfling is allowed, it will use maxY as + * a springback boundary. + * @param overX Overfling range. If > 0, horizontal overfling in either + * direction will be possible. + * @param overY Overfling range. If > 0, vertical overfling in either + * direction will be possible. + */ + public void fling(int startX, int startY, int velocityX, int velocityY, + int minX, int maxX, int minY, int maxY, int overX, int overY) { + // Continue a scroll or fling in progress + if (mFlywheel && !isFinished()) { + float oldVelocityX = mScrollerX.mCurrVelocity; + float oldVelocityY = mScrollerY.mCurrVelocity; + if (Math.signum(velocityX) == Math.signum(oldVelocityX) && + Math.signum(velocityY) == Math.signum(oldVelocityY)) { + velocityX += oldVelocityX; + velocityY += oldVelocityY; + } + } + + mMode = FLING_MODE; + mScrollerX.fling(startX, velocityX, minX, maxX, overX); + mScrollerY.fling(startY, velocityY, minY, maxY, overY); + } + + /** + * Notify the scroller that we've reached a horizontal boundary. + * Normally the information to handle this will already be known + * when the animation is started, such as in a call to one of the + * fling functions. However there are cases where this cannot be known + * in advance. This function will transition the current motion and + * animate from startX to finalX as appropriate. + * + * @param startX Starting/current X position + * @param finalX Desired final X position + * @param overX Magnitude of overscroll allowed. This should be the maximum + * desired distance from finalX. Absolute value - must be positive. + */ + public void notifyHorizontalEdgeReached(int startX, int finalX, int overX) { + mScrollerX.notifyEdgeReached(startX, finalX, overX); + } + + /** + * Notify the scroller that we've reached a vertical boundary. + * Normally the information to handle this will already be known + * when the animation is started, such as in a call to one of the + * fling functions. However there are cases where this cannot be known + * in advance. This function will animate a parabolic motion from + * startY to finalY. + * + * @param startY Starting/current Y position + * @param finalY Desired final Y position + * @param overY Magnitude of overscroll allowed. This should be the maximum + * desired distance from finalY. Absolute value - must be positive. + */ + public void notifyVerticalEdgeReached(int startY, int finalY, int overY) { + mScrollerY.notifyEdgeReached(startY, finalY, overY); + } + + /** + * Returns whether the current Scroller is currently returning to a valid position. + * Valid bounds were provided by the + * {@link #fling(int, int, int, int, int, int, int, int, int, int)} method. + * + * One should check this value before calling + * {@link #startScroll(int, int, int, int)} as the interpolation currently in progress + * to restore a valid position will then be stopped. The caller has to take into account + * the fact that the started scroll will start from an overscrolled position. + * + * @return true when the current position is overscrolled and in the process of + * interpolating back to a valid value. + */ + public boolean isOverScrolled() { + return ((!mScrollerX.mFinished && + mScrollerX.mState != SplineOverScroller.SPLINE) || + (!mScrollerY.mFinished && + mScrollerY.mState != SplineOverScroller.SPLINE)); + } + + /** + * Stops the animation. Contrary to {@link #forceFinished(boolean)}, + * aborting the animating causes the scroller to move to the final x and y + * positions. + * + * @see #forceFinished(boolean) + */ + public void abortAnimation() { + mScrollerX.finish(); + mScrollerY.finish(); + } + + /** + * Returns the time elapsed since the beginning of the scrolling. + * + * @return The elapsed time in milliseconds. + * + * @hide + */ + public int timePassed() { + final long time = AnimationUtils.currentAnimationTimeMillis(); + final long startTime = Math.min(mScrollerX.mStartTime, mScrollerY.mStartTime); + return (int) (time - startTime); + } + + /** + * @hide + */ + public boolean isScrollingInDirection(float xvel, float yvel) { + final int dx = mScrollerX.mFinal - mScrollerX.mStart; + final int dy = mScrollerY.mFinal - mScrollerY.mStart; + return !isFinished() && Math.signum(xvel) == Math.signum(dx) && + Math.signum(yvel) == Math.signum(dy); + } + + static class SplineOverScroller { + // Initial position + private int mStart; + + // Current position + private int mCurrentPosition; + + // Final position + private int mFinal; + + // Initial velocity + private int mVelocity; + + // Current velocity + private float mCurrVelocity; + + // Constant current deceleration + private float mDeceleration; + + // Animation starting time, in system milliseconds + private long mStartTime; + + // Animation duration, in milliseconds + private int mDuration; + + // Duration to complete spline component of animation + private int mSplineDuration; + + // Distance to travel along spline animation + private int mSplineDistance; + + // Whether the animation is currently in progress + private boolean mFinished; + + // The allowed overshot distance before boundary is reached. + private int mOver; + + // Fling friction + private float mFlingFriction = ViewConfiguration.getScrollFriction(); + + // Current state of the animation. + private int mState = SPLINE; + + // Constant gravity value, used in the deceleration phase. + private static final float GRAVITY = 2000.0f; + + // A context-specific coefficient adjusted to physical values. + private float mPhysicalCoeff; + + private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9)); + private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1) + private static final float START_TENSION = 0.5f; + private static final float END_TENSION = 1.0f; + private static final float P1 = START_TENSION * INFLEXION; + private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION); + + private static final int NB_SAMPLES = 100; + private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1]; + private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1]; + + private static final int SPLINE = 0; + private static final int CUBIC = 1; + private static final int BALLISTIC = 2; + + static { + float x_min = 0.0f; + float y_min = 0.0f; + for (int i = 0; i < NB_SAMPLES; i++) { + final float alpha = (float) i / NB_SAMPLES; + + float x_max = 1.0f; + float x, tx, coef; + while (true) { + x = x_min + (x_max - x_min) / 2.0f; + coef = 3.0f * x * (1.0f - x); + tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x; + if (Math.abs(tx - alpha) < 1E-5) break; + if (tx > alpha) x_max = x; + else x_min = x; + } + SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x; + + float y_max = 1.0f; + float y, dy; + while (true) { + y = y_min + (y_max - y_min) / 2.0f; + coef = 3.0f * y * (1.0f - y); + dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y; + if (Math.abs(dy - alpha) < 1E-5) break; + if (dy > alpha) y_max = y; + else y_min = y; + } + SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y; + } + SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f; + } + + void setFriction(float friction) { + mFlingFriction = friction; + } + + SplineOverScroller(Context context) { + mFinished = true; + final float ppi = context.getResources().getDisplayMetrics().density * 160.0f; + mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) + * 39.37f // inch/meter + * ppi + * 0.84f; // look and feel tuning + } + + void updateScroll(float q) { + mCurrentPosition = mStart + Math.round(q * (mFinal - mStart)); + } + + /* + * Get a signed deceleration that will reduce the velocity. + */ + static private float getDeceleration(int velocity) { + return velocity > 0 ? -GRAVITY : GRAVITY; + } + + /* + * Modifies mDuration to the duration it takes to get from start to newFinal using the + * spline interpolation. The previous duration was needed to get to oldFinal. + */ + private void adjustDuration(int start, int oldFinal, int newFinal) { + final int oldDistance = oldFinal - start; + final int newDistance = newFinal - start; + final float x = Math.abs((float) newDistance / oldDistance); + final int index = (int) (NB_SAMPLES * x); + if (index < NB_SAMPLES) { + final float x_inf = (float) index / NB_SAMPLES; + final float x_sup = (float) (index + 1) / NB_SAMPLES; + final float t_inf = SPLINE_TIME[index]; + final float t_sup = SPLINE_TIME[index + 1]; + final float timeCoef = t_inf + (x - x_inf) / (x_sup - x_inf) * (t_sup - t_inf); + mDuration *= timeCoef; + } + } + + void startScroll(int start, int distance, int duration) { + mFinished = false; + + mStart = start; + mFinal = start + distance; + + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mDuration = duration; + + // Unused + mDeceleration = 0.0f; + mVelocity = 0; + } + + void finish() { + mCurrentPosition = mFinal; + // Not reset since WebView relies on this value for fast fling. + // TODO: restore when WebView uses the fast fling implemented in this class. + // mCurrVelocity = 0.0f; + mFinished = true; + } + + void setFinalPosition(int position) { + mFinal = position; + mFinished = false; + } + + void extendDuration(int extend) { + final long time = AnimationUtils.currentAnimationTimeMillis(); + final int elapsedTime = (int) (time - mStartTime); + mDuration = elapsedTime + extend; + mFinished = false; + } + + boolean springback(int start, int min, int max) { + mFinished = true; + + mStart = mFinal = start; + mVelocity = 0; + + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mDuration = 0; + + if (start < min) { + startSpringback(start, min, 0); + } else if (start > max) { + startSpringback(start, max, 0); + } + + return !mFinished; + } + + private void startSpringback(int start, int end, int velocity) { + // mStartTime has been set + mFinished = false; + mState = CUBIC; + mStart = start; + mFinal = end; + final int delta = start - end; + mDeceleration = getDeceleration(delta); + // TODO take velocity into account + mVelocity = -delta; // only sign is used + mOver = Math.abs(delta); + mDuration = (int) (1000.0 * Math.sqrt(-2.0 * delta / mDeceleration)); + } + + void fling(int start, int velocity, int min, int max, int over) { + mOver = over; + mFinished = false; + mCurrVelocity = mVelocity = velocity; + mDuration = mSplineDuration = 0; + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mCurrentPosition = mStart = start; + + if (start > max || start < min) { + startAfterEdge(start, min, max, velocity); + return; + } + + mState = SPLINE; + double totalDistance = 0.0; + + if (velocity != 0) { + mDuration = mSplineDuration = getSplineFlingDuration(velocity); + totalDistance = getSplineFlingDistance(velocity); + } + + mSplineDistance = (int) (totalDistance * Math.signum(velocity)); + mFinal = start + mSplineDistance; + + // Clamp to a valid final position + if (mFinal < min) { + adjustDuration(mStart, mFinal, min); + mFinal = min; + } + + if (mFinal > max) { + adjustDuration(mStart, mFinal, max); + mFinal = max; + } + } + + private double getSplineDeceleration(int velocity) { + return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff)); + } + + private double getSplineFlingDistance(int velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l); + } + + /* Returns the duration, expressed in milliseconds */ + private int getSplineFlingDuration(int velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return (int) (1000.0 * Math.exp(l / decelMinusOne)); + } + + private void fitOnBounceCurve(int start, int end, int velocity) { + // Simulate a bounce that started from edge + final float durationToApex = - velocity / mDeceleration; + final float distanceToApex = velocity * velocity / 2.0f / Math.abs(mDeceleration); + final float distanceToEdge = Math.abs(end - start); + final float totalDuration = (float) Math.sqrt( + 2.0 * (distanceToApex + distanceToEdge) / Math.abs(mDeceleration)); + mStartTime -= (int) (1000.0f * (totalDuration - durationToApex)); + mStart = end; + mVelocity = (int) (- mDeceleration * totalDuration); + } + + private void startBounceAfterEdge(int start, int end, int velocity) { + mDeceleration = getDeceleration(velocity == 0 ? start - end : velocity); + fitOnBounceCurve(start, end, velocity); + onEdgeReached(); + } + + private void startAfterEdge(int start, int min, int max, int velocity) { + if (start > min && start < max) { + mFinished = true; + return; + } + final boolean positive = start > max; + final int edge = positive ? max : min; + final int overDistance = start - edge; + boolean keepIncreasing = overDistance * velocity >= 0; + if (keepIncreasing) { + // Will result in a bounce or a to_boundary depending on velocity. + startBounceAfterEdge(start, edge, velocity); + } else { + final double totalDistance = getSplineFlingDistance(velocity); + if (totalDistance > Math.abs(overDistance)) { + fling(start, velocity, positive ? min : start, positive ? start : max, mOver); + } else { + startSpringback(start, edge, velocity); + } + } + } + + void notifyEdgeReached(int start, int end, int over) { + // mState is used to detect successive notifications + if (mState == SPLINE) { + mOver = over; + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + // We were in fling/scroll mode before: current velocity is such that distance to + // edge is increasing. This ensures that startAfterEdge will not start a new fling. + startAfterEdge(start, end, end, (int) mCurrVelocity); + } + } + + private void onEdgeReached() { + // mStart, mVelocity and mStartTime were adjusted to their values when edge was reached. + float distance = mVelocity * mVelocity / (2.0f * Math.abs(mDeceleration)); + final float sign = Math.signum(mVelocity); + + if (distance > mOver) { + // Default deceleration is not sufficient to slow us down before boundary + mDeceleration = - sign * mVelocity * mVelocity / (2.0f * mOver); + distance = mOver; + } + + mOver = (int) distance; + mState = BALLISTIC; + mFinal = mStart + (int) (mVelocity > 0 ? distance : -distance); + mDuration = - (int) (1000.0f * mVelocity / mDeceleration); + } + + boolean continueWhenFinished() { + switch (mState) { + case SPLINE: + // Duration from start to null velocity + if (mDuration < mSplineDuration) { + // If the animation was clamped, we reached the edge + mStart = mFinal; + // TODO Better compute speed when edge was reached + mVelocity = (int) mCurrVelocity; + mDeceleration = getDeceleration(mVelocity); + mStartTime += mDuration; + onEdgeReached(); + } else { + // Normal stop, no need to continue + return false; + } + break; + case BALLISTIC: + mStartTime += mDuration; + startSpringback(mFinal, mStart, 0); + break; + case CUBIC: + return false; + } + + update(); + return true; + } + + /* + * Update the current position and velocity for current time. Returns + * true if update has been done and false if animation duration has been + * reached. + */ + boolean update() { + final long time = AnimationUtils.currentAnimationTimeMillis(); + final long currentTime = time - mStartTime; + + if (currentTime > mDuration) { + return false; + } + + double distance = 0.0; + switch (mState) { + case SPLINE: { + final float t = (float) currentTime / mSplineDuration; + final int index = (int) (NB_SAMPLES * t); + float distanceCoef = 1.f; + float velocityCoef = 0.f; + if (index < NB_SAMPLES) { + final float t_inf = (float) index / NB_SAMPLES; + final float t_sup = (float) (index + 1) / NB_SAMPLES; + final float d_inf = SPLINE_POSITION[index]; + final float d_sup = SPLINE_POSITION[index + 1]; + velocityCoef = (d_sup - d_inf) / (t_sup - t_inf); + distanceCoef = d_inf + (t - t_inf) * velocityCoef; + } + + distance = distanceCoef * mSplineDistance; + mCurrVelocity = velocityCoef * mSplineDistance / mSplineDuration * 1000.0f; + break; + } + + case BALLISTIC: { + final float t = currentTime / 1000.0f; + mCurrVelocity = mVelocity + mDeceleration * t; + distance = mVelocity * t + mDeceleration * t * t / 2.0f; + break; + } + + case CUBIC: { + final float t = (float) (currentTime) / mDuration; + final float t2 = t * t; + final float sign = Math.signum(mVelocity); + distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); + mCurrVelocity = sign * mOver * 6.0f * (- t + t2); + break; + } + } + + mCurrentPosition = mStart + (int) Math.round(distance); + + return true; + } + } +} + diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/Scroller.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/Scroller.java new file mode 100644 index 0000000..061d347 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/Scroller.java @@ -0,0 +1,586 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lechange.demo.localvideo.timeshaftbar; + +import android.content.Context; +import android.hardware.SensorManager; +import android.os.Build; +import android.view.ViewConfiguration; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + + +/** + *

    This class encapsulates scrolling. You can use scrollers ({@link Scroller} + * or {@link OverScroller}) to collect the data you need to produce a scrolling + * animation—for example, in response to a fling gesture. Scrollers track + * scroll offsets for you over time, but they don't automatically apply those + * positions to your view. It's your responsibility to get and apply new + * coordinates at a rate that will make the scrolling animation look smooth.

    + * + *

    Here is a simple example:

    + * + *
     private Scroller mScroller = new Scroller(context);
    + * ...
    + * public void zoomIn() {
    + *     // Revert any animation currently in progress
    + *     mScroller.forceFinished(true);
    + *     // Start scrolling by providing a starting point and
    + *     // the distance to travel
    + *     mScroller.startScroll(0, 0, 100, 0);
    + *     // Invalidate to request a redraw
    + *     invalidate();
    + * }
    + * + *

    To track the changing positions of the x/y coordinates, use + * {@link #computeScrollOffset}. The method returns a boolean to indicate + * whether the scroller is finished. If it isn't, it means that a fling or + * programmatic pan operation is still in progress. You can use this method to + * find the current offsets of the x and y coordinates, for example:

    + * + *
    if (mScroller.computeScrollOffset()) {
    + *     // Get current x and y positions
    + *     int currX = mScroller.getCurrX();
    + *     int currY = mScroller.getCurrY();
    + *    ...
    + * }
    + */ +public class Scroller { + private int mMode; + + private int mStartX; + private int mStartY; + private int mFinalX; + private int mFinalY; + + private int mMinX; + private int mMaxX; + private int mMinY; + private int mMaxY; + + private int mCurrX; + private int mCurrY; + private long mStartTime; + private int mDuration; + private float mDurationReciprocal; + private float mDeltaX; + private float mDeltaY; + private boolean mFinished; + private Interpolator mInterpolator; + private boolean mFlywheel; + + private float mVelocity; + private float mCurrVelocity; + private int mDistance; + + private float mFlingFriction = ViewConfiguration.getScrollFriction(); + + private static final int DEFAULT_DURATION = 250; + private static final int SCROLL_MODE = 0; + private static final int FLING_MODE = 1; + + private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9)); + private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1) + private static final float START_TENSION = 0.5f; + private static final float END_TENSION = 1.0f; + private static final float P1 = START_TENSION * INFLEXION; + private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION); + + private static final int NB_SAMPLES = 100; + private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1]; + private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1]; + + private float mDeceleration; + private final float mPpi; + + // A context-specific coefficient adjusted to physical values. + private float mPhysicalCoeff; + + static { + float x_min = 0.0f; + float y_min = 0.0f; + for (int i = 0; i < NB_SAMPLES; i++) { + final float alpha = (float) i / NB_SAMPLES; + + float x_max = 1.0f; + float x, tx, coef; + while (true) { + x = x_min + (x_max - x_min) / 2.0f; + coef = 3.0f * x * (1.0f - x); + tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x; + if (Math.abs(tx - alpha) < 1E-5) break; + if (tx > alpha) x_max = x; + else x_min = x; + } + SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x; + + float y_max = 1.0f; + float y, dy; + while (true) { + y = y_min + (y_max - y_min) / 2.0f; + coef = 3.0f * y * (1.0f - y); + dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y; + if (Math.abs(dy - alpha) < 1E-5) break; + if (dy > alpha) y_max = y; + else y_min = y; + } + SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y; + } + SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f; + + // This controls the viscous fluid effect (how much of it) + sViscousFluidScale = 8.0f; + // must be set to 1.0 (used in viscousFluid()) + sViscousFluidNormalize = 1.0f; + sViscousFluidNormalize = 1.0f / viscousFluid(1.0f); + + } + + private static float sViscousFluidScale; + private static float sViscousFluidNormalize; + + /** + * Create a Scroller with the default duration and interpolator. + */ + public Scroller(Context context) { + this(context, null); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. "Flywheel" behavior will + * be in effect for apps targeting Honeycomb or newer. + */ + public Scroller(Context context, Interpolator interpolator) { + this(context, interpolator, + context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. Specify whether or + * not to support progressive "flywheel" behavior in flinging. + */ + public Scroller(Context context, Interpolator interpolator, boolean flywheel) { + mFinished = true; + mInterpolator = interpolator; + mPpi = context.getResources().getDisplayMetrics().density * 160.0f; + mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction()); + mFlywheel = flywheel; + + mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning + } + + /** + * The amount of friction applied to flings. The default value + * is {@link ViewConfiguration#getScrollFriction}. + * + * @param friction A scalar dimension-less value representing the coefficient of + * friction. + */ + public final void setFriction(float friction) { + mDeceleration = computeDeceleration(friction); + mFlingFriction = friction; + } + + private float computeDeceleration(float friction) { + return SensorManager.GRAVITY_EARTH // g (m/s^2) + * 39.37f // inch/meter + * mPpi // pixels per inch + * friction; + } + + /** + * + * Returns whether the scroller has finished scrolling. + * + * @return True if the scroller has finished scrolling, false otherwise. + */ + public final boolean isFinished() { + return mFinished; + } + + /** + * Force the finished field to a particular value. + * + * @param finished The new finished value. + */ + public final void forceFinished(boolean finished) { + mFinished = finished; + } + + /** + * Returns how long the scroll event will take, in milliseconds. + * + * @return The duration of the scroll in milliseconds. + */ + public final int getDuration() { + return mDuration; + } + + /** + * Returns the current X offset in the scroll. + * + * @return The new X offset as an absolute distance from the origin. + */ + public final int getCurrX() { + return mCurrX; + } + + /** + * Returns the current Y offset in the scroll. + * + * @return The new Y offset as an absolute distance from the origin. + */ + public final int getCurrY() { + return mCurrY; + } + + /** + * Returns the current velocity. + * + * @return The original velocity less the deceleration. Result may be + * negative. + */ + public float getCurrVelocity() { + return mMode == FLING_MODE ? + mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f; + } + + /** + * Returns the start X offset in the scroll. + * + * @return The start X offset as an absolute distance from the origin. + */ + public final int getStartX() { + return mStartX; + } + + /** + * Returns the start Y offset in the scroll. + * + * @return The start Y offset as an absolute distance from the origin. + */ + public final int getStartY() { + return mStartY; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final X offset as an absolute distance from the origin. + */ + public final int getFinalX() { + return mFinalX; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final Y offset as an absolute distance from the origin. + */ + public final int getFinalY() { + return mFinalY; + } + + /** + * Call this when you want to know the new location. If it returns true, + * the animation is not yet finished. + */ + public boolean computeScrollOffset() { + if (mFinished) { + return false; + } + + int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); + + if (timePassed < mDuration) { + switch (mMode) { + case SCROLL_MODE: + float x = timePassed * mDurationReciprocal; + + if (mInterpolator == null) + x = viscousFluid(x); + else + x = mInterpolator.getInterpolation(x); + + mCurrX = mStartX + Math.round(x * mDeltaX); + mCurrY = mStartY + Math.round(x * mDeltaY); + break; + case FLING_MODE: + final float t = (float) timePassed / mDuration; + final int index = (int) (NB_SAMPLES * t); + float distanceCoef = 1.f; + float velocityCoef = 0.f; + if (index < NB_SAMPLES) { + final float t_inf = (float) index / NB_SAMPLES; + final float t_sup = (float) (index + 1) / NB_SAMPLES; + final float d_inf = SPLINE_POSITION[index]; + final float d_sup = SPLINE_POSITION[index + 1]; + velocityCoef = (d_sup - d_inf) / (t_sup - t_inf); + distanceCoef = d_inf + (t - t_inf) * velocityCoef; + } + + mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f; + + mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX)); + // Pin to mMinX <= mCurrX <= mMaxX + mCurrX = Math.min(mCurrX, mMaxX); + mCurrX = Math.max(mCurrX, mMinX); + + mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY)); + // Pin to mMinY <= mCurrY <= mMaxY + mCurrY = Math.min(mCurrY, mMaxY); + mCurrY = Math.max(mCurrY, mMinY); + + if (mCurrX == mFinalX && mCurrY == mFinalY) { + mFinished = true; + } + + break; + } + } + else { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + return true; + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * The scroll will use the default value of 250 milliseconds for the + * duration. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + */ + public void startScroll(int startX, int startY, int dx, int dy) { + startScroll(startX, startY, dx, dy, DEFAULT_DURATION); + } + + /** + * Start scrolling by providing a starting point, the distance to travel, + * and the duration of the scroll. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + * @param duration Duration of the scroll in milliseconds. + */ + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + mMode = SCROLL_MODE; + mFinished = false; + mDuration = duration; + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + mFinalX = startX + dx; + mFinalY = startY + dy; + mDeltaX = dx; + mDeltaY = dy; + mDurationReciprocal = 1.0f / (float) mDuration; + } + + /** + * Start scrolling based on a fling gesture. The distance travelled will + * depend on the initial velocity of the fling. + * + * @param startX Starting point of the scroll (X) + * @param startY Starting point of the scroll (Y) + * @param velocityX Initial velocity of the fling (X) measured in pixels per + * second. + * @param velocityY Initial velocity of the fling (Y) measured in pixels per + * second + * @param minX Minimum X value. The scroller will not scroll past this + * point. + * @param maxX Maximum X value. The scroller will not scroll past this + * point. + * @param minY Minimum Y value. The scroller will not scroll past this + * point. + * @param maxY Maximum Y value. The scroller will not scroll past this + * point. + */ + public void fling(int startX, int startY, int velocityX, int velocityY, + int minX, int maxX, int minY, int maxY) { + // Continue a scroll or fling in progress + if (mFlywheel && !mFinished) { + float oldVel = getCurrVelocity(); + + float dx = (float) (mFinalX - mStartX); + float dy = (float) (mFinalY - mStartY); + float hyp = (float) Math.sqrt(dx * dx + dy * dy); + + float ndx = dx / hyp; + float ndy = dy / hyp; + + float oldVelocityX = ndx * oldVel; + float oldVelocityY = ndy * oldVel; + if (Math.signum(velocityX) == Math.signum(oldVelocityX) && + Math.signum(velocityY) == Math.signum(oldVelocityY)) { + velocityX += oldVelocityX; + velocityY += oldVelocityY; + } + } + + mMode = FLING_MODE; + mFinished = false; + + float velocity = (float) Math.sqrt(velocityX * velocityX + velocityY * velocityY); + + mVelocity = velocity; + mDuration = getSplineFlingDuration(velocity); + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + + float coeffX = velocity == 0 ? 1.0f : velocityX / velocity; + float coeffY = velocity == 0 ? 1.0f : velocityY / velocity; + + double totalDistance = getSplineFlingDistance(velocity); + mDistance = (int) (totalDistance * Math.signum(velocity)); + + mMinX = minX; + mMaxX = maxX; + mMinY = minY; + mMaxY = maxY; + + mFinalX = startX + (int) Math.round(totalDistance * coeffX); + // Pin to mMinX <= mFinalX <= mMaxX + mFinalX = Math.min(mFinalX, mMaxX); + mFinalX = Math.max(mFinalX, mMinX); + + mFinalY = startY + (int) Math.round(totalDistance * coeffY); + // Pin to mMinY <= mFinalY <= mMaxY + mFinalY = Math.min(mFinalY, mMaxY); + mFinalY = Math.max(mFinalY, mMinY); + } + + private double getSplineDeceleration(float velocity) { + return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff)); + } + + private int getSplineFlingDuration(float velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return (int) (1000.0 * Math.exp(l / decelMinusOne)); + } + + private double getSplineFlingDistance(float velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l); + } + + static float viscousFluid(float x) + { + x *= sViscousFluidScale; + if (x < 1.0f) { + x -= (1.0f - (float) Math.exp(-x)); + } else { + float start = 0.36787944117f; // 1/e == exp(-1) + x = 1.0f - (float) Math.exp(1.0f - x); + x = start + x * (1.0f - start); + } + x *= sViscousFluidNormalize; + return x; + } + + /** + * Stops the animation. Contrary to {@link #forceFinished(boolean)}, + * aborting the animating cause the scroller to move to the final x and y + * position + * + * @see #forceFinished(boolean) + */ + public void abortAnimation() { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + + /** + * Extend the scroll animation. This allows a running animation to scroll + * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. + * + * @param extend Additional time to scroll in milliseconds. + * @see #setFinalX(int) + * @see #setFinalY(int) + */ + public void extendDuration(int extend) { + int passed = timePassed(); + mDuration = passed + extend; + mDurationReciprocal = 1.0f / mDuration; + mFinished = false; + } + + /** + * Returns the time elapsed since the beginning of the scrolling. + * + * @return The elapsed time in milliseconds. + */ + public int timePassed() { + return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); + } + + /** + * Sets the final position (X) for this scroller. + * + * @param newX The new X offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalY(int) + */ + public void setFinalX(int newX) { + mFinalX = newX; + mDeltaX = mFinalX - mStartX; + mFinished = false; + } + + /** + * Sets the final position (Y) for this scroller. + * + * @param newY The new Y offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalX(int) + */ + public void setFinalY(int newY) { + mFinalY = newY; + mDeltaY = mFinalY - mStartY; + mFinished = false; + } + + /** + * @hide + */ + public boolean isScrollingInDirection(float xvel, float yvel) { + return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) && + Math.signum(yvel) == Math.signum(mFinalY - mStartY); + } +} + diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimebarTick.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimebarTick.java new file mode 100644 index 0000000..47b2097 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimebarTick.java @@ -0,0 +1,103 @@ +/* + * This source code is licensed under the MIT-style license found in the + * LICENSE file in the root directory of this source tree. + */ +package com.lechange.demo.localvideo.timeshaftbar; + +/** + * 时间轴显示的等级 + */ +public class TimebarTick { + /** + * 时间轴总长度 + */ + private long viewLength; + + /** + * 时间轴未缩放时的标准长度 + */ + private long standardViewLength; + + /** + * 间隔距离 + */ + private float intervel; + + + /** + * 时间轴未缩放时的屏幕显示的时间(秒) + */ + private int totalSecondsInOneScreen; + + /** + * 时间轴中大刻度之间的时间间隔(秒) + */ + private int maxTickInSecond; + + /** + * 时间轴中小刻度之间的时间间隔(秒) + */ + private int minTickInSecond; + + /** + * 刻度显示的格式 + */ + private String dataPattern; + + public long getViewLength() { + return viewLength; + } + + public void setViewLength(long viewLength) { + this.viewLength = viewLength; + } + + public int getTotalSecondsInOneScreen() { + return totalSecondsInOneScreen; + } + + public void setTotalSecondsInOneScreen(int totalSecondsInOneScreen) { + this.totalSecondsInOneScreen = totalSecondsInOneScreen; + } + + public int getMaxTickInSecond() { + return maxTickInSecond; + } + + public void setMaxTickInSecond(int maxTickInSecond) { + this.maxTickInSecond = maxTickInSecond; + } + + public int getMinTickInSecond() { + return minTickInSecond; + } + + public void setMinTickInSecond(int minTickInSecond) { + this.minTickInSecond = minTickInSecond; + } + + public String getDataPattern() { + return dataPattern; + } + + public void setDataPattern(String dataPattern) { + this.dataPattern = dataPattern; + } + + public long getStandardViewLength() { + return standardViewLength; + } + + public void setStandardViewLength(long standardViewLength) { + this.standardViewLength = standardViewLength; + this.viewLength = this.standardViewLength; + } + + public void setIntervel(float intervel) { + this.intervel = intervel; + } + + public float getIntervel() { + return intervel; + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftBar.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftBar.java new file mode 100644 index 0000000..278d776 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftBar.java @@ -0,0 +1,731 @@ +package com.lechange.demo.localvideo.timeshaftbar; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +/** + * 项目名称:EZUIKitDemo + * 类描述:回放时间轴 + * 创建人:dingwei3 + * 创建时间:2017/4/12 14:03 + * 修改人:dingwei3 + * 修改时间:2017/4/12 14:03 + * 修改备注: + */ +public class TimerShaftBar extends View implements TimerShaftInterface { + private static final String TAG = "TimerShaftBar"; + /** + * Touch默认模式 + */ + private final static int TOUCH_MODE_NONE = 0; + /** + * 滑动事件 + */ + private final static int TOUCH_MODE_SCROLLER = 1; + /** + * 缩放事件 + */ + private final static int TOUCH_MODE_SCALE = 2; + /** + * 滑动FlING事件 + */ + private final static int TOUCH_MODE_SCROLLER_FlING = 3; + private Context mContext; + /** + * 手势事件处理 + */ + private GestureDetector mGestureDetector; + /** + * 缩放手势事件处理 + */ + private ScaleGestureDetector mScaleGestureDetector; + /** + * 手势事件模式 + */ + private int mTouchMode = TOUCH_MODE_NONE; + + + /** + * 滑动处理 + */ + private LayoutController mLayoutController; + /** + * 是否触摸屏幕 + */ + private boolean isTouchScreent = false; + /** + * 组件屏幕上现实的宽度 + */ + private int mWidth; + /** + * 组件屏幕上现实的高度 + */ + private int mHeight; + /** + * + */ + private TimebarTick mTimebarTick; + + /** + * 绘制时间轴起始时间 + */ + private Calendar mStartCalendar; + /** + * 绘制时间轴结束时间 + */ + private Calendar mEndCalendar; + + /** + * 绘制时间轴总时长(秒) + */ + private long TOTOAL_TIME = 24 * 60 * 60L; + /** + * 时间刻度画笔 + */ + private Paint mTextPaint = new Paint(); + + /** + * 当前时间刻度画笔 + */ + private Paint mCurrentTimeLinePaint = new Paint(); + /** + * 时间区域画笔 + */ + private Paint mTimeRegionPaint = new Paint(); + + /** + * 时间轴区域背景画笔 + */ + private Paint mBackParint = new Paint(); + /** + * 当前时间画笔 + */ + private Paint mCurrentTimePaint = new Paint(); + /** + * 时间轴与上边距间距 + */ + private int mTop; + + /** + * 播放时间显示区域高度 + */ + private int mCurrentTimeTextHeight; + + private Paint.FontMetrics mFontMetrics; + + private ArrayList mTimebarTicks = new ArrayList(); + private ArrayList mTimeShaftItems = new ArrayList<>(); + + /** + * 对比起始位置的时间(秒) + */ + private int mCurrentSecond; + + /** + * 组件当前位置 + */ + private int mCurrentPosition; + + /** + * 单位距离(每秒) + */ + private float mPixelsPerSecond = 0; + + /** + * 当前屏幕位置的起始秒数 + */ + private long mStartSecondOnScreen; + /** + * 当前屏幕位置的结束秒数 + */ + private long mEndSecondOnScreen; + + private TimerShaftBarListener mTimerShaftBarListener; + + /** + * 大刻度绘线绘制高度 + */ + private int mMaxScaleHeight; + + /** + * 中刻度绘线绘制高度 + */ + private int mMidScaleHeight; + + /** + * 小刻度绘线绘制高度 + */ + private int mMinScaleHeight; + + /** + * 刻度显示字体大小 + */ + private int mScaleTextSize = 10; + + /** + * 当前时间显示字体大小 + */ + private int mCurrentScaleTextSize = 10; + + /** + * 刻度显示字体高度 + */ + private int mScaleTextHeight; + + /** + * 绘制包含时间区域的颜色 + */ + private int mRegionCloudBackColor = 0xFFFF0606; + + /** + * 绘制包含时间区域的颜色 + */ + private int mRegionLocalBackColor = 0xFFFF0606; + + + /** + * 刻度已经时间显示字体颜色 + */ + private int mTextColor = 0xFF888888; + + /** + * 绘制时间轴区域的颜色 + */ + private int mBackColor = 0xFFF5F5F5; + + /** + * 绘制当前时间轴区域的颜色 + */ + private int mCurrentTimeLineColor = 0xFFF7AC00; + + /** + * 当前时间calendar + */ + private Calendar mPositonCalendar; + + /** + * 更具播放器进度显示当前位置 + */ + private boolean isRefereshPlayTimeWithPlayer = false; + + + public TimerShaftBar(Context context) { + super(context); + mContext = context; + init(); + } + + + public TimerShaftBar(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + mContext = context; + init(); + } + + private static int dip2px(Context context, float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + /** + * 设置时间轴事件监听 + * + * @param timerShaftBarListener + */ + @Override + public void setTimerShaftLayoutListener(TimerShaftBarListener timerShaftBarListener) { + mTimerShaftBarListener = timerShaftBarListener; + } + + /** + * 设置绘制区域 + * + * @param timeShaftItems 绘制区域item + */ + public void setTimeShaftItems(ArrayList timeShaftItems) { + /*if (mTimeShaftItems.size() != 0) { + mTimeShaftItems.clear(); + }*/ + mTimeShaftItems = timeShaftItems; + if (mTimeShaftItems != null && mTimeShaftItems.size() > 0) { + Calendar calendar = mTimeShaftItems.get(0).getStartCalendar(); + mStartCalendar = (Calendar) calendar.clone(); + + calendar = mTimeShaftItems.get(mTimeShaftItems.size() - 1).getEndCalendar(); + mEndCalendar = (Calendar) calendar.clone(); + mEndCalendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1); + initCalendar(); + } + initTimebarTicks(); + } + + /** + * 设置时间轴是否根据接受外部播放进度,当播放成功是需要调用设置用来刷新播放时间 + */ + @Override + public void setRefereshPlayTimeWithPlayer() { + isRefereshPlayTimeWithPlayer = true; + } + + /** + * 设置播放当前时间 + * + * @param calendar + */ + @Override + public void setPlayCalendar(Calendar calendar) { + Log.i("setPlayCalendar", calendar.getTime().toString()); + if (!mLayoutController.computeScrollOffset() && !isTouchScreent && isRefereshPlayTimeWithPlayer) { + mPositonCalendar = (Calendar) calendar.clone(); + mCurrentSecond = (int) ((mPositonCalendar.getTimeInMillis() - mStartCalendar.getTimeInMillis()) / 1000); + mLayoutController.setPosition((int) (mCurrentSecond * mPixelsPerSecond)); + invalidate(); + } + } + + /** + * 初始化时间轴显示的等级 + */ + private void initTimebarTicks() { + if (mTimebarTicks.size() <= 0) { + TimebarTick timebarTick1 = new TimebarTick(); + timebarTick1.setTotalSecondsInOneScreen(24 * 60 * 60); + timebarTick1.setMaxTickInSecond(4 * 60 * 60); + timebarTick1.setMinTickInSecond(60 * 60); + timebarTick1.setDataPattern("HH:mm"); + timebarTick1.setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) timebarTick1.getTotalSecondsInOneScreen()))); + + TimebarTick timebarTick2 = new TimebarTick(); + timebarTick2.setTotalSecondsInOneScreen(18 * 60 * 60); + timebarTick2.setMaxTickInSecond(2 * 60 * 60); + timebarTick2.setMinTickInSecond(30 * 60); + timebarTick2.setDataPattern("HH:mm"); + timebarTick2.setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) timebarTick2.getTotalSecondsInOneScreen()))); + + TimebarTick timebarTick3 = new TimebarTick(); + timebarTick3.setTotalSecondsInOneScreen(8 * 60 * 60); + timebarTick3.setMaxTickInSecond(60 * 60); + timebarTick3.setMinTickInSecond(12 * 60); + timebarTick3.setDataPattern("HH:mm"); + timebarTick3.setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) timebarTick3.getTotalSecondsInOneScreen()))); + + TimebarTick timebarTick4 = new TimebarTick(); + timebarTick4.setTotalSecondsInOneScreen(3 * 30 * 60); + timebarTick4.setMaxTickInSecond(10 * 60); + timebarTick4.setMinTickInSecond(2 * 60); + timebarTick4.setDataPattern("HH:mm"); + timebarTick4.setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) timebarTick4.getTotalSecondsInOneScreen()))); + + TimebarTick timebarTick5 = new TimebarTick(); + timebarTick5.setTotalSecondsInOneScreen(30 * 60); + timebarTick5.setMaxTickInSecond(10 * 60); + timebarTick5.setMinTickInSecond(2 * 60); + timebarTick5.setDataPattern("HH:mm"); + timebarTick5.setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) timebarTick5.getTotalSecondsInOneScreen()))); + + mTimebarTicks.add(timebarTick5); + mTimebarTicks.add(timebarTick4); + mTimebarTicks.add(timebarTick3); + mTimebarTicks.add(timebarTick2); + mTimebarTicks.add(timebarTick1); + } else { + for (int i = 0; i < mTimebarTicks.size(); i++) { + mTimebarTicks.get(i).setStandardViewLength(((long) ((double) mWidth * TOTOAL_TIME / (double) mTimebarTicks.get(i).getTotalSecondsInOneScreen()))); + } + } + setTimebarScaleIndex(1, 0); + + } + + private void setTimebarScaleIndex(int position, int length) { + mTimebarTick = mTimebarTicks.get(position); + if (length <= 0) { + mTimebarTick.setViewLength(mTimebarTick.getStandardViewLength()); + mLayoutController.setLayoutSize(mWidth, mHeight, (int) mTimebarTick.getViewLength()); + } else { + mTimebarTick.setViewLength(length); + mLayoutController.setLayoutSize(mWidth, mHeight, length); + } + mPixelsPerSecond = mTimebarTick.getViewLength() / (float) TOTOAL_TIME; + Log.d(TAG, "pixelsPerSecond = " + mPixelsPerSecond); + mLayoutController.setPosition((int) (mCurrentSecond * mPixelsPerSecond)); + invalidate(); + } + + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + Log.d(TAG, "onSizeChanged"); + mWidth = w; + mHeight = h; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mWidth == 0) { + mWidth = MeasureSpec.getSize(widthMeasureSpec); + mHeight = MeasureSpec.getSize(widthMeasureSpec); + initTimebarTicks(); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private void init() { + initCalendar(); + mMaxScaleHeight = dip2px(mContext, 12); + mMidScaleHeight = dip2px(mContext, 7); + mMinScaleHeight = dip2px(mContext, 5); + + //编辑起始时间绘制 + mTextPaint.setColor(mTextColor); + mTextPaint.setTextSize(dip2px(mContext, mScaleTextSize)); + mFontMetrics = mTextPaint.getFontMetrics();// 得到系统默认字体属性 + mScaleTextHeight = (int) (mFontMetrics.bottom - mFontMetrics.top); + + //编辑当前时间绘制 + mCurrentTimePaint.setColor(mTextColor); + mCurrentTimePaint.setTextSize(dip2px(mContext, mCurrentScaleTextSize)); + mFontMetrics = mTextPaint.getFontMetrics();// 得到系统默认字体属性 + mCurrentTimeTextHeight = (int) (mFontMetrics.bottom - mFontMetrics.top); + mTop = mCurrentTimeTextHeight + dip2px(mContext, 10); + mBackParint.setColor(mBackColor); + mCurrentTimeLinePaint = new Paint(); + mCurrentTimeLinePaint.setColor(mCurrentTimeLineColor); + mLayoutController = new LayoutController(mContext); + mScaleGestureDetector = new ScaleGestureDetector(mContext, new ScaleGestureDetector.OnScaleGestureListener() { + @Override + public boolean onScale(ScaleGestureDetector detector) { + Log.d(TAG, "onScale detector = " + detector.getScaleFactor()); + scaleTimebar(detector.getScaleFactor() * (1 + (detector.getScaleFactor() - 1) * 1.2f)); + return true; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + Log.d(TAG, "onScaleBegin detector = " + detector.getScaleFactor()); + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + Log.d(TAG, "onScaleEnd = " + detector.getScaleFactor()); + } + }); + mGestureDetector = new GestureDetector(mContext, new GestureDetector.OnGestureListener() { + @Override + public boolean onDown(MotionEvent e) { + Log.d(TAG, "GestureDetector onDown "); + return false; + } + + @Override + public void onShowPress(MotionEvent e) { + Log.d(TAG, "GestureDetector onShowPress "); + } + + @Override + public boolean onSingleTapUp(MotionEvent e) { + Log.d(TAG, "GestureDetector onSingleTapUp "); + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + Log.d(TAG, "GestureDetector onScroll "); + if (mTouchMode == TOUCH_MODE_SCROLLER) { + isRefereshPlayTimeWithPlayer = false; + mLayoutController.startScroll(Math.round(distanceX), 0, mLayoutController.getScrollLimit()); + invalidate(); + } + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + Log.d(TAG, "GestureDetector onLongPress "); + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + Log.d(TAG, "GestureDetector onFling "); + if (mTouchMode == TOUCH_MODE_SCROLLER) { + int scrollLimit = mLayoutController.getScrollLimit(); + if (scrollLimit == 0) + return false; + mLayoutController.fling((int) (-velocityX), 0, scrollLimit); + invalidate(); + } + return true; + } + }); + } + + private void initCalendar() { + if (mStartCalendar == null) { + mStartCalendar = Calendar.getInstance(); + mStartCalendar.set(Calendar.DATE, mStartCalendar.get(Calendar.DATE)); + } + if (mEndCalendar == null) { + mEndCalendar = (Calendar) mStartCalendar.clone(); + mEndCalendar.set(Calendar.DATE, mEndCalendar.get(Calendar.DATE) + 1); + } + mStartCalendar.set(Calendar.HOUR_OF_DAY, 0); + mStartCalendar.set(Calendar.MINUTE, 0); + mStartCalendar.set(Calendar.SECOND, 0); + + mEndCalendar.set(Calendar.HOUR_OF_DAY, 0); + mEndCalendar.set(Calendar.MINUTE, 0); + mEndCalendar.set(Calendar.SECOND, 0); + mPositonCalendar = (Calendar) mStartCalendar.clone(); + TOTOAL_TIME = (mEndCalendar.getTimeInMillis() - mStartCalendar.getTimeInMillis()) / 1000; + } + + @Override + protected void onDraw(Canvas canvas) { + long b = System.currentTimeMillis(); + boolean ret = mLayoutController.computeScrollOffset(); + + mCurrentPosition = mLayoutController.getPosition(); + //算开始时缩放时不重新获取当前播放时间 + // mCurrentSecond = (int) ((mCurrentPosition) * TOTOAL_TIME / mTimebarTick.getViewLength()); + if (mTouchMode == TOUCH_MODE_SCROLLER) { + mCurrentSecond = (int) (mCurrentPosition / mPixelsPerSecond); + } + drawBack(canvas); + drawScale(canvas); + drawRegionRect(canvas); + drawCurrentPositionLine(canvas); + drawCurrentTime(canvas); + Log.d(TAG, "onDraw position = " + mCurrentSecond + " computeScrollOffset = " + ret); + if (ret) { + invalidate(); + } else { + if (mTouchMode == TOUCH_MODE_SCROLLER) { + Log.d(TAG, "isTouchScreent = " + isTouchScreent); + if (!isTouchScreent) { + mTouchMode = TOUCH_MODE_NONE; + } + mPositonCalendar.setTimeInMillis(mStartCalendar.getTimeInMillis() + mCurrentSecond * 1000); + if (mTimerShaftBarListener != null) { + mTimerShaftBarListener.onTimerShaftBarPosChanged(mPositonCalendar); + } + } + if (mTouchMode == TOUCH_MODE_SCALE && !isTouchScreent) { + mTouchMode = TOUCH_MODE_NONE; + } + } + Log.d(TAG, "on draw time = " + String.valueOf(System.currentTimeMillis() - b)); + } + + /** + * 绘制当前时间 + * + * @param canvas + */ + private void drawCurrentTime(Canvas canvas) { + if (mTouchMode == TOUCH_MODE_SCROLLER || mLayoutController.computeScrollOffset()) { + mPositonCalendar.setTimeInMillis(mStartCalendar.getTimeInMillis() + mCurrentSecond * 1000); + } + String text = getTime(mPositonCalendar.getTimeInMillis(), "yyyy-MM-dd HH:mm:ss"); + canvas.drawText(text, mWidth / 2 - mCurrentTimePaint.measureText(text) / 2, mCurrentTimeTextHeight, mCurrentTimePaint); + } + + /** + * 绘制当前时间 + * k + * + * @param canvas + */ + private void drawBack(Canvas canvas) { + canvas.drawRect(new Rect(0, mTop, mWidth, getHeight()), mBackParint); + } + + /** + * 绘制标尺 + * + * @param canvas + */ + private void drawScale(Canvas canvas) { + long b = System.currentTimeMillis(); + canvas.drawLine(0, mTop, mWidth, mTop, mTextPaint); + canvas.drawLine(0, getHeight() - 1, mWidth, getHeight() - 1, mTextPaint); + + mStartSecondOnScreen = (long) ((mCurrentPosition - mLayoutController.getPaddingLeft()) / mPixelsPerSecond); + mEndSecondOnScreen = (long) (mStartSecondOnScreen + mWidth / mPixelsPerSecond); + + Log.d(TAG, "onDraw startTikeStart = " + mStartSecondOnScreen); + Log.d(TAG, "onDraw endTikeStart = " + mEndSecondOnScreen); + if (mEndSecondOnScreen > TOTOAL_TIME) { + mEndSecondOnScreen = TOTOAL_TIME; + } + for (long i = mStartSecondOnScreen - 20; i < mEndSecondOnScreen + 20; i++) { + if (i < 0 || i > TOTOAL_TIME) { + continue; + } + long startX = (long) ((i - mStartSecondOnScreen) * mPixelsPerSecond); + if (i % (60 * 60) == 0) { + canvas.drawLine(startX, mTop, startX, mTop + mMaxScaleHeight, mTextPaint); + canvas.drawLine(startX, getHeight() - mMaxScaleHeight, startX, getHeight(), mTextPaint); + } + if (i % mTimebarTick.getMaxTickInSecond() == 0) { + if (i % (60 * 60) != 0) { + canvas.drawLine(startX, mTop, startX, mTop + mMidScaleHeight, mTextPaint); + canvas.drawLine(startX, getHeight() - mMidScaleHeight, startX, getHeight(), mTextPaint); + String timeText = getTime((i * 1000l + mStartCalendar.getTimeInMillis()), mTimebarTick.getDataPattern()); + canvas.drawText(timeText, startX - mTextPaint.measureText(timeText) / 2, mTop + mMidScaleHeight + mScaleTextHeight / 2 + dip2px(mContext, 10), mTextPaint); + } else { + String timeText = getTime((i * 1000l + mStartCalendar.getTimeInMillis()), mTimebarTick.getDataPattern()); + canvas.drawText(timeText, startX - mTextPaint.measureText(timeText) / 2, mTop + mMaxScaleHeight + mScaleTextHeight / 2 + dip2px(mContext, 10), mTextPaint); + } + } else if (i % mTimebarTick.getMinTickInSecond() == 0) { + canvas.drawLine(startX, mTop, startX, mTop + mMinScaleHeight, mTextPaint); + canvas.drawLine(startX, getHeight() - mMinScaleHeight, startX, getHeight(), mTextPaint); + } + } + Log.d(TAG, "drawtime drawScale time = " + (System.currentTimeMillis() - b)); + } + + /** + * 绘制包含时间所在区域 + * + * @param canvas + */ + private void drawRegionRect(Canvas canvas) { + if (mTimeShaftItems != null) { + long b = System.currentTimeMillis(); + for (int y = 0; y < mTimeShaftItems.size(); y++) { + TimerShaftRegionItem timeShaftItem = mTimeShaftItems.get(y); + if (timeShaftItem.getEndCalendar().getTimeInMillis() - mStartCalendar.getTimeInMillis() - mStartSecondOnScreen * 1000l < -10000) { + continue; + } + if (timeShaftItem.getStartCalendar().getTimeInMillis() - mStartCalendar.getTimeInMillis() - mEndSecondOnScreen * 1000l > 10000) { + continue; + } + int startTime = (int) ((timeShaftItem.getStartCalendar().getTimeInMillis() - mStartCalendar.getTimeInMillis()) / 1000); + int endTime = (int) ((timeShaftItem.getEndCalendar().getTimeInMillis() - mStartCalendar.getTimeInMillis()) / 1000); + int startX = (int) ((startTime - mStartSecondOnScreen) * mPixelsPerSecond); + int endX = (int) ((endTime - mStartSecondOnScreen) * mPixelsPerSecond); + mTimeRegionPaint.setColor(mRegionCloudBackColor); + /*if (timeShaftItem.getRecType() == 1) { + //云存储 + mTimeRegionPaint.setColor(mRegionCloudBackColor); + } else if (timeShaftItem.getRecType() == 2) { + //本地录像 + mTimeRegionPaint.setColor(mRegionLocalBackColor); + + }*/ + canvas.drawRect(new Rect(startX, mTop, endX, getHeight()), mTimeRegionPaint); + } + Log.d(TAG, "drawtime drawRegionRect time = " + (System.currentTimeMillis() - b)); + } + } + + /** + * 绘制标示当前位置的线 + * + * @param canvas + */ + private void drawCurrentPositionLine(Canvas canvas) { + long b = System.currentTimeMillis(); + //绘制中心线 + canvas.drawRect(new Rect(mWidth / 2 - dip2px(mContext, 0.5f), mTop, mWidth / 2 + dip2px(mContext, 0.5f), getHeight()), mCurrentTimeLinePaint); + Path path = new Path(); + path.moveTo(mWidth / 2 - dip2px(mContext, 4), mTop);// 此点为多边形的起点 + path.lineTo(mWidth / 2 + dip2px(mContext, 4), mTop); + path.lineTo(mWidth / 2, dip2px(mContext, 5) + mTop); + path.close(); // 使这些点构成封闭的多边形 + canvas.drawPath(path, mCurrentTimeLinePaint); + Log.d(TAG, "drawtime drawCurrentPositionLine time = " + (System.currentTimeMillis() - b)); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int actionType = event.getActionMasked(); + switch (actionType) { + case MotionEvent.ACTION_DOWN: + mTouchMode = TOUCH_MODE_SCROLLER; + isTouchScreent = true; + // 第一个点被按下 + // Toast.makeText(getContext(), "第一个点被按下", Toast.LENGTH_SHORT); + break; + case MotionEvent.ACTION_POINTER_DOWN: + // Toast.makeText(getContext(), "第一个点被按下", Toast.LENGTH_SHORT); + mTouchMode = TOUCH_MODE_SCALE; + isRefereshPlayTimeWithPlayer = true; + break; + case MotionEvent.ACTION_MOVE: + Log.d(TAG, "ACTION_MOVE "); + break; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP + " + !mLayoutController.computeScrollOffset()); + isTouchScreent = false; + if (mTouchMode == TOUCH_MODE_SCALE) { + isRefereshPlayTimeWithPlayer = true; + mTouchMode = TOUCH_MODE_NONE; + } + break; + } + mGestureDetector.onTouchEvent(event); + mScaleGestureDetector.onTouchEvent(event); + return true; + } + + private void scaleTimebar(float scaleFactor) { + int newWidth = (int) (mTimebarTick.getViewLength() * scaleFactor); + Log.d(TAG, "scaleTimebarByFactor mTimebarTick.getViewLength() = " + mTimebarTick.getViewLength() + " newWidth = " + newWidth); + if (newWidth >= mTimebarTicks.get(0).getStandardViewLength()) { + setTimebarScaleIndex(0, 0); + } else if (newWidth < mTimebarTicks.get(0).getStandardViewLength() && newWidth >= mTimebarTicks.get(1).getStandardViewLength()) { + setTimebarScaleIndex(1, newWidth); + } else if (newWidth < mTimebarTicks.get(1).getStandardViewLength() && newWidth >= mTimebarTicks.get(2).getStandardViewLength()) { + setTimebarScaleIndex(2, newWidth); + } else if (newWidth < mTimebarTicks.get(2).getStandardViewLength() && newWidth >= mTimebarTicks.get(3).getStandardViewLength()) { + setTimebarScaleIndex(3, newWidth); + } else if (newWidth < mTimebarTicks.get(3).getStandardViewLength() && newWidth >= mTimebarTicks.get(4).getStandardViewLength()) { + setTimebarScaleIndex(4, newWidth); + } else if (newWidth <= mTimebarTicks.get(4).getStandardViewLength()) { + setTimebarScaleIndex(4, 0); + } + } + + private String getTime(long duration, String formate) { + Date mDate = new Date(); + mDate.setTime(duration); + SimpleDateFormat mDateFormat = new SimpleDateFormat(formate, Locale.getDefault()); + return mDateFormat.format(mDate); + } + + /** + * 时间轴事件监听 + */ + public interface TimerShaftBarListener { + /** + * 当TimerShaftBar滑动时的通知 + * + * @param calendar 当前calendar + */ + void onTimerShaftBarPosChanged(Calendar calendar); + + /** + * 时间轴手指按下时触发 + */ + void onTimerShaftBarDown(); + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftInterface.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftInterface.java new file mode 100644 index 0000000..b32fb8c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftInterface.java @@ -0,0 +1,39 @@ +package com.lechange.demo.localvideo.timeshaftbar; + +import java.util.ArrayList; +import java.util.Calendar; + +/** + * 项目名称:EZUIKitDemo + * 类描述: + * 创建人:dingwei3 + * 创建时间:2017/5/2 15:15 + * 修改人:dingwei3 + * 修改时间:2017/5/2 15:15 + * 修改备注: + */ +public interface TimerShaftInterface { + + /** + * 设置时间轴事件监听 + * @param timerShaftBarListener + */ + void setTimerShaftLayoutListener(TimerShaftBar.TimerShaftBarListener timerShaftBarListener); + + /** + * 设置绘制区域 + * @param timeShaftItems 绘制区域item + */ + void setTimeShaftItems(ArrayList timeShaftItems); + + /** + * 设置时间轴是否根据接受外部播放进度,当播放成功时需要调用此方法,用来刷新播放时间进度 + */ + void setRefereshPlayTimeWithPlayer(); + + /** + * 设置播放当前时间 + * @param calendar + */ + void setPlayCalendar(Calendar calendar); +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftRegionItem.java b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftRegionItem.java new file mode 100644 index 0000000..3966da6 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/timeshaftbar/TimerShaftRegionItem.java @@ -0,0 +1,80 @@ +package com.lechange.demo.localvideo.timeshaftbar; + +import java.util.Calendar; + +/** + * 项目名称:EZUIKitDemo + * 类描述:时间轴显示的区域对象 + * 创建人:dingwei3 + * 创建时间:2017/4/20 14:28 + * 修改人:dingwei3 + * 修改时间:2017/4/20 14:28 + * 修改备注: + */ +public class TimerShaftRegionItem { + + /** + * 开始时间 + */ + private long mStartTime; + /** + * 结束时间 + */ + private long mEndTime; + + private Calendar mStartCalendar; + + private Calendar mEndCalendar; + + private int recType = 0; + + public TimerShaftRegionItem(long startTime, long endTime, int recType) { + mStartTime = startTime; + mEndTime = endTime; + mStartCalendar = Calendar.getInstance(); + mStartCalendar.setTimeInMillis(mStartTime); + mEndCalendar = Calendar.getInstance(); + mEndCalendar.setTimeInMillis(mEndTime); + this.recType = recType; + } + + public int getRecType() { + return recType; + } + + public void setRecType(int recType) { + this.recType = recType; + } + + public long getStartTime() { + return mStartTime; + } + + public void setStartTime(long startTime) { + mStartTime = startTime; + } + + public long getEndTime() { + return mEndTime; + } + + public void setEndTime(long endTime) { + mEndTime = endTime; + } + + public Calendar getStartCalendar() { + return mStartCalendar; + } + + public void setStartCalendar(Calendar startCalendar) { + mStartCalendar = startCalendar; + } + + public Calendar getEndCalendar() { + return mEndCalendar; + } + + public void setEndCalendar(Calendar endCalendar) { + mEndCalendar = endCalendar; + } +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/turnview/AXLog.java b/app/src/main/java/com/lechange/demo/localvideo/turnview/AXLog.java new file mode 100644 index 0000000..1770391 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/turnview/AXLog.java @@ -0,0 +1,249 @@ +package com.lechange.demo.localvideo.turnview; + + +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * Created by wzy on 15/11/27. + * 模仿logger,创建自己的日志操作类 + */ +public class AXLog { + public static final String TAG = AXLog.class.getSimpleName(); + /** + * 控制变量,是否显示log日志 + */ + public static boolean isShowLog = true; + public static String defaultMsg = ""; + public static final int V = 1; + public static final int D = 2; + public static final int I = 3; + public static final int W = 4; + public static final int E = 5; + + private static String logPath = null;//log日志存放路径 + + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US);//日期格式; + + private static Date date = new Date();//因为log日志是使用日期命名的,使用静态成员变量主要是为了在整个程序运行期间只存在一个.log文件中; + +// /** +// * 初始化,须在使用之前设置,最好在Application创建时调用 +// * +// * @param context +// */ +// public static void init(Context context) { +// logPath = getFilePath(context) + "/Logs";//获得文件储存路径,在后面加"/Logs"建立子文件夹 +// } + + /** + * 获得文件存储路径 + * + * @return + */ + private static String getFilePath(Context context) { + + if (Environment.MEDIA_MOUNTED.equals(Environment.MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {//如果外部储存可用 + return context.getExternalFilesDir(null).getPath();//获得外部存储路径,默认路径为 /storage/emulated/0/Android/data/com.waka.workspace.logtofile/files/Logs/log_2016-03-14_16-15-09.log + } else { + return context.getFilesDir().getPath();//直接存在/data/data里,非root手机是看不到的 + } + } + + /** + * 初始化控制变量 + * + * @param isShowLog + */ + public static void init(boolean isShowLog) { + AXLog.isShowLog = isShowLog; + } + + /** + * 初始化控制变量和默认日志 + * + * @param isShowLog + * @param defaultMsg + */ + public static void init(boolean isShowLog, String defaultMsg) { + AXLog.isShowLog = isShowLog; + AXLog.defaultMsg = defaultMsg; + } + + public static void v() { + llog(V, null, defaultMsg); + } + + public static void v(Object obj) { + llog(V, null, obj); + } + + public static void v(String tag, Object obj) { + llog(V, tag, obj); + } + + public static void d() { + llog(D, null, defaultMsg); + } + + public static void d(Object obj) { + llog(D, null, obj); + } + + public static void d(String tag, Object obj) { + llog(D, tag, obj); + } + + public static void i() { + llog(I, null, defaultMsg); + } + + public static void i(Object obj) { + llog(I, null, obj); + } + + public static void i(String tag, String obj) { + llog(I, tag, obj); + } + + public static void w() { + llog(W, null, defaultMsg); + } + + public static void w(Object obj) { + llog(W, null, obj); + } + + public static void w(String tag, Object obj) { + llog(W, tag, obj); + } + + public static void e() { + llog(E, null, defaultMsg); + } + + public static void e(Object obj) { + llog(E, null, obj); + } + + public static void e(String tag, Object obj) { + llog(E, tag, obj); + } + + + /** + * 执行打印方法 + * + * @param type + * @param tagStr + * @param obj + */ + public static void llog(int type, String tagStr, Object obj) { + String msg; + if (!isShowLog) { + return; + } + + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + + int index = 4; + String className = stackTrace[index].getFileName(); + String methodName = stackTrace[index].getMethodName(); + int lineNumber = stackTrace[index].getLineNumber(); + + String tag = (tagStr == null ? className : tagStr); + methodName = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("[ (").append(className).append(":").append(lineNumber).append(")#").append(methodName).append(" ] "); + + if (obj == null) { + msg = "Log with null Object"; + } else { + msg = obj.toString(); + } + if (msg != null) { + stringBuilder.append(msg); + } + + String logStr = stringBuilder.toString(); + + switch (type) { + case V: + Log.v(tag, logStr); + break; + case D: + Log.d(tag, logStr); + break; + case I: + Log.i(tag, logStr); + break; + case W: + Log.w(tag, logStr); + break; + case E: + Log.e(tag, logStr); + break; + } + } + + /** + * 将log信息写入文件中 + * + * @param type + * @param tag + * @param msg + */ + private static void writeToFile(char type, String tag, String msg) { + + if (null == logPath) { + Log.e(TAG, "logPath == null ,未初始化MLog"); + return; + } + + String fileName = logPath + "/log_" + dateFormat.format(new Date()) + ".log";//log日志名,使用时间命名,保证不重复 + String log = dateFormat.format(date) + " " + type + " " + tag + " " + msg + "\n";//log日志内容,可以自行定制 + + //如果父路径不存在 + File file = new File(logPath); + if (!file.exists()) { + file.mkdirs();//创建父路径 + } + + FileOutputStream fos = null;//FileOutputStream会自动调用底层的close()方法,不用关闭 + BufferedWriter bw = null; + try { + + fos = new FileOutputStream(fileName, true);//这里的第二个参数代表追加还是覆盖,true为追加,flase为覆盖 + bw = new BufferedWriter(new OutputStreamWriter(fos)); + bw.write(log); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bw != null) { + bw.close();//关闭缓冲流 + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/localvideo/turnview/OnValueChangeListener.java b/app/src/main/java/com/lechange/demo/localvideo/turnview/OnValueChangeListener.java new file mode 100644 index 0000000..6f52de6 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/turnview/OnValueChangeListener.java @@ -0,0 +1,10 @@ +package com.lechange.demo.localvideo.turnview; + +/** + * Created by Administrator on 2017/10/19. + */ + +public interface OnValueChangeListener { + public void onValueChange(float value); + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/turnview/RecordInfo.java b/app/src/main/java/com/lechange/demo/localvideo/turnview/RecordInfo.java new file mode 100644 index 0000000..0d35e6f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/turnview/RecordInfo.java @@ -0,0 +1,54 @@ +package com.lechange.demo.localvideo.turnview; + +public class RecordInfo { + + private long startTime; + private long endTime; + + private int startValue; + private int endValue; + + public int getStartValue() { + return startValue; + } + + public void setStartValue(int startValue) { + this.startValue = startValue; + } + + public int getEndValue() { + return endValue; + } + + public void setEndValue(int endValue) { + this.endValue = endValue; + } + + public RecordInfo() { + super(); + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return " startTime:" + startTime + " endTime:" + endTime + " startValue:" + startValue + " endValue:" + endValue; + } + + +} diff --git a/app/src/main/java/com/lechange/demo/localvideo/turnview/TunlView.java b/app/src/main/java/com/lechange/demo/localvideo/turnview/TunlView.java new file mode 100644 index 0000000..ee92526 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/localvideo/turnview/TunlView.java @@ -0,0 +1,646 @@ +package com.lechange.demo.localvideo.turnview; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.text.Layout; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import com.yonsz.z1.R; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +/** + * Created by Administrator on 2017/10/19. + */ + +public class TunlView extends View { + + /** + * 图片放大状态常量 + */ + public static final int STATUS_ZOOM_OUT = 1; + + /** + * 图片缩小状态常量 + */ + public static final int STATUS_ZOOM_IN = 2; + + /** + * 记录两指同时放在屏幕上时,中心点的横坐标值 + */ + private float centerPointX; + + /** + * 记录两指同时放在屏幕上时,中心点的纵坐标值 + */ + private float centerPointY; + + /** + * 记录按下两指之间的距离 + */ + private double lastFingerDis; + + /** + * 记录当前操作的状态,可选值为STATUS_ZOOM_OUT、STATUS_ZOOM_IN + */ + private int currentStatus; + + + private static final float TEXT_SIZE = 12; + + public int mWidth,mHeight,mlastX,mMove; + + int mValue; //当前时间轴中点所在得刻度尺value + + public static final float LINE_DIVIDER = 2.0f; //初始化每个刻度间距为2 + + float mLineDivider = LINE_DIVIDER ;//记录一刻度屏幕上得距离 + + static float lastItemDivider = LINE_DIVIDER;//缩放后一刻度得屏幕距离 + + private float mDensity; + private float ITEM_MAX_HEIGHT = 30; + private float ITEM_MIN_HEIGHT = 15; + private float textWidth; + + Calendar calendar1 = Calendar.getInstance(); + + List list = new ArrayList<>(); + private String[] timeString0 = {"00:00", "00:30", "01:00", "01:30", "02:00", "02:30", "03:00", "03:30", "04:00", "04:30", + "05:00", "05:30", "06:00", "06:30", "07:00", "07:30", "08:00", "08:30", "09:00", "09:30", "10:00", "10:30", + "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", + "17:00", "17:30", "18:00", "18:30", "19:00", "19:30", "20:00", "20:30", "21:00", "21:30", "22:00", "22:30", + "23:00", "23:30"}; + + private String[] timeString1 = {"00:00", "01:00", "02:00", "03:00", "04:00", + "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", + "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", + "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", + "23:00"}; + + private String[] timeString2 = {"00:00", "03:00", "06:00", "9:00", "12:00", "15:00","18:00","21:00"}; + + private String[] timeString3 = {"00:00", "12:00"}; + + private String[] timeString4 = {"00:00"}; + + public int Mode = Mode_1 ; // 当前的刻度尺缩放模式,默认模式一 + public static final int Mode_0 = 0; //模式一,当前刻度尺显示timeString0 + public static final int Mode_1 = 1; //模式一,当前刻度尺显示timeString1 + public static final int Mode_2 = 2; //模式一,当前刻度尺显示timeString2 + public static final int Mode_3 = 3; //模式一,当前刻度尺显示timeString3 + public static final int Mode_4 = 4; //模式一,当前刻度尺显示timeString4 + + /** + * 代表value值增加60,刻度尺对应多少(一个大刻度对应多少value) + * Mode_0代表半个小时 + * Mode_1代表1个小时 + * Mode_2代表3个小时 + * Mode_3代表12个小时 + * Mode_4代表24个小时 + */ + int largeScaleValue = 60; + + /** + * 代表value值增加10,刻度尺对应多少(一个小刻度对应多少value) + * Mode_0代表5分钟 + * Mode_1代表10分钟 + * Mode_2代表15分钟 + * Mode_3代表60分钟 + * Mode_4代表120分钟 + */ + int smallScaleValue = 10; + + public static int valueToSencond ; // 代表mvalue加1,刻度尺增加多少秒 + + private int REFRESH_TIME = valueToSencond*1000; + + public String[] useString; + + private float scaledRatio; + + private OnValueChangeListener mListener; + + public OnValueChangeListener getmListener() { + return mListener; + } + + public void setmListener(OnValueChangeListener mListener) { + this.mListener = mListener; + } + + Paint linePaint = new Paint(); + Paint shadowPaint = new Paint(); + + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + public TunlView(Context context) { + super(context); + } + + public TunlView(Context context, AttributeSet attrs) { + super(context, attrs); + + useString = timeString1; + valueToSencond = 60 ; //当选择timeString1时,mvlaue加一,刻度尺增加60秒 + + mDensity = getContext().getResources().getDisplayMetrics().density; + setBackgroundResource(R.drawable.bg_wheel); + + //过二十五秒让mValue自增一次,模拟在录像状态 + postDelayed(new Runnable() { + @Override + public void run() { + postDelayed(this, valueToSencond*1000); + mValue++; + postInvalidate(); + } + }, valueToSencond*1000); + + + initData(); + shadowPaint.setStyle(Paint.Style.FILL); + shadowPaint.setColor(Color.parseColor("#83D7DD")); + shadowPaint.setAlpha(101); + + } + + + public void initData() { + list.clear(); + mValue = getNowValue(); + + Date d = new Date(); + RecordInfo info1 = new RecordInfo(); + + + RecordInfo info2 = new RecordInfo(); + info2.setStartTime(d.getTime() - 60 * 60 * 1000 * 8); + info2.setEndTime(d.getTime() - 60 * 60 * 1000 * 7); + info2.setStartValue(getmValue(info2.getStartTime())); + info2.setEndValue(getmValue(info2.getEndTime())); + + info1.setStartTime(d.getTime() - 60 * 60 * 1000); + info1.setEndTime(d.getTime()); + // info1.setCurrentDate("2017-10-23"); + info1.setStartValue(getmValue(info1.getStartTime())); + info1.setEndValue(getmValue(info1.getEndTime())); + + list.add(info2); + list.add(info1); + + postDelayed(new Runnable() { + @Override + public void run() { + postDelayed(this, 60 * 1000); + RecordInfo info = new RecordInfo(); + info.setStartTime(System.currentTimeMillis() - 60 * 1000); + info.setEndTime(System.currentTimeMillis()); + info.setStartValue(getmValue(info.getStartTime())); + info.setEndValue(getmValue(info.getEndTime())); + AXLog.e("wzytest", "info.StartTime:" + info.getStartTime() + " info.getEndTime():" + info.getEndTime()); + addNoRepeatList(info); + postInvalidate(); + } + + }, 60 * 1000); + + } + + /** + * 时间轴在跑动,不能每秒都往录像list 增加一条录像, + * 判断如果前后录像文件时间戳相差不大于一秒,则代表录像时间相连, + * 并不往录像列表增加一条记录(为何不判断相等?) + * @param info + */ + private void addNoRepeatList(RecordInfo info) { + RecordInfo lastInfo = list.get(list.size() - 1); + if (info.getStartTime() - lastInfo.getEndTime() < 1000) { + AXLog.e("wzytest", "前一个数据的最后时间小于当前的开始时间不超过一秒"); + lastInfo.setEndTime(info.getEndTime()); + lastInfo.setEndValue(info.getEndValue()); + } else { + list.add(info); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + drawScaleLine(canvas); + drawMiddleLine(canvas); + drawShadow(canvas); + } + + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + mWidth = getWidth(); + mHeight = getHeight(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + + //划线 + public void drawScaleLine(Canvas canvas) { + linePaint.setStrokeWidth(2); + linePaint.setColor(Color.BLACK); + + textPaint.setTextSize(TEXT_SIZE * mDensity); + textPaint.setTextSize(16); + textWidth = Layout.getDesiredWidth("0", textPaint); + + int width = mWidth, drawCount = 0; + + float xPosition; + + for (int i = 0; drawCount < width * 2; i++) { + xPosition = (mWidth / 2 + mMove) + i * mDensity * (mLineDivider); + if (((mValue + i)) % largeScaleValue == 0) { + canvas.drawLine(xPosition, 0, xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint); + if ((((mValue + i)) / largeScaleValue % useString.length) < 0) { + canvas.drawText(useString[useString.length + (((mValue + i)) / largeScaleValue % useString.length)], countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint); + } else { + canvas.drawText(useString[((mValue + i)) / largeScaleValue % useString.length], countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint); + } + + } else { + if ((mValue + i) % smallScaleValue == 0) { + canvas.drawLine(xPosition, 0, xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint); + } + } + + xPosition = (mWidth / 2 + mMove) - i * mDensity * (mLineDivider); + if (( (mValue - i)) % largeScaleValue == 0) { + canvas.drawLine(xPosition, 0, xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint); + if ((( (mValue - i)) / largeScaleValue % useString.length) < 0) { + canvas.drawText(useString[useString.length + (((mValue - i)) / largeScaleValue % useString.length)], countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint); + } else { + canvas.drawText(useString[( (mValue - i)) / largeScaleValue % useString.length], countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint); + } + } else { + if ( (mValue - i) % smallScaleValue == 0) { + canvas.drawLine(xPosition, 0, xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint); + } + } + drawCount += mDensity * (mLineDivider); + + } + } + + public void drawShadow(Canvas canvas){ + float startXPosition ; + float endXPosition ; + // TODO: 2017/10/24 画阴影面积 + for (int j = 0; j < list.size(); j++) { + RecordInfo info = list.get(j); + int startvalue = info.getStartValue(); + int endvalue = info.getEndValue(); + + //获取当前得value + AXLog.e("wzytest","getNowValue:"+getNowValue() +"mvalue:"+mValue); + + startXPosition = mWidth/2 - (mValue-startvalue) * mDensity * (mLineDivider); + endXPosition = mWidth/2 + (endvalue-mValue) * mDensity * (mLineDivider); + + canvas.drawRect(startXPosition,0,endXPosition,mHeight,shadowPaint); + } + } + + /** + * 计算数字显示位置的辅助方法 + * + * @param value + * @param xPosition + * @param textWidth + * @return + */ + private float countLeftStart(int value, float xPosition, float textWidth) { + float xp; + xp = xPosition - (textWidth * 5 / 2); //从2.5个字开始写 + return xp; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + + int xPosition = (int) event.getX(); + int xMove; + switch (event.getActionMasked()) { + case MotionEvent.ACTION_POINTER_DOWN: + if (event.getPointerCount() == 2) { + // 当有两个手指按在屏幕上时,计算两指之间的距离 + lastFingerDis = distanceBetweenFingers(event); + } + break; + case MotionEvent.ACTION_DOWN: + mlastX = xPosition; + mMove = 0; + break; + case MotionEvent.ACTION_UP: + //当滑动到停止,改变当前刻度值 + xMove = (int) (mMove / (mLineDivider * mDensity)); + mValue -= xMove; + notifyValueChange(); + mMove = 0; + break; + case MotionEvent.ACTION_MOVE: + if (event.getPointerCount() == 1) { + mMove = xPosition - mlastX; + xMove = (int) (mMove / (mLineDivider * mDensity)); + mValue -= xMove; + notifyValueChange(); + invalidate(); + } else if (event.getPointerCount() == 2) { + // 有两个手指按在屏幕上移动时,为缩放状态 + centerPointBetweenFingers(event); + double fingerDis = distanceBetweenFingers(event); + + if (fingerDis > lastFingerDis) { + currentStatus = STATUS_ZOOM_OUT; + } else { + currentStatus = STATUS_ZOOM_IN; + } + + if(Mode==Mode_0&¤tStatus==STATUS_ZOOM_OUT||Mode==Mode_4&¤tStatus==STATUS_ZOOM_IN){ + AXLog.e("wzytest","Mode_0 时放大 和 Mode_4 时候缩小不做任何处理"); + }else{ + scaledRatio = (float) (fingerDis / lastFingerDis ); + shadowPaint.setStrokeWidth(6*scaledRatio); + mLineDivider = lastItemDivider * scaledRatio; //缩放后一刻度在屏幕上的距离 + } + + if(currentStatus==STATUS_ZOOM_IN&&Mode==Mode_0){ + if(2*mLineDividerLINE_DIVIDER){ + mLineDivider = 2; + lastItemDivider = 2; + useString = timeString3; + Mode = Mode_3; + valueToSencond = valueToSencond/2; + //重新获取当前value + mValue = getNowValue(); + //重新计算蓝色录像时间轴 + initData(); + } + }else if(currentStatus==STATUS_ZOOM_OUT&&Mode==Mode_3){ + if(mLineDivider/4>LINE_DIVIDER){ + mLineDivider = 2; + lastItemDivider = 2; + useString = timeString2; + Mode = Mode_2; + valueToSencond = valueToSencond/4; + AXLog.e("wzytest","mvalue:"+mValue); + //重新获取当前value + mValue = getNowValue(); + AXLog.e("wzytest","重新获取的value:"+mValue); + //重新计算蓝色录像时间轴 + initData(); + } + }else if(currentStatus==STATUS_ZOOM_OUT&&Mode==Mode_2){ + if(mLineDivider/3>LINE_DIVIDER){ + mLineDivider = 2; + lastItemDivider = 2; + useString = timeString1; + Mode = Mode_1; + valueToSencond = valueToSencond/3; + mValue = getNowValue(); + //重新计算蓝色录像时间轴 + initData(); + } + }else if(currentStatus==STATUS_ZOOM_OUT&&Mode==Mode_1){ + if(mLineDivider/2>LINE_DIVIDER){ + mLineDivider = 2; + lastItemDivider = 2; + useString = timeString0; + Mode = Mode_0; + valueToSencond = valueToSencond/2; + //重新获取当前value + mValue = getNowValue(); + //重新计算蓝色录像时间轴 + initData(); + } + } + + AXLog.e("wzytest","itemDivider:"+mLineDivider+" lastItemDivider:"+lastItemDivider); + postInvalidate(); + } + break; + case MotionEvent.ACTION_POINTER_UP: + if (event.getPointerCount() == 2) { + //lastValueTosecond = valueToSencond; + lastItemDivider = mLineDivider; + } + break; + case MotionEvent.ACTION_CANCEL: + AXLog.e("wzytest", "ACTION_CANCEL......."); + break; + default: + break; + } + return true; +// return super.onTouchEvent(event); + } + + private void notifyValueChange() { + + if (null != mListener) { + mListener.onValueChange(mValue); + } + } + + + /** + * 获取当前刻度值 + * + * @return + */ + public float getValue() { + return mValue; + } + + /** + * 设置当前刻度值 + * + * @param mValue + */ + public void setmValue(int mValue) { + this.mValue = mValue; + } + + /** + * 画中间的红色指示线 + * + * @param canvas + */ + private void drawMiddleLine(Canvas canvas) { + int indexWidth = 5; + String color = "#66999999"; + Paint redPaint = new Paint(); + redPaint.setStrokeWidth(indexWidth); + redPaint.setColor(Color.RED); + // canvas.drawLine(mWidth / 2, 0, mWidth / 2 , mHeight, shadowPaint); + canvas.drawLine(mWidth / 2, 0, mWidth / 2, mHeight, redPaint); + + } + + public static int getNowValue() { + Calendar c = Calendar.getInstance();//可以对每个时间域单独修改 + + int hour = c.get(Calendar.HOUR_OF_DAY); + int minute = c.get(Calendar.MINUTE); + int second = c.get(Calendar.SECOND); + Log.e("wzytest", "hour:" + hour + " minute:" + minute + " second:" + second); + + //一个mvalue代表25 秒,两个刻度中间间隔了(60/5)个mvalue + return ((hour * 60 + minute) * 60 + second) / valueToSencond ; + // return 360; + } + + /** + * 获取mValue 所对应的时间 + * @param mValue + * @return + */ + public static String getTime(float mValue) { + // TODO: 2017/10/23 超过24小时 和 少于0小时的处理 + + int day = (int) (mValue * valueToSencond / (3600 * 24)); // 天数 + int hour = (int) ((mValue * valueToSencond - (60 * 60 * 24) * day) / 3600); + int minute = (int) (mValue * valueToSencond - 3600 * hour - (60 * 60 * 24) * day) / 60; + int second = (int) mValue * valueToSencond - hour * 3600 - minute * 60 - (60 * 60 * 24) * day; + + AXLog.e("wzytest", "hour:" + hour + " minute:" + minute + " second:" + second + " day:" + day); + Calendar calendar1 = Calendar.getInstance(); + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + /** + * 从00:00:00开始设置时间 + */ + calendar1.add(Calendar.DATE, day); + calendar1.set(Calendar.HOUR_OF_DAY, hour); + calendar1.set(Calendar.MINUTE, minute); + calendar1.set(Calendar.SECOND, second); + + String moveDate = sdf1.format(calendar1.getTime()); + return moveDate; + } + + + /** + * 获取时间戳所对应的mvalue + * @param time 录像时间段time + * @return + */ + private int getmValue(long time) { + /** + * 从00:00:00开始设置时间 + */ + calendar1.set(Calendar.HOUR_OF_DAY, 0); + calendar1.set(Calendar.MINUTE, 0); + calendar1.set(Calendar.SECOND, 0); + long l1 = calendar1.getTimeInMillis(); + return (int) (time - l1) / (1000 * valueToSencond); + } + + /** + * 计算两个手指之间的距离。 + * + * @param event + * @return 两个手指之间的距离 + */ + private double distanceBetweenFingers(MotionEvent event) { + float disX = Math.abs(event.getX(0) - event.getX(1)); + float disY = Math.abs(event.getY(0) - event.getY(1)); + return Math.sqrt(disX * disX + disY * disY); + } + + /** + * 计算两个手指之间中心点的坐标。 + * + * @param event + */ + private void centerPointBetweenFingers(MotionEvent event) { + float xPoint0 = event.getX(0); + float yPoint0 = event.getY(0); + float xPoint1 = event.getX(1); + float yPoint1 = event.getY(1); + centerPointX = (xPoint0 + xPoint1) / 2; + centerPointY = (yPoint0 + yPoint1) / 2; + } + + +} diff --git a/app/src/main/java/com/lechange/demo/login/BindUserActivity.java b/app/src/main/java/com/lechange/demo/login/BindUserActivity.java new file mode 100644 index 0000000..3fff5b2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/login/BindUserActivity.java @@ -0,0 +1,193 @@ +package com.lechange.demo.login; + + +import android.app.Activity; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import com.lechange.demo.business.Business; +import com.lechange.demo.common.CommonTitle; +import com.lechange.demo.common.CommonTitle.OnTitleClickListener; +import com.yonsz.z1.R; + +public class BindUserActivity extends Activity{ + + private CommonTitle mCommonTitle; + + private EditText mAuthCodeEdit ; + private Button mGetAuthCodeBtn; + private Button mBindBtn; + private TextView mNoticeText; + private String mPhoneNumber; + private int mTime = 0; + private final Handler handler = new Handler(){ + @Override + public void handleMessage(Message msg) { + if(msg.what > 1) + { + sendEmptyMessageDelayed(mTime--, 1000); + mGetAuthCodeBtn.setText("重新获取(" + mTime +")"); + } + else if(msg.what <= 1) + { + mGetAuthCodeBtn.setText("重新获取"); + mGetAuthCodeBtn.setTextColor(Color.BLUE); + } + + } + + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.setContentView(R.layout.activity_user_bind); + mPhoneNumber = getIntent().getStringExtra("phoneNumber"); + initView(); + initTitle(); + setListener(); + } + + public void initView() + { + mAuthCodeEdit = (EditText) findViewById(R.id.authCodeEdit); + mGetAuthCodeBtn = (Button) findViewById(R.id.getAuthCode); + mBindBtn = (Button) findViewById(R.id.bind); + mNoticeText = (TextView) findViewById(R.id.authCodeNotice); + mNoticeText.setText(this.getString(R.string.bind_user_notice) + mPhoneNumber); + } + + public void initTitle() + { + //绘制标题 + mCommonTitle = (CommonTitle) findViewById(R.id.title); + mCommonTitle.initView(R.drawable.title_btn_back, 0, R.string.user_bind); + + mCommonTitle.setOnTitleClickListener(new OnTitleClickListener() { + @Override + public void onCommonTitleClick(int id) { + // TODO Auto-generated method stub + switch (id) { + case CommonTitle.ID_LEFT: + finish(); + } + } + }); + } + + public void setListener() + { + mBindBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + checkSms(); + } + }); + mGetAuthCodeBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + //还在倒计时 + if(mTime > 0) + return; + getUserSms(); + } + }); + + mAuthCodeEdit.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int arg2, int arg3) { + if(s.length() != 0){ + mBindBtn.setBackgroundColor(Color.rgb(0x4e, 0xa7, 0xf2)); + } + else{ + mBindBtn.setBackgroundColor(Color.rgb(0x8a, 0xb9, 0xe1)); + } + + } + + @Override + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, + int arg3) { + } + + @Override + public void afterTextChanged(Editable arg0) { + + } + }); + } + + @Override + protected void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + } + + + public void checkSms(){ + mNoticeText.setVisibility(View.INVISIBLE); + mBindBtn.setClickable(false); + String smsCode = mAuthCodeEdit.getText().toString().trim(); + if(smsCode.length() == 0) + { + Toast.makeText(getApplicationContext(), R.string.toast_userbind_no_idcode, Toast.LENGTH_LONG).show(); + mBindBtn.setClickable(true); + return; + } + + Business.getInstance().checkUserSms(mPhoneNumber, smsCode, new Handler(){ + @Override + public void handleMessage(Message msg) { + if(0 == msg.what) + { + finish(); + } + else + { + mNoticeText.setText((String)msg.obj); + mNoticeText.setVisibility(View.VISIBLE); + } + mBindBtn.setClickable(true); + } + + }); + } + + /** + * 获取短信验证码 + */ + public void getUserSms(){ + mNoticeText.setVisibility(View.INVISIBLE); + Business.getInstance().getUserSms(mPhoneNumber, new Handler(){ + @Override + public void handleMessage(Message msg) { + if(0 == msg.what) + { + mGetAuthCodeBtn.setTextColor(Color.rgb(195, 195, 200)); + mTime = 60; + handler.obtainMessage(60).sendToTarget(); + + mNoticeText.setText(getApplication().getResources().getString(R.string.bind_user_notice) + mPhoneNumber); + mNoticeText.setVisibility(View.VISIBLE); + } + else + { + String result = (String)msg.obj; + mNoticeText.setText(result); + mNoticeText.setVisibility(View.VISIBLE); + } + } + + }); + } +} diff --git a/app/src/main/java/com/lechange/demo/login/SplashActivity.java b/app/src/main/java/com/lechange/demo/login/SplashActivity.java new file mode 100644 index 0000000..1bcdb79 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/login/SplashActivity.java @@ -0,0 +1,65 @@ +/* + * 项目名: YYS + * 文件名: YysApp.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.login; + + +import android.app.Activity; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.os.Bundle; +import com.lechange.demo.login.fragment.SplashErrFragment; +import com.lechange.demo.login.fragment.SplashNormalFragment; +import com.yonsz.z1.R; + +/** + * + * 描述:启动界面 + * + * @author:fuwl + */ + +public class SplashActivity extends Activity { + public static final String tag = "LoginActivity"; + public SplashNormalFragment mFragemnt; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + this.setContentView(R.layout.activity_splash); + FragmentManager fragementManager = getFragmentManager(); + FragmentTransaction fragmentTansaction = fragementManager.beginTransaction(); + mFragemnt = new SplashNormalFragment(); + + fragmentTansaction.add(R.id.frame_content, mFragemnt); + fragmentTansaction.commit(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + public void changeFragment() + { + FragmentManager fragementManager = getFragmentManager(); + FragmentTransaction fragmentTansaction = fragementManager.beginTransaction(); + SplashErrFragment errorFragment = new SplashErrFragment(); + Bundle bundle = new Bundle(); + bundle.putString("appId", mFragemnt.getAppId()); + bundle.putString("appSecret", mFragemnt.getAppSecret()); + errorFragment.setArguments(bundle); + fragmentTansaction.replace(R.id.frame_content, errorFragment); + fragmentTansaction.addToBackStack(null); + fragmentTansaction.commit(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/login/UserLoginActivity.java b/app/src/main/java/com/lechange/demo/login/UserLoginActivity.java new file mode 100644 index 0000000..fb97c2e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/login/UserLoginActivity.java @@ -0,0 +1,191 @@ +package com.lechange.demo.login; + + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.lechange.demo.business.Business; +import com.lechange.demo.common.CommonTitle; +import com.lechange.demo.common.CommonTitle.OnTitleClickListener; +import com.lechange.demo.listview.DevicelistActivity; +import com.yonsz.z1.R; + +public class UserLoginActivity extends Activity { + + private String tag = "UserLoginActivity"; + private EditText mZoomEdit; + private EditText mPhoneEdit; + private Button mBindUserBtn; + private Button mDeviceListBtn; + private TextView notice; + private CommonTitle mCommonTitle; + private SharedPreferences sp; //固化数据 + + @Override + protected void onCreate(Bundle savedInstanceState) { + // TODO Auto-generated method stub + super.onCreate(savedInstanceState); + this.setContentView(R.layout.activity_user_login); + sp = this.getSharedPreferences("OpenSDK", MODE_PRIVATE); + initView(); + initTitle(); + setListener(); + } + + public void initView() { + mZoomEdit = (EditText) findViewById(R.id.zoneView); + mZoomEdit.setText(sp.getString("zone", "+86")); + mPhoneEdit = (EditText) findViewById(R.id.phoneEdit); + mPhoneEdit.setText(sp.getString("userphonenumber", "")); + + mBindUserBtn = (Button) findViewById(R.id.bindUser); + mDeviceListBtn = (Button) findViewById(R.id.deviceList); + notice = (TextView) findViewById(R.id.notice); + } + + public void initTitle() { + //绘制标题 + mCommonTitle = (CommonTitle) findViewById(R.id.title); + mCommonTitle.initView(R.drawable.title_btn_back, 0, R.string.user_login_name); + + mCommonTitle.setOnTitleClickListener(new OnTitleClickListener() { + @Override + public void onCommonTitleClick(int id) { + // TODO Auto-generated method stub + switch (id) { + case CommonTitle.ID_LEFT: + finish(); + } + } + }); + } + + public void setListener() { + mBindUserBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + userLogin(mBindUserBtn.getId()); + } + }); + + mDeviceListBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + userLogin(mDeviceListBtn.getId()); + } + }); + + + } + + @Override + protected void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + } + + + /** + * 获取usertoken + */ + public void userLogin(final int id) { + notice.setVisibility(View.INVISIBLE); + String zone = mZoomEdit.getText().toString().trim(); + String phoneNumber = mPhoneEdit.getText().toString().trim(); + + if (phoneNumber.length() != 11) { + notice.setText(R.string.user_no_input); + notice.setVisibility(View.VISIBLE); + return; + } + + + mBindUserBtn.setClickable(false); + mDeviceListBtn.setClickable(false); + + Editor editor = sp.edit(); + editor.putString("userphonenumber", phoneNumber); + editor.putString("zone", zone); + editor.commit(); + + if (!zone.endsWith("86") && !zone.equals("")) { + phoneNumber = zone + phoneNumber; + } + + + Business.getInstance().userlogin(phoneNumber, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + switch (id) { + case R.id.bindUser: + notice.setText(R.string.user_bind_err); + notice.setVisibility(View.VISIBLE); + break; + case R.id.deviceList: + String userToken = (String) msg.obj; + Log.d(tag, "userToken" + userToken); + Business.getInstance().setToken(userToken); + startActivity(); + break; + } + } else { + switch (id) { + case R.id.bindUser: + if (1 == msg.what) + startBindUserActivity(); + else { + String result = (String) msg.obj; + notice.setText(result); + notice.setVisibility(View.VISIBLE); + } + break; + case R.id.deviceList: + if (1 != msg.what) { + String result = (String) msg.obj; + notice.setText(result); + } else { + notice.setText(R.string.user_nobind_err); + } + + notice.setVisibility(View.VISIBLE); + break; + } + } + mBindUserBtn.setClickable(true); + mDeviceListBtn.setClickable(true); + } + + }); + } + + public void startBindUserActivity() { + Intent intent = new Intent(UserLoginActivity.this, BindUserActivity.class); + intent.putExtra("phoneNumber", mPhoneEdit.getText().toString()); + startActivity(intent); + } + + /** + * 跳转到主页 + */ + public void startActivity() { + Intent mIntent = new Intent(this, DevicelistActivity.class); + Bundle b = getIntent().getExtras(); + if (b != null) { + mIntent.putExtras(getIntent().getExtras()); + } + startActivity(mIntent); + finish(); + } +} diff --git a/app/src/main/java/com/lechange/demo/login/fragment/SplashErrFragment.java b/app/src/main/java/com/lechange/demo/login/fragment/SplashErrFragment.java new file mode 100644 index 0000000..3f4c545 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/login/fragment/SplashErrFragment.java @@ -0,0 +1,54 @@ +package com.lechange.demo.login.fragment; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.LinearLayout; + +import com.yonsz.z1.R; + +public class SplashErrFragment extends Fragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + return inflater.inflate(R.layout.fragment_splash_err, container, false); + + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + // TODO Auto-generated method stub + super.onActivityCreated(savedInstanceState); + EditText appId = (EditText) getView().findViewById(R.id.editAppId); + EditText appSecret = (EditText) getView().findViewById( + R.id.editAppSectet); + appId.setText(getArguments().getString("appId")); + appSecret.setText(getArguments().getString("appSecret")); + LinearLayout layout = (LinearLayout) getView().findViewById( + R.id.container); + layout.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + getFragmentManager().popBackStack(); + + } + + }); + } + + @Override + public void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + } + + + +} diff --git a/app/src/main/java/com/lechange/demo/login/fragment/SplashNormalFragment.java b/app/src/main/java/com/lechange/demo/login/fragment/SplashNormalFragment.java new file mode 100644 index 0000000..49c5c7e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/login/fragment/SplashNormalFragment.java @@ -0,0 +1,192 @@ +package com.lechange.demo.login.fragment; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Toast; +import com.lechange.demo.business.Business; +import com.lechange.demo.listview.DevicelistActivity; +import com.lechange.demo.login.SplashActivity; +import com.lechange.demo.login.UserLoginActivity; +import com.yonsz.z1.R; + +public class SplashNormalFragment extends Fragment{ + + private EditText appId = null; + private EditText appSecret = null; + private EditText appUrl = null; + private ImageView adminBtn = null; + private ImageView userBtn = null; + private SharedPreferences sp; //固化数据 + private Activity mActivity; + + + public String getAppId() { + return appId.getText().toString(); + } + + + + public String getAppSecret() { + return appSecret.getText().toString(); + } + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + sp = getActivity().getSharedPreferences("OpenSDK", SplashActivity.MODE_PRIVATE); + return inflater.inflate(R.layout.fragment_splash_normal, container,false); + + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + initView(); + setListener(); + +// inner online + appId.setText(sp.getString("appid", "")); + appSecret.setText(sp.getString("appsecret", "")); + appUrl.setText(sp.getString("appurl", Business.getInstance().isOversea ? "openapi.easy4ip.com:443" : "openapi.lechange.cn:443")); + appUrl.setVisibility(View.INVISIBLE); + + } + + @Override + public void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + } + + private void initView() + { + mActivity = getActivity(); + + appId = (EditText) getView().findViewById(R.id.editAppId); + appSecret = (EditText) getView().findViewById(R.id.editAppSectet); + appUrl = (EditText) getView().findViewById(R.id.editappurl); + adminBtn = (ImageView) getView().findViewById(R.id.adminButton); + userBtn = (ImageView) getView().findViewById(R.id.userButton); + + if(!getResources().getConfiguration().locale.getLanguage().endsWith("zh")){ + userBtn.setVisibility(View.GONE); + } + } + + private void setListener() + { + adminBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if(!validCheck()) + { + SplashActivity splashActivity = (SplashActivity) getActivity(); + splashActivity.changeFragment(); + return; + } + //按钮不能点击,防止连击开启多个activity;也可以修改启动模式 + adminBtn.setClickable(false); + + //初始化需要的数据 + Business.getInstance().init(appId.getText().toString(), appSecret.getText().toString(), appUrl.getText().toString()); + + Editor editor=sp.edit(); + editor.putString("appid", appId.getText().toString()); + editor.putString("appsecret", appSecret.getText().toString()); + editor.putString("appurl", appUrl.getText().toString()); + editor.commit(); + + adminLogin(); + } + + }); + + userBtn.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + if(!validCheck()) + { + SplashActivity splashActivity = (SplashActivity) getActivity(); + splashActivity.changeFragment(); + return; + } + + //初始化需要的数据 + Business.getInstance().init(appId.getText().toString(), appSecret.getText().toString(), appUrl.getText().toString()); + + Editor editor=sp.edit(); + editor.putString("appid", appId.getText().toString()); + editor.putString("appsecret", appSecret.getText().toString()); + editor.putString("appurl", appUrl.getText().toString()); + editor.commit(); + + Intent intent = new Intent(getActivity(),UserLoginActivity.class ); + getActivity().startActivity(intent); + + } + + }); + } + + private void adminLogin() { + Business.getInstance().adminlogin(new Handler(){ + @Override + public void handleMessage(Message msg) { + if(0 == msg.what) + { + String accessToken = (String) msg.obj; + Business.getInstance().setToken(accessToken); + + //恢复可点击 + adminBtn.setClickable(true); + startActivity(); + } + else{ + if(1 == msg.what){ + Toast.makeText(mActivity, "getToken failed", Toast.LENGTH_SHORT).show(); + }else{ + String result = (String)msg.obj; + Toast.makeText(mActivity, result, Toast.LENGTH_SHORT).show(); + } + //恢复可点击 + adminBtn.setClickable(true); + } + } + + }); + } + + private void startActivity() { + Intent mIntent = new Intent(this.getActivity(), DevicelistActivity.class); + Bundle b = mActivity.getIntent().getExtras(); + if (b != null) { + mIntent.putExtras(mActivity.getIntent().getExtras()); + } + startActivity(mIntent); + } + + private boolean validCheck() + { + + if(appId.getText().length()==0 || appSecret.getText().length() == 0) + { + return false; + } + return true; + } + +} diff --git a/app/src/main/java/com/lechange/demo/manager/DeviceAddActivity.java b/app/src/main/java/com/lechange/demo/manager/DeviceAddActivity.java new file mode 100644 index 0000000..2b6c4d7 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/manager/DeviceAddActivity.java @@ -0,0 +1,895 @@ +package com.lechange.demo.manager; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.text.TextUtils; +import android.util.Log; +import android.widget.EditText; + +import com.alibaba.fastjson.JSON; +import com.lechange.common.configwifi.LCSmartConfig; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.RetObject; +import com.lechange.demo.business.util.TaskPoolHelper; +import com.lechange.demo.business.util.TaskPoolHelper.RunnableTask; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.yonsz.AddCompleteAndRenameActivity; +import com.lechange.demo.yonsz.TimeOutActivity; +import com.lechange.opensdk.api.bean.DeviceOnline; +import com.lechange.opensdk.configwifi.LCOpenSDK_ConfigWifi; +import com.lechange.opensdk.media.DeviceInitInfo; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.gateway.AddLCSafeCompleteActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.AppIdUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.view.StateButton; +import com.yonsz.z1.view.TitleView; + +import java.util.HashMap; +import java.util.List; + +import de.greenrobot.event.EventBus; + +import static com.yonsz.z1.UniKongApp.getActivity; +import static com.yonsz.z1.difference.DifferConstans.LECHENG_KEY; +import static com.yonsz.z1.net.Constans.GATE_WAY; +import static com.yonsz.z1.net.Constans.UPDATE_SEC; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; +import static com.yonsz.z1.net.Constans.localAddAddressId; +import static com.yonsz.z1.net.NetWorkUrl.BIND_DEVICE; +import static com.yonsz.z1.version5.MainFragment5.isRefreshCamera; + +public class DeviceAddActivity extends BaseActivity implements + ActivityCompat.OnRequestPermissionsResultCallback { + public final static String tag = "AddDeviceActivity"; + // 无线配置参数 + private static final int PROGRESS_TIMEOUT_TIME = 120 * 1000; + private static final int PROGRESS_DELAY_TIME = 10 * 1000; + private final int startPolling = 0x10; + private final int successOnline = 0x11; + private final int asynWaitOnlineTimeOut = 0x12; + private final int successAddDevice = 0x13; + // private final int successOffline = 0x14; + // private final int addDeviceTimeOut = 0x15; + // private final int failedAddDevice = 0x16; + // private final int successOnlineEx = 0x17; + private final int deviceInitSuccess = 0x18; + private final int deviceInitFailed = 0x19; + private final int deviceInitByIPFailed = 0x1A; + private final int deviceSearchSuccess = 0x1B; + private final int deviceSearchFailed = 0x1C; + private final int INITMODE_UNICAST = 0; + private final int INITMODE_MULTICAST = 1; + private TitleView mTitleView; + private int curInitMode = INITMODE_MULTICAST; + private ProgressDialog mProgressDialog; // 播放加载使用 + private String key = ""; + private Handler mHandler; + private boolean mIsOffline = true; + private boolean mIsDeviceSearched = false; //设备初始化标志,保证设备初始化接口只调用一次 + + // 配对方式 + private boolean mIsDeviceInitSuccess = false; + private ConfigStatus mConfigStatus = ConfigStatus.query; // 默认为轮询状态 + private int time = 25; + + private String deviceSN, deviceCode = ""; + private StateButton mStateButton; + private int sec = 100; + + /** + * 无线配对超时任务 + */ + private Runnable progressRun = new Runnable() { + @Override + public void run() { + // TODO Auto-generated method stub + toast("超时配置失败"); + stopConfig(); + gotoTimeOutActivity(); + } + }; + /** + * 轮询定时启动任务 + */ + private Runnable progressPoll = new Runnable() { + @Override + public void run() { + // TODO Auto-generated method stub + mHandler.obtainMessage(startPolling).sendToTarget(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_device_lcadd); + + initView(); + } + + private void initView() { + deviceSN = getIntent().getExtras().get("deviceSN").toString(); + deviceCode = getIntent().getExtras().get("deviceCode").toString(); + // load组件 + mStateButton = (StateButton) findViewById(R.id.bt_sec); + mProgressDialog = (ProgressDialog) this.findViewById(R.id.query_load); + mTitleView = (TitleView) findViewById(R.id.title_lecheng_add); + mTitleView.setHead(R.string.add_device); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + if (sec > 0) { + showIsFinishThis(); + } else { + finish(); + } + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + Log.d(tag, "msg.what" + msg.what); + switch (msg.what) { + // 无线配对消息回调 + /*case LCOpenSDK_ConfigWifi.ConfigWifi_Event_Success: + Log.d(tag, "smartConfig success"); + mConfigStatus = ConfigStatus.wifipair; + toast("smartConfig success"); + stopConfig(); + mHandler.removeCallbacks(progressPoll); + if (!mIsDeviceSearched) { + mIsDeviceSearched = true; +// searchDevice(); + } + break;*/ + case deviceSearchSuccess: + Log.d(tag, "deviceSearchSuccess"); + initDevice((DeviceInitInfo) msg.obj, curInitMode); + break; + case deviceSearchFailed: + Log.d(tag, "deviceSearchFailed:" + (String) msg.obj); + toast("deviceSearchFailed:" + (String) msg.obj); + gotoTimeOutActivity(); + break; + case deviceInitSuccess: + Log.d(tag, "deviceInitSuccess"); + toast("deviceInitSuccess!"); + mIsDeviceInitSuccess = true; + if (mIsOffline) + checkOnline(); + else + mHandler.obtainMessage(successOnline).sendToTarget(); + break; + case deviceInitFailed: + toast("deviceInitFailed: " + (String) msg.obj); + //组播失败后走单播 + curInitMode = INITMODE_UNICAST; + // searchDevice(); + break; + case deviceInitByIPFailed: + toast("deviceInitByIPFailed: " + (String) msg.obj); + curInitMode = INITMODE_MULTICAST; + time = 0; + mProgressDialog.setStop(); + break; + case startPolling: + checkOnline(); + break; + // 校验消息回调 + case asynWaitOnlineTimeOut: + Log.d(tag, "checkIsOnlineTimeOut"); + break; + case successOnline: + Log.d(tag, "successOnline"); + stopConfig(); + if (deviceCode.equals("123456")) { + bindDevice(); + } else { + if (!mIsDeviceSearched) { + mIsDeviceSearched = true; + searchDevice(PROGRESS_TIMEOUT_TIME); + } else if (mIsDeviceInitSuccess) {//设备初始化成功且在线,则绑定 + unBindDeviceInfo(); + } + } + // unBindDeviceInfo(); + break; + case successAddDevice: + // DeviceInfo device = (DeviceInfo) msg.obj; + // success(device.getUuid()); + isRefreshCamera = true; + Log.d(tag, "SuccessAddDevice"); + toast("SuccessAddDevice"); + // 只有这么一种情况 + setResult(RESULT_OK); + EventBus.getDefault().post( + new ChooseHomeEvent("5")); + EventBus.getDefault().post( + new EventBusEntity("关闭")); + sec = 101; + Intent intent; + if (getIntent().getExtras().get("deviceType").toString().equals(GATE_WAY)) { + intent = new Intent(DeviceAddActivity.this, AddLCSafeCompleteActivity.class); + intent.putExtra("deviceType", getIntent().getExtras().get("deviceType").toString()); + } else { + intent = new Intent(DeviceAddActivity.this, AddCompleteAndRenameActivity.class); + } + intent.putExtra("deviceSN", deviceSN); + intent.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + startActivity(intent); + finish(); + break; + case UPDATE_SEC: + if (sec > 1 && sec < 101) { + sec--; + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + mStateButton.setText(getResources().getString(R.string.sec_30, sec)); + } else if (sec <= 1) { + gotoTimeOutActivity(); + } + break; + default: + break; + } + } + }; + + //开始匹配 + mIsDeviceSearched = false; + mIsOffline = true; + mIsDeviceInitSuccess = false; + showWifiConfig(); + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + } + + private void gotoTimeOutActivity() { + EventBus.getDefault().post( + new EventBusEntity("关闭")); + Intent intent1 = new Intent(DeviceAddActivity.this, TimeOutActivity.class); + intent1.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent1.putExtra("password", getIntent().getExtras().get("password").toString()); + intent1.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + intent1.putExtra("deviceType", getIntent().getExtras().get("deviceType").toString()); + intent1.putExtra("deviceSN", deviceSN); + intent1.putExtra("deviceCode", deviceCode); + intent1.putExtra("from", "LcnDeviceAddActivity"); + startActivity(intent1); + finish(); + } + + @Override + public void onBackPressed() { + // super.onBackPressed(); + if (sec > 0) { + showIsFinishThis(); + } else { + finish(); + } + } + + private void showIsFinishThis() { + ConfirmDialog dialog = new ConfirmDialog(getActivity(), new Callback() { + @Override + public void callback(int position) { + switch (position) { + case 0: + break; + case 1: + EventBus.getDefault().post( + new EventBusEntity("关闭")); + sec = 101; + stopConfig(); + finish(); + break; + } + } + }); + dialog.setContent("您还未完成配置,如果退出,您将可能重新开始配置流程"); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn(R.string.sure); + dialog.setCancelable(false); + dialog.show(); + } + + @Override + public void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + sec = 101; + time = 0; + stopConfig(); + } + + @Override + public void callBackUiThread(Message msg) { + + } + + /** + * 校验在线 + */ + + /*private void checkOnline() { + Business.getInstance().checkOnline(devId, + new Handler() { + @Override + public void handleMessage(Message msg) { + Business.RetObject retObject = (Business.RetObject) msg.obj; + switch (msg.what) { + case 0: + if (((DeviceOnline.Response) retObject.resp).data.onLine.equals("1")) { + toast("Online"); + mHandler.obtainMessage(successOnline).sendToTarget(); + } else { + if(isCheckOnline) { + Logger.d(TAG,"onLine : "+((DeviceOnline.Response) retObject.resp).data.onLine); + mHandler.obtainMessage(CHECK_DEVICE_ONLINE).sendToTarget(); + } + } + break; + case -1000: + Logger.e(TAG,"check_online_respond : -1000"); + mHandler.obtainMessage(ON_LINE_FAILED).sendToTarget(); + break; + default: + Logger.e(TAG,"checkonline : "+msg.what); + mHandler.obtainMessage(ON_LINE_FAILED).sendToTarget(); + break; + } + } + }); + + }*/ + private void checkOnline() { + // 隔两秒轮询..... + Log.d(tag, "轮询" + deviceSN); + Business.getInstance().checkOnline(deviceSN, + new Handler() { + @Override + public void handleMessage(Message msg) { + if (!mIsOffline) + return; + + RetObject retObject = (RetObject) msg.obj; + Log.d(tag, "轮询" + msg.what); + switch (msg.what) { + case 0: + if (((DeviceOnline.Response) retObject.resp).data.onLine.equals("1")) { + switch (mConfigStatus) { + case wired: + Log.d(tag, "有线配对...."); + break; + case query: + Log.d(tag, "轮询...."); + stopConfig(); + case wifipair: + mProgressDialog.setStop(); + } + toast("Online"); + mIsOffline = false; + mHandler.obtainMessage(successOnline).sendToTarget(); + } else { + if (mConfigStatus == ConfigStatus.wired) { + Log.d(tag, "offline..... wired"); + toast("offline"); + gotoTimeOutActivity(); + } else if (time > 0) { + Log.d(tag, "offline..... try again checkOnline"); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + time--; + mHandler.obtainMessage(startPolling) + .sendToTarget(); + } else { + Log.d(tag, "offline..... try again max"); + mProgressDialog.setStop(); + time = 25; + toast("offline"); + } + } + break; + case -1000: + if (time > 0) { + Log.d(tag, + "code:-1000..... try again checkOnline"); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + time--; + mHandler.obtainMessage(startPolling) + .sendToTarget(); + } + break; + default: + switch (mConfigStatus) { + case wired: + Log.d(tag, "有线配对失败...."); + break; + case query: + Log.d(tag, "轮询失败...."); + stopConfig(); + case wifipair: + mProgressDialog.setStop(); + } + toast(retObject.mMsg); + break; + } + } + }); + + } + + /** + * 绑定 + */ + private void bindDevice() { + //调后台接口 + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", deviceSN); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + map.put("code", key); + if (AppIdUtil.isBaseZhiKong()) { + map.put("addressId", localAddAddressId); + } else { + if (null != getIntent().getExtras().get("deviceAddress")) { + map.put("addressId", getIntent().getExtras().get("deviceAddress").toString()); + } else { + map.put("addressId", "1"); + } + } + map.put("deviceModel", "0"); + map.put("deviceType", getIntent().getExtras().get("deviceType").toString()); + map.put("wifiName", getIntent().getExtras().get("ssid").toString()); + if (null != homeListEntity && TextUtils.isEmpty(homeListEntity.getData().get(deviceNumListPosition).getFloorList())) { + if (null != getIntent().getExtras().get("floor")) { + map.put("floor", getIntent().getExtras().get("floor").toString()); + } + } + netWorkUtil.requestPostByAsynewApi(BIND_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("bindDevice", "onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + mHandler.obtainMessage(successAddDevice).sendToTarget(); + } + + @Override + public void onFail(String message) { + toast("addDevice failed"); + } + }); + } + + private void unBindDeviceInfo() { + if (!Business.getInstance().isOversea) { + Business.getInstance().unBindDeviceInfo(deviceSN, new Handler() { + public void handleMessage(Message msg) { + String message = (String) msg.obj; + Log.d(tag, "unBindDeviceInfo," + message); + if (msg.what == 0) { + if (message.contains("Auth")) { + if (sec > 99) { + return; + } + bindDevice(); + } else if (message.contains("RegCode")) { + key = deviceCode; + if (sec > 99) { + return; + } + bindDevice(); + } else { + key = ""; + if (sec > 99) { + return; + } + bindDevice(); + } + } else { + /*toast("unBindDeviceInfo failed"); + Log.d(tag, message);*/ + + if (!deviceCode.equals("123456")) { + key = deviceCode; + } else { + key = "ysz123456"; + } + bindDevice(); + } + } + }); + } else { //oversea + // unBindDeviceInfo(); + if (!deviceCode.equals("123456")) { + key = deviceCode; + } else { + key = "ysz123456"; + } + bindDevice(); + } + + } + + /** + * 启动无线配对 + */ + private void startConfig() { + // 开启播放加载控件 + mProgressDialog.setStart(getString(R.string.wifi_config_loading)); + + /*String ssid = mWifiInfo.getSSID().replaceAll("\"", ""); + String ssid_pwd = mPwdText.getText().toString(); + String code = mSnText.getText().toString().toUpperCase();*/ + + String ssid = getIntent().getExtras().get("ssid").toString().replaceAll("\"", ""); + String ssid_pwd = getIntent().getExtras().get("password").toString(); + String code = deviceSN.toUpperCase(); + + String mCapabilities = getWifiCapabilities(ssid); + // 无线超时任务 + mHandler.postDelayed(progressRun, PROGRESS_TIMEOUT_TIME); + // 10s开启轮询 + // mHandler.postDelayed(progressPoll, PROGRESS_DELAY_TIME); + // 调用接口,开始通过smartConfig匹配 + // System.out.println("mLinkIPCProxy.start"); + /*LCOpenSDK_ConfigWifi.configWifiStart(code, ssid, ssid_pwd, + mCapabilities, mHandler);*/ + LCOpenSDK_ConfigWifi.configWifiStart(code, ssid, ssid_pwd, "WPA2", LCSmartConfig.ConfigType.LCConfigWifi_Type_ALL, true, 11000, 1); + + //LCOpenSDK_ConfigWifi.configWifiStart(code, ssid, ssid_pwd, "WPA2", LCSmartConfig.ConfigType.LCConfigWifi_Type_ALL,true,11000,1); + searchDevice(PROGRESS_TIMEOUT_TIME); + } + + /** + * 关闭无线配对 + */ + private void stopConfig() { + mHandler.removeCallbacks(progressRun); + LCOpenSDK_ConfigWifi.configWifiStop();// 调用smartConfig停止接口 + } + + /** + * 获取wifi加密信息 + */ + private String getWifiCapabilities(String ssid) { + String mCapabilities = null; + ScanResult mScanResult = null; + WifiManager mWifiManager = (WifiManager) getApplicationContext().getSystemService(Activity.WIFI_SERVICE); + if (mWifiManager != null) { + WifiInfo mWifi = mWifiManager.getConnectionInfo(); + if (mWifi != null) { + // 判断SSID是否�?�� + if (mWifi.getSSID() != null + && mWifi.getSSID().replaceAll("\"", "").equals(ssid)) { + List mList = mWifiManager.getScanResults(); + if (mList != null) { + for (ScanResult s : mList) { + if (s.SSID.replaceAll("\"", "").equals(ssid)) { + mScanResult = s; + break; + } + } + } + } + } + } + mCapabilities = mScanResult != null ? mScanResult.capabilities : null; + return mCapabilities; + } + + private void toast(String content) { + /*Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT) + .show();*/ + /*runOnUiThread(new Runnable() { + @Override + public void run() { + ToastUtil.show(LcnDeviceAddActivity.this, content); + } + });*/ + } + + @Override + public void onRequestPermissionsResult(int requestCode, + @NonNull String[] permissions, @NonNull int[] grantResults) { + // TODO Auto-generated method stub + if (grantResults.length == 1 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // Camera permission has been granted, preview can be displayed + showPairDescription(); + + } else { + toast(getString(R.string.toast_permission_location_forbidden)); + + } + + } + + /** + * 开启无线配网流程(权限检查,配对说明) + */ + public void showWifiConfig() { + boolean isMinSDKM = Build.VERSION.SDK_INT < 23; + boolean isGranted = ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; + if (isMinSDKM || isGranted) { + + showPairDescription(); + // 开启无线配对 + return; + } + + requestLocationPermission(); + } + + /** + * 显示配对说明 + */ + private void showPairDescription() { + startConfig(); + /*DialogInterface.OnClickListener dialogOnclicListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case Dialog.BUTTON_POSITIVE: + startConfig(); + break; + case Dialog.BUTTON_NEGATIVE: + break; + case Dialog.BUTTON_NEUTRAL: + break; + } + } + }; + // dialog参数设置 + AlertDialog.Builder builder = new AlertDialog.Builder( + LcnDeviceAddActivity.this); // 先得到构造器 + builder.setTitle(R.string.devices_config_dialog_title); // 设置标题 + builder.setMessage(R.string.devices_config_dialog_message); // 设置内容 + builder.setPositiveButton(R.string.dialog_positive, + dialogOnclicListener); + builder.setNegativeButton(R.string.dialog_negative, + dialogOnclicListener); + builder.create().show();*/ + } + + /** + * 请求相关权限 + */ + private void requestLocationPermission() { + if (ActivityCompat.shouldShowRequestPermissionRationale(this, + Manifest.permission.ACCESS_FINE_LOCATION)) { + + Log.d("Uriah", "Uriah + shouldShowRequestPermission true"); + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + 1); + } else { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + 1); + } + } + + private void searchDevice(int timeout) { + final String deviceId = deviceSN; + Business.getInstance().searchDevice(deviceId, timeout, new Handler() { + public void handleMessage(final Message msg) { + if (msg.what < 0) { + if (msg.what == -2) + mHandler.obtainMessage(deviceSearchFailed, "device not found").sendToTarget(); + else + mHandler.obtainMessage(deviceSearchFailed, "StartSearchDevices failed").sendToTarget(); + return; + } + + mHandler.obtainMessage(deviceSearchSuccess, msg.obj).sendToTarget(); + } + }); + } + + private void searchDeviceEx() { + final EditText et = new EditText(DeviceAddActivity.this); + final String deviceId = deviceSN; + + //设备初始化 + Business.getInstance().searchDevice(deviceId, 15000, new Handler() { + public void handleMessage(final Message msg) { + if (msg.what < 0) { + if (msg.what == -2) + mHandler.obtainMessage(deviceInitFailed, "device not found").sendToTarget(); + else + mHandler.obtainMessage(deviceInitFailed, "StartSearchDevices failed").sendToTarget(); + return; + } + + final DeviceInitInfo deviceInitInfo = (DeviceInitInfo) msg.obj; + final int status = deviceInitInfo.mStatus; + + //not support init + if (status == 0 && !Business.getInstance().isOversea) { + key = ""; + mHandler.obtainMessage(deviceInitSuccess, "inner, go bind without key").sendToTarget(); + } else { + if (status == 1) { + et.setHint(getString(R.string.toast_adddevice_input_device_key_to_init)); + } else { + et.setHint(getString(R.string.toast_adddevice_input_device_key_after_init)); + } + + AlertDialog dialog = new AlertDialog.Builder(DeviceAddActivity.this) + .setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info) + .setView(et) + .setPositiveButton(R.string.dialog_positive, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + key = et.getText().toString(); + if (status == 0 || status == 2) { + if (Business.getInstance().isOversea) + checkPwdValidity(deviceId, key, mHandler); + else + mHandler.obtainMessage(deviceInitSuccess, "Inner, go bind with key").sendToTarget(); + } else if (status == 1) { + Business.getInstance().initDevice(deviceInitInfo.mMac, key, new Handler() { + public void handleMessage(Message msg) { + String message = (String) msg.obj; + if (msg.what == 0) { + mHandler.obtainMessage(deviceInitSuccess, message).sendToTarget(); + } else { + mHandler.obtainMessage(deviceInitFailed, message).sendToTarget(); + } + } + + ; + }); + } + } + }) + .setNegativeButton(R.string.dialog_negative, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mHandler.obtainMessage(deviceInitFailed, "Init has been cancelled").sendToTarget(); + } + }) + .create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + } + } + }); + + } + + public void initDevice(final DeviceInitInfo deviceInitInfo, int initMode) { + //1.使用组播进行初始化(initMode=INITMODE_MULTICAST),走else流程 + //2.组播失败后再使用单播(initMode=INITMODE_UNICAST),此时直接使用组播时输入的秘钥进行初始化 + if (initMode == INITMODE_UNICAST) { + Business.getInstance().initDeviceByIP(deviceInitInfo.mMac, deviceInitInfo.mIp, key, new Handler() { + public void handleMessage(Message msg) { + String message = (String) msg.obj; + if (msg.what == 0) { + mHandler.obtainMessage(deviceInitSuccess, message).sendToTarget(); + } else { + mHandler.obtainMessage(deviceInitByIPFailed, message).sendToTarget(); + } + } + }); + } else { + final EditText et = new EditText(DeviceAddActivity.this); + final String deviceId = deviceSN; + final int status = deviceInitInfo.mStatus; + //not support init + if (status == 0 && !Business.getInstance().isOversea) { + key = ""; + mHandler.obtainMessage(deviceInitSuccess, "inner, go bind without key").sendToTarget(); + } else { + key = LECHENG_KEY; + if (status == 0 || status == 2) { + if (Business.getInstance().isOversea) + checkPwdValidity(deviceId, key, mHandler); + else + mHandler.obtainMessage(deviceInitSuccess, "Inner, go bind with key").sendToTarget(); + } else if (status == 1) { + Business.getInstance().initDevice(deviceInitInfo.mMac, key, new Handler() { + public void handleMessage(Message msg) { + String message = (String) msg.obj; + if (msg.what == 0) { + mHandler.obtainMessage(deviceInitSuccess, message).sendToTarget(); + } else { + mHandler.obtainMessage(deviceInitFailed, message).sendToTarget(); + } + } + + ; + }); + } + + /*AlertDialog dialog = new AlertDialog.Builder(LcnDeviceAddActivity.this) + .setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info) + .setView(et) + .setPositiveButton(R.string.dialog_positive, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }) + .setNegativeButton(R.string.dialog_negative, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mHandler.obtainMessage(deviceInitByIPFailed, "Init has been cancelled").sendToTarget(); + } + }) + .create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show();*/ + } + } + } + + public void checkPwdValidity(final String deviceId, final String key, final Handler handler) { + TaskPoolHelper.addTask(new RunnableTask("real") { + @Override + public void run() { + if (0 == Business.getInstance().checkPwdValidity(deviceId, key)) { + handler.obtainMessage(deviceInitSuccess, "checkPwdValidity success").sendToTarget(); + } else { + handler.obtainMessage(deviceInitByIPFailed, "checkPwdValidity failed").sendToTarget(); + } + } + }); + } + + private enum ConfigStatus { + query, wifipair, wired + } +} diff --git a/app/src/main/java/com/lechange/demo/manager/DeviceSetActivity.java b/app/src/main/java/com/lechange/demo/manager/DeviceSetActivity.java new file mode 100644 index 0000000..cc9a73f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/manager/DeviceSetActivity.java @@ -0,0 +1,348 @@ +package com.lechange.demo.manager; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ToggleButton; + +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.RetObject; +import com.lechange.demo.common.CommonTitle; +import com.lechange.demo.common.CommonTitle.OnTitleClickListener; +import com.lechange.demo.login.SplashActivity; +import com.yonsz.z1.R; + +public class DeviceSetActivity extends Activity { + + private String tag = "DeviceSetActivity"; + private SharedPreferences mSharedPreferences; + private CommonTitle mCommonTitle; + private ToggleButton mSwitch; // 报警订阅开关 + private ToggleButton mCloudMealBtn; // 云存储套餐开关 + private Button mModifyPwd; //修改设备密码 + private TextView mUpgrade; // 云升级开关 + private String mChannelUUID = null; + private int mCloudMealStates; // 云套餐状态 + private int mAlarmStates; // 报警计划状态 + private boolean mCanBeUpgrade; //设备是否可云升级 + private boolean IsClickSwitchBtn; // 是否主动修改动检开关(手势触发) + private boolean IsClickCloudMealBtn; // 是否主动修改套餐状态 (手势触发) + private LinearLayout mCloudStorageLL; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_device_set); + + mSharedPreferences = getSharedPreferences("OpenSDK", + SplashActivity.MODE_PRIVATE); + + mChannelUUID = getIntent().getStringExtra("UUID"); // 获取通道的UUID + + mSwitch = (ToggleButton) findViewById(R.id.switchPlan); + mCloudMealBtn = (ToggleButton) findViewById(R.id.cloudMealBtn); + mModifyPwd = (Button) findViewById(R.id.modify_device_pwd); + mUpgrade = (TextView) findViewById(R.id.device_upgrade_icon); + mCloudStorageLL= (LinearLayout) findViewById(R.id.cloudMeal); + mSwitch.setClickable(false); + mCloudMealBtn.setClickable(false); + mUpgrade.setClickable(false); + initTitle(); + setListener(); + getOriginStatus(); + + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + } + + /** + * 初始化标题栏 + */ + public void initTitle() { + // 绘制标题 + mCommonTitle = (CommonTitle) findViewById(R.id.title); + mCommonTitle.initView(R.drawable.title_btn_back, 0, + R.string.devices_operation_name); + + mCommonTitle.setOnTitleClickListener(new OnTitleClickListener() { + @Override + public void onCommonTitleClick(int id) { + // TODO Auto-generated method stub + switch (id) { + case CommonTitle.ID_LEFT: + + finish(); + break; + } + } + }); + + if(!Business.getInstance().isOversea){ + mCloudStorageLL.setVisibility(View.VISIBLE); + } + } + + /** + * 获取初始状态 + */ + private void getOriginStatus() { +// String status = mSharedPreferences.getString("alarmPlan", ""); +// if (status != null) { +// mSwitch.setChecked(status.equals("open") ? true : false); +// } else {// 默认没有打开报警订阅 +// mSwitch.setChecked(false); +// mSharedPreferences.edit().putString("alarmPlan", "close").commit(); +// } +// mSwitch.setVisibility(View.VISIBLE); +// IsClickSwitchBtn = true; +// mSwitch.setClickable(true); + + // 初始化数据 + Business.getInstance().getDeviceInfo(mChannelUUID, new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + Bundle bundle = (Bundle) msg.obj; + if (msg.what == 0) { + + mAlarmStates = bundle.getInt("alarmStatus"); + mCloudMealStates = bundle.getInt("cloudStatus"); + mCanBeUpgrade = bundle.getBoolean("canBeUpgrade"); + + if (mCloudMealStates == 1) { + IsClickCloudMealBtn = false; + mCloudMealBtn.setChecked(true); + } + if (mAlarmStates == 1) { + IsClickSwitchBtn = false; + mSwitch.setChecked(true); + } + + if (!mCanBeUpgrade) { + mUpgrade.setVisibility(View.INVISIBLE); + } + + mSwitch.setVisibility(View.VISIBLE); + mCloudMealBtn.setVisibility(View.VISIBLE); + + } else { + Toast.makeText(DeviceSetActivity.this, + R.string.toast_device_get_init_info_failed, + Toast.LENGTH_SHORT).show(); + } + + IsClickCloudMealBtn = true; + IsClickSwitchBtn = true; + mSwitch.setClickable(true); + mCloudMealBtn.setClickable(true); + mUpgrade.setClickable(true); + } + }); + } + + /** + * 设置监听函数 + */ + public void setListener() { + mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton view, boolean state) { + + // 如果是手势触发,则进行网络请求 + if (IsClickSwitchBtn) { + modifyAlarmPlan(state); + } + + } + }); + + mCloudMealBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton view, boolean state) { + // 如果是手势触发,则进行网络请求 + if (IsClickCloudMealBtn) { + //暂不支持此功能 +// Toast.makeText(DeviceSetActivity.this, "Not support now", Toast.LENGTH_SHORT).show(); + setStorageStrategy(state); + } + } + }); + + mModifyPwd.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + modifyDevicePassword(); + } + }); + + mUpgrade.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + if (!mCanBeUpgrade) { + Toast.makeText(DeviceSetActivity.this, "No upgrade", Toast.LENGTH_SHORT).show(); + return; + } + + UpgradeDevice(); + } + }); + } + + /** + * 设置云套餐状态 + * + * @param states + * 开启关闭状态 + */ + public void setStorageStrategy(final boolean state) { + + mCloudMealBtn.setClickable(false); + String states = null; + if (state) { + states = "on"; + } else { + states = "off"; + } + Business.getInstance().setStorageStartegy(states, mChannelUUID, + new Handler() { + + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + DeviceSetActivity.this, + R.string.toast_storagestrategy_update_success, + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + DeviceSetActivity.this, + R.string.toast_storagestrategy_update_failed, + Toast.LENGTH_SHORT).show(); + IsClickCloudMealBtn = false; + mCloudMealBtn.setChecked(!state); + } + IsClickCloudMealBtn = true; + mCloudMealBtn.setClickable(true); + } + }); + } + + /** + * 修改动检计划状态 + * + * @param enable + * 动检计划开启与否 + */ + public void modifyAlarmPlan(final boolean enable) { + + mSwitch.setClickable(false); + Business.getInstance().modifyAlarmStatus(enable, mChannelUUID, + new Handler() { + + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText(DeviceSetActivity.this, + R.string.toast_alarmplan_modifyalarmstatus_success, + Toast.LENGTH_LONG).show(); + + mSharedPreferences + .edit() + .putString("alarmPlan", enable ? "open" : "close").commit(); + } else { + Toast.makeText(DeviceSetActivity.this, + R.string.toast_alarmplan_modifyalarmstatus_failed, + Toast.LENGTH_LONG).show(); + IsClickSwitchBtn = false; + mSwitch.setChecked(!enable); + } + IsClickSwitchBtn = true; + mSwitch.setClickable(true); + } + + }); + } + + /** + * 修改设备密码 + */ + public void modifyDevicePassword() { + LinearLayout layout = (LinearLayout) LinearLayout.inflate(this, R.layout.dialog_modify_device_password, null); + final EditText oldPwd = (EditText) layout.findViewById(R.id.old_pwd); + final EditText newPwd = (EditText) layout.findViewById(R.id.new_pwd); + new AlertDialog.Builder(DeviceSetActivity.this) + .setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info) + .setView(layout) + .setPositiveButton(R.string.dialog_positive, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + String oldKey = oldPwd.getText().toString(); + String newKey = newPwd.getText().toString(); + String deviceId = Business.getInstance().getChannel(mChannelUUID).getDeviceCode(); + + Business.getInstance().modifyDevicePwd(deviceId, oldKey, newKey, new Handler(){ + @Override + public void handleMessage(Message msg) { + RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0) { + Toast.makeText(DeviceSetActivity.this, "modigyDevicePwd success", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(DeviceSetActivity.this, retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + } + }); + } + }).setNegativeButton(R.string.dialog_negative, null).show(); + } + + /** + * 设备云升级 + */ + public void UpgradeDevice() { + + mUpgrade.setClickable(false); + Business.getInstance().upgradeDevice(mChannelUUID, new Handler() { + + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText(DeviceSetActivity.this, + R.string.toast_cloudupdate_success, + Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(DeviceSetActivity.this, + R.string.toast_cloudupdate_failed, + Toast.LENGTH_LONG).show(); + } + mUpgrade.setClickable(true); + } + + }); + } +} diff --git a/app/src/main/java/com/lechange/demo/manager/SoftAPActivity.java b/app/src/main/java/com/lechange/demo/manager/SoftAPActivity.java new file mode 100644 index 0000000..06afe02 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/manager/SoftAPActivity.java @@ -0,0 +1,608 @@ +package com.lechange.demo.manager; + +import android.content.Intent; +import android.content.IntentFilter; +import android.net.wifi.WifiInfo; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.lechange.common.log.Logger; +import com.lechange.demo.dialog.PasswordDialog; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.util.WifiManagerUtil; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.listener.PasswordSetListener; +import com.lechange.demo.yonsz.TimeOutActivity; +import com.lechange.opensdk.api.bean.CheckDeviceBindOrNot; +import com.lechange.opensdk.api.bean.DeviceOnline; +import com.lechange.opensdk.softap.LCOpenSDK_SoftAPConfig; +import com.lechange.opensdk.utils.NetWorkUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.gateway.AddLCSafeCompleteActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.utils.AppIdUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.view.StateButton; +import com.yonsz.z1.view.TitleView; + +import java.util.HashMap; + +import de.greenrobot.event.EventBus; + +import static com.yonsz.z1.net.Constans.GATE_WAY; +import static com.yonsz.z1.net.Constans.UPDATE_SEC; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; +import static com.yonsz.z1.net.Constans.localAddAddressId; +import static com.yonsz.z1.net.NetWorkUrl.BIND_DEVICE; + +public class SoftAPActivity extends FragmentActivity implements Handler.Callback, View.OnClickListener, PasswordSetListener, Runnable { + + public static final String CONNECTIVITY_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + private static final String TAG = "LCOpenSDK_Demo_SoftAPActivity"; + private final int ON_LINE_SUCCESS = 0x11; + private final int ON_LINE_FAILED = 0x12; + private final int CHECK_DEVICE_ONLINE = 0X1B; + private final int ADD_DEVICE_SUCCESS = 0x13; + // MyBroadcastReceiver broadcastReceiver; + TextView mSSidView; + TitleView mTitleView; + private boolean isCheckOnline = true; + private boolean isSC = false; + private Handler handler; + Runnable checkRunnable = new Runnable() { + @Override + public void run() { + //30秒后移除在线检查,并且返回失败,正常情况第一次就可以查询到在线的状态 + handler.removeCallbacksAndMessages(CHECK_DEVICE_ONLINE); + handler.obtainMessage(ON_LINE_FAILED).sendToTarget(); + isCheckOnline = false; + Logger.d(TAG, "check online timeout"); + } + }; + private String devHotSpot = ""; + private String ssid = ""; + private String pwd = ""; + private String scCode = ""; + private String devId; + private String devType; + private WifiManagerUtil managerUtil; + private PasswordDialog passwordDialog; + private ProgressDialog mProgressDialog; // 播放加载使用 + private String key = ""; + private StateButton mStateButton; + private int sec = 120; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.soft_ap_activity); + // 绘制标题 + mTitleView = (TitleView) findViewById(R.id.title_lecheng_add); + mTitleView.setHead("设备添加"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + mStateButton = (StateButton) findViewById(R.id.bt_sec); + mProgressDialog = (ProgressDialog) this.findViewById(R.id.query_load); + /*findViewById(R.id.start_softAP_config).setOnClickListener(this); + findViewById(R.id.start_check_online).setOnClickListener(this);*/ + managerUtil = new WifiManagerUtil(getApplicationContext()); + devId = getIntent().getStringExtra("devId"); + devType = getIntent().getStringExtra("devType"); + ssid = getIntent().getStringExtra("ssid"); + pwd = getIntent().getStringExtra("mPwd"); + scCode = getIntent().getStringExtra("scCode"); + if (scCode != null && scCode.length() == 8) { + isSC = true; + } + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(CONNECTIVITY_CHANGE_ACTION); + // broadcastReceiver=new MyBroadcastReceiver(); + // registerReceiver(broadcastReceiver, intentFilter); + handler = new Handler(this); + passwordDialog = new PasswordDialog(); + passwordDialog.setListener(this); + devHotSpot = devType + "-" + devId.substring(devId.length() - 4); + // mSSidView.setText(getResources().getString(R.string.connect_wifi_name) + " : " + ssid); + + startApConfig(); + + handler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + } + + + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case LCOpenSDK_SoftAPConfig.MSG_WHAT: + mProgressDialog.setStop(); + Toast.makeText(getApplicationContext(), String.valueOf(msg.arg1), Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), getResources().getString(R.string.switch_wifi_and_start_check_online), Toast.LENGTH_LONG).show(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + checkOnlineState(); + } + }, 35000); + break; + case CHECK_DEVICE_ONLINE: + // checkOnline(); + // checkOnBindAndRemind(); + bindDevice(); + // unBindDevice(); + break; + case ON_LINE_FAILED: + Logger.d(TAG, "check_online_failed"); + Toast.makeText(getApplicationContext(), "check_online_failed", Toast.LENGTH_SHORT).show(); + handler.removeCallbacksAndMessages(CHECK_DEVICE_ONLINE); + mProgressDialog.setStop(); + break; + case ON_LINE_SUCCESS: + //设备在线 + Logger.d(TAG, "check_online_success"); + handler.removeCallbacks(checkRunnable); + if (scCode != null && scCode.length() == 8) { + key = scCode; + bindDevice(); + Logger.d(TAG, "scDevice, key = " + key + ", scCode = " + scCode); + } else { + unBindDeviceInfo(); + } + mProgressDialog.setStart(getResources().getString(R.string.binding_device)); + break; + case ADD_DEVICE_SUCCESS: + mProgressDialog.setStop(); + Logger.d(TAG, "add_device_success"); + Toast.makeText(getApplicationContext(), "SuccessAddDevice", Toast.LENGTH_SHORT).show(); + /*startActivity(new Intent(SoftAPActivity.this, DevicelistActivity.class)); + finish();*/ + EventBus.getDefault().post( + new ChooseHomeEvent("5")); + EventBus.getDefault().post( + new EventBusEntity("关闭")); + Intent intent = new Intent(SoftAPActivity.this, AddLCSafeCompleteActivity.class); + intent.putExtra("deviceType", GATE_WAY); + intent.putExtra("deviceSN", devId); + intent.putExtra("deviceModel", "1"); + intent.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + startActivity(intent); + finish(); + break; + case UPDATE_SEC: + if (sec > 1 && sec < 121) { + sec--; + handler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + mStateButton.setText(getResources().getString(R.string.sec_30, sec)); + } else if (sec <= 1) { + gotoTimeOutActivity(); + } + break; + + + } + + return false; + } + + private void gotoTimeOutActivity() { + EventBus.getDefault().post( + new EventBusEntity("关闭")); + Intent intent1 = new Intent(SoftAPActivity.this, TimeOutActivity.class); + intent1.putExtra("ssid", ssid); + intent1.putExtra("pwd", pwd); + intent1.putExtra("devId", devId); + intent1.putExtra("scCode", scCode); + intent1.putExtra("devType", devType); + intent1.putExtra("from", "SoftAPActivity"); + startActivity(intent1); + finish(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + /*case R.id.start_softAP_config: + startApConfig(); + + // } else { + // Toast.makeText(getApplicationContext(), getString(R.string.connect_device_wifi), Toast.LENGTH_SHORT).show(); + // } + break; + + case R.id.start_check_online: + checkOnlineState(); + break;*/ + } + } + + private void checkOnlineState() { + isCheckOnline = true; + handler.obtainMessage(CHECK_DEVICE_ONLINE).sendToTarget(); + handler.postDelayed(checkRunnable, 30 * 1000); + mProgressDialog.setStart(getResources().getString(R.string.checking_device_online)); + } + + private void startApConfig() { + if (!managerUtil.isWifi(getApplicationContext())) { + Toast.makeText(getApplicationContext(), getString(R.string.connect_device_wifi), Toast.LENGTH_SHORT).show(); + return; + } + Logger.d(SoftAPActivity.this.getClass().getSimpleName(), " devHotSpot : " + devHotSpot); + // if (isConnectedDevHot()) { + if (null != passwordDialog && !passwordDialog.isAdded()) { + handler.removeCallbacks(SoftAPActivity.this); + mProgressDialog.setStart(getString(R.string.search_devices)); + Business.getInstance().searchDevice(devId, 30 * 1000, new Handler() { + public void handleMessage(final Message msg) { + if (msg.what == 0 || msg.what == 1 || msg.what == 2) { + /*//需要初始化 + passwordDialog.setCurrentType(1); + passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + } else if (msg.what == 2) { + //已经初始化 + passwordDialog.setCurrentType(2); + passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + } else if (msg.what == 0) { + //不需要初始化 + passwordDialog.setCurrentType(0); + passwordDialog.show(getSupportFragmentManager(), "passwordDialog");*/ + mProgressDialog.setStart(getResources().getString(R.string.soft_ap_config)); + key = scCode; + LCOpenSDK_SoftAPConfig.startSoftAPConfig(ssid, pwd, devId, key, isSC, handler, 30 * 1000); + } else { + Toast.makeText(getApplicationContext(), getResources().getString(R.string.search_devices_timeout), Toast.LENGTH_LONG).show(); + mProgressDialog.setStop(); + } + } + }); + + } + } + + + //是否已连上设备热点 + public boolean isConnectedDevHot() { + // return true; + boolean isWifiConnected = NetWorkUtil.NetworkType.NETWORK_WIFI.equals(NetWorkUtil.getNetworkType(getApplicationContext())); + WifiInfo wifiInfo = managerUtil.getCurrentWifiInfo(); + if (wifiInfo == null || !isWifiConnected) { + return false; + } else { + String ssid = "\"" + this.devHotSpot + "\""; + return wifiInfo.getSSID().equals(ssid); + } + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + // unregisterReceiver(broadcastReceiver); + LCOpenSDK_SoftAPConfig.cancel(); + if (handler != null) { + handler.removeCallbacksAndMessages(null); + isCheckOnline = false; + handler = null; + } + + } + + + /** + * 校验在线 + */ + private void checkOnline() { + Business.getInstance().checkOnline(devId, + new Handler() { + @Override + public void handleMessage(Message msg) { + Business.RetObject retObject = (Business.RetObject) msg.obj; + switch (msg.what) { + case 0: + if (((DeviceOnline.Response) retObject.resp).data.onLine.equals("1")) { + handler.obtainMessage(ON_LINE_SUCCESS).sendToTarget(); + } else { + if (isCheckOnline) { + Logger.d(TAG, "onLine : " + ((DeviceOnline.Response) retObject.resp).data.onLine); + handler.obtainMessage(CHECK_DEVICE_ONLINE).sendToTarget(); + } + } + break; + case -1000: + Logger.e(TAG, "check_online_respond : -1000 " + ((Business.RetObject) msg.obj).mMsg); + handler.obtainMessage(ON_LINE_FAILED).sendToTarget(); + Toast.makeText(getApplicationContext(), ((Business.RetObject) msg.obj).mMsg, Toast.LENGTH_SHORT).show(); + break; + default: + Logger.e(TAG, "checkonline : " + msg.what); + handler.obtainMessage(ON_LINE_FAILED).sendToTarget(); + Toast.makeText(getApplicationContext(), ((Business.RetObject) msg.obj).mMsg, Toast.LENGTH_SHORT).show(); + break; + } + } + }); + + } + + private void unBindDevice() { + Business.getInstance().unBindDevice(devId, new Handler() { + @Override + public void handleMessage(Message msg) { + Business.RetObject retObject = (Business.RetObject) msg.obj; + if (msg.what == 0) { + Toast.makeText(getApplicationContext(), R.string.toast_device_delete_success, Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(getApplicationContext(), retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + + } + }); + } + + private void unBindDeviceInfo() { + Logger.e(TAG, "------------isOversea = " + Business.getInstance().isOversea()); + if (!Business.getInstance().isOversea()) { + + Business.getInstance().unBindDeviceInfo(devId, new Handler() { + public void handleMessage(Message msg) { + String message = (String) msg.obj; + // Log.d(tag, "unBindDeviceInfo,"+message); + if (msg.what == 0) { + if (message.contains("Auth")) { + Logger.d(TAG, " Auth bindDevice(), key = :" + key + ", deviceID = " + devId); + bindDevice(); + } else if (message.contains("RegCode")) { + /*final EditText et = new EditText(SoftAPActivity.this); + final AlertDialog dialog = new AlertDialog.Builder(SoftAPActivity.this) + .setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info) + .setView(et) + .setPositiveButton(R.string.dialog_positive, null) + .setNegativeButton(R.string.dialog_negative, null) + .create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + if (TextUtils.isEmpty(et.getText())) { + Toast.makeText(getApplicationContext(), "Input can't be empty", Toast.LENGTH_SHORT).show(); + return; + } + key = et.getText().toString(); + bindDevice(); + dialog.dismiss(); + } + });*/ + key = scCode; + bindDevice(); + } else { + key = ""; + bindDevice(); + } + } else { + mProgressDialog.setStop(); + Toast.makeText(getApplicationContext(), "unBindDeviceInfo failed", Toast.LENGTH_SHORT).show(); + Logger.d(TAG, message); + } + } + }); + } else { //oversea + Logger.d(TAG, " oversea bindDevice(), key = :" + key + ", deviceID = " + devId); + bindDevice(); + } + + } + + + /** + * 绑定 + */ + /*private void bindDevice() { + //设备绑定 + Business.getInstance().bindDevice(devId, key, + new Handler() { + @Override + public void handleMessage(Message msg) { + Business.RetObject retObject = (Business.RetObject) msg.obj; + if (msg.what == 0) { + handler.obtainMessage(ADD_DEVICE_SUCCESS).sendToTarget(); + } else { + Toast.makeText(getApplicationContext(), getResources().getString(R.string.addDevice_failed), Toast.LENGTH_SHORT).show(); + Logger.d(TAG, retObject.mMsg); + } + } + }); + }*/ + + + /** + * 绑定 + */ + private void bindDevice() { + com.yonsz.z1.net.NetWorkUtil netWorkUtil = com.yonsz.z1.net.NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", devId); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + map.put("code", key); + if (AppIdUtil.isBaseZhiKong()) { + map.put("addressId", localAddAddressId); + } else { + if (null != getIntent().getExtras().get("deviceAddress")) { + map.put("addressId", getIntent().getExtras().get("deviceAddress").toString()); + } else { + map.put("addressId", "1"); + } + } + map.put("deviceModel", "1"); + map.put("thirdModel", "G2"); + map.put("deviceType", GATE_WAY); + map.put("wifiName", ssid); + if (null != homeListEntity && !TextUtils.isEmpty(homeListEntity.getData().get(deviceNumListPosition).getFloorList())) { + if (null != getIntent().getExtras().get("floor")) { + map.put("floor", getIntent().getExtras().get("floor").toString()); + } + } + netWorkUtil.requestPostByAsynewApi(BIND_DEVICE, map, new com.yonsz.z1.net.NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("bindDevice", "onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + handler.obtainMessage(ADD_DEVICE_SUCCESS).sendToTarget(); + } else { + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(getApplicationContext(), obj.getMsg(), Toast.LENGTH_SHORT).show(); + } + }); + } + } + + @Override + public void onFail(String message) { +// Toast.makeText(getApplicationContext(), getResources().getString(R.string.addDevice_failed), Toast.LENGTH_SHORT).show(); + } + }); + } + + + @Override + public void onSaveSuccess(String psw1) { + mProgressDialog.setStart(getResources().getString(R.string.soft_ap_config)); + // if(Business.getInstance().isOversea()){//海外软AP需携带code过去 + key = psw1; + // } + LCOpenSDK_SoftAPConfig.startSoftAPConfig(ssid, pwd, devId, psw1, isSC, handler, 30 * 1000); + } + + @Override + public void onWifiPassWord(String psw1) { + + } + + @Override + public void run() { + //超时操作 + Toast.makeText(getApplicationContext(), getString(R.string.switch_wifi_timeout), Toast.LENGTH_SHORT).show(); + } + + /** + * 检查是否已被绑定 + */ + public void checkOnBindAndRemind() { + Business.getInstance().checkBindOrNot(devId, + new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + Business.RetObject retObject = (Business.RetObject) msg.obj; + if (msg.what == 0) { + CheckDeviceBindOrNot.Response resp = (CheckDeviceBindOrNot.Response) retObject.resp; + if (!resp.data.isBind) { + checkOnline(); + } else if (resp.data.isBind && resp.data.isMine) { + Toast.makeText(getApplicationContext(), getString(R.string.toast_adddevice_already_binded_by_self), Toast.LENGTH_SHORT).show(); + handler.removeCallbacks(checkRunnable); + mProgressDialog.setStop(); + } else { + Toast.makeText(getApplicationContext(), getString(R.string.toast_adddevice_already_binded_by_others), Toast.LENGTH_SHORT).show(); + handler.removeCallbacks(checkRunnable); + mProgressDialog.setStop(); + } + } else { + Toast.makeText(getApplicationContext(), retObject.mMsg, Toast.LENGTH_SHORT).show(); + handler.removeCallbacks(checkRunnable); + mProgressDialog.setStop(); + } + } + }); + } + + // public class MyBroadcastReceiver extends android.content.BroadcastReceiver { + // @Override + // public void onReceive(Context context, Intent intent) { + // if (intent.getAction().equals(CONNECTIVITY_CHANGE_ACTION)) { + // if (isConnectedDevHot()) { + // if (null != passwordDialog && !passwordDialog.isAdded()) { + // handler.removeCallbacks(SoftAPActivity.this); + // mProgressDialog.setStart(getString(R.string.switch_wifi_success)); + // Business.getInstance().searchDevice(devId, 30 * 1000, new Handler() { + // public void handleMessage(final Message msg) { + // if (msg.what == 1) { + // passwordDialog.setCurrentType(1); + // passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + // } else if (msg.what == 2) { + // Toast.makeText(getApplicationContext(), getString(R.string.please_reset_device), Toast.LENGTH_LONG).show(); + // passwordDialog.setCurrentType(1); + // passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + // } else if (msg.what == 0) { + // passwordDialog.setCurrentType(1); + // passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + // } + // } + // }); + // + // } + // + // } + // } + // + // } + // } + + + @Override + protected void onResume() { + super.onResume(); + // if (isConnectedDevHot()) { + // if (null != passwordDialog && !passwordDialog.isAdded()) { + // handler.removeCallbacks(SoftAPActivity.this); + // mProgressDialog.setStart(getString(R.string.switch_wifi_success)); + // Business.getInstance().searchDevice(devId, 30 * 1000, new Handler() { + // public void handleMessage(final Message msg) { + // if (msg.what == 1) { + // passwordDialog.setCurrentType(1); + // passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + // } else if (msg.what == 2) { + // Toast.makeText(getApplicationContext(), getString(R.string.please_reset_device), Toast.LENGTH_LONG).show(); + // mProgressDialog.setStop(); + // } else if (msg.what == 0) { + // passwordDialog.setCurrentType(1); + // passwordDialog.show(getSupportFragmentManager(), "passwordDialog"); + // } + // } + // }); + // } + // } + } +} diff --git a/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayActivity.java b/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayActivity.java new file mode 100644 index 0000000..d7d0ebf --- /dev/null +++ b/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayActivity.java @@ -0,0 +1,218 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayActivity.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.mediaplay; + +import android.Manifest; +import android.content.Intent; +import android.os.Bundle; +import android.os.Message; +import android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.View; + +import com.lechange.demo.business.Business; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.util.PermissionHelper; +import com.lechange.demo.mediaplay.fragment.MediaPlayFragment; +import com.lechange.demo.mediaplay.fragment.MediaPlayOnlineFragment; +import com.lechange.demo.yonsz.CameraDetailActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.view.TitleView; + +import java.util.ArrayList; + +import de.greenrobot.event.EventBus; + +/** + * 描述:视频播放Activity 作者: lc + */ +public class MediaPlayActivity extends BaseActivity implements + MediaPlayFragment.BackHandlerInterface, + OnRequestPermissionsResultCallback { + public static final int IS_VIDEO_ONLINE = 1; + public static final int IS_VIDEO_REMOTE_RECORD = 2; + public static final int IS_VIDEO_REMOTE_CLOUD_RECORD = 3; + private final static String tag = "MediaPlayActivity"; + private TitleView mTitleView; + private MediaPlayFragment mMediaPlayFragment; + private ArrayList uuidStringList; + private int firstPosition; + + public void onEventMainThread(EventBusEntity event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + if (msg.equals("关闭")) { + finish(); + } + } + + public void onEventMainThread(ChooseHomeEvent event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + if (msg.equals("1") || msg.equals("3") || msg.equals("2") || msg.equals("5")) { + + } else { + mTitleView.setHead(msg); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_media_video); + initView(); + } + + private void initView() { + /*uuidStringList = getIntent().getExtras().getStringArrayList("UUIDStringList"); + firstPosition = (int) getIntent().getExtras().get("position");*/ + ChannelInfo channel = Business.getInstance().getChannel(getIntent().getStringExtra("UUID")); + mTitleView = (TitleView) findViewById(R.id.title_media_play); + if (null != channel) { + mTitleView.setHead(channel.getName()); + } else { + mTitleView.setHead("实时预览"); + } + mTitleView.setHeadFuntion(R.drawable.icon_setup); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + // Intent intent = new Intent(MediaPlayActivity.this, DeviceSetActivity.class); + Intent intent = new Intent(MediaPlayActivity.this, CameraDetailActivity.class); + intent.putExtra("UUID", getIntent().getStringExtra("UUID")); + intent.putExtra("alarmPlanStatus", true); + intent.putExtra("cloudMealStatus", true); + startActivity(intent); + } + + @Override + public void onFunctionText() { + + } + }); + + PermissionHelper.requestPermission(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}); + // 嵌入使用的帧 + MediaPlayFragment mediaPlayFragment; // 引用的布局帧 + Bundle b = new Bundle(); + String resId; // 资源id号 + mediaPlayFragment = new MediaPlayOnlineFragment(); + // VideoContainerFragment containerFragment = new VideoContainerFragment(); + resId = getIntent().getStringExtra("UUID"); + // resId = uuidStringList.get(firstPosition); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + /*switch (getIntent().getIntExtra("TYPE", 0)) { + case IS_VIDEO_ONLINE: + mediaPlayFragment = new MediaPlayOnlineFragment(); + // VideoContainerFragment containerFragment = new VideoContainerFragment(); + resId = getIntent().getStringExtra("UUID"); + // resId = uuidStringList.get(firstPosition); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + *//*containerFragment.setArguments(b); + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, containerFragment) + .commitAllowingStateLoss();*//* + break; + case IS_VIDEO_REMOTE_RECORD: + mediaPlayFragment = new MediaPlayBackFragment(); + resId = getIntent().getStringExtra("ID"); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + break; + case IS_VIDEO_REMOTE_CLOUD_RECORD: + mediaPlayFragment = new MediaPlayBackFragment(); + resId = getIntent().getStringExtra("ID"); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + break; + default: + break; + }*/ + } + + /** + * boolean) 描述:切换fragment + */ + public void changeFragment(Fragment targetFragment, boolean isAddToStack) { + if (isAddToStack) { + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, targetFragment) + .addToBackStack(null).commitAllowingStateLoss(); + } else { + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, targetFragment) + .commitAllowingStateLoss(); + } + + } + + @Override + public void onBackPressed() { + if (mMediaPlayFragment == null || !mMediaPlayFragment.onBackPressed()) { + Log.d(tag, "onBackPressed"); + super.onBackPressed(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().post( + new ChooseHomeEvent("5")); + } + + @Override + public void callBackUiThread(Message msg) { + + } + + @Override + public void setSelectedFragment(MediaPlayFragment backHandledFragment) { + // TODO Auto-generated method stub + this.mMediaPlayFragment = backHandledFragment; + } + + // 横竖屏切换需要,隐藏标题栏 + public void toggleTitle(boolean isShow) { + mTitleView.setVisibility(isShow ? View.VISIBLE : View.GONE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String[] permissions, int[] grantResults) { + + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + // if (grantResults.length == 1 + // && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // + // } else { + // Toast.makeText(this, R.string.no_access_write_external_storage, + // Toast.LENGTH_SHORT).show(); + // } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayBackActivity.java b/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayBackActivity.java new file mode 100644 index 0000000..234314c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/mediaplay/MediaPlayBackActivity.java @@ -0,0 +1,197 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayActivity.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.mediaplay; + +import android.Manifest; +import android.content.Intent; +import android.os.Bundle; +import android.os.Message; +import android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.View; + +import com.lechange.demo.business.util.PermissionHelper; +import com.lechange.demo.mediaplay.fragment.MediaPlayBackFragment; +import com.lechange.demo.mediaplay.fragment.MediaPlayFragment; +import com.lechange.demo.yonsz.CameraDetailActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.view.TitleView; + +import java.util.ArrayList; + +import de.greenrobot.event.EventBus; + +/** + * 描述:视频播放Activity 作者: lc + */ +public class MediaPlayBackActivity extends BaseActivity implements + MediaPlayFragment.BackHandlerInterface, + OnRequestPermissionsResultCallback { + public static final int IS_VIDEO_ONLINE = 1; + public static final int IS_VIDEO_REMOTE_RECORD = 2; + public static final int IS_VIDEO_REMOTE_CLOUD_RECORD = 3; + private final static String tag = "MediaPlayActivity"; + private TitleView mTitleView; + private MediaPlayFragment mMediaPlayFragment; + private ArrayList uuidStringList; + private int firstPosition; + + public void onEventMainThread(EventBusEntity event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_media_video); + initView(); + } + + private void initView() { + /*uuidStringList = getIntent().getExtras().getStringArrayList("UUIDStringList"); + firstPosition = (int) getIntent().getExtras().get("position");*/ + mTitleView = (TitleView) findViewById(R.id.title_media_play); + mTitleView.setHead("本地录像"); + mTitleView.setHeadFuntion(R.drawable.icon_setup); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + // Intent intent = new Intent(MediaPlayActivity.this, DeviceSetActivity.class); + Intent intent = new Intent(MediaPlayBackActivity.this, CameraDetailActivity.class); + intent.putExtra("UUID", getIntent().getStringExtra("UUID")); + intent.putExtra("alarmPlanStatus", true); + intent.putExtra("cloudMealStatus", true); + startActivity(intent); + } + + @Override + public void onFunctionText() { + + } + }); + + PermissionHelper.requestPermission(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}); + // 嵌入使用的帧 + MediaPlayBackFragment mediaPlayFragment; // 引用的布局帧 + Bundle b = new Bundle(); + String resId; // 资源id号 + mediaPlayFragment = new MediaPlayBackFragment(); + resId = getIntent().getStringExtra("ID"); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + /*switch (getIntent().getIntExtra("TYPE", 0)) { + case IS_VIDEO_ONLINE: + mediaPlayFragment = new MediaPlayOnlineFragment(); + // VideoContainerFragment containerFragment = new VideoContainerFragment(); + resId = getIntent().getStringExtra("UUID"); + // resId = uuidStringList.get(firstPosition); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + *//*containerFragment.setArguments(b); + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, containerFragment) + .commitAllowingStateLoss();*//* + break; + case IS_VIDEO_REMOTE_RECORD: + mediaPlayFragment = new MediaPlayBackFragment(); + resId = getIntent().getStringExtra("ID"); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + break; + case IS_VIDEO_REMOTE_CLOUD_RECORD: + mediaPlayFragment = new MediaPlayBackFragment(); + resId = getIntent().getStringExtra("ID"); + b.putString("RESID", resId); + mediaPlayFragment.setArguments(b); + changeFragment(mediaPlayFragment, false); + break; + default: + break; + }*/ + } + + /** + * boolean) 描述:切换fragment + */ + public void changeFragment(Fragment targetFragment, boolean isAddToStack) { + if (isAddToStack) { + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, targetFragment) + .addToBackStack(null).commitAllowingStateLoss(); + } else { + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, targetFragment) + .commitAllowingStateLoss(); + } + + } + + @Override + public void onBackPressed() { + if (mMediaPlayFragment == null || !mMediaPlayFragment.onBackPressed()) { + Log.d(tag, "onBackPressed"); + super.onBackPressed(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().post( + new ChooseHomeEvent("5")); + } + + @Override + public void callBackUiThread(Message msg) { + + } + + @Override + public void setSelectedFragment(MediaPlayFragment backHandledFragment) { + // TODO Auto-generated method stub + this.mMediaPlayFragment = backHandledFragment; + } + + // 横竖屏切换需要,隐藏标题栏 + public void toggleTitle(boolean isShow) { + mTitleView.setVisibility(isShow ? View.VISIBLE : View.GONE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String[] permissions, int[] grantResults) { + + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + // if (grantResults.length == 1 + // && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // + // } else { + // Toast.makeText(this, R.string.no_access_write_external_storage, + // Toast.LENGTH_SHORT).show(); + // } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayBackFragment.java b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayBackFragment.java new file mode 100644 index 0000000..5990987 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayBackFragment.java @@ -0,0 +1,1124 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayBackFragment.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.mediaplay.fragment; + +import android.app.NotificationManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.media.AudioManager; +import android.media.MediaScannerConnection; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.CloudStorageCode; +import com.lechange.demo.business.Business.PlayerResultCode; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.business.util.TimeHelper; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.common.RecoderSeekBar; +import com.lechange.demo.localvideo.RecordListActivity; +import com.lechange.demo.localvideo.calendar.CalendarPopipWindow; +import com.lechange.demo.localvideo.timeshaftbar.TimerShaftBar; +import com.lechange.demo.localvideo.timeshaftbar.TimerShaftRegionItem; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.yonsz.z1.R; +import com.yonsz.z1.utils.DateTimeUitl; +import com.yonsz.z1.view.loading.LoadingDialog; + +import java.io.FileOutputStream; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Queue; + +import static com.lechange.demo.mediaplay.fragment.MediaPlayOnlineFragment.getLoacalBitmap; + + +/** + * 描述:远程录像回放(目前包括录像回放和告警消息两个场景) 作者: lc + */ +public class MediaPlayBackFragment extends MediaPlayFragment implements OnClickListener { + static private boolean sthls = false; + private final String tag = "MediaPlayBackFragment"; + private RecordInfo recordInfo; + private ChannelInfo channelInfo; + //SeekBar使用 + private int progress; + private String beginTime; + private Queue mSeekQueue = new LinkedList(); //云录像时间记忆 + private LinearLayout mRecordMenu; + private RelativeLayout mRecordMenu1; + private ImageView mRecordPlayPause, mRecordPlayPause1; + private TextView mRecordStartTime; + private RecoderSeekBar mRecordSeekbar; + private TextView mRecordEndTime; + private ImageView mRecordScale, mRecordScale1, record_no_voice1; + private PlayStatus mOpenPlay = PlayStatus.play_close; //语音对讲状态 + + private TextView mCalendarTv; + private TimerShaftBar mTimerShaftBar; + private ArrayList mTimeShaftItems = new ArrayList<>(); + private LinearLayout ll_all_video; + private List mRecordList = new ArrayList<>(); + + private ImageView mLiveScreenshot; + private ImageView iv_screen_shot, mLiveRecord; + private LinearLayout ll_record_time; + private TextView tv_record_time; + private TextView netSpeedTv; + private Handler mHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case 100: + netSpeedTv.setText(msg.obj.toString()); + break; + } + super.handleMessage(msg); + } + }; + //计时器 + private boolean isRecord = false; + private Handler mhandle = new Handler(); + private boolean isPause = false;//是否暂停 + private long currentSecond = 0;//当前毫秒数 + private Runnable timeRunable = new Runnable() { + @Override + public void run() { + currentSecond = currentSecond + 1000; + tv_record_time.setText(DateTimeUitl.getFormatHMS(currentSecond)); + if (!isPause) { + //递归调用本runable对象,实现每隔一秒一次执行任务 + mhandle.postDelayed(this, 1000); + } + } + }; + + private TextView tv_before_day, tv_last_day; + private boolean isOpenVoice = true; + private long lastTimeToPlay; + private LoadingDialog mLoadingDialog; + + /** + * 描述:获取录像通道参数 + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle b = getArguments(); + if (b != null) { + String id = b.getString("RESID"); + recordInfo = Business.getInstance().getAllRecord(id); + channelInfo = Business.getInstance().getChannel(recordInfo.getChnlUuid()); + } + if (recordInfo == null && channelInfo == null) { + toast(getString(R.string.toast_playback_no_records)); + getActivity().finish(); + } + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View mView = inflater.inflate(R.layout.fragment_media_record, container, false); + //必须赋值,父类需要使用到 + mSurfaceParentView = (ViewGroup) mView.findViewById(R.id.record_window); + //初始化窗口大小 + LayoutParams mLayoutParams = (LayoutParams) mSurfaceParentView.getLayoutParams(); + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + mSurfaceParentView.setLayoutParams(mLayoutParams); + + mPlayWin.initPlayWindow(this.getActivity(), (ViewGroup) mView.findViewById(R.id.record_window_content),0, true); + + mProgressDialog = (ProgressDialog) mView.findViewById(R.id.record_play_load); + mReplayTip = (TextView) mView.findViewById(R.id.record_play_pressed); + + mRecordMenu = (LinearLayout) mView.findViewById(R.id.record_menu); + mRecordMenu1 = (RelativeLayout) mView.findViewById(R.id.record_menu1); + mRecordPlayPause = (ImageView) mView.findViewById(R.id.record_play_pause); + mRecordPlayPause1 = (ImageView) mView.findViewById(R.id.record_play_pause1); + mRecordStartTime = (TextView) mView.findViewById(R.id.record_startTime); + mRecordSeekbar = (RecoderSeekBar) mView.findViewById(R.id.record_seekbar); + mRecordEndTime = (TextView) mView.findViewById(R.id.record_endTime); + mRecordScale = (ImageView) mView.findViewById(R.id.record_scale); + mRecordScale1 = (ImageView) mView.findViewById(R.id.record_scale1); + record_no_voice1 = (ImageView) mView.findViewById(R.id.record_no_voice1); + iv_screen_shot = (ImageView) mView.findViewById(R.id.iv_screen_shot); + netSpeedTv = (TextView) mView.findViewById(R.id.tv_net_speed); + ll_record_time = (LinearLayout) mView.findViewById(R.id.ll_record_time); + tv_record_time = (TextView) mView.findViewById(R.id.tv_record_time); + mLiveRecord = (ImageView) mView.findViewById(R.id.live_record); + tv_before_day = (TextView) mView.findViewById(R.id.tv_before_day); + tv_last_day = (TextView) mView.findViewById(R.id.tv_last_day); + + + tv_before_day.setOnClickListener(this); + tv_last_day.setOnClickListener(this); + mLiveRecord.setOnClickListener(this); + mReplayTip.setOnClickListener(this); + mRecordPlayPause.setOnClickListener(this); + mRecordPlayPause1.setOnClickListener(this); + mRecordScale.setOnClickListener(this); + mRecordScale1.setOnClickListener(this); + record_no_voice1.setOnClickListener(this); + + mCalendarTv = (TextView) mView.findViewById(R.id.tv_calendar); + mLiveScreenshot = (ImageView) mView.findViewById(R.id.live_screenshot); + mLiveScreenshot.setOnClickListener(this); + + mLiveRecord.setEnabled(false); + mLiveScreenshot.setEnabled(false); + + SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd"); + final String dateStr = dateformat.format(System.currentTimeMillis()); + mCalendarTv.setText(dateStr); + mCalendarTv.setOnClickListener(this); + mCalendarTv.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + String s1 = s.toString(); + if (s1.equals(dateStr) || s1.compareTo(dateStr) > 0) { + tv_last_day.setVisibility(View.GONE); + } else { + tv_last_day.setVisibility(View.VISIBLE); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + ll_all_video = (LinearLayout) mView.findViewById(R.id.ll_all_video); + ll_all_video.setOnClickListener(this); + mTimerShaftBar = (TimerShaftBar) mView.findViewById(R.id.timershaft_bar); + mTimerShaftBar.setTimerShaftLayoutListener(new TimerShaftBar.TimerShaftBarListener() { + @Override + public void onTimerShaftBarPosChanged(Calendar calendar) { + Log.i("mTimerShaftBar", "onTimerShaftBarPosChanged " + calendar.getTime().toString()); + //滑动的时间 + if (mTimeShaftItems.size() == 0 || mRecordList.size() == 0) { + return; + } + long timeInMillis = calendar.getTimeInMillis(); + if (lastTimeToPlay != timeInMillis) { + stop(-1); + } + long firstStartTime = mTimeShaftItems.get(mTimeShaftItems.size() - 1).getStartTime(); + long lastEndTime = mTimeShaftItems.get(0).getEndTime(); + if (timeInMillis <= firstStartTime) { + // Toast.makeText(getContext(), "我在最左边", Toast.LENGTH_SHORT).show(); + // play(-1, 1, firstStartTime, mRecordList.get(0).getEndTime(), mRecordList.get(0).getRecordID()); + stop(-1); + Toast.makeText(getContext(), "暂无视频", Toast.LENGTH_SHORT).show(); + } else if (lastEndTime <= timeInMillis) { + stop(-1); + Toast.makeText(getContext(), "暂无视频", Toast.LENGTH_SHORT).show(); + } else { + for (int i = mTimeShaftItems.size() - 1; i >= 0; i--) { + long startTime = mTimeShaftItems.get(i).getStartTime(); + long endTime = mTimeShaftItems.get(i).getEndTime(); + Log.i("mTimeShaftItems", i + "/" + mTimeShaftItems.size() + "---" + startTime + "---" + endTime + "---" + timeInMillis); + //如果再最左边 + if (startTime <= timeInMillis && timeInMillis <= endTime) { + // Toast.makeText(getContext(), "播放第" + i + "个视频中间", Toast.LENGTH_SHORT).show(); + play(-1, 2, timeInMillis, endTime, mRecordList.get(i).getRecordID()); + i = -1; + } else if (timeInMillis <= startTime) { + Toast.makeText(getContext(), "暂无视频", Toast.LENGTH_SHORT).show(); + stop(-1); + // Toast.makeText(getContext(), "播放第" + i + "个视频开头", Toast.LENGTH_SHORT).show(); + /*play(-1, 1, startTime, endTime, mRecordList.get(i).getRecordID()); + i = -1;*/ + } else { + // Toast.makeText(getContext(), "还没到播放的那个", Toast.LENGTH_SHORT).show(); + } + } + } + } + + @Override + public void onTimerShaftBarDown() { + //按下的时间 + } + }); + if (null != getActivity().getIntent().getExtras().get("dateString")) { + long dateString = (long) getActivity().getIntent().getExtras().get("dateString"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd"); + String date = String.valueOf(sdf2.format(dateString)); + mCalendarTv.setText(date); + queryRecordNum(date, "0"); + + Calendar calendar = Calendar.getInstance(); // 默认是当前日期 + calendar.setTimeInMillis(dateString * 1000); + if (calendar != null) { + Log.i("onPlayTime", "onPlayTime calendar = " + calendar.getTime().toString()); + mTimerShaftBar.setPlayCalendar(calendar); + } + + } else { + queryRecordNum("1", "0"); + } + + initSeekBarAndTime(); + play(-1); + return mView; + } + + private void initLoadDialog() { + mLoadingDialog = new LoadingDialog(getContext()); + mLoadingDialog.setMessage("加载数据中"); + mLoadingDialog.show(); + } + + private void queryRecordNum(final String dateString, final String type) { + initLoadDialog(); + final String startTime; + final String endTime; + if (dateString.equals("1")) { + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + startTime = df.format(new Date()) + " 00:00:00"; + endTime = df.format(new Date()) + " 23:59:59"; + } else { + stop(-1); //无效资源号 + startTime = dateString + " 00:00:00"; + endTime = dateString + " 23:59:59"; + } + Business.getInstance().queryRecordNum(recordInfo.getChnlUuid(), startTime, endTime, new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + Toast.makeText(getContext(), getString(R.string.toast_recordlist_query_failed) + msg.what, Toast.LENGTH_SHORT).show(); + if (mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + } else if (msg.what == 0) { + if (msg.arg1 > 0) { + Business.getInstance().queryRecordList(recordInfo.getChnlUuid(), startTime, endTime, msg.arg2, msg.arg1, new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + Toast.makeText(getContext(), getString(R.string.toast_recordlist_query_failed) + msg.obj, Toast.LENGTH_SHORT).show(); + } else { + mTimeShaftItems.clear(); + mRecordList = (List) msg.obj; + List obj = (List) msg.obj; + if (obj != null && obj.size() > 0) { + Log.i(tag, "loadRecrodList mRecordList.size:" + mRecordList.size()); + for (int i = 0; i < obj.size(); i++) { + TimerShaftRegionItem timeShaftItem = new TimerShaftRegionItem(obj.get(i).getStartTime(), obj.get(i).getEndTime(), 0); + mTimeShaftItems.add(timeShaftItem); + } + mTimerShaftBar.setTimeShaftItems(mTimeShaftItems); + if (mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + if (type.equals("1")) { + play(-1, 2, mTimeShaftItems.get(mTimeShaftItems.size() - 1).getStartTime(), mTimeShaftItems.get(mTimeShaftItems.size() - 1).getEndTime(), mRecordList.get(mTimeShaftItems.size() - 1).getRecordID()); + } + } else { + if (mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + Toast.makeText(getContext(), "没有录像", Toast.LENGTH_SHORT).show(); + } + } + } + }); + } else { + mTimeShaftItems.clear(); + long currentWithFormate = 0; + try { + currentWithFormate = DateTimeUitl.dateToStamp(startTime); + } catch (ParseException e) { + e.printStackTrace(); + } + TimerShaftRegionItem timeShaftItem = new TimerShaftRegionItem(currentWithFormate, currentWithFormate, 0); + mTimeShaftItems.add(timeShaftItem); + mTimerShaftBar.setTimeShaftItems(mTimeShaftItems); + Toast.makeText(getContext(), "没有录像", Toast.LENGTH_SHORT).show(); + mProgressDialog.setStop(); //关闭加载窗口 + if (mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + } + } + } + }); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + //SeekBar监听 + setSeekBarListener(); + //禁止拖动 + setCanSeekChanged(false); + + listener = new MyBasePlayerEventListener(); + mPlayWin.setWindowListener(listener); + mPlayWin.openTouchListener(); + + //开启横竖屏切换 + startListener(); + } + + @Override + public void onResume() { + // TODO Auto-generated method stub + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + stop(-1); //无效资源号 + } + + @Override + public void onDestroyView() { + // TODO Auto-generated method stub + super.onDestroyView(); + mPlayWin.uninitPlayWindow();// 销毁底层资源 + } + + /** + * @param mConfiguration 描述:实现个性化界面 + */ + @Override + protected void resetViews(Configuration mConfiguration) { + super.resetViews(mConfiguration); + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + mRecordScale.setTag("LANDSCAPE"); + mRecordScale.setImageResource(R.drawable.record_btn_smallscreen); + mRecordScale1.setTag("LANDSCAPE"); + mRecordScale1.setImageResource(R.drawable.record_btn_smallscreen); + mRecordMenu.setVisibility(View.VISIBLE); + mRecordMenu1.setVisibility(View.GONE); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + mRecordScale.setTag("PORTRAIT"); + mRecordScale.setImageResource(R.drawable.record_btn_fullscreen); + mRecordScale1.setTag("PORTRAIT"); + mRecordScale1.setImageResource(R.drawable.record_btn_fullscreen); + mRecordMenu.setVisibility(View.GONE); + mRecordMenu1.setVisibility(View.VISIBLE); + } + + } + + private void initSeekBarAndTime() { + String mStartTime = TimeHelper.getTimeHMS(recordInfo.getStartTime()); + String mEndTime = TimeHelper.getTimeHMS(recordInfo.getEndTime()); + mRecordSeekbar.setMax((int) ((recordInfo.getEndTime() - recordInfo.getStartTime()) / 1000)); + mRecordSeekbar.setProgress(0); + mRecordStartTime.setText(mStartTime); + mRecordEndTime.setText(mEndTime); + } + + private void setSeekBarListener() { + mRecordSeekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + if (mRecordSeekbar.getMax() - MediaPlayBackFragment.this.progress <= 2) { + toast(getString(R.string.toast_playback_no_iframe)); + seek(mRecordSeekbar.getMax() >= 2 ? mRecordSeekbar.getMax() - 2 : 0); + } else { + seek(MediaPlayBackFragment.this.progress); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean byUser) { + if (byUser) { + MediaPlayBackFragment.this.progress = progress; + } + } + }); + } + + /** + * 描述:继续播放 + */ + public void resume() { + mPlayWin.resumeAsync(); + mOpenPlay = PlayStatus.play_open; + mRecordPlayPause.setImageResource(R.drawable.record_btn_pause); + mRecordPlayPause1.setImageResource(R.drawable.record_btn_pause); + } + + /** + * 描述:暂停播放 + */ + public void pause() { + mPlayWin.pauseAsync(); + mOpenPlay = PlayStatus.play_pause; + mRecordPlayPause.setImageResource(R.drawable.record_btn_play); + mRecordPlayPause1.setImageResource(R.drawable.record_btn_play); + } + + public boolean openAudio() { + return mPlayWin.playAudio() == retOK; + } + + public boolean closeAudio() { + return mPlayWin.stopAudio() == retOK; + } + + public void seek(int index) { + System.out.println("index:" + index); + + long seekTime = recordInfo.getStartTime() / 1000 + index; + //先暂存时间记录 + MediaPlayBackFragment.this.beginTime = TimeHelper.getTimeHMS(seekTime * 1000); + MediaPlayBackFragment.this.progress = index; + mRecordSeekbar.setProgress(index); + mRecordStartTime.setText(MediaPlayBackFragment.this.beginTime); + + mPlayWin.seek(index); + + // if (recordInfo != null&& (recordInfo.getType() == RecordInfo.RecordType.PublicCloud)) { + // if (mOpenPlay == PlayStatus.play_pause) { + // resume(); + // } + // mPlayWin.seek(index); + // System.out.println(tag + "tag-publicClound Seek to: " + index); + // }else{ + // playSeek(seekTime * 1000, recordInfo.getEndTime()); + // System.out.println(tag + "tag-deviceRecord Seek to: " + index); + // } + } + + public void play(int strRes, int type, long startTime, long endTime, String recordID) { + //if (mOpenPlay == PlayStatus.play_open) { + stop(-1); + //} + if (strRes > 0) { + showLoading(strRes); + } else { + showLoading(R.string.common_loading); + } + mOpenPlay = PlayStatus.play_opening; + mRecordPlayPause.setImageResource(R.drawable.record_btn_pause); + mRecordPlayPause1.setImageResource(R.drawable.record_btn_pause); + // mPlayWin.setStreamCallback(1); //启用标准流回调,测试代码 + if (recordInfo.getType() == RecordInfo.RecordType.PublicCloud) { + //播放起始时间默认设为0,开发者自行 + mPlayWin.playCloud(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + String.valueOf(channelInfo.getIndex()), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + recordInfo.getRecordID(), 1000, 0, 24 * 3600); + } else { + switch (type) { + case 1: + mPlayWin.playRtspPlayback(Business.getInstance().getToken(), channelInfo.getDeviceCode(), channelInfo.getIndex(), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), recordID, + startTime, endTime, 0, 0, true); + break; + case 2: + //按时间回放 + /*mPlayWin.playRtspPlaybackByUtcTime(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + channelInfo.getIndex(), startTime, endTime);*/ + + mPlayWin.playRtspPlayback(Business.getInstance().getToken(), channelInfo.getDeviceCode(), channelInfo.getIndex(), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), recordID, + startTime, endTime, 0, 0, true); + break; + case 3: + //按文件名回放,播放起始时间默认设为0,开发者自行修改 + /*mPlayWin.playRtspPlaybackByFileName(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + recordInfo.getRecordPath(), 0);*/ + break; + default: + + break; + } + } + + //允许拖动 + setCanSeekChanged(true); + } + + public void play(int strRes) { + //if (mOpenPlay == PlayStatus.play_open) { + stop(-1); + //} + if (strRes > 0) { + showLoading(strRes); + } else { + showLoading(R.string.common_loading); + } + mOpenPlay = PlayStatus.play_opening; + mRecordPlayPause.setImageResource(R.drawable.record_btn_pause); + mRecordPlayPause1.setImageResource(R.drawable.record_btn_pause); + // mPlayWin.setStreamCallback(1); //启用标准流回调,测试代码 + lastTimeToPlay = recordInfo.getStartTime(); + if (recordInfo.getType() == RecordInfo.RecordType.PublicCloud) { + //播放起始时间默认设为0,开发者自行 + mPlayWin.playCloud(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + String.valueOf(channelInfo.getIndex()), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + recordInfo.getRecordID(), 1000, 0, 24 * 3600); + } else { + mPlayWin.playRtspPlayback(Business.getInstance().getToken(), channelInfo.getDeviceCode(), channelInfo.getIndex(), + channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), recordInfo.getRecordID(), + recordInfo.getStartTime(), recordInfo.getEndTime(), 0, 0, true); + // //按时间回放 + // mPlayWin.playRtspPlaybackByUtcTime(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + // channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + // channelInfo.getIndex(), recordInfo.getStartTime(), recordInfo.getEndTime()); + + //按文件名回放,播放起始时间默认设为0,开发者自行修改 + // mPlayWin.playRtspPlaybackByFileName(Business.getInstance().getToken(), channelInfo.getDeviceCode(), + // channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), + // recordInfo.getRecordPath(), 0); + + } + + //允许拖动 + setCanSeekChanged(true); + } + + public void stop(final int res) { + //关闭播放加载控件 + mProgressDialog.setStop(); + stopPlayWindow(); + mOpenPlay = PlayStatus.play_close; + mRecordPlayPause.setImageResource(R.drawable.record_btn_play); + mRecordPlayPause1.setImageResource(R.drawable.record_btn_play); + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + if (res > 0) + showErrorTip(res); + } + } + }); + } + //禁止拖动 + setCanSeekChanged(false); + } + + // private void playSeek(long startTime, long endTime) { + // //打开加载进度栏 + // showLoading(R.string.common_loading); + // if (mOpenPlay != PlayStatus.play_close) { + // stopPlayWindow(); + // } + // mOpenPlay = PlayStatus.play_opening; + // mRecordPlayPause.setImageResource(R.drawable.record_btn_pause); + // + // mPlayWin.playRtspPlaybackByUtcTime(Business.getInstance().getToken(), + // channelInfo.getDeviceCode(), channelInfo.getEncryptKey() != null ? channelInfo.getEncryptKey() : channelInfo.getDeviceCode(), channelInfo.getIndex(), startTime, endTime); + // } + + /** + * 描述 :单独关闭播放 ! 注意:组件要求必须要主线程调用 + */ + public void stopPlayWindow() { + closeAudio();// 关闭音频 + if (recordInfo.getType() == RecordInfo.RecordType.PublicCloud) + mPlayWin.stopCloud(true); + else + mPlayWin.stopRtspPlayback(true);// 关闭视频 + } + + /** + * 描述:设置拖动进度条是否能使用 + */ + public void setCanSeekChanged(boolean canSeek) { + mRecordSeekbar.setCanTouchAble(canSeek); + } + + @Override + public void onClick(View view) { + // TODO Auto-generated method stub + switch (view.getId()) { + case R.id.record_play_pause: + case R.id.record_play_pause1: + switch (mOpenPlay) { + case play_open: + pause(); + break; + case play_pause: + resume(); + break; + case play_opening: + stop(-1); //因为准备播放过程异步执行,这个状态里,无法精准的控制停止操作 + break; + case play_close: + initSeekBarAndTime(); + // play(-1); + if (mTimeShaftItems.size() > 0) { + play(-1, 2, mTimeShaftItems.get(mTimeShaftItems.size() - 1).getStartTime(), mTimeShaftItems.get(mTimeShaftItems.size() - 1).getEndTime(), mRecordList.get(mTimeShaftItems.size() - 1).getRecordID()); + } + break; + default: + break; + } + break; + case R.id.record_scale: + case R.id.record_scale1: + if ("LANDSCAPE".equals(mRecordScale.getTag())) { + mOrientation = ORIENTATION.isPortRait; + getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else { + mOrientation = ORIENTATION.isLandScape; + getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + break; + case R.id.record_play_pressed: + initSeekBarAndTime(); + // play(-1); + if (mTimeShaftItems.size() > 0) { + play(-1, 2, mTimeShaftItems.get(mTimeShaftItems.size() - 1).getStartTime(), mTimeShaftItems.get(mTimeShaftItems.size() - 1).getEndTime(), mRecordList.get(mTimeShaftItems.size() - 1).getRecordID()); + } + break; + case R.id.tv_calendar: + showCalendarBottom(mCalendarTv.getText().toString()); + break; + case R.id.ll_all_video: + Intent intent1 = new Intent(getContext(), RecordListActivity.class); + intent1.putExtra("UUID", channelInfo.getUuid()); + intent1.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent1.putExtra("dateString", mCalendarTv.getText().toString()); + intent1.putExtra("MEDIA_TITLE", R.string.local_records_name); + startActivity(intent1); + break; + case R.id.record_no_voice1: + if (isOpenVoice) { + record_no_voice1.setImageResource(R.drawable.live_btn_sound_off); + closeAudio(); + isOpenVoice = false; + } else { + record_no_voice1.setImageResource(R.drawable.live_btn_sound_on); + openAudio(); + isOpenVoice = true; + } + /* AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + if (audioManager != null) { + if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { + record_no_voice1.setImageResource(R.drawable.live_btn_sound_on); + silentSwitchOff(audioManager); + openAudio(); + } else if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) { + record_no_voice1.setImageResource(R.drawable.live_btn_sound_off); + silentSwitchOn(audioManager); + closeAudio(); + } + }*/ + break; + case R.id.live_screenshot: + mLiveScreenshot.setImageResource(R.drawable.icon_photograph_pre); + capture(); + mLiveScreenshot.setImageResource(R.drawable.icon_photograph_nor); + break; + case R.id.live_record: + if (!isRecord) { + // boolean result = startRecord(); + if (true) { + toastWithImg(getString(R.string.video_monitor_media_record), R.drawable.live_pic_record); + isRecord = true; + isPause = false; + mLiveRecord.setImageResource(R.drawable.icon_videotape_pre); + ll_record_time.setVisibility(View.VISIBLE); + //显示录制时间 + timeRunable.run(); + } + } else { + isPause = true; + stopRecord(); + } + break; + case R.id.tv_before_day: + String beforeFromTarget = DateTimeUitl.getBeforeFromTarget(mCalendarTv.getText().toString()); + mCalendarTv.setText(beforeFromTarget); + queryRecordNum(beforeFromTarget, "1"); + break; + case R.id.tv_last_day: + String futureFromTarget = DateTimeUitl.getFutureFromTarget(mCalendarTv.getText().toString()); + mCalendarTv.setText(futureFromTarget); + queryRecordNum(futureFromTarget, "1"); + break; + default: + break; + } + } + + /** + * 关闭录像 + */ + public void stopRecord() { + mPlayWin.stopRecord(); + isRecord = false; + toast(getString(R.string.video_monitor_video_record_success)); + mLiveRecord.setImageResource(R.drawable.icon_videotape_nor); + currentSecond = 0; + ll_record_time.setVisibility(View.GONE); + + /*MediaScannerConnection.scanFile(getActivity(), new String[]{path}, + null, null);*/ + } + + /** + * 描述:抓拍图像 + */ + public String capture() { + String captureFilePath = null; + // 判断SD卡是否已存在 + // SD卡容量检查 + // FIXME 检查设备是否在线 + // 抓图 + String channelName = null; + if (channelInfo != null) { + channelName = channelInfo.getName(); + } else { + channelName = ""; + } + + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + + captureFilePath = MediaPlayHelper.getCaptureAndVideoPath(MediaPlayHelper.DHFilesType.DHImage, channelName); + int ret = mPlayWin.snapShot(captureFilePath); + if (ret == retOK) { + // 扫描到相册中 + MediaScannerConnection.scanFile(getActivity(), new String[]{captureFilePath}, null, null); + Bitmap loacalBitmap = getLoacalBitmap(captureFilePath); + iv_screen_shot.setImageBitmap(loacalBitmap); + iv_screen_shot.setVisibility(View.VISIBLE); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + iv_screen_shot.setVisibility(View.GONE); + } + }, 2000); + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_success, + Toast.LENGTH_SHORT).show(); + } else { + captureFilePath = null; + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_failed, + Toast.LENGTH_SHORT).show(); + } + return captureFilePath; + } + + //获取Do not disturb权限,才可进行音量操作 + private void getDoNotDisturb() { + NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !notificationManager.isNotificationPolicyAccessGranted()) { + Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); + startActivity(intent); + } + } + + private void showCalendarBottom(String date) { + View rootview = LayoutInflater.from(getContext()).inflate(R.layout.fragment_media_record, null); + CalendarPopipWindow popupWindow = new CalendarPopipWindow(getContext(), date.substring(0, 4) + "年" + date.substring(5, 7) + "月", new CalendarPopipWindow.OnCompleteListener() { + @Override + public void onComplete(String dayStr) { + /*int year = Integer.parseInt(dayStr.substring(0, 4)); + int month = Integer.parseInt(dayStr.substring(5, 7)); + int day = Integer.parseInt(dayStr.substring(dayStr.indexOf("月") + 1, dayStr.indexOf("日"))); + String date = DateTimeUitl.formatDateFromInt(year, month, day);*/ + mCalendarTv.setText(dayStr); + queryRecordNum(dayStr, "1"); + } + }); + popupWindow.showAtLocation(rootview, Gravity.BOTTOM, 0, 0); + } + + private void silentSwitchOn(AudioManager audioManager) { + if (audioManager != null) { + audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); + audioManager.getStreamVolume(AudioManager.STREAM_RING); + Log.d("Silent:", "RINGING 已被静音"); + } + } + + private void silentSwitchOff(AudioManager audioManager) { + if (audioManager != null) { + audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); + audioManager.getStreamVolume(AudioManager.STREAM_RING); + Log.d("SilentListenerService", "RINGING 取消静音"); + } + } + + private enum PlayStatus {play_close, play_open, play_opening, play_pause} + + class MyBasePlayerEventListener extends LCOpenSDK_EventListener { + @Override + public void onPlayerResult(int index, String code, int type) { + System.out.println("winIndex:" + "code:" + code + "type:" + type); + if (type == Business.RESULT_SOURCE_OPENAPI) { + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + System.out.println("save stop"); + stop(R.string.video_monitor_play_error); + } + } + }); + } + } else if (recordInfo != null && recordInfo.getType() == RecordInfo.RecordType.PublicCloud) { + if (code.equals(CloudStorageCode.HLS_DOWNLOAD_FAILD) || + code.equals(CloudStorageCode.HLS_KEY_ERROR)) { + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + System.out.println("save stop"); + stop(R.string.video_monitor_play_error); + } + } + }); + } + } else if (code.equals(CloudStorageCode.HLS_SEEK_FAILD)) { + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_seek_error); + } + } + }); + } + } + return; + } else if (code.equals(PlayerResultCode.STATE_RTSP_TEARDOWN_ERROR)) { + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_online_fail_restart); + } + } + }); + } + } else if (code.equals(PlayerResultCode.STATE_PACKET_FRAME_ERROR) || + code.equals(PlayerResultCode.STATE_RTSP_AUTHORIZATION_FAIL) || + code.equals(PlayerResultCode.STATE_RTSP_KEY_MISMATCH)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_play_error); + } + } + }); + } + } + } + + @Override + public void onStreamCallback(int index, byte[] data, int len) { + // Log.d(tag, "LCOpenSDK_EventListener::onStreamCallback-size : " + len); + try { + String path = Environment.getExternalStorageDirectory().getPath() + "/streamCallback.ts"; + FileOutputStream fout = new FileOutputStream(path, true); + fout.write(data); + fout.close(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Override + public void onPlayBegan(int index) { + // TODO Auto-generated method stub + if (recordInfo.getType() == RecordInfo.RecordType.PublicCloud) { + //if(code.equals(CloudStorageCode.HLS_DOWNLOAD_BEGIN)){ + // 云录像播放第二步 + System.out.println(tag + "*****+play pulic cloud video from CloudStorageCode.HLS_DOWNLOAD_BEGIN"); + if (mSeekQueue.size() > 0) { // 从上次停止的地方播放 + long time = mSeekQueue.poll(); + System.out.println(tag + "*****onPlay+play pulic cloud video from time:" + time); + mSeekQueue.clear(); + mPlayWin.seek(time); + } + // // 显示码率 + // if (mHander != null) { + // mHander.post(MediaPlayBackFragment.this); + // } + mOpenPlay = PlayStatus.play_open; + openAudio();//默认打开声音 + //关闭播放加载控件 + mProgressDialog.setStop(); + } else { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + mLiveRecord.setEnabled(true); + mLiveRecord.setAlpha(1.0f); + mLiveScreenshot.setAlpha(1.0f); + mLiveScreenshot.setEnabled(true); + } + }); + } + mTimerShaftBar.setRefereshPlayTimeWithPlayer(); + //if(code.equals(PlayerResultCode.STATE_RTSP_PLAY_READY)){ + // // 显示码率 + // if (mHander != null) { + // mHander.post(MediaPlayBackFragment.this); + // } + mOpenPlay = PlayStatus.play_open; + + openAudio();//默认打开声音 + //关闭播放加载控件 + mProgressDialog.setStop(); + } + } + + + @Override + public void onPlayFinished(int index) { + // TODO Auto-generated method stub + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_online_restart); + mLiveRecord.setAlpha(0.5f); + mLiveRecord.setEnabled(false); + mLiveScreenshot.setAlpha(0.5f); + mLiveScreenshot.setEnabled(false); + } + } + }); + } + } + + // @Override + // public void onReceiveData( int len) { + // // 流量统计 + // mTotalFlow += len; + // } + @Override + public void onPlayerTime(int index, final long current) { + System.out.println("timetest" + current); + long startTime; + if (sthls) { + startTime = 0; + } else { + startTime = recordInfo.getStartTime() / 1000; + } + MediaPlayBackFragment.this.progress = (int) (current - startTime); + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (sthls) { + if (isAdded()) { + mRecordSeekbar.setProgress(MediaPlayBackFragment.this.progress); + MediaPlayBackFragment.this.beginTime = TimeHelper.getTimeHMS(current * 1000); + int bh = (int) current / 3600; + int bm = (int) current / 60 % 60; + int bs = (int) current % 60; + MediaPlayBackFragment.this.beginTime = String.format(Locale.US, "%02d:%02d:%02d", bh, bm, bs); + System.out.println("onPlayerTimetest:" + MediaPlayBackFragment.this.beginTime); + mRecordStartTime.setText(MediaPlayBackFragment.this.beginTime); + } + } else { + if (isAdded()) { + mRecordSeekbar.setProgress(MediaPlayBackFragment.this.progress); + MediaPlayBackFragment.this.beginTime = TimeHelper.getTimeHMS(current * 1000); + mRecordStartTime.setText(MediaPlayBackFragment.this.beginTime); + Calendar calendar = Calendar.getInstance(); // 默认是当前日期 + calendar.setTimeInMillis(current * 1000); + if (calendar != null) { + // TODO: 2017/2/16 当前播放时间 + Log.i("onPlayTime", "onPlayTime calendar = " + calendar.getTime().toString()); + mTimerShaftBar.setPlayCalendar(calendar); + } + } + } + } + }); + } + } + + @Override + public void onWindowDBClick(int index, float dx, float dy) { + // TODO Auto-generated method stub + switch (mRecordMenu.getVisibility()) { + case View.GONE: + mRecordMenu.setVisibility(View.VISIBLE); + break; + case View.VISIBLE: + mRecordMenu.setVisibility(View.GONE); + break; + default: + break; + } + } + } +} diff --git a/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayFragment.java b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayFragment.java new file mode 100644 index 0000000..2dbbf3e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayFragment.java @@ -0,0 +1,266 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayFragment.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.mediaplay.fragment; + +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.hardware.SensorManager; +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.OrientationEventListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.demo.mediaplay.MediaPlayBackActivity; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; + + +/** + * 描述:视频播放组件基类 作者: lc + */ +public class MediaPlayFragment extends Fragment { + //底层返回值 + protected static final int retOK = 0; + protected static final int retNG = -1; + protected static final String AUDIO_TALK_ERROR = "-1000"; //实时对讲初始化失败 + private final static String tag = "MediaPlayFragment"; + protected LCOpenSDK_EventListener listener; + protected LCOpenSDK_PlayWindow mPlayWin = new LCOpenSDK_PlayWindow(); + protected Handler mHander = new Handler(); + // 统计当前累计总流量,单位:字节 + //protected long mTotalFlow; + protected ViewGroup mSurfaceParentView; + protected ProgressDialog mProgressDialog; //播放加载使用 + protected TextView mReplayTip; + protected ORIENTATION mOrientation = ORIENTATION.isNone; //禁止横竖屏标志 + protected boolean isCanChangeScreen = true; + // 屏幕方向改变监听器 + private OrientationEventListener mOrientationListener; + + //吐司类工具 + protected void toast(int resId) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT).show(); + } + } + + protected void toast(String content) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast.makeText(getActivity(), content, Toast.LENGTH_SHORT).show(); + } + } + + public void toastWithImg(String content, int imgId) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast toast = Toast.makeText(getActivity(), content, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastView = (LinearLayout) toast.getView(); + ImageView imageCodeProject = new ImageView(getActivity()); + imageCodeProject.setImageResource(imgId); + toastView.addView(imageCodeProject, 0); + toast.show(); + } + } + + //播放失败提示器 + protected void showErrorTip(int resId) { + mReplayTip.setVisibility(View.VISIBLE); + mReplayTip.setText(resId); + } + + protected void showErrorTip(String res) { + mReplayTip.setVisibility(View.VISIBLE); + mReplayTip.setText(res); + } + + //播放缓冲提示器 + protected void showLoading(int res) { + mReplayTip.setVisibility(View.GONE); + mProgressDialog.setStart(getString(res)); //开启播放加载控件 + } + + protected void showLoading(String res) { + mReplayTip.setVisibility(View.GONE); + mProgressDialog.setStart(res); //开启播放加载控件 + } + + @Override + public void onStart() { + super.onStart(); + //将自己的实例传出去 + if (!(getActivity() instanceof BackHandlerInterface)) { + throw new ClassCastException("Hosting activity must implement BackHandlerInterface"); + } else { + ((BackHandlerInterface) getActivity()).setSelectedFragment(this); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mOrientationListener != null) { + mOrientationListener.disable(); + mOrientationListener = null; + } + } + + /** + * 描述:开启屏幕方向监听 + */ + protected final void startListener() { + if (getActivity() == null || getActivity().isFinishing()) { + return; + } + mOrientationListener = new OrientationEventListener(getContext(), SensorManager.SENSOR_DELAY_NORMAL) { + @Override + public void onOrientationChanged(int rotation) { + // 设置竖屏 + if (getActivity() == null || getActivity().isFinishing()) { + return; + } + if (!isCanChangeScreen) { + return; + } + requestedOrientation(rotation); + } + }; + if (mOrientationListener.canDetectOrientation()) { + mOrientationListener.enable(); + } else { + mOrientationListener.disable(); + } + + } + + /** + * 描述:改变屏幕方向 + */ + private void requestedOrientation(int rotation) { + if (rotation < 10 || rotation > 350) {// 手机顶部向上 + setPortOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else if (rotation < 100 && rotation > 80) {// 手机右边向上 + setLandOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + } else if (rotation < 190 && rotation > 170) {// 手机低边向上 + setPortOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); + } else if (rotation < 280 && rotation > 260) {// 手机左边向上 + setLandOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + } + + private void setPortOrientation(int type) { + switch (mOrientation) { + case isNone: + getActivity().setRequestedOrientation(type); + break; + case isPortRait: + mOrientation = ORIENTATION.isNone; + break; + default: + break; + } + } + + private void setLandOrientation(int type) { + switch (mOrientation) { + case isNone: + getActivity().setRequestedOrientation(type); + break; + case isLandScape: + mOrientation = ORIENTATION.isNone; + break; + default: + break; + } + } + + /** + * @see Fragment#onConfigurationChanged(Configuration) + * 描述:屏幕方向改变时重新绘制界面 + */ + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + initWindow(newConfig); + initSurFace(newConfig); + resetViews(newConfig); + } + + /** + * 描述:初始化playWindow + */ + protected void initWindow(Configuration mConfiguration) { + LayoutParams mLayoutParams = (LayoutParams) mSurfaceParentView.getLayoutParams(); + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.heightPixels; // 屏幕高度(像素) + mLayoutParams.setMargins(0, 0, 0, 0); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + } + mSurfaceParentView.setLayoutParams(mLayoutParams); + } + + /** + * 描述:初始化全屏或非全屏 + */ + private void initSurFace(Configuration mConfiguration) { + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + if (getActivity() instanceof MediaPlayActivity) { + ((MediaPlayActivity) getActivity()).toggleTitle(false); + } + if (getActivity() instanceof MediaPlayBackActivity) { + ((MediaPlayBackActivity) getActivity()).toggleTitle(false); + } + MediaPlayHelper.setFullScreen(getActivity()); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + if (getActivity() instanceof MediaPlayActivity) { + ((MediaPlayActivity) getActivity()).toggleTitle(true); + } + if (getActivity() instanceof MediaPlayBackActivity) { + ((MediaPlayBackActivity) getActivity()).toggleTitle(true); + } + MediaPlayHelper.quitFullScreen(getActivity()); + } + } + + /** + * 重置View,子类实现 + */ + protected void resetViews(Configuration mConfiguration) { + } + + public boolean onBackPressed() { + return false; + } + + public enum ORIENTATION {isPortRait, isLandScape, isNone} + + public interface BackHandlerInterface { + public void setSelectedFragment(MediaPlayFragment backHandledFragment); + } +} + diff --git a/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayOnlineFragment.java b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayOnlineFragment.java new file mode 100644 index 0000000..3e0626e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/mediaplay/fragment/MediaPlayOnlineFragment.java @@ -0,0 +1,1365 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayOnlineFragment.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.mediaplay.fragment; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.MediaScannerConnection; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.ActivityCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.common.log.Logger; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.PlayerResultCode; +import com.lechange.demo.business.Business.RetObject; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.entity.ChannelPTZInfo; +import com.lechange.demo.business.entity.RecordInfo; +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.business.util.MediaPlayHelper.DHFilesType; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.localvideo.RecordListActivity; +import com.lechange.demo.localvideo.TodayLocalAdapter; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.demo.mediaplay.MediaPlayBackActivity; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.listener.LCOpenSDK_TalkerListener; +import com.lechange.opensdk.media.LCOpenSDK_Talk; +import com.yonsz.z1.R; +import com.yonsz.z1.listener.OnRecyclerClickListener; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.utils.DateTimeUitl; +import com.yonsz.z1.utils.DensityUtil; +import com.yonsz.z1.utils.NetWorkSpeedUtils; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.version5.weidget.RecyclerViewNoBugLinearLayoutManager; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 描述:实时视频监控 作者: lc + */ +public class MediaPlayOnlineFragment extends MediaPlayFragment implements + OnClickListener, View.OnLongClickListener { + + protected static final int MediaMain = 0; // 主码流 + protected static final int MediaAssist = 1; // 辅码流 + protected static final int RECORDER_TYPE_DAV = 3; // 录制格式DAV + protected static final int RECORDER_TYPE_MP4 = 4; // 录制格式MP4 + private static final String TAG = "MediaPlayOnlineFragment"; + /** + * 描述:开始录制 + */ + String path = null; + // 状态值 + private int bateMode = MediaAssist; + private AudioTalkStatus mOpenTalk = AudioTalkStatus.talk_close; // 语音对讲状态 + private boolean isRecord = false; // 正在录制 + private boolean isOpenSound = false; // 声音打开 + private boolean isPlaying; // 正在播放 + private boolean IsPTZOpen = false; // 云台打开 + private ChannelInfo channelInfo; + private LinearLayout mLiveMenu; + private TextView mLiveMode; + private ImageView mLivePtz, iv_live_ptz; + private RelativeLayout rl_live_ptz, rl_full_ptz, rl_local_video; + private ImageView mLiveSound; + private ImageView mLiveScale; + private ImageView mLiveStop; + private LinearLayout mLiveUseLayout; + private LinearLayout mLiveBack; + private ImageView mLiveScreenshot; + private ImageView live_ptz1, live_screenshot1, live_talk1, live_record1; + private ImageView mLiveTalk; + private ImageView mLiveRecord; + private TextView netSpeedTv; + private ImageView iv_top, iv_down, iv_left, iv_right, iv_top1, iv_down1, iv_left1, iv_right1; + private ImageView iv_screen_shot; + private String channelId; + private UIHandle mHandler; + private ImageView list_device_localvideo; + private TextView tv_device_localvideo; + + + /*private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case 100: + netSpeedTv.setText(msg.obj.toString()); + break; + } + super.handleMessage(msg); + } + };*/ + private ImageView list_device_cloudvideo; + private RecyclerView horizontalRecyclerView; + private TextView tv_no_sdcard; + private TodayLocalAdapter mHorizontalAdapter; + private List mOnLineRecordList = new ArrayList<>(); + private LinearLayout ll_record_time; + private TextView tv_record_time; + private CheckBox iv_lock_screen; + //计时器 + private Handler mhandle = new Handler(); + private boolean isPause = false;//是否暂停 + private long currentSecond = 0;//当前毫秒数 + private Runnable timeRunable = new Runnable() { + @Override + public void run() { + currentSecond = currentSecond + 1000; + tv_record_time.setText(DateTimeUitl.getFormatHMS(currentSecond)); + if (!isPause) { + //递归调用本runable对象,实现每隔一秒一次执行任务 + mhandle.postDelayed(this, 1000); + } + } + }; + private boolean isCanRefrash = true; + + public static Bitmap getLoacalBitmap(String url) { + try { + FileInputStream fis = new FileInputStream(url); + return BitmapFactory.decodeStream(fis); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + } + + private void callBackUiThread(Message msg) { + switch (msg.what) { + case 100: + netSpeedTv.setText(msg.obj.toString()); + break; + } + } + + /** + * @param savedInstanceState + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mHandler = new UIHandle(this); + Bundle b = getArguments(); + if (b != null) { + channelId = b.getString("RESID"); + channelInfo = Business.getInstance().getChannel(channelId); + } + if (channelInfo == null) { + toast("设备不存在"); + getActivity().setResult(-1); + getActivity().finish(); + } + } + + /** + * ViewGroup, Bundle) 描述: + * + * @return + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View mView = inflater.inflate(R.layout.fragment_media_live, container, + false); + // 必须赋值,父类需要使用到 + mSurfaceParentView = (ViewGroup) mView.findViewById(R.id.live_window); + // 初始化窗口大小 + LayoutParams mLayoutParams = (LayoutParams) mSurfaceParentView + .getLayoutParams(); + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + mSurfaceParentView.setLayoutParams(mLayoutParams); + + mPlayWin.initPlayWindow(this.getActivity(), + (ViewGroup) mView.findViewById(R.id.live_window_content), 0, true); + + mProgressDialog = (ProgressDialog) mView + .findViewById(R.id.live_play_load); + mReplayTip = (TextView) mView.findViewById(R.id.live_play_pressed); + + iv_top = (ImageView) mView.findViewById(R.id.iv_top); + iv_down = (ImageView) mView.findViewById(R.id.iv_down); + iv_left = (ImageView) mView.findViewById(R.id.iv_left); + iv_right = (ImageView) mView.findViewById(R.id.iv_right); + iv_top1 = (ImageView) mView.findViewById(R.id.iv_top1); + iv_down1 = (ImageView) mView.findViewById(R.id.iv_down1); + iv_left1 = (ImageView) mView.findViewById(R.id.iv_left1); + iv_right1 = (ImageView) mView.findViewById(R.id.iv_right1); + list_device_localvideo = (ImageView) mView.findViewById(R.id.list_device_localvideo); + tv_device_localvideo = (TextView) mView.findViewById(R.id.tv_device_localvideo); + list_device_cloudvideo = (ImageView) mView.findViewById(R.id.list_device_cloudvideo); + netSpeedTv = (TextView) mView.findViewById(R.id.tv_net_speed); + mLiveMenu = (LinearLayout) mView.findViewById(R.id.live_menu); + mLiveMode = (TextView) mView.findViewById(R.id.live_mode); + mLivePtz = (ImageView) mView.findViewById(R.id.live_ptz); + iv_live_ptz = (ImageView) mView.findViewById(R.id.iv_live_ptz); + rl_live_ptz = (RelativeLayout) mView.findViewById(R.id.rl_live_ptz); + rl_full_ptz = (RelativeLayout) mView.findViewById(R.id.rl_full_ptz); + rl_local_video = (RelativeLayout) mView.findViewById(R.id.rl_local_video); + mLiveSound = (ImageView) mView.findViewById(R.id.live_sound); + mLiveUseLayout = (LinearLayout) mView.findViewById(R.id.live_use_layout); + mLiveBack = (LinearLayout) mView.findViewById(R.id.live_video_back_layout); + mLiveScale = (ImageView) mView.findViewById(R.id.live_scale); + mLiveStop = (ImageView) mView.findViewById(R.id.live_stop); + mLiveScreenshot = (ImageView) mView.findViewById(R.id.live_screenshot); + live_ptz1 = (ImageView) mView.findViewById(R.id.live_ptz1); + live_screenshot1 = (ImageView) mView.findViewById(R.id.live_screenshot1); + live_talk1 = (ImageView) mView.findViewById(R.id.live_talk1); + live_record1 = (ImageView) mView.findViewById(R.id.live_record1); + mLiveTalk = (ImageView) mView.findViewById(R.id.live_talk); + mLiveRecord = (ImageView) mView.findViewById(R.id.live_record); + ll_record_time = (LinearLayout) mView.findViewById(R.id.ll_record_time); + tv_record_time = (TextView) mView.findViewById(R.id.tv_record_time); + iv_screen_shot = (ImageView) mView.findViewById(R.id.iv_screen_shot); + iv_lock_screen = (CheckBox) mView.findViewById(R.id.iv_lock_screen); + + horizontalRecyclerView = (RecyclerView) mView.findViewById(R.id.horizontal_RecyclerView); + tv_no_sdcard = (TextView) mView.findViewById(R.id.tv_no_sdcard); + + initListener(); + + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + String startTime = df.format(new Date()) + " 00:00:00"; + String endTime = df.format(new Date()) + " 23:59:59"; + //初始化数据 + loadRecrodList(startTime, endTime); + + new NetWorkSpeedUtils(getContext(), mHandler).startShowNetSpeed(); + return mView; + + } + + private void loadRecrodList(final String startTime, final String endTime) { + Business.getInstance().queryRecordNum(channelId, startTime, + endTime, new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + tv_no_sdcard.setVisibility(View.VISIBLE); +// Toast.makeText(getContext(), getString(R.string.toast_recordlist_query_failed) + msg.what, Toast.LENGTH_SHORT).show(); + } else if (msg.what == 0) { + if (msg.arg1 > 0) { + int firstNumber = 1; + int lastNumber = msg.arg1; + if (msg.arg1 > 5) { + lastNumber = 5; + firstNumber = msg.arg1 - 4; + } + Business.getInstance().queryRecordList(channelId, startTime, + endTime, firstNumber, msg.arg1, new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + Toast.makeText(getContext(), getString(R.string.toast_recordlist_query_failed) + msg.obj, Toast.LENGTH_SHORT).show(); + } else { + if (isCanRefrash) { + mOnLineRecordList.addAll((List) msg.obj); + } else { + return; + } + if (mOnLineRecordList != null && mOnLineRecordList.size() > 0) { + Log.d("loadRecrodList", "loadRecrodList mRecordList.size:" + mOnLineRecordList.size()); + tv_no_sdcard.setVisibility(View.GONE); + mHorizontalAdapter = new TodayLocalAdapter(getActivity(), mOnLineRecordList, channelId); + RecyclerViewNoBugLinearLayoutManager manage = new RecyclerViewNoBugLinearLayoutManager(getActivity()); + manage.setOrientation(LinearLayoutManager.HORIZONTAL); + horizontalRecyclerView.setLayoutManager(manage); + horizontalRecyclerView.setAdapter(mHorizontalAdapter); + mHorizontalAdapter.setmOnItemClickListener(new OnRecyclerClickListener() { + @Override + public void onClick(View view, int position) { + Intent intent = new Intent(getActivity(), MediaPlayBackActivity.class); + if (TextUtils.isEmpty(mOnLineRecordList.get(position).getId())) { + return; + } + intent.putExtra("TYPE", MediaPlayBackActivity.IS_VIDEO_REMOTE_RECORD); + intent.putExtra("ID", mOnLineRecordList.get(position).getId()); + intent.putExtra("dateString", mOnLineRecordList.get(position).getStartTime()); + startActivity(intent); + } + }); + isCanRefrash = false; + } else { + tv_no_sdcard.setVisibility(View.VISIBLE); + // RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + Toast.makeText(getContext(), "没有录像", Toast.LENGTH_SHORT).show(); + } + } + } + }); + } else { + tv_no_sdcard.setVisibility(View.VISIBLE); + // RecordListActivity.this.findViewById(R.id.list_records_novideo).setVisibility(View.VISIBLE); + } + } + } + }); + } + + private void initListener() { + mReplayTip.setOnClickListener(this); + mLiveMode.setOnClickListener(this); + mLivePtz.setOnClickListener(this); + iv_live_ptz.setOnClickListener(this); + mLiveSound.setOnClickListener(this); + mLiveScale.setOnClickListener(this); + mLiveScale.setTag("PORTRAIT"); + mLiveStop.setOnClickListener(this); + mLiveScreenshot.setOnClickListener(this); + mLiveTalk.setOnClickListener(this); + mLiveRecord.setOnClickListener(this); + list_device_localvideo.setOnClickListener(this); + tv_device_localvideo.setOnClickListener(this); + list_device_cloudvideo.setOnClickListener(this); + iv_top.setOnClickListener(this); + iv_down.setOnClickListener(this); + iv_left.setOnClickListener(this); + iv_right.setOnClickListener(this); + iv_top1.setOnClickListener(this); + iv_down1.setOnClickListener(this); + iv_left1.setOnClickListener(this); + iv_right1.setOnClickListener(this); + iv_top.setOnLongClickListener(this); + iv_down.setOnLongClickListener(this); + iv_left.setOnLongClickListener(this); + iv_right.setOnLongClickListener(this); + live_ptz1.setOnClickListener(this); + live_screenshot1.setOnClickListener(this); + live_talk1.setOnClickListener(this); + live_record1.setOnClickListener(this); + iv_lock_screen.setOnClickListener(this); + } + + /** + * 描述:MediaPlayActivity创建完毕 + * + * @param savedInstanceState + */ + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + listener = new MyBaseWindowListener(); + mPlayWin.setWindowListener(listener); + mPlayWin.openTouchListener(); + + // 开启横竖屏切换 + startListener(); + + + // int ability = channelInfo.getAbility(); + // if ((ability & ChannelInfo.Ability.AudioTalk) == 0) { + // if (getActivity().getResources().getConfiguration().orientation == + // Configuration.ORIENTATION_LANDSCAPE) { + // mLiveTalk.setOnClickListener(new OnClickListener() { + // @Override + // public void onClick(View v) { + // toast(R.string.video_monitor_unsupport_audio_talk); + // } + // }); + // } else if + // (getActivity().getResources().getConfiguration().orientation == + // Configuration.ORIENTATION_PORTRAIT) { + // mLiveTalk.setOnClickListener(new OnClickListener() { + // @Override + // public void onClick(View v) { + // toast(R.string.video_monitor_unsupport_audio_talk); + // } + // }); + // } + // } + } + + @Override + public void onResume() { + // TODO Auto-generated method stub + super.onResume(); + play(0); + } + + @Override + public void onPause() { + super.onPause(); + // 停止实时视频,无效资源号 + stop(-1); + // 关闭语音对讲 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + } + + @Override + public void onDestroyView() { + // TODO Auto-generated method stub + super.onDestroyView(); + mPlayWin.uninitPlayWindow();// 销毁底层资源 + } + + /** + * 描述:实现个性化界面 + * + * @param mConfiguration + */ + @Override + protected void resetViews(Configuration mConfiguration) { + super.resetViews(mConfiguration); + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + mLiveUseLayout.setVisibility(View.GONE); + mLiveBack.setVisibility(View.GONE); + mLiveScale.setTag("LANDSCAPE"); + mLiveScale.setImageResource(R.drawable.live_btn_smallscreen); + live_ptz1.setVisibility(View.VISIBLE); + live_screenshot1.setVisibility(View.VISIBLE); + live_talk1.setVisibility(View.VISIBLE); + live_record1.setVisibility(View.VISIBLE); + if (IsPTZOpen) { + rl_full_ptz.setVisibility(View.VISIBLE); + } + iv_lock_screen.setVisibility(View.VISIBLE); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + mLiveUseLayout.setVisibility(View.VISIBLE); + mLiveBack.setVisibility(View.VISIBLE); + mLiveScale.setTag("PORTRAIT"); + mLiveScale.setImageResource(R.drawable.live_btn_fullscreen); + rl_full_ptz.setVisibility(View.GONE); + live_ptz1.setVisibility(View.GONE); + live_screenshot1.setVisibility(View.GONE); + live_talk1.setVisibility(View.GONE); + live_record1.setVisibility(View.GONE); + iv_lock_screen.setVisibility(View.GONE); + isCanChangeScreen = true; + } + } + + private void sendCloudOrder(final Cloud mCloud, final boolean longclick) { + if (IsPTZOpen && isPlaying) { + // super.sendCloudOrder(mCloud, longclick); + Log.d(TAG, "-----is longclick:" + longclick); + ChannelPTZInfo.Operation operation = ChannelPTZInfo.Operation.Move; + ChannelPTZInfo.Direction direction = null; + switch (mCloud) { + case up: + direction = ChannelPTZInfo.Direction.Up; + Log.d(TAG, "-----Up"); + break; + case down: + direction = ChannelPTZInfo.Direction.Down; + Log.d(TAG, "-----Down"); + break; + case left:// 手势向左, 摄像头向右转 + direction = ChannelPTZInfo.Direction.Left; + Log.d(TAG, "-----case left"); + break; + case right: + direction = ChannelPTZInfo.Direction.Right; + Log.d(TAG, "-----case right"); + break; + case zoomin: + direction = ChannelPTZInfo.Direction.ZoomIn; + Log.d(TAG, "-----ZoomIn"); + break; + case zoomout: + direction = ChannelPTZInfo.Direction.ZoomOut; + Log.d(TAG, "-----ZoomOut"); + break; + case stop: + Log.d(TAG, "-----stop"); + operation = ChannelPTZInfo.Operation.Stop; + // direction = ChannelPTZInfo.Direction.Down; + break; + default: + break; + } + ChannelPTZInfo ptzInfo = new ChannelPTZInfo(operation, direction); + ptzInfo.setDuration(ChannelPTZInfo.Duration.Short); + if (longclick) { + ptzInfo.setDuration(ChannelPTZInfo.Duration.Long); + } + + Business.getInstance().AsynControlPtz(channelId, + ptzInfo, new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isAdded() || getActivity() == null) { + Log.d(TAG, "*******page not exits"); + return; + } + // Log.d(TAG, + // "-----control callback what:"+msg.what); + RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0) { + Log.d(TAG, "-----control result: true"); + } else + toast(retObject.mMsg); + } + }); + } + } + + /** + * 描述:开始播放 + */ + public void play(final int strRes) { + if (DensityUtil.checkNetworkConnection(getContext())) { + playOnline(strRes); + } else { + if (SharedpreferencesUtil.get("isShowMobilePlay", "").toString().equals("1")) { + playOnline(strRes); + } else { + ConfirmDialog dialog = new ConfirmDialog(getActivity(), new Callback() { + @Override + public void callback(int position) { + switch (position) { + case 0: + break; + case 1: + SharedpreferencesUtil.save("isShowMobilePlay", "1"); + playOnline(strRes); + break; + } + } + }); + dialog.setContent("你正在使用非WIFI网络继续播放将产生流量费用"); + dialog.setCancleBtn("暂停播放"); + dialog.setSureBtn("继续播放"); + dialog.setCancelable(false); + dialog.show(); + } + } + } + + private void playOnline(int strRes) { + stop(-1); + // } + if (strRes > 0) { + showLoading(strRes); + } else { + showLoading(R.string.common_loading); + } + mPlayWin.playRtspReal( + Business.getInstance().getToken(), + channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo + .getEncryptKey() : channelInfo.getDeviceCode(), + channelInfo.getIndex(), bateMode, true);//最后一个参数为true,表示使用长连接 + } + + /** + * 描述:停止播放 + */ + public void stop(final int res) { + // 关闭播放加载控件 + mProgressDialog.setStop(); + + if (isRecord) { + stopRecord();// 关闭录像 + } + + if (isOpenSound) { + closeAudio();// 关闭音频 + isOpenSound = false; + mLiveSound.setImageResource(R.drawable.live_btn_sound_off); + } + mPlayWin.stopRtspReal(false);// 关闭视频 + isPlaying = false; + + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + if (res > 0) + showErrorTip(res); + } + } + }); + } + } + + /** + * 描述:抓拍图像 + */ + public String capture() { + String captureFilePath = null; + // 判断SD卡是否已存在 + // SD卡容量检查 + // FIXME 检查设备是否在线 + // 抓图 + String channelName = null; + if (channelInfo != null) { + channelName = channelInfo.getName(); + } else { + channelName = ""; + } + + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + + captureFilePath = MediaPlayHelper.getCaptureAndVideoPath(DHFilesType.DHImage, channelName); + int ret = mPlayWin.snapShot(captureFilePath); + if (ret == retOK) { + // 扫描到相册中 + MediaScannerConnection.scanFile(getActivity(), new String[]{captureFilePath}, null, null); + Bitmap loacalBitmap = getLoacalBitmap(captureFilePath); + iv_screen_shot.setImageBitmap(loacalBitmap); + iv_screen_shot.setVisibility(View.VISIBLE); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + iv_screen_shot.setVisibility(View.GONE); + } + }, 2000); + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_success, + Toast.LENGTH_SHORT).show(); + } else { + captureFilePath = null; + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_failed, + Toast.LENGTH_SHORT).show(); + } + return captureFilePath; + } + + public boolean startRecord() { + if (!isPlaying) { + toast(R.string.video_monitor_video_record_failed); + return false; + } + // 判断SD卡是否已存在 + // SD卡容量检查 + + // FIXME 要做 ~~~~检查设备是否在线 + + // 录像的路径 + String channelName = null; + if (channelInfo != null) { + channelName = channelInfo.getName(); + } else { + channelName = ""; + } + + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + + path = MediaPlayHelper.getCaptureAndVideoPath(DHFilesType.DHVideo, + channelName); + int recordType = 1; + long spaceRemain = 0x7FFFFFFF; //保留字段 + // 开始录制 1 + int ret = mPlayWin.startRecord(path, recordType, spaceRemain); + if (ret != retOK) { + toast(R.string.video_monitor_video_record_failed); + return false; + } + + return true; + } + + /** + * 关闭录像 + */ + public void stopRecord() { + mPlayWin.stopRecord(); + isRecord = false; + toast(getString(R.string.video_monitor_video_record_success)); + live_record1.setImageResource(R.drawable.icon_column_videotape); + mLiveRecord.setImageResource(R.drawable.icon_videotape_nor); + currentSecond = 0; + ll_record_time.setVisibility(View.GONE); + + MediaScannerConnection.scanFile(getActivity(), new String[]{path}, + null, null); + } + + /** + * 打开声音 + */ + public boolean openAudio() { + return mPlayWin.playAudio() == retOK; + } + + /** + * 关闭声音 + */ + public boolean closeAudio() { + return mPlayWin.stopAudio() == retOK; + } + + /** + * 描述:开始对讲 + */ + public void startTalk() { + if (!isPlaying) { + toast(R.string.video_monitor_talk_open_error); + return; + } + + toastWithImg(getString(R.string.video_monitor_media_talk), R.drawable.live_pic_talkback); + + // 替换图片 + live_talk1.setImageResource(R.drawable.icon_column_suspend_per); + mLiveTalk.setImageResource(R.drawable.icon_dialogue_pre); + mOpenTalk = AudioTalkStatus.talk_opening; + // 关闭扬声器 默认为关 + if (isOpenSound) { + closeAudio(); + mLiveSound.setImageResource(R.drawable.live_btn_sound_off); + } + mLiveSound.setClickable(false); + LCOpenSDK_Talk.setListener(new AudioTalkerListener()); + LCOpenSDK_Talk.playTalk( + Business.getInstance().getToken(), + channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo + .getEncryptKey() : channelInfo.getDeviceCode(), true);//对讲使用长连接 + + + + /*LCOpenSDK_ParamTalk paramTalk = new LCOpenSDK_ParamTalk( + LCDeviceEngine.newInstance().accessToken, + deviceListBean.deviceId, + deviceListBean.channels.size() > 1 ? Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId) : -1, + TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey, + deviceListBean.playToken, + true + ); + LCOpenSDK_Talk.playTalk(paramTalk);*/ + } + + /** + * 描述:停止对讲 + */ + public void stopTalk() { + Log.d("playAudio", "stopTalk press"); + toast(R.string.video_monitor_media_talk_close); + // 替换图片 + live_talk1.setImageResource(R.drawable.icon_column_suspend1); + mLiveTalk.setImageResource(R.drawable.icon_dialogue_nor); + LCOpenSDK_Talk.stopTalk(); + // 解决gc回收问题 + LCOpenSDK_Talk.setListener(null); + mOpenTalk = AudioTalkStatus.talk_close; + // 开启扬声器 + if (isOpenSound && isPlaying) { + openAudio(); + mLiveSound.setImageResource(R.drawable.live_btn_sound_on); + } + mLiveSound.setClickable(true); + } + + @Override + public void onClick(View view) { + // TODO Auto-generated method stub + switch (view.getId()) { + case R.id.live_ptz: + case R.id.live_ptz1: + if (!isPlaying) { + return; + } + if ((channelInfo.getAbility() & ChannelInfo.Ability.PTZ) != 0) { + if (1 == 1) { + Log.i("393", "MediaPlayOnlineFragment onClick()" + (393 & 64)); + Log.i("457", "MediaPlayOnlineFragment onClick()" + (457 & 64)); + if ((channelInfo.getAbility() & ChannelInfo.Ability.PTZ) != 0) { + if (IsPTZOpen) { + // 测试专用 + // mPlayWin.setStreamCallback(0); + IsPTZOpen = false; + rl_live_ptz.setVisibility(View.GONE); + rl_full_ptz.setVisibility(View.GONE); + rl_local_video.setVisibility(View.VISIBLE); + mLivePtz.setImageResource(R.drawable.icon_control_nor); + live_ptz1.setImageResource(R.drawable.icon_column_control_nor); + } else { + // 测试专用 + // mPlayWin.setStreamCallback(1); + IsPTZOpen = true; + rl_local_video.setVisibility(View.GONE); + rl_live_ptz.setVisibility(View.VISIBLE); + mLivePtz.setImageResource(R.drawable.icon_control_pre); + live_ptz1.setImageResource(R.drawable.icon_column_control_pre); + if (mLiveScale.getTag().toString().equals("LANDSCAPE")) { + rl_full_ptz.setVisibility(View.VISIBLE); + } + } + } else { + toast(R.string.toast_device_ability_no_ptz); + } + } + } + break; + case R.id.iv_live_ptz: + if (IsPTZOpen) { + // 测试专用 + // mPlayWin.setStreamCallback(0); + IsPTZOpen = false; + mLivePtz.setImageResource(R.drawable.icon_control_nor); + rl_live_ptz.setVisibility(View.GONE); + rl_local_video.setVisibility(View.VISIBLE); + } + break; + case R.id.live_scale: + if ("LANDSCAPE".equals(mLiveScale.getTag())) { + mOrientation = ORIENTATION.isPortRait; + getActivity().setRequestedOrientation( + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else { + mOrientation = ORIENTATION.isLandScape; + getActivity().setRequestedOrientation( + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + break; + case R.id.live_stop: + if (isPlaying) { + mReplayTip.setVisibility(View.VISIBLE); + setButtonAlpha(0.5f); + // 停止实时视频,无效资源号 + stop(-1); + mLiveStop.setImageResource(R.drawable.icon_column_play); + // 关闭语音对讲 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + } else { + mReplayTip.setVisibility(View.GONE); + setButtonAlpha(1.0f); + mLiveStop.setImageResource(R.drawable.icon_column_suspend); + play(0); + } + break; + case R.id.live_mode: + // if(isPlaying) //播放是个异步的,多次点击会使停止播放顺序乱掉 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + // 高清切换到流畅 + if (bateMode == MediaMain) { + bateMode = MediaAssist; + mLiveMode.setText("流畅"); + play(R.string.video_monitor_change_stream_normal); + }// 流畅切换到高清 + else if (bateMode == MediaAssist) { + bateMode = MediaMain; + mLiveMode.setText("高清"); + play(R.string.video_monitor_change_stream_hd); + } + break; + case R.id.live_talk: + case R.id.live_talk1: + switch (mOpenTalk) { + case talk_open: + case talk_opening: + stopTalk(); + break; + case talk_close: + openTalk(); + // startTalk(); + break; + default: + break; + } + break; + case R.id.live_sound: + if (mOpenTalk != AudioTalkStatus.talk_close || !isPlaying) { + toast(R.string.video_monitor_load_talk_sound_error); + } else { + if (isOpenSound) { + boolean result = closeAudio(); + if (result) { + mLiveSound + .setImageResource(R.drawable.live_btn_sound_off); + toast(R.string.video_monitor_sound_close); + isOpenSound = false; + } + } else { + boolean result = openAudio(); + if (result) { + mLiveSound + .setImageResource(R.drawable.live_btn_sound_on); + toast(R.string.video_monitor_sound_open); + isOpenSound = true; + } + } + } + break; + case R.id.live_screenshot: + case R.id.live_screenshot1: + live_screenshot1.setImageResource(R.drawable.icon_column_photograph); + mLiveScreenshot.setImageResource(R.drawable.icon_photograph_pre); + capture(); + mLiveScreenshot.setImageResource(R.drawable.icon_photograph_nor); + break; + case R.id.live_record: + case R.id.live_record1: + if (!isRecord) { + boolean result = startRecord(); + if (result) { + toastWithImg(getString(R.string.video_monitor_media_record), R.drawable.live_pic_record); + isRecord = true; + isPause = false; + live_record1.setImageResource(R.drawable.icon_column_videotape_per); + mLiveRecord.setImageResource(R.drawable.icon_videotape_pre); + ll_record_time.setVisibility(View.VISIBLE); + //显示录制时间 + timeRunable.run(); + } + } else { + isPause = true; + stopRecord(); + } + break; + case R.id.live_play_pressed: + mLiveStop.setImageResource(R.drawable.icon_column_suspend); + setButtonAlpha(1.0f); + play(-1); + break; + case R.id.list_device_cloudvideo: + Intent intent = new Intent(getContext(), RecordListActivity.class); + intent.putExtra("UUID", channelId); + intent.putExtra("MEDIA_TITLE", R.string.cloud_records_name); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD); + startActivity(intent); + break; + case R.id.list_device_localvideo: + case R.id.tv_device_localvideo: + Intent intent1 = new Intent(getContext(), RecordListActivity.class); + intent1.putExtra("UUID", channelId); + intent1.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent1.putExtra("MEDIA_TITLE", R.string.local_records_name); + startActivity(intent1); + break; + case R.id.iv_top: + case R.id.iv_top1: + sendCloudOrder(Cloud.up, false); + break; + case R.id.iv_down: + case R.id.iv_down1: + sendCloudOrder(Cloud.down, false); + break; + case R.id.iv_left: + case R.id.iv_left1: + sendCloudOrder(Cloud.left, false); + break; + case R.id.iv_right: + case R.id.iv_right1: + sendCloudOrder(Cloud.right, false); + break; + case R.id.iv_lock_screen: + if (iv_lock_screen.isChecked()) { + Toast.makeText(getContext(), "横屏已锁定", Toast.LENGTH_SHORT).show(); + isCanChangeScreen = false; + } else { + Toast.makeText(getContext(), "解除横屏锁定", Toast.LENGTH_SHORT).show(); + isCanChangeScreen = true; + } + break; + default: + break; + } + } + + private void setButtonAlpha(float alpha) { + live_ptz1.setAlpha(alpha); + live_screenshot1.setAlpha(alpha); + live_talk1.setAlpha(alpha); + live_record1.setAlpha(alpha); + mLiveMode.setAlpha(alpha); + mLiveSound.setAlpha(alpha); + } + + @Override + public boolean onLongClick(View v) { + switch (v.getId()) { + case R.id.iv_top: + sendCloudOrder(Cloud.up, false); + break; + case R.id.iv_down: + sendCloudOrder(Cloud.down, false); + break; + case R.id.iv_left: + sendCloudOrder(Cloud.left, false); + break; + case R.id.iv_right: + sendCloudOrder(Cloud.right, false); + break; + } + return false; + } + + /** + * 权限检查) + */ + public void openTalk() { + boolean isMinSDKM = Build.VERSION.SDK_INT < 23; + boolean isGranted = ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED; + if (isMinSDKM || isGranted) { + startTalk(); + // 对讲权限 + return; + } + requestRecordAudioPermission(); + } + + private void requestRecordAudioPermission() { + + if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), + Manifest.permission.RECORD_AUDIO)) { + + Logger.d("Uriah", "Uriah + shouldShowRequestPermission true"); + ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.RECORD_AUDIO}, + 1); + } else { + ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.RECORD_AUDIO}, + 1); + } + } + + public enum Cloud { + up, down, left, right, leftUp, rightUp, leftDown, RightDown, zoomin, zoomout, stop + } + + private enum AudioTalkStatus { + talk_close, talk_opening, talk_open + } + + //handler + static class UIHandle extends Handler { + WeakReference weakReference; + + public UIHandle(MediaPlayOnlineFragment activity) { + weakReference = new WeakReference(activity); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + MediaPlayOnlineFragment activity = weakReference.get(); + activity.callBackUiThread(msg); + } + } + + class MyBaseWindowListener extends LCOpenSDK_EventListener { + @Override + public void onPlayerResult(int index, String code, int type) { + if (type == Business.RESULT_SOURCE_OPENAPI) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_play_error); + } + } + }); + } + } else { + if (code.equals(PlayerResultCode.STATE_PACKET_FRAME_ERROR) + || code.equals(PlayerResultCode.STATE_RTSP_TEARDOWN_ERROR) + || code.equals(PlayerResultCode.STATE_RTSP_AUTHORIZATION_FAIL) + || code.equals(PlayerResultCode.STATE_RTSP_KEY_MISMATCH)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_play_error); + } + } + }); + } + } + } + } + + @Override + public void onPlayBegan(int index) { + // TODO Auto-generated method stub + // 显示码率 + // if (mHander != null) { + // mHander.post(MediaPlayOnlineFragment.this); + // } + isPlaying = true; + // 建立码流,自动开启音频 + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + // showLoading(R.string.video_monitor_data_cache); + onClick(mLiveSound); + } + } + }); + } + // 关闭播放加载控件 + mProgressDialog.setStop(); + } + + // public void onReceiveData(int len) { + // // 流量统计 + // mTotalFlow += len; + // } + @Override + public void onStreamCallback(int index, byte[] data, int len) { + // Log.d(TAG, "LCOpenSDK_EventListener::onStreamCallback-size : " + + // len); + try { + String path = Environment.getExternalStorageDirectory() + .getPath() + "/streamCallback.ts"; + FileOutputStream fout = new FileOutputStream(path, true); + fout.write(data); + fout.close(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Override + public void onWindowLongPressBegin(int index, Direction dir, float dx, + float dy) { + sendCloudOrder(direction2Cloud(dir), true); + } + + @Override + public void onWindowLongPressEnd(int index) { + sendCloudOrder(Cloud.stop, false); + } + + // 电子缩放 + @Override + public void onZooming(int index, float dScale) { + if (IsPTZOpen == false) { + mPlayWin.doScale(dScale); + } + + } + + // 云台缩放 + @Override + public void onZoomEnd(int index, ZoomType zoom) { + Log.d(TAG, "onZoomEnd" + zoom); + if (IsPTZOpen == false) { + return; + } + // TODO Auto-generated method stub + sendCloudOrder(zoom == ZoomType.ZOOM_IN ? Cloud.zoomin + : Cloud.zoomout, false); + } + + // 滑动开始 + @Override + public boolean onSlipBegin(int index, Direction dir, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin "); + } + sendCloudOrder(direction2Cloud(dir), false); + return true; + } + + // 滑动中 + @Override + public void onSlipping(int index, Direction dir, float prex, + float prey, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin onFlinging"); + mPlayWin.doTranslate(dx, dy); + } + } + + // 滑动结束 + @Override + public void onSlipEnd(int index, Direction dir, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin onFlingEnd"); + return; + } + + // sendCloudOrder(Cloud.stop, false); + } + + private Cloud direction2Cloud(Direction dir) { + Cloud cloud = null; + switch (dir) { + case Up: + cloud = Cloud.up; + break; + case Down: + cloud = Cloud.down; + break; + case Left: + cloud = Cloud.left; + break; + case Right: + cloud = Cloud.right; + break; + case Left_up: + cloud = Cloud.leftUp; + break; + case Left_down: + cloud = Cloud.leftDown; + break; + case Right_up: + cloud = Cloud.rightUp; + break; + case Right_down: + cloud = Cloud.RightDown; + break; + default: + break; + } + return cloud; + } + + public void onWindowDBClick(int index, float dx, float dy) { + // TODO Auto-generated method stub + switch (mLiveMenu.getVisibility()) { + case View.GONE: + mLiveMenu.setVisibility(View.VISIBLE); + break; + case View.VISIBLE: + mLiveMenu.setVisibility(View.GONE); + break; + default: + break; + } + } + + } + + class AudioTalkerListener extends LCOpenSDK_TalkerListener { + /** + * 描述:对讲状态获取 + */ + @Override + public void onTalkResult(String error, int type) { + // TODO Auto-generated method stub + if (type == Business.RESULT_SOURCE_OPENAPI + || error.equals(AUDIO_TALK_ERROR) + || error.equals(PlayerResultCode.STATE_PACKET_FRAME_ERROR) + || error.equals(PlayerResultCode.STATE_RTSP_TEARDOWN_ERROR) + || error.equals(PlayerResultCode.STATE_RTSP_AUTHORIZATION_FAIL)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + // 提示对讲打开失败 + toast(R.string.video_monitor_talk_open_error); + stopTalk();// 关闭播放 + } + } + }); + } + } else if (error.equals(PlayerResultCode.STATE_RTSP_PLAY_READY)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + // 提示对讲打开成功 + toast(R.string.video_monitor_media_talk_ready); + } + } + }); + } + mOpenTalk = AudioTalkStatus.talk_open; + } + + } + + @Override + public void onTalkPlayReady() { + // TODO Auto-generated method stub + + } + + @Override + public void onAudioRecord(byte[] pData, int length, int audioFormat, int sampleRate, int sampleDepth) { + super.onAudioRecord(pData, length, audioFormat, sampleRate, sampleDepth); + BufferedOutputStream bufferedOutputStream; + FileOutputStream fileOutputStream; + String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/AudioFile.pcm"; + File file = new File(filePath); + if (file.exists()) { + try { + fileOutputStream = new FileOutputStream(file, true); + bufferedOutputStream = new BufferedOutputStream(fileOutputStream); + try { + bufferedOutputStream.write(pData); + bufferedOutputStream.flush(); + bufferedOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + + } + } else { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public void onAudioReceive(byte[] pData, int length, int audioFormat, int sampleRate, int sampleDepth) { + super.onAudioReceive(pData, length, audioFormat, sampleRate, sampleDepth); + } + + } +} diff --git a/app/src/main/java/com/lechange/demo/message/AlarmMessageActivity.java b/app/src/main/java/com/lechange/demo/message/AlarmMessageActivity.java new file mode 100644 index 0000000..7b9b264 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/message/AlarmMessageActivity.java @@ -0,0 +1,389 @@ +package com.lechange.demo.message; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.entity.AlarmMessageInfo; +import com.lechange.demo.business.util.ImageHelper; +import com.lechange.demo.business.util.TaskPoolHelper; +import com.lechange.demo.common.CommonTitle; +import com.lechange.demo.common.CommonTitle.OnTitleClickListener; +import com.lechange.demo.common.DatePicker; +import com.lechange.demo.common.DatePicker.OnTimeClickListener; +import com.lechange.demo.common.ProgressDialog; +import com.yonsz.z1.R; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class AlarmMessageActivity extends Activity { + + private String tag="AlarmMessageActivity"; + private String mChannelUUID = null; + + private DatePicker mDatePicker; + private LinearLayout mDatePickerContainer; //放置DatePicker的容器 + private ListView mAlarmMsgListView; //放置报警信息的listview + private CommonTitle mCommonTitle; + private ProgressDialog mProgressDialog; //播放加载使用 + private AlarmMsgListAdapter mAlarmMsgAdapt; + private List mAlarmMsgInfoList; // 保存报警信息 + + private ImageView mNoMsgImageView; //无报警消息 + private ImageView mShowBigImageView; //显示大图 + + private String mStartTime; //开始时间 + private String mEndTime; //结束时间 + + @Override + protected void onCreate(Bundle savedInstanceState) { + // TODO Auto-generated method stub + super.onCreate(savedInstanceState); + this.setContentView(R.layout.activity_alarm_message); + + mChannelUUID = getIntent().getStringExtra("UUID"); //获取通道的UUID + initTitle(); + //开启播放加载控件 + mProgressDialog = (ProgressDialog) this.findViewById(R.id.query_load); + mProgressDialog.setStart(getString(R.string.common_loading)); + + initAlarmMsgListView(); + initBigImageView(); + + + } + + /** + * 初始化大图,并添加点击事件 + * @note 当大图显示中,界面只显示此控件。点击此控件,该控件隐藏,mAlarmMsgListView与mCommonTitle显示 + */ + public void initBigImageView(){ + mShowBigImageView = (ImageView) findViewById(R.id.showBigPhoto); + mShowBigImageView.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View arg0) { + mProgressDialog.setStop(); //关闭加载窗口 + mShowBigImageView.setTag(0); + + mDatePickerContainer.setVisibility(View.VISIBLE); + mAlarmMsgListView.setVisibility(View.VISIBLE); + mCommonTitle.setVisibility(View.VISIBLE); + mShowBigImageView.setVisibility(View.GONE); + } + }); + } + + /** + * 初始化标题栏,管理mDatePickerContainer + * @note 点击右边按钮,会弹出时间选择器 + */ + public void initTitle() { + mDatePickerContainer = (LinearLayout) findViewById(R.id.timerContainer); + // 绘制标题 + mCommonTitle = (CommonTitle) findViewById(R.id.title); + mCommonTitle.initView(R.drawable.title_btn_back, + R.drawable.title_btn_search, R.string.alarm_message_name); + + mCommonTitle.setOnTitleClickListener(new OnTitleClickListener() { + @Override + public void onCommonTitleClick(int id) { + // TODO Auto-generated method stub + switch (id) { + case CommonTitle.ID_LEFT: + finish(); + break; + case CommonTitle.ID_RIGHT: + // 添加时间选择控件 + Log.d(tag,tag + mDatePickerContainer.getChildCount()); + if (mDatePickerContainer.getChildCount() > 0) { + return; + } + + // undo 添加datepicker + if (mDatePicker == null) { + mDatePicker = new DatePicker(getApplicationContext()); + initDatePicker(); + } + + LayoutParams lp = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); + mDatePickerContainer.addView(mDatePicker, lp); + break; + default: + break; + } + } + }); + } + + /** + * 初始化时间选择控件,主要是添加事件响应函数 + */ + + public void initDatePicker() { + if (mDatePicker == null) { + return; + } + + mDatePicker.setOnTimeClickListener(new OnTimeClickListener() { + + @Override + public void onCommonTimeClick(int id) { + if (id == DatePicker.ID_LEFT) { // 点击左边 + mDatePickerContainer.removeView(mDatePicker); + } else { // 点击右边 + Date time = mDatePicker.getSelectedDate(); + + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + String date = df.format(time); + + mStartTime = date + " 00:00:00"; + mEndTime = date + " 23:59:59"; + + mDatePickerContainer.removeView(mDatePicker); + loadAlarmMsgList(mStartTime, mEndTime); + //清空屏幕 + mAlarmMsgAdapt.notifyDataSetChanged(); + mNoMsgImageView.setVisibility(View.GONE); + mProgressDialog.setStart(getString(R.string.common_loading)); + } + + } + }); + } + + /** + * 初始化报警消息列表 + */ + public void initAlarmMsgListView(){ + + mAlarmMsgListView = (ListView) findViewById(R.id.messageList); + mNoMsgImageView = (ImageView) findViewById(R.id.noMsgImg); + + mAlarmMsgAdapt = new AlarmMsgListAdapter(this); + mAlarmMsgListView.setAdapter(mAlarmMsgAdapt); + + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + mStartTime = df.format(new Date()) + " 00:00:00"; + mEndTime = df.format(new Date()) + " 23:59:59"; + + loadAlarmMsgList(mStartTime,mEndTime); + } + + /** + * 更新报警消息 + * @param startTime 报警开始时间段 + * @param endTime 报警结束时间段 + */ + + public void loadAlarmMsgList(String startTime, String endTime) { + //查10条 + Business.getInstance().queryAlarmMessageList(mChannelUUID, startTime, endTime, 10, new Handler() { + @SuppressWarnings("unchecked") + @Override + public void handleMessage(Message msg) { + mProgressDialog.setStop(); //关闭加载窗口 + if (msg.what != 0) { + Toast.makeText(AlarmMessageActivity.this, getString(R.string.toast_alarmmsg_query_failed) + msg.arg1, Toast.LENGTH_SHORT).show(); + } else if (msg.what == 0) { + mAlarmMsgInfoList = (List) msg.obj; + if (mAlarmMsgInfoList != null && mAlarmMsgInfoList.size() > 0) { + mAlarmMsgAdapt.notifyDataSetChanged(); + } else { + mNoMsgImageView.setVisibility(View.VISIBLE); + //Toast.makeText(AlarmMessageActivity.this, "没有报警消息", Toast.LENGTH_SHORT).show(); + } + } + } + }); + } + + @Override + protected void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + TaskPoolHelper.clearTask(); + } + + class AlarmMsgListAdapter extends BaseAdapter { + private LayoutInflater mInflater; + + public AlarmMsgListAdapter(Context context) { + this.mInflater = LayoutInflater.from(context); + } + + @Override + public int getCount() { + return mAlarmMsgInfoList != null ? mAlarmMsgInfoList.size():0; + } + + @Override + public AlarmMessageInfo getItem(int position) { + return mAlarmMsgInfoList.get(position); + } + + @Override + public long getItemId(int position) { + // TODO Auto-generated method stub + return position; + } + + /** + * 删除某条报警信息 + * @param info + */ + private void deleteAlarmMsg(final AlarmMessageInfo info) { + Business.getInstance().deleteAlarmMessage(info, new Handler() { + + @Override + public void handleMessage(Message msg) { + if (msg.what != 0) { + Toast.makeText(AlarmMessageActivity.this, R.string.toast_alarmmsg_delete_failed, + Toast.LENGTH_LONG).show(); + } else { + //mAlarmMsgInfoList.remove(info); + //mAlarmMsgAdapt.notifyDataSetChanged(); + + loadAlarmMsgList(mStartTime,mEndTime); + //清空屏幕 + mAlarmMsgAdapt.notifyDataSetChanged(); + mNoMsgImageView.setVisibility(View.GONE); + mProgressDialog.setStart(getString(R.string.common_loading)); + } + } + }); + } + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + final ViewHolder holder; + + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate( + R.layout.activity_alarm_message_item, null); + holder.photo = (ImageView) convertView.findViewById(R.id.photo); + holder.timeText = (TextView) convertView + .findViewById(R.id.alarmTime); + holder.deleteButton = (ImageView) convertView + .findViewById(R.id.delete); + + // 删除按钮添加响应事件 + holder.deleteButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + DialogInterface.OnClickListener dialogOnclicListener=new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface dialog, int which) { + switch(which){ + case Dialog.BUTTON_POSITIVE: + deleteAlarmMsg(holder.info); + break; + case Dialog.BUTTON_NEGATIVE: + break; + case Dialog.BUTTON_NEUTRAL: + break; + } + } + }; + //dialog参数设置 + AlertDialog.Builder builder=new AlertDialog.Builder(AlarmMessageActivity.this); //先得到构造器 + builder.setTitle(R.string.alarm_message_delete_dialog_title); //设置标题 + builder.setMessage(R.string.alarm_message_delete_dialog_message); //设置内容 + builder.setPositiveButton(R.string.dialog_positive,dialogOnclicListener); + builder.setNegativeButton(R.string.dialog_negative,dialogOnclicListener); + builder.create().show(); + } + }); + + holder.photo.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + mAlarmMsgListView.setVisibility(View.GONE); + mCommonTitle.setVisibility(View.GONE); + mDatePickerContainer.setVisibility(View.GONE); + + mProgressDialog.setStart(getString(R.string.common_loading)); + mShowBigImageView.setTag(holder.info.getPicUrl().hashCode()); + mShowBigImageView.setImageDrawable(null); + mShowBigImageView.setVisibility(View.VISIBLE); + if(holder.info.getPicUrl() != null && holder.info.getPicUrl().length() > 0) + ImageHelper.loadRealImage(holder.info.getPicUrl(), holder.info.getDeviceId(),holder.info.getDeviceKey() != null ? holder.info.getDeviceKey() : holder.info.getDeviceId(), new Handler(){ + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if ((Integer)mShowBigImageView.getTag() == msg.what) { + mProgressDialog.setStop(); //关闭加载窗口 + if (msg.obj != null) { + mShowBigImageView.setImageDrawable((Drawable)msg.obj); + } else { + Toast.makeText(AlarmMessageActivity.this, R.string.toast_alarmmsg_load_failed, Toast.LENGTH_SHORT).show(); + } + } + } + }); + } + }); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + //修改数据信息 + holder.info = getItem(position); + Log.d("", "index : " + position); + + //背景\holder.photo图片清空 + holder.photo.setBackgroundResource(R.drawable.list_bg_device); + if(holder.info.getThumbUrl() != null && holder.info.getThumbUrl().length() > 0) + ImageHelper.loadCacheImage(holder.info.getThumbUrl(),holder.info.getDeviceId(),holder.info.getDeviceKey() != null ? holder.info.getDeviceKey() : holder.info.getDeviceId(), new Handler(){ + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if(holder.info.getThumbUrl().hashCode() == msg.what && msg.obj != null){ + //Log.d(tag, msg.obj.toString()); + holder.photo.setBackgroundDrawable((Drawable)msg.obj); + } + } + }); + // 报警时间更新 + holder.timeText.setText(holder.info.getLocalDate()); + + + return convertView; + } + + + } + + static class ViewHolder { + public ImageView photo; + public TextView timeText; + public ImageView deleteButton; + public AlarmMessageInfo info; + } + +} diff --git a/app/src/main/java/com/lechange/demo/tools/DateHelper.java b/app/src/main/java/com/lechange/demo/tools/DateHelper.java new file mode 100644 index 0000000..acf7e7f --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/DateHelper.java @@ -0,0 +1,51 @@ +package com.lechange.demo.tools; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +public class DateHelper { + public static Date string2Date(String time) { + try { + String str = time; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = (Date) sdf.parse(str); + return date; + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + public static String dateFormat(Date date) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + String dateString = formatter.format(date); + return dateString; + } + + public static String dateFormatTiming(long date) { + SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); + formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00")); + String dateString = formatter.format(date); + return dateString; + } + + public static String getTimeHMS(long time) { + SimpleDateFormat format1 = new SimpleDateFormat("HH:mm:ss"); + Date date = new Date(time); + String date1 = format1.format(date); + return date1; + } + + public static long parseMills(String dateTime) { + try { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateTime)); + return calendar.getTimeInMillis(); + } catch (ParseException e) { + return 0; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/tools/DeviceAbilityHelper.java b/app/src/main/java/com/lechange/demo/tools/DeviceAbilityHelper.java new file mode 100644 index 0000000..bc3e007 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/DeviceAbilityHelper.java @@ -0,0 +1,19 @@ +package com.lechange.demo.tools; + +public class DeviceAbilityHelper { + + + public static boolean isHasAbility(String deviceAbility,String channelAbility,String ability1,String ability2){ + if (deviceAbility==null||channelAbility==null)return false; + + if (deviceAbility.contains(ability1)||deviceAbility.contains(ability2)){ + return true; + }else if (channelAbility.contains(ability1)||channelAbility.contains(ability2)){ + return true; + } + + return false; + + } + +} diff --git a/app/src/main/java/com/lechange/demo/tools/DialogUtils.java b/app/src/main/java/com/lechange/demo/tools/DialogUtils.java new file mode 100644 index 0000000..32d82af --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/DialogUtils.java @@ -0,0 +1,47 @@ +package com.lechange.demo.tools; + +import android.app.Activity; + +import com.lechange.demo.dialog.LoadingDialog; + +public class DialogUtils { + static LoadingDialog mLoadingDialog; + static Activity activity; + + public static void show(Activity mActivity) { + if (mActivity.isFinishing()) { + return; + } + if (activity != null) { + if (activity == mActivity) { + if (null != mLoadingDialog) { + if (mLoadingDialog.isShowing()) { + return; + } + } + } + } + activity = mActivity; + if (null != mLoadingDialog) { + dismiss(); + } + mLoadingDialog = new LoadingDialog(mActivity); + mLoadingDialog.show(); + } + + public static void dismiss() { + if (null == mLoadingDialog) { + return; + } + if (mLoadingDialog.isShowing()) { + try { + mLoadingDialog.dismissLoading(); + mLoadingDialog = null; + activity = null; + } catch (Exception e) { + mLoadingDialog = null; + activity = null; + } + } + } +} diff --git a/app/src/main/java/com/lechange/demo/tools/ImageHelper.java b/app/src/main/java/com/lechange/demo/tools/ImageHelper.java new file mode 100644 index 0000000..93a3f94 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/ImageHelper.java @@ -0,0 +1,217 @@ +package com.lechange.demo.tools; + +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.BitmapFactory.Options; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.LruCache; + +import com.lechange.common.log.Logger; +import com.lechange.opensdk.utils.LCOpenSDK_Utils; +import com.mm.android.deviceaddmodule.LCDeviceEngine; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class ImageHelper { + + private final static String TAG = "LCOpenSDK_Demo_ImageHelper"; + private static Options mDefaultOption; + //最近最少使用算法的缓存策略 + private static LruCache mImageCache = new LruCache(100); + + static { + mDefaultOption = new Options(); + //demo里面为了降低使用内存,图片缩小了一倍 + mDefaultOption.inSampleSize = 2; + mDefaultOption.inPreferredConfig = Config.RGB_565; + } + + public static void loadRealImage(final String url, final Handler handler) { + downloadImage(url, "real", handler); + } + + /** + * 加载普通图片(缓存) + * + * @param url + * @param handler + */ + public static void loadCacheImage(final String url, final Handler handler) { + String[] imageIDBuffer = url.split("[/?]"); + final String imageID = imageIDBuffer[imageIDBuffer.length - 2]; + Drawable drawable = mImageCache.get(imageID); + if (drawable != null) { + Message msg = new Message(); + msg.what = url.hashCode(); + msg.obj = drawable; + handler.handleMessage(msg); + } else { + downloadImage(url, imageID, handler); + } + } + + /** + * 加载加密图片(缓存) + * + * @param url + * @param key + * @param handler + */ + public static void loadCacheImage(final String url, final String deviceId, String key, int position,final Handler handler) { + String[] imageIDBuffer = url.split("[/?]"); + String imageID; + if (imageIDBuffer.length - 2 > 0) { + imageID = imageIDBuffer[imageIDBuffer.length - 2]; + } else { + imageID = ""; + } + Drawable drawable = mImageCache.get(imageID); + if (drawable != null) { + Message msg = new Message(); + msg.what = url.hashCode(); + msg.obj = drawable; + msg.arg1=position; + handler.handleMessage(msg); + } else { + downloadImage(url, imageID, deviceId, key, position, handler); + } + } + + /** + * 下载普通图片任务 + * + * @param url + * @param imageID + * @param handler + */ + private static void downloadImage(final String url, final String imageID, final Handler handler) { + TaskPoolHelper.addTask(new TaskPoolHelper.RunnableTask(imageID) { + @Override + public void run() { + Drawable drawable = null; + try { + //创建一个url对象 + URL resurl = new URL(url); + //设置超时时间 + HttpURLConnection urlConn = (HttpURLConnection) resurl.openConnection(); + urlConn.setConnectTimeout(5000); + urlConn.setReadTimeout(5000); + //打开URL对应的资源输入流 + InputStream is = urlConn.getInputStream(); + //从InputStream流中解析出图片 + Bitmap bitmap = BitmapFactory.decodeStream(is, null, mDefaultOption); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + //加入缓存 + mImageCache.put(imageID, drawable); + //关闭输入流 + is.close(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解析设备列表信息 + handler.obtainMessage(url.hashCode(), drawable).sendToTarget(); // 发送成功消息到界面 + } + }); + } + + /** + * 下载加密图片任务 + * + * @param url + * @param imageID + * @param key + * @param handler + */ + private static void downloadImage(final String url, final String imageID, final String deviceId, final String key, final int position, final Handler handler) { + TaskPoolHelper.addTask(new TaskPoolHelper.RunnableTask(imageID) { + @Override + public void run() { + Drawable drawable = null; + try { + //创建一个url对象 + URL resurl = new URL(url); + //设置超时时间 + HttpURLConnection urlConn = (HttpURLConnection) resurl.openConnection(); + urlConn.setConnectTimeout(5000); + urlConn.setReadTimeout(5000); + int code = urlConn.getResponseCode(); + Logger.e(TAG, "====getResponseCode, code=" + code + ", resurl.file=" + resurl.getFile()); + //打开URL对应的资源输入流 + InputStream is = urlConn.getInputStream(); + //从InputStream流中解析出图片 + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + byte[] buff = new byte[500]; + int rc = 0; + int length = 0; + while ((rc = is.read(buff, 0, 500)) > 0) { + length += rc; + swapStream.write(buff, 0, rc); + } + byte[] srcBuf = swapStream.toByteArray(); + byte[] dstBuf = new byte[500000]; + int[] dstLen = new int[1]; + dstLen[0] = 500000; + Bitmap bitmap; //=null + //调用图片解密新接口:三码合一 + int res = LCOpenSDK_Utils.decryptPic(LCDeviceEngine.newInstance().accessToken, srcBuf, length, deviceId, key, dstBuf, dstLen); + Logger.e(TAG, "====LCOpenSDK_Utils.decryptPic, res=" + res + ", length=" + length); + switch (res) { + case 0: //解密成功 + bitmap = BitmapFactory.decodeByteArray(dstBuf, 0, dstLen[0], mDefaultOption); + if (bitmap == null) { + String filepath = "sdcard/temp.jpg"; + //String sd = Environment.getExternalStorageDirectory() + "/temp.jpg"; + File file = new File(filepath); + OutputStream outputStream = new FileOutputStream(file); + outputStream.write(dstBuf); + outputStream.flush(); + outputStream.close(); + bitmap = BitmapFactory.decodeFile(filepath); + Logger.e(TAG, "BitmapFactory.decodeFile"); + } + + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + break; + case 1://待解密数据不完整 + case 3: //图片非加密 + bitmap = BitmapFactory.decodeByteArray(srcBuf, 0, length, mDefaultOption); + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + } + break; + default: //解密失败 + break; + } + //加入缓存 + mImageCache.put(imageID, drawable); + //关闭输入流 + is.close(); + swapStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + // 解析设备列表信息 + handler.obtainMessage(url.hashCode(), position,0,drawable).sendToTarget(); // 发送成功消息到界面 + } + }); + } + + public static void clear() { + TaskPoolHelper.clearTask(); + mImageCache.evictAll(); + } +} diff --git a/app/src/main/java/com/lechange/demo/tools/MediaPlayHelper.java b/app/src/main/java/com/lechange/demo/tools/MediaPlayHelper.java new file mode 100644 index 0000000..286e426 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/MediaPlayHelper.java @@ -0,0 +1,277 @@ +package com.lechange.demo.tools; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.media.MediaScannerConnection; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.MediaStore; +import android.view.WindowManager; + +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.net.FileNameMap; +import java.net.URLConnection; +import java.text.SimpleDateFormat; + +public class MediaPlayHelper { + + private final static String ProjectName = "LechangeDemo"; + + private static Context mContext; + + public static void initContext(Context context) { + mContext = context; + } + + public enum DHFilesType { + DHImage, + DHVideo, + DHImageCache + } + + public static void setFullScreen(Activity activity) { + activity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + public static void quitFullScreen(Activity activity) { + final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); + attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); + activity.getWindow().setAttributes(attrs); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + + + /** + * 创建文件路径 + * + * @param file + * @param filePath + * @return + */ + public static boolean createFilePath(File file, String filePath) { + LogUtil.debugLog("20210513", "filePath::" + filePath); + int index = filePath.indexOf("/"); + if (index == -1) { + LogUtil.debugLog("20210513", "filePath---------:" + file.getAbsolutePath() + " filepath::" + filePath); + LogUtil.debugLog("20210513", "filePath---------::" + file.getPath() + " " + file.getName() + " " + file.getParent()); + // scanFile(file); + return false; + } + if (index == 0) { + filePath = filePath.substring(index + 1, filePath.length()); + index = filePath.indexOf("/"); + } + String path = filePath.substring(0, index); + File fPath; + if (file == null) { + fPath = new File(path); + } else { + fPath = new File(file.getPath() + "/" + path); + } + if (!fPath.exists()) { + if (!fPath.mkdir()) // SD卡已满无法在下载文件 + { + return false; + } + } + if (index < (filePath.length() - 1)) { + String exPath = filePath.substring(index + 1, filePath.length()); + createFilePath(fPath, exPath); + } + return true; + } + + /** + * 生成抓图路径或录像存放路径 + */ + public static String getCaptureAndVideoPath(DHFilesType type, String cameraName) { + String path = null; + String picType = null; + java.util.Date now = new java.util.Date(); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + String sdPath = null; + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + sdPath = mContext.getExternalFilesDir("demo").getAbsolutePath(); + } else { + }*/ + sdPath = Environment.getExternalStorageDirectory().getPath(); + + + if (type == DHFilesType.DHImage) { + picType = "image"; + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + cameraName + ".jpg"; + } else { + picType = "video"; + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + cameraName + ".mp4"; + } + if (type == DHFilesType.DHImageCache) { + picType = "imageCache"; + path = sdPath + "/" + ProjectName + "/" + picType + "/" + tf.format(now) + "_" + + cameraName + ".jpg"; + } + createFilePath(null, path); + return path; + } + + + public static void updatePhotoAlbum(String path) { + if (path == null) return; + String[] split = path.split("/"); + String fileName = split[split.length - 1]; + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + ContentValues values = new ContentValues(); + values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName); + values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); + values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM); + ContentResolver contentResolver = mContext.getContentResolver(); + Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + + if (uri == null) { + return; + } + OutputStream out = null; + FileInputStream fis= null; + try { + out = contentResolver.openOutputStream(uri); + fis = new FileInputStream(path); + FileUtils.copy(fis, out); + fis.close(); + out.close(); + + //导出相册成功后,删除App沙盒内的临时文件 + MediaPlayHelper.delete(path); + } catch (Exception e) { + e.printStackTrace(); + } + } else { }*/ + MediaScannerConnection.scanFile(mContext.getApplicationContext(), new String[]{path}, new String[]{"image/jpeg"}, new MediaScannerConnection.OnScanCompletedListener() { + @Override + public void onScanCompleted(String path, Uri uri) { + + } + }); + + } + + public static void updatePhotoVideo(String path) { + if (path == null) return; + String[] split = path.split("/"); + String fileName = split[split.length - 1]; + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + ContentValues values = new ContentValues(); + values.put(MediaStore.Video.VideoColumns.DISPLAY_NAME, fileName); + values.put(MediaStore.Video.VideoColumns.MIME_TYPE, "video/3gp"); + values.put(MediaStore.Video.VideoColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM); + ContentResolver contentResolver = mContext.getContentResolver(); + Uri uri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values); + + if (uri == null) { + return; + } + OutputStream out = null; + FileInputStream fis = null; + try { + out = contentResolver.openOutputStream(uri); + fis = new FileInputStream(path); + FileUtils.copy(fis, out); + fis.close(); + out.close(); + + //导出相册成功后,删除App沙盒内的临时文件 + MediaPlayHelper.delete(path); + + } catch (Exception e) { + e.printStackTrace(); + } + } else {}*/ + MediaScannerConnection.scanFile(mContext.getApplicationContext(), new String[]{path}, new String[]{"video/3gp"}, new MediaScannerConnection.OnScanCompletedListener() { + @Override + public void onScanCompleted(String path, Uri uri) { + + } + }); + + } + + + public static String getMimeType(File file) { + FileNameMap fileNameMap = URLConnection.getFileNameMap(); + String type = fileNameMap.getContentTypeFor(file.getName()); + return type; + } + + + /** + * 生成下载录像存放路径 + */ + public static String getDownloadVideoPath(int type, String recordID, long startTime) { + String path = null; + String sdPath = null; + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + sdPath = mContext.getExternalFilesDir("demo").getAbsolutePath(); + } else { + }*/ + sdPath = Environment.getExternalStorageDirectory().getPath(); + + String picType = "download"; + picType += type == 0 ? "_cloud" : "_remote"; + java.util.Date now = new java.util.Date(startTime); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + recordID + ".mp4"; + createFilePath(null, path); + return path; + } + + /** + * 删除下载录像存放的录像 + */ + public static void deleteDownloadVideo(String recordID, long startTime) { + String path = null; + String sdPath = Environment.getExternalStorageDirectory().getPath(); + String picType = "download"; + java.util.Date now = new java.util.Date(startTime); + SimpleDateFormat tf = new SimpleDateFormat("yyyyMMddHHmmss"); + path = sdPath + "/" + ProjectName + "/" + tf.format(now) + "_" + picType + "_" + + recordID + ".mp4"; + File soFile = new File(path); + if (soFile.exists()) { + soFile.delete(); + } + } + + /** + * 删除缓存文件 + */ + public static void delete(String path) { + File file = new File(path); + if (file.exists()) { + file.delete(); + } + } + + public static BitmapDrawable picDrawable(String path) { + try { + FileInputStream fis = new FileInputStream(path); + Bitmap bitmap = BitmapFactory.decodeStream(fis); + BitmapDrawable bd = new BitmapDrawable(bitmap); + return bd; + } catch (Throwable e) { + return null; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/tools/RootUtil.java b/app/src/main/java/com/lechange/demo/tools/RootUtil.java new file mode 100644 index 0000000..fd28fcf --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/RootUtil.java @@ -0,0 +1,47 @@ +package com.lechange.demo.tools; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; + +public class RootUtil { + public static boolean isDeviceRooted() { + return checkRootMethod1() || checkRootMethod2() || checkRootMethod3(); + } + + private static boolean checkRootMethod1() { + String buildTags = android.os.Build.TAGS; + return buildTags != null && buildTags.contains("test-keys"); + } + + private static boolean checkRootMethod2() { + String[] paths = {"/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", + "/system/xbin/su", "/data/local/xbin/su", + "/data/local/bin/su", "/system/sd/xbin/su", + "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"}; + for (String path : paths) { + if (new File(path).exists()) { + return true; + } + } + return false; + } + + private static boolean checkRootMethod3() { + Process process = null; + try { + process = Runtime.getRuntime().exec(new String[]{"/system/xbin/which", "su"}); + BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); + if (in.readLine() != null) { + return true; + } + return false; + } catch (Throwable t) { + return false; + } finally { + if (process != null) { + process.destroy(); + } + } + } +} diff --git a/app/src/main/java/com/lechange/demo/tools/TaskPoolHelper.java b/app/src/main/java/com/lechange/demo/tools/TaskPoolHelper.java new file mode 100644 index 0000000..1fdf3c5 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/tools/TaskPoolHelper.java @@ -0,0 +1,103 @@ +package com.lechange.demo.tools; + +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.locks.LockSupport; + +public class TaskPoolHelper { + private final static String TAG = "lcop_TaskPoolHelper"; + + /** + * 构造具备过滤的task + */ + public static abstract class RunnableTask implements Runnable { + public String mTaskID; + + public RunnableTask(String taskID){ + this.mTaskID = taskID; + } + } + + //private static ExecutorService mPool = Executors.newFixedThreadPool(3); + //队列属性的task + private static ArrayBlockingQueue mQueueTask = new ArrayBlockingQueue(50); + private static List mFilteTask = new ArrayList(); + private static Thread mQueueThread; + + //实时属性的task + private static RunnableTask mRealTask; //=null + private static Thread mRealThread; + + static { + mQueueThread = new Thread() { + @Override + public void run() { + // TODO Auto-generated method stub + super.run(); + while (true) { + try { + //自带阻塞光环 + RunnableTask task = mQueueTask.take(); + task.run(); + mFilteTask.remove(task.mTaskID); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + }; + mQueueThread.start(); + + mRealThread = new Thread() { + @Override + public void run() { + // TODO Auto-generated method stub + super.run(); + while (true) { + if (mRealTask == null) { + LockSupport.park(); + } else { + RunnableTask task = mRealTask; + mRealTask = null; + task.run(); + } + } + } + }; + mRealThread.start(); + } + + + public static void addTask(RunnableTask task) { + //过滤 + if (task.mTaskID.equals("real")) { + mRealTask = task; + LockSupport.unpark(mRealThread); + return; + } + if (mFilteTask.contains(task.mTaskID)) { + return; + } + + try { + mQueueTask.add(task); + mFilteTask.add(task.mTaskID); + } catch(IllegalStateException e) { + LogUtil.debugLog(TAG, e.getMessage()); + mQueueTask.clear(); + mFilteTask.clear(); + } + } + + + + public static void clearTask(){ + mQueueTask.clear(); + mFilteTask.clear(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceCloudRecordListFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceCloudRecordListFragment.java new file mode 100644 index 0000000..8bfc4ac --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceCloudRecordListFragment.java @@ -0,0 +1,416 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceRecordService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.CloudRecordsData; +import com.common.openapi.entity.DeleteCloudRecordsData; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.RecordListData; +import com.common.openapi.entity.RecordsData; +import com.lechange.demo.adapter.DeviceRecordListAdapter; +import com.lechange.demo.tools.DateHelper; +import com.lechange.demo.tools.DialogUtils; +import com.lechange.demo.view.LcPullToRefreshRecyclerView; +import com.lechange.pulltorefreshlistview.Mode; +import com.lechange.pulltorefreshlistview.PullToRefreshBase; +import com.mm.android.deviceaddmodule.mobilecommon.dialog.LCAlertDialog; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.mm.android.deviceaddmodule.mobilecommon.utils.TimeUtils; +import com.mm.android.deviceaddmodule.mobilecommon.utils.UIUtils; +import com.yonsz.z1.R; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +public class DeviceCloudRecordListFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IDeviceCloudRecordCallBack, IGetDeviceInfoCallBack.IDeviceDeleteRecordCallBack, PullToRefreshBase.OnRefreshListener2 { + private static final String TAG = DeviceCloudRecordListFragment.class.getSimpleName(); + private Bundle arguments; + private String searchDate; + private long searchDate1; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private RecyclerView recyclerView; + private TextView tvMonthDay; + private DeviceRecordService deviceRecordService = ClassInstanceManager.newInstance().getDeviceRecordService(); + private List recordListDataList = new ArrayList<>(); + private DeviceRecordListAdapter deviceRecordListAdapter; + private long oneDay = 24 * 60 * 60 * 1000; + private static DeviceCloudRecordListFragment fragment; + private DeviceRecordListActivity deviceRecordListActivity; + private boolean editStatus = false; + private TextView tvDelete; + private List recordRegionIds = new ArrayList<>(); + private LcPullToRefreshRecyclerView deviceList; + private int pageSize = 30; + private long nextRecordId = -1; + private LCAlertDialog mLCAlertDialog; + private TextView tvToday; + + public static DeviceCloudRecordListFragment newInstance() { + fragment = new DeviceCloudRecordListFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + arguments = getArguments(); + searchDate = DateHelper.dateFormat(new Date(System.currentTimeMillis())); + searchDate1 = DateHelper.parseMills(searchDate + " 00:00:00"); + deviceRecordListActivity = (DeviceRecordListActivity) getActivity(); + deviceRecordListActivity.llEdit.setOnClickListener(this); + deviceRecordListActivity.llAll.setOnClickListener(this); + deviceRecordListActivity.llEdit.setVisibility(View.GONE); + deviceRecordListActivity.llAll.setVisibility(View.GONE); + deviceRecordListActivity.llBack.setVisibility(View.VISIBLE); + } + + public void deleteCloudRecord() { + if (!isAdded()) { + return; + } + initCloudRecord(false); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_cloud_list, container, false); + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (!hidden) { +// deviceRecordListActivity.llEdit.setVisibility(View.VISIBLE); + deviceRecordListActivity.llAll.setVisibility(editStatus ? View.VISIBLE : View.GONE); + deviceRecordListActivity.llBack.setVisibility(editStatus ? View.GONE : View.VISIBLE); + } else { + deviceRecordListActivity.llEdit.setVisibility(View.GONE); + deviceRecordListActivity.llAll.setVisibility(View.GONE); + deviceRecordListActivity.llBack.setVisibility(View.VISIBLE); + } + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(view); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + if (deviceListBean == null) { + return; + } + initData(); + } + + private ImageView mNextDayTv; + + private void initView(View view) { + view.findViewById(R.id.iv_day_pre).setOnClickListener(this); + mNextDayTv = view.findViewById(R.id.iv_day_next); + tvDelete = view.findViewById(R.id.tv_delete); + tvMonthDay = view.findViewById(R.id.tv_month_day); + deviceList = view.findViewById(R.id.record_list); + tvToday = view.findViewById(R.id.tv_today); + deviceList.setOnRefreshListener(this); + mNextDayTv.setOnClickListener(this); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + refreshMode(Mode.PULL_FROM_START); + refreshState(true); + } + }, 200); + recyclerView = deviceList.getRefreshableView(); + tvDelete.setOnClickListener(this); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView.setLayoutManager(linearLayoutManager); + } + + private void refreshState(boolean refresh) { + if (refresh) { + deviceList.setRefreshing(true); + } else { + deviceList.onRefreshComplete(); + } + } + + private void refreshMode(Mode mode) { + deviceList.setMode(mode); + } + + private void initData() { + tvMonthDay.setText(searchDate); + mCalendar.setTime(TimeUtils.stringToDate(searchDate, "yyyy-MM-dd HH:mm:ss")); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + } + + protected Calendar mCalendar = Calendar.getInstance(); + + private void initCloudRecord(boolean isLoadMore) { + if (isLoadMore) { + nextRecordId = nextRecordId; + } else { + nextRecordId = -1; + time = ""; + recordListDataList.clear(); + } + DialogUtils.show(getActivity()); + getCloudData(); + /* deviceRecordService.queryCloudUse(deviceListBean.deviceId, deviceListBean.channels.get(deviceListBean.checkedChannel).channelId, new IGetDeviceInfoCallBack.ICommon() { + @Override + public void onCommonBack(Integer response) { + if (response==-1||response==0){ + DialogUtils.dismiss(); + refreshState(false); + editStatus(false); + tvToday.setVisibility(View.VISIBLE); + tvToday.setText(getActivity().getResources().getString(R.string.lc_demo_device_cloud_not_open)); + }else{ + getCloudData(); + } + } + + @Override + public void onError(Throwable throwable) { + Toast.makeText(getActivity(),throwable.getMessage(),Toast.LENGTH_SHORT).show(); + } + });*/ + } + + private void getCloudData() { + CloudRecordsData cloudRecordsData = new CloudRecordsData(); + cloudRecordsData.data.deviceId = deviceListBean.deviceId; + cloudRecordsData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + cloudRecordsData.data.beginTime = searchDate + " 00:00:00"; + cloudRecordsData.data.endTime = searchDate + " 23:59:59"; + cloudRecordsData.data.nextRecordId = nextRecordId; + cloudRecordsData.data.count = pageSize; + deviceRecordService.getCloudRecords(cloudRecordsData, this); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.iv_day_pre) { + searchDate1 = searchDate1 - oneDay; + searchDate = DateHelper.dateFormat(new Date(searchDate1)); + tvMonthDay.setText(searchDate); + mCalendar.setTime(new Date(searchDate1)); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + initCloudRecord(false); + } else if (id == R.id.tv_delete) { + recordRegionIds.clear(); + for (RecordListData recordListData : recordListDataList) { + for (RecordsData recordsData : recordListData.recordsData) { + if (recordsData.check) { + recordRegionIds.add(recordsData.recordRegionId); + } + } + } + if (recordRegionIds.size() == 0) { + return; + } + LCAlertDialog.Builder builder = new LCAlertDialog.Builder(getContext()); + builder.setTitle(R.string.lc_demo_device_delete_sure); + builder.setMessage(""); + builder.setCancelButton(com.mm.android.deviceaddmodule.R.string.common_cancel, null); + builder.setConfirmButton(com.mm.android.deviceaddmodule.R.string.common_confirm, + new LCAlertDialog.OnClickListener() { + @Override + public void onClick(LCAlertDialog dialog, int which, boolean isChecked) { + //删除 + DialogUtils.show(getActivity()); + DeleteCloudRecordsData deleteCloudRecordsData = new DeleteCloudRecordsData(); + deleteCloudRecordsData.data.recordRegionIds = recordRegionIds; + deviceRecordService.deleteCloudRecords(deleteCloudRecordsData, DeviceCloudRecordListFragment.this); + } + }); + + mLCAlertDialog = builder.create(); + mLCAlertDialog.show(getActivity().getSupportFragmentManager(), "delete"); + } else if (id == R.id.iv_day_next) { + searchDate1 = searchDate1 + oneDay; + searchDate = DateHelper.dateFormat(new Date(searchDate1)); + tvMonthDay.setText(searchDate); + mCalendar.setTime(new Date(searchDate1)); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + initCloudRecord(false); + } else if (id == R.id.ll_edit) { + editStatus(!editStatus); + if (editStatus && recordListDataList.size() <= 0) { + return; + } + for (RecordListData recordListData : recordListDataList) { + for (RecordsData recordsData : recordListData.recordsData) { + recordsData.check = false; + } + } + deviceRecordListAdapter.notifyDataSetChanged(); + } else if (id == R.id.ll_all) { + if (recordListDataList.size() <= 0) { + return; + } + for (RecordListData recordListData : recordListDataList) { + for (RecordsData recordsData : recordListData.recordsData) { + recordsData.check = true; + } + } + deviceRecordListAdapter.notifyDataSetChanged(); + } + } + + @Override + public void deviceCloudRecord(CloudRecordsData.Response result) { + if (!isAdded()) { + return; + } + tvToday.setVisibility(View.GONE); + recyclerView.setVisibility(View.VISIBLE); + DialogUtils.dismiss(); + refreshState(false); + editStatus(false); + if (result != null && result.data != null && result.data.records != null && result.data.records.size() > 0) { + if (result.data.records.size() >= pageSize) { + refreshMode(Mode.BOTH); + nextRecordId = Long.parseLong(result.data.records.get(result.data.records.size() - 1).recordId); + } else { + refreshMode(Mode.PULL_FROM_START); + } + recordListDataList = dealCloudRecord(result); + } else { + if (nextRecordId == -1) { + tvToday.setVisibility(View.VISIBLE); + recyclerView.setVisibility(View.GONE); + } + refreshMode(Mode.PULL_FROM_START); + } + showList(); + } + + private void editStatus(boolean b) { + editStatus = b; + tvDelete.setVisibility(editStatus ? View.VISIBLE : View.GONE); + deviceRecordListActivity.tvEdit.setText(editStatus ? getResources().getString(R.string.lc_demo_device_record_edit_finish) : getResources().getString(R.string.lc_demo_device_record_edit)); + deviceRecordListActivity.llAll.setVisibility(editStatus ? View.VISIBLE : View.GONE); + deviceRecordListActivity.llBack.setVisibility(editStatus ? View.GONE : View.VISIBLE); + } + + @Override + public void deleteDeviceRecord() { + if (!isAdded()) { + return; + } + DialogUtils.dismiss(); + initCloudRecord(false); + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()) { + return; + } + LogUtil.errorLog(TAG, "error", throwable); + DialogUtils.dismiss(); + refreshState(false); + refreshMode(Mode.PULL_FROM_START); + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + nextRecordId = -1; + time = ""; + recordListDataList.clear(); + editStatus(false); + showList(); + } + + private void showList() { + if (deviceRecordListAdapter == null) { + deviceRecordListAdapter = new DeviceRecordListAdapter(getContext(), recordListDataList); + recyclerView.setAdapter(deviceRecordListAdapter); + } else { + deviceRecordListAdapter.notifyDataSetChanged(); + } + deviceRecordListAdapter.setEditClickListener(new DeviceRecordListAdapter.EditClickListener() { + @Override + public void edit(int outPosition, int innerPosition) { + LogUtil.debugLog(TAG, outPosition + "..." + innerPosition); + if (editStatus) { + recordListDataList.get(outPosition).recordsData.get(innerPosition).check = !recordListDataList.get(outPosition).recordsData.get(innerPosition).check; + deviceRecordListAdapter.notifyDataSetChanged(); + } else { + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + bundle.putSerializable(MethodConst.ParamConst.recordData, recordListDataList.get(outPosition).recordsData.get(innerPosition)); + bundle.putInt(MethodConst.ParamConst.recordType, MethodConst.ParamConst.recordTypeCloud); + Intent intent = new Intent(getContext(), DeviceRecordPlayActivity.class); + intent.putExtras(bundle); + startActivityForResult(intent, 0); + } + } + }); + } + + String time = ""; + + private List dealCloudRecord(CloudRecordsData.Response result) { + for (CloudRecordsData.ResponseData.RecordsBean recordsBean : result.data.records) { + String innerTime = recordsBean.beginTime.substring(11, 13); + RecordsData a = new RecordsData(); + a.recordType = 0; + a.recordId = recordsBean.recordId; + a.deviceId = recordsBean.deviceId; + a.channelID = recordsBean.channelId; + a.beginTime = recordsBean.beginTime; + a.endTime = recordsBean.endTime; + a.size = recordsBean.size; + a.thumbUrl = recordsBean.thumbUrl; + a.encryptMode = recordsBean.encryptMode; + a.recordRegionId = recordsBean.recordRegionId; + a.type = recordsBean.type; + if (!innerTime.equals(time)) { + RecordListData r = new RecordListData(); + r.period = innerTime + ":00"; + r.recordsData = new ArrayList<>(); + r.recordsData.add(a); + recordListDataList.add(r); + time = innerTime; + } else { + RecordListData b = recordListDataList.get(recordListDataList.size() - 1); + b.recordsData.add(a); + } + } + LogUtil.debugLog(TAG, recordListDataList.size() + ""); + return recordListDataList; + } + + @Override + public void onPullDownToRefresh(PullToRefreshBase pullToRefreshBase) { + initCloudRecord(false); + } + + @Override + public void onPullUpToRefresh(PullToRefreshBase pullToRefreshBase) { + initCloudRecord(true); + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailDeploymentFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailDeploymentFragment.java new file mode 100644 index 0000000..09846e5 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailDeploymentFragment.java @@ -0,0 +1,138 @@ +package com.lechange.demo.ui; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceDetailService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceAlarmStatusData; +import com.common.openapi.entity.DeviceChannelInfoData; +import com.common.openapi.entity.DeviceDetailListData; +import com.lechange.demo.tools.DialogUtils; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.mine.mydevice.DeviceDetailActivity; + +public class DeviceDetailDeploymentFragment extends Fragment implements IGetDeviceInfoCallBack.IDeviceChannelInfoCallBack, View.OnClickListener, IGetDeviceInfoCallBack.IDeviceAlarmStatusCallBack { + private static final String TAG = DeviceDetailDeploymentFragment.class.getSimpleName(); + private Bundle arguments; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private DeviceDetailLCActivity deviceDetailActivity; + private ImageView ivMoveCheck; + private int alarmStatus; + + public static DeviceDetailDeploymentFragment newInstance() { + DeviceDetailDeploymentFragment fragment = new DeviceDetailDeploymentFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.GONE); + arguments = getArguments(); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_detail_deployment, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(view); + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_deployment_title)); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + if (deviceListBean == null) { + return; + } + initData(); + } + + private void initView(View view) { + ivMoveCheck = view.findViewById(R.id.iv_move_check); + ivMoveCheck.setOnClickListener(this); + } + + private void initData() { + //获取动检状态/设备详情 + DialogUtils.show(getActivity()); + DeviceDetailService deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + DeviceChannelInfoData deviceChannelInfoData = new DeviceChannelInfoData(); + deviceChannelInfoData.data.deviceId = deviceListBean.deviceId; + deviceChannelInfoData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + deviceDetailService.bindDeviceChannelInfo(deviceChannelInfoData, this); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void deviceChannelInfo(DeviceChannelInfoData.Response result) { + if (!isAdded()){ + return; + } + DialogUtils.dismiss(); + this.alarmStatus = result.data.alarmStatus; + if (result.data.alarmStatus == 1) { + ivMoveCheck.setImageDrawable(getResources().getDrawable(R.mipmap.lc_demo_switch_on)); + } else { + ivMoveCheck.setImageDrawable(getResources().getDrawable(R.mipmap.lc_demo_switch_off)); + } + } + + @Override + public void deviceAlarmStatus(boolean result) { + if (!isAdded()){ + return; + } + DialogUtils.dismiss(); + this.alarmStatus = (this.alarmStatus == 1) ? 0 : 1; + if (this.alarmStatus == 1) { + ivMoveCheck.setImageDrawable(getResources().getDrawable(R.mipmap.lc_demo_switch_on)); + } else { + ivMoveCheck.setImageDrawable(getResources().getDrawable(R.mipmap.lc_demo_switch_off)); + } + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()){ + return; + } + DialogUtils.dismiss(); + LogUtil.errorLog(TAG, "error", throwable); + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } + + @Override + public void onClick(View v) { + //设置动检状态 + DialogUtils.show(getActivity()); + DeviceDetailService deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + DeviceAlarmStatusData deviceAlarmStatusData = new DeviceAlarmStatusData(); + deviceAlarmStatusData.data.deviceId = deviceListBean.deviceId; + deviceAlarmStatusData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + //现在是开启状态,则关闭,反之 + deviceAlarmStatusData.data.enable = alarmStatus == 1 ? false : true; + deviceDetailService.modifyDeviceAlarmStatus(deviceAlarmStatusData, this); + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailLCActivity.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailLCActivity.java new file mode 100644 index 0000000..ce18fb3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailLCActivity.java @@ -0,0 +1,109 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.common.openapi.IGetDeviceInfoCallBack; +import com.mm.android.deviceaddmodule.device_wifi.DeviceConstant; +import com.yonsz.z1.R; + +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.CAT_EYE; + +public class DeviceDetailLCActivity extends AppCompatActivity implements View.OnClickListener, IGetDeviceInfoCallBack.IModifyDeviceName { + + public LinearLayout llOperate; + public LinearLayout llBack; + public TextView tvTitle; + public RelativeLayout rlTitle; + public FrameLayout frContent; + public RelativeLayout rlLoading; + private Bundle bundle; + private String name; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_device_detail_lc); + initView(); + initData(); + gotoDetailMainPage(); + } + + private void initData() { + bundle = getIntent().getExtras(); + } + + private void initView() { + llOperate = findViewById(R.id.ll_operate); + llBack = findViewById(R.id.ll_back); + tvTitle = findViewById(R.id.tv_title); + rlTitle = findViewById(R.id.rl_title); + frContent = findViewById(R.id.fr_content); + rlLoading = findViewById(R.id.rl_loading); + llOperate.setOnClickListener(this); + llBack.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.ll_back) { + goBack(); + } else if (id == R.id.ll_operate) { + + } + } + + @Override + public void onBackPressed() { + goBack(); + } + + private void goBack() { + if (llOperate != null) { + llOperate.setVisibility(View.GONE); + } + if (getSupportFragmentManager().getBackStackEntryCount() > 1) { + getSupportFragmentManager().popBackStack(); + } else { + if (!TextUtils.isEmpty(name)) { + Intent intent = new Intent(); + intent.putExtra(DeviceConstant.IntentKey.DHDEVICE_NEW_NAME, name); + setResult(100, intent); + } + finish(); + } + } + + public void gotoDetailMainPage() { + if (getIntent().getExtras().get("deviceType").equals(CAMERA_TAG) || getIntent().getExtras().get("deviceType").equals(CAT_EYE)) { + DeviceDetailMainFragment fragment = DeviceDetailMainFragment.newInstance(); + fragment.setArguments(bundle); + fragment.setModifyNameListener(this); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } else { + DeviceDetailLockFragment fragment = DeviceDetailLockFragment.newInstance(); + fragment.setArguments(bundle); + fragment.setModifyNameListener(this); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + } + + @Override + public void deviceName(String newName) { + name = newName; + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailLockFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailLockFragment.java new file mode 100644 index 0000000..51cd2f3 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailLockFragment.java @@ -0,0 +1,727 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceDetailService; +import com.common.openapi.DeviceLocalCacheService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceLocalCacheData; +import com.common.openapi.entity.DeviceUnBindData; +import com.lechange.demo.business.Business; +import com.lechange.demo.tools.DialogUtils; +import com.lechange.demo.tools.MediaPlayHelper; +import com.lechange.demo.yonsz.RecoverSDCardActivity; +import com.mm.android.deviceaddmodule.LCDeviceEngine; +import com.mm.android.deviceaddmodule.device_wifi.CurWifiInfo; +import com.mm.android.deviceaddmodule.device_wifi.DeviceConstant; +import com.mm.android.deviceaddmodule.mobilecommon.entity.device.DHDevice; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.database.entity.entity4.DeviceSimpleEntity; +import com.yonsz.z1.database.entity.entity5.BaseVersion5Entity; +import com.yonsz.z1.database.entity.entitya2.SafeVoiceEntity; +import com.yonsz.z1.gateway.AddLCSafeCompleteActivity; +import com.yonsz.z1.gateway.UnlockRecordActivity; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUrl; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.AddressNameUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.utils.ToastUtil; +import com.yonsz.z1.version4.DeviceControlActivity; +import com.yonsz.z1.version5.ChooseA1AddDeviceActivity; +import com.yonsz.z1.version5.ChooseA1OrUnbindActivity; +import com.yonsz.z1.version5.ModifyRoomActivity; +import com.yonsz.z1.version5.model.ModelBindActivity; + +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.util.HashMap; + +import de.greenrobot.event.EventBus; + +import static android.app.Activity.RESULT_OK; +import static com.mm.android.deviceaddmodule.device_wifi.DeviceConstant.IntentCode.DEVICE_SETTING_WIFI_LIST; +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.CHECK_USER_BIND_FAIL; +import static com.yonsz.z1.net.Constans.DELLIGHT_ENTITY_SUCCESS; +import static com.yonsz.z1.net.Constans.GET_SWITCHER_CHANGE_INFO; +import static com.yonsz.z1.net.Constans.GET_USERDEVICES4_SIMPLEINFO_FAIL; +import static com.yonsz.z1.net.Constans.GET_USERDEVICES4_SIMPLEINFO_SUCCESS; +import static com.yonsz.z1.net.Constans.INTELLIGENT_DOOR_LOCK; +import static com.yonsz.z1.net.Constans.MODEL_REAPEAT; +import static com.yonsz.z1.net.Constans.MODIFY_DEVICE_NAME; +import static com.yonsz.z1.net.Constans.SELECT_SAFETY_DETAIL_FAIL; +import static com.yonsz.z1.net.Constans.SELECT_SAFETY_DETAIL_SUCCESS; +import static com.yonsz.z1.net.Constans.SEND_UPDATEVOICE_CONTROL_FAIL; +import static com.yonsz.z1.net.Constans.SEND_UPDATEVOICE_CONTROL_SUCCESS; +import static com.yonsz.z1.net.Constans.SWITCH_TAG; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_FAIL; +import static com.yonsz.z1.net.NetWorkUrl.MODIFY_ALARM_STATUS; +import static com.yonsz.z1.net.NetWorkUrl.SUBSET_GETDETAIL; +import static com.yonsz.z1.net.NetWorkUrl.UNBIND_DEVICE; + +public class DeviceDetailLockFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IUnbindDeviceCallBack, IGetDeviceInfoCallBack.IDeviceCacheCallBack, IGetDeviceInfoCallBack.IModifyDeviceName { + private static final String TAG = DeviceDetailLockFragment.class.getSimpleName(); + private RelativeLayout rlDeviceDetail; + private RelativeLayout rlDetailVersion; + private RelativeLayout rlDeployment; + private RelativeLayout rlDetele; + private TextView tvDeviceName; + private ImageView ivDevicePic; + private TextView tvDeviceVersion; + private Bundle arguments; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private DeviceDetailLCActivity deviceDetailActivity; + private DeviceDetailService deviceDetailService; + private CurWifiInfo wifiInfo; + private TextView tvCurrentWifi; + private RelativeLayout rlCurWifi; + private IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener; + private String fromWhere; + + private TextView tv_device_address, tv_electric, tv_bind_ai, tv_safe_model, localStageTv; + private String devicePosition = "1"; + private String deviceId; + private RelativeLayout rl_device_storage, unlockRecordRl, rl_bind_ai, safeModelRl; + private UIHandle mHandler; + private String bindZiId = ""; + private String modelId = "", modelName = ""; + private int modelDelay = -1; + private String autoCloseAfterTrigger = "true"; + private CheckBox mCheckBox; + + public static DeviceDetailLockFragment newInstance() { + DeviceDetailLockFragment fragment = new DeviceDetailLockFragment(); + return fragment; + } + + public void onEventMainThread(EventBusEntity event) { + subsetGetDetail(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.GONE); + EventBus.getDefault().register(this); + arguments = getArguments(); + mHandler = new UIHandle(this); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_detail_lock, container, false); + } + + public void setModifyNameListener(IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener) { + this.modifyNameListener = modifyNameListener; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + rlDeviceDetail = view.findViewById(R.id.rl_device_detail); + rlDetailVersion = view.findViewById(R.id.rl_detail_version); + rlDeployment = view.findViewById(R.id.rl_deployment); + rlDetele = view.findViewById(R.id.rl_detele); + tvDeviceName = view.findViewById(R.id.tv_device_name); + ivDevicePic = view.findViewById(R.id.iv_device_pic); + tvDeviceVersion = view.findViewById(R.id.tv_device_version); + tvCurrentWifi = view.findViewById(R.id.tv_current_wifi); + rlCurWifi = view.findViewById(R.id.rl_cur_wifi); + localStageTv = (TextView) view.findViewById(R.id.tv_local_stage); + tv_device_address = (TextView) view.findViewById(R.id.tv_device_address); + tv_electric = (TextView) view.findViewById(R.id.tv_electric); + tv_bind_ai = (TextView) view.findViewById(R.id.tv_bind_ai); + tv_safe_model = (TextView) view.findViewById(R.id.tv_safe_model); + rl_device_storage = (RelativeLayout) view.findViewById(R.id.rl_device_storage); + unlockRecordRl = (RelativeLayout) view.findViewById(R.id.rl_unlock_record); + safeModelRl = (RelativeLayout) view.findViewById(R.id.rl_safe_model); + rl_bind_ai = (RelativeLayout) view.findViewById(R.id.rl_bind_ai); + mCheckBox = (CheckBox) view.findViewById(R.id.cb_device_defence); + + rlDeployment.setOnClickListener(this); + rlDetele.setOnClickListener(this); + rlDeviceDetail.setOnClickListener(this); + rlCurWifi.setOnClickListener(this); + tv_device_address.setOnClickListener(this); + rl_device_storage.setOnClickListener(this); + unlockRecordRl.setOnClickListener(this); + rl_bind_ai.setOnClickListener(this); + mCheckBox.setOnClickListener(this); + safeModelRl.setOnClickListener(this); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_detail_title)); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + //不为空 列表页跳转 + fromWhere = arguments.getString(MethodConst.ParamConst.fromList); + if (deviceListBean == null) { + return; + } + deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 1) { + //多通道 + if (MethodConst.ParamConst.fromList.equals(fromWhere)) { + //设备详情 + tvDeviceName.setText(deviceListBean.name); + tvDeviceVersion.setText(deviceListBean.version); + rlDeployment.setVisibility(View.GONE); + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + //通道详情 + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + getDeviceLocalCache(); + rlDetailVersion.setVisibility(View.GONE); + rlCurWifi.setVisibility(View.GONE); + rlDetele.setVisibility(View.GONE); + } + } else if (deviceListBean.channels != null && deviceListBean.channels.size() == 1) { + //单通道 + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + getDeviceLocalCache(); + tvDeviceVersion.setText(deviceListBean.version); + if (deviceListBean.deviceSource == 2) { + rlDetele.setVisibility(View.GONE); + } + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + //多通道但是没有挂载通道 + //设备详情 + tvDeviceName.setText(deviceListBean.name); + tvDeviceVersion.setText(deviceListBean.version); + rlDeployment.setVisibility(View.GONE); + if (deviceListBean.ability.contains("WLAN")) { + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + rlCurWifi.setVisibility(View.GONE); + } + + } + if (deviceListBean.channels != null && deviceListBean.channels.size() == 0) { + if ("offline".equals(deviceListBean.status)) { + rlCurWifi.setVisibility(View.GONE); + } else { + rlDetailVersion.setOnClickListener(this); + } + } else { + if (deviceListBean.channels != null && "offline".equals(deviceListBean.channels.get(deviceListBean.checkedChannel).status)) { + rlCurWifi.setVisibility(View.GONE); + } else { + rlDetailVersion.setOnClickListener(this); + } + } + + + deviceId = getActivity().getIntent().getExtras().get("deviceId").toString(); + devicePosition = getActivity().getIntent().getExtras().get("addressId").toString(); + tv_device_address.setText(AddressNameUtil.getAddressName(devicePosition)); + + subsetGetDetail(); + } + + /** + * 获取设备缓存信息 + */ + private void getDeviceLocalCache() { + DeviceLocalCacheData deviceLocalCacheData = new DeviceLocalCacheData(); + deviceLocalCacheData.setDeviceId(deviceListBean.deviceId); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + deviceLocalCacheData.setChannelId(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + } + DeviceLocalCacheService deviceLocalCacheService = ClassInstanceManager.newInstance().getDeviceLocalCacheService(); + deviceLocalCacheService.findLocalCache(deviceLocalCacheData, this); + } + + private void getCurrentWifiInfo() { + //设备才能获取WIFI + DialogUtils.show(getActivity()); + deviceDetailService.currentDeviceWifi(deviceListBean.deviceId, new IGetDeviceInfoCallBack.IDeviceCurrentWifiInfoCallBack() { + @Override + public void deviceCurrentWifiInfo(CurWifiInfo curWifiInfo) { + DialogUtils.dismiss(); + if (!isAdded() || curWifiInfo == null) { + return; + } + rlCurWifi.setVisibility(View.VISIBLE); + if (curWifiInfo.isLinkEnable()) { + wifiInfo = curWifiInfo; + tvCurrentWifi.setText(wifiInfo.getSsid()); + } + } + + @Override + public void onError(Throwable throwable) { + DialogUtils.dismiss(); + } + }); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + public void gotoModifyNamePage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailNameFragment fragment = DeviceDetailNameFragment.newInstance(); + fragment.setArguments(arguments); + fragment.setModifyNameListener(this); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + public void gotoUpdatePage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailVersionFragment fragment = DeviceDetailVersionFragment.newInstance(); + fragment.setArguments(arguments); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + public void gotoDeploymentPage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailDeploymentFragment fragment = DeviceDetailDeploymentFragment.newInstance(); + fragment.setArguments(arguments); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.rl_device_detail) { + gotoModifyNamePage(getActivity()); + } else if (id == R.id.rl_cur_wifi) { + DHDevice device = new DHDevice(); + device.setDeviceId(deviceListBean.deviceId); + device.setName(deviceListBean.name); + device.setStatus(deviceListBean.status); + LCDeviceEngine.newInstance().deviceOnlineChangeNet(getActivity(), device, wifiInfo); + } else if (id == R.id.rl_deployment) { + gotoDeploymentPage(getActivity()); + } else if (id == R.id.rl_detail_version) { + gotoUpdatePage(getActivity()); + } else if (id == R.id.rl_detele) { + //解绑设备 + /* deviceDetailActivity.rlLoading.setVisibility(View.VISIBLE); + DeviceDetailService deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + *//* DeviceUnBindData deviceUnBindData = new DeviceUnBindData(); + deviceUnBindData.data.deviceId = deviceListBean.deviceId; + deviceDetailService.unBindDevice(deviceUnBindData, this);*//* + deviceDetailService.deletePermission(deviceListBean.deviceId, null, this);*/ + ConfirmDialog dialog = new ConfirmDialog(getContext(), new Callback() { + @Override + public void callback(int position1) { + switch (position1) { + case 0: + break; + case 1: + unBindDevice(); + break; + } + } + }); + dialog.setContent(R.string.sure_delete_device); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn(R.string.sure); + dialog.setCancelable(false); + dialog.show(); + } else if (id == R.id.tv_device_address) { + Intent intent2; + intent2 = new Intent(getActivity(), ModifyRoomActivity.class); + intent2.putExtra("deviceId", deviceId); + intent2.putExtra("ziId", ""); + intent2.putExtra("deviceType", CAMERA_TAG); + intent2.putExtra("deviceModel", "1"); + intent2.putExtra("deviceAddress", devicePosition); + intent2.putExtra("addressId", devicePosition); + startActivityForResult(intent2, GET_SWITCHER_CHANGE_INFO); + } else if (id == R.id.rl_device_storage) { + Intent intent = new Intent(getContext(), RecoverSDCardActivity.class); + intent.putExtra("UUID", deviceListBean.deviceId); + startActivity(intent); + } + switch (id) { + case R.id.rl_bind_ai: + getAideviceList(INTELLIGENT_DOOR_LOCK); + break; + case R.id.cb_camera_reverse: + + break; + case R.id.rl_unlock_record: + Intent intent = new Intent(getContext(), UnlockRecordActivity.class); + intent.putExtra("deviceId", deviceListBean.deviceId); + startActivity(intent); + break; + case R.id.rl_safe_model: + intent = new Intent(getContext(), ModelBindActivity.class); + intent.putExtra("modelId", modelId); + intent.putExtra("modelDelay", modelDelay); + intent.putExtra("modelName", modelName); + intent.putExtra("autoCloseAfterTrigger", autoCloseAfterTrigger); + intent.putExtra("deviceId", getActivity().getIntent().getExtras().get("id").toString()); + intent.putExtra("deviceType", INTELLIGENT_DOOR_LOCK); + intent.putExtra("deviceModel", "1"); + startActivityForResult(intent, MODEL_REAPEAT); + break; + case R.id.cb_device_defence: + if (mCheckBox.isChecked()) { + mCheckBox.setChecked(false); + subseSetVoice("1"); + } else { + mCheckBox.setChecked(true); + subseSetVoice("0"); + } + break; + + } + } + + @Override + public void unBindDevice(boolean result) { + if (!isAdded()) { + return; + } + DeviceUnBindData deviceUnBindData = new DeviceUnBindData(); + deviceUnBindData.data.deviceId = deviceListBean.deviceId; + deviceDetailService.unBindDevice(deviceUnBindData, this); + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + Toast.makeText(getContext(), getResources().getString(R.string.lc_demo_device_unbind_success), Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(); + intent.putExtra(DeviceConstant.IntentKey.DHDEVICE_UNBIND, true); + deviceDetailActivity.setResult(RESULT_OK, intent); + deviceDetailActivity.finish(); + } + + @Override + public void deviceCache(DeviceLocalCacheData deviceLocalCacheData) { + if (!isAdded()) { + return; + } + BitmapDrawable bitmapDrawable = MediaPlayHelper.picDrawable(deviceLocalCacheData.getPicPath()); + if (bitmapDrawable != null) { + ivDevicePic.setImageDrawable(bitmapDrawable); + } + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()) { + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + LogUtil.errorLog(TAG, "error", throwable); + if (!"null point".equals(throwable.getMessage()) && isAdded()) { + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == DEVICE_SETTING_WIFI_LIST && resultCode == RESULT_OK && data != null) { + CurWifiInfo curWifiInfo = (CurWifiInfo) data.getSerializableExtra(DeviceConstant.IntentKey.DEVICE_CURRENT_WIFI_INFO); + if (curWifiInfo != null) { + wifiInfo = curWifiInfo; + tvCurrentWifi.setText(wifiInfo.getSsid()); + } + } + switch (requestCode) { + case GET_SWITCHER_CHANGE_INFO: + case MODIFY_DEVICE_NAME: + if (data != null && data.getExtras().get("addressId") != null) { + String addressId = data.getExtras().get("addressId").toString(); + tv_device_address.setText(AddressNameUtil.getAddressName(addressId)); + } + break; + } + } + + + @Override + public void deviceName(String newName) { + tvDeviceName.setText(newName); + //多通道设备详情 + if (deviceListBean.channels.size() == 0 || (deviceListBean.channels.size() > 1 && MethodConst.ParamConst.fromList.equals(fromWhere))) { + deviceListBean.name = newName; + } else { + deviceListBean.channels.get(deviceListBean.checkedChannel).channelName = newName; + } + if (modifyNameListener != null) { + modifyNameListener.deviceName(newName); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void subsetGetDetail() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", getActivity().getIntent().getExtras().get("id").toString()); + map.put("deviceModel", "1"); + map.put("deviceType", INTELLIGENT_DOOR_LOCK); + map.put("ziId", ""); + netWorkUtil.requestGetByAsy(SUBSET_GETDETAIL, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + ToastUtil.i("subsetGetDetail", "onSuccess()" + respone); + SafeVoiceEntity obj = JSON.parseObject(respone, SafeVoiceEntity.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(SELECT_SAFETY_DETAIL_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(SELECT_SAFETY_DETAIL_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(SELECT_SAFETY_DETAIL_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void unBindDevice() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", deviceId); + netWorkUtil.requestPostByAsynewApi(UNBIND_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("unBindDevice", "onSuccess()" + respone); + BaseVersion5Entity obj = JSON.parseObject(respone, BaseVersion5Entity.class); + if (1 == obj.getFlag()) { + EventBus.getDefault().post( + new EventBusEntity("关闭")); + EventBus.getDefault().post( + new ChooseHomeEvent("2")); + getActivity().finish(); + } else { + Message msg = mHandler.obtainMessage(SEND_UPDATEVOICE_CONTROL_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(SEND_UPDATEVOICE_CONTROL_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void getAideviceList(String deviceTypeCode) { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + map.put("standardCodes", "A1-L,A2-L,D1-L,B1-L,B3-L,B3-L-A"); + map.put("deviceType", deviceTypeCode); + util.requestGetByAsy(NetWorkUrl.DEIVCE_AIDEVICE_LIST, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + // Log.i("getZ1Info", "MainFragment4 onSuccess()" + respone); + ToastUtil.i("getAideviceList", respone); + DeviceSimpleEntity entity = JSON.parseObject(respone, DeviceSimpleEntity.class); + if (1 == entity.getFlag()) { + Message msg = mHandler.obtainMessage(GET_USERDEVICES4_SIMPLEINFO_SUCCESS); + msg.obj = entity; + msg.arg1 = 0; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(GET_USERDEVICES4_SIMPLEINFO_FAIL); + msg.obj = entity.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(); + msg.what = GET_USERDEVICES4_SIMPLEINFO_FAIL; + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + //handler + private static class UIHandle extends Handler { + WeakReference weakReference; + + public UIHandle(DeviceDetailLockFragment activity) { + weakReference = new WeakReference(activity); + } + + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + DeviceDetailLockFragment activity = weakReference.get(); + activity.callBackUiThread(msg); + } + } + + private void callBackUiThread(Message msg) { + switch (msg.what) { + case GET_USERDEVICES4_SIMPLEINFO_SUCCESS: + DeviceSimpleEntity simpleEntity = (DeviceSimpleEntity) msg.obj; + if (simpleEntity.getData().size() != 0) { + Intent intent = new Intent(getContext(), ChooseA1OrUnbindActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("dataBeanList", (Serializable) simpleEntity.getData()); + intent.putExtras(bundle); + intent.putExtra("addressId", devicePosition); + intent.putExtra("deviceType", INTELLIGENT_DOOR_LOCK); + intent.putExtra("deviceModel", "1"); + intent.putExtra("deviceId", getActivity().getIntent().getExtras().get("id").toString()); + intent.putExtra("subType", "0"); + intent.putExtra("ziId", bindZiId); + startActivityForResult(intent, MODIFY_DEVICE_NAME); + } else { + ToastUtil.show(getContext(), "暂无可绑定的语音管家"); + } + break; + case SELECT_SAFETY_DETAIL_SUCCESS: + SafeVoiceEntity voiceEntity = (SafeVoiceEntity) msg.obj; + SafeVoiceEntity.DataBean.ThirdInfoBean.ElectricitysBean electricitysBean = voiceEntity.getData().getThirdInfo().getElectricitys().get(0); + tv_electric.setText("碱性电池" + electricitysBean.getAlkElec() + "%、" + "锂电池" + electricitysBean.getLitElec() + "%"); + bindZiId = voiceEntity.getData().getTarget().getZiId(); + tv_bind_ai.setText(voiceEntity.getData().getThirdInfo().getGatewayName()); + if (null != voiceEntity.getData().getModeTrigger()) { + if (!voiceEntity.getData().getModeTrigger().getAutoCloseAfterTrigger().isEmpty()) { + autoCloseAfterTrigger = voiceEntity.getData().getModeTrigger().getAutoCloseAfterTrigger(); + } + modelId = voiceEntity.getData().getModeTrigger().getModeId(); + modelDelay = voiceEntity.getData().getModeTrigger().getValidTimeAfter(); + modelName = voiceEntity.getData().getModeTrigger().getModeName(); + tv_safe_model.setText(modelName); + if (null != voiceEntity.getData().getTarget()) { + if (voiceEntity.getData().getTarget().isModeTriggerFlag()) { + mCheckBox.setChecked(true); + mCheckBox.setVisibility(View.VISIBLE); + localStageTv.setText("场景联动开"); + } else { + mCheckBox.setChecked(false); + mCheckBox.setVisibility(View.VISIBLE); + localStageTv.setText("场景联动关"); + } + } + } else { + modelName = ""; + modelDelay = 0; + tv_safe_model.setText(" 设置您需要联动的场景模式"); + } + break; + case SEND_UPDATEVOICE_CONTROL_SUCCESS: + String obj1 = (String) msg.obj; + if (obj1.equals("1")) { + mCheckBox.setChecked(true); + mCheckBox.setVisibility(View.VISIBLE); + localStageTv.setText("场景联动开"); + } else { + mCheckBox.setChecked(false); + mCheckBox.setVisibility(View.VISIBLE); + localStageTv.setText("场景联动关"); + } + break; + case SEND_UPDATEVOICE_CONTROL_FAIL: + case SELECT_SAFETY_DETAIL_FAIL: + case CHECK_USER_BIND_FAIL: + ToastUtil.show(getContext(), (String) msg.obj); + break; + } + } + + private void subseSetVoice(final String flag) { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", getActivity().getIntent().getExtras().get("id").toString()); + map.put("deviceModel", "1"); + map.put("deviceType", INTELLIGENT_DOOR_LOCK); + map.put("modeTriggerFlag", flag); + map.put("ziId", ""); + util.requestPostByAsyBody(NetWorkUrl.SUBSET_SETMODETRIGGERFLAG, map, "{}", new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("subseSetVoice", "ShareDeviceActivity onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(SEND_UPDATEVOICE_CONTROL_SUCCESS); + msg.obj = flag; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailMainFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailMainFragment.java new file mode 100644 index 0000000..fa4eb43 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailMainFragment.java @@ -0,0 +1,691 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.graphics.drawable.BitmapDrawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceDetailService; +import com.common.openapi.DeviceLocalCacheService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceLocalCacheData; +import com.common.openapi.entity.DeviceUnBindData; +import com.lechange.demo.business.Business; +import com.lechange.demo.tools.DialogUtils; +import com.lechange.demo.tools.MediaPlayHelper; +import com.lechange.demo.yonsz.CameraDetailActivity; +import com.lechange.demo.yonsz.RecoverSDCardActivity; +import com.mm.android.deviceaddmodule.LCDeviceEngine; +import com.mm.android.deviceaddmodule.device_wifi.CurWifiInfo; +import com.mm.android.deviceaddmodule.device_wifi.DeviceConstant; +import com.mm.android.deviceaddmodule.mobilecommon.entity.device.DHDevice; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.createfamily.floor.ChooseRoomInFloorActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.database.entity.entity5.BaseVersion5Entity; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.mine.mydevice.DeviceDetailActivity; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUrl; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.AddressNameUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.utils.ToastUtil; +import com.yonsz.z1.version4.fragment.FanA2Fragment; +import com.yonsz.z1.version5.ModifyRoomActivity; + +import java.lang.ref.WeakReference; +import java.util.HashMap; + +import de.greenrobot.event.EventBus; + +import static android.app.Activity.RESULT_OK; +import static com.mm.android.deviceaddmodule.device_wifi.DeviceConstant.IntentCode.DEVICE_SETTING_WIFI_LIST; +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.CHECK_USER_BIND_FAIL; +import static com.yonsz.z1.net.Constans.GET_SWITCHER_CHANGE_INFO; +import static com.yonsz.z1.net.Constans.INTELLIGENT_DOOR_LOCK; +import static com.yonsz.z1.net.Constans.MODIFY_ALARM_STATUS_SUCCESS; +import static com.yonsz.z1.net.Constans.MODIFY_DEVICE_NAME; +import static com.yonsz.z1.net.Constans.SEND_UPDATEVOICE_CONTROL_FAIL; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; +import static com.yonsz.z1.net.NetWorkUrl.MODIFY_ALARM_STATUS; +import static com.yonsz.z1.net.NetWorkUrl.UNBIND_DEVICE; + +public class DeviceDetailMainFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IUnbindDeviceCallBack, IGetDeviceInfoCallBack.IDeviceCacheCallBack, IGetDeviceInfoCallBack.IModifyDeviceName { + private static final String TAG = DeviceDetailMainFragment.class.getSimpleName(); + private RelativeLayout rlDeviceDetail; + private RelativeLayout rlDetailVersion; + private RelativeLayout rlDeployment; + private RelativeLayout rlDetele; + private TextView tvDeviceName; + private ImageView ivDevicePic; + private TextView tvDeviceVersion; + private Bundle arguments; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private DeviceDetailLCActivity deviceDetailActivity; + private DeviceDetailService deviceDetailService; + private CurWifiInfo wifiInfo; + private TextView tvCurrentWifi; + private RelativeLayout rlCurWifi; + private IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener; + private String fromWhere; + private LinearLayout ll_fanren; + + private TextView tv_device_address; + private String devicePosition = "1"; + private String deviceId, deviceType = CAMERA_TAG; + private RelativeLayout rl_device_storage; + private CheckBox cb_camera_reverse, cb_device_light, cb_device_alarm; + private UIHandle mHandler; + + public static DeviceDetailMainFragment newInstance() { + DeviceDetailMainFragment fragment = new DeviceDetailMainFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.GONE); + arguments = getArguments(); + mHandler = new UIHandle(this); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_detail_main, container, false); + } + + public void setModifyNameListener(IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener) { + this.modifyNameListener = modifyNameListener; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ll_fanren = view.findViewById(R.id.ll_fanren); + rlDeviceDetail = view.findViewById(R.id.rl_device_detail); + rlDetailVersion = view.findViewById(R.id.rl_detail_version); + rlDeployment = view.findViewById(R.id.rl_deployment); + rlDetele = view.findViewById(R.id.rl_detele); + tvDeviceName = view.findViewById(R.id.tv_device_name); + ivDevicePic = view.findViewById(R.id.iv_device_pic); + tvDeviceVersion = view.findViewById(R.id.tv_device_version); + tvCurrentWifi = view.findViewById(R.id.tv_current_wifi); + rlCurWifi = view.findViewById(R.id.rl_cur_wifi); + cb_camera_reverse = (CheckBox) view.findViewById(R.id.cb_camera_reverse); + cb_device_light = (CheckBox) view.findViewById(R.id.cb_device_light); + cb_device_alarm = (CheckBox) view.findViewById(R.id.cb_device_alarm); + tv_device_address = (TextView) view.findViewById(R.id.tv_device_address); + rl_device_storage = (RelativeLayout) view.findViewById(R.id.rl_device_storage); + + rlDeployment.setOnClickListener(this); + rlDetele.setOnClickListener(this); + rlDeviceDetail.setOnClickListener(this); + rlCurWifi.setOnClickListener(this); + tv_device_address.setOnClickListener(this); + rl_device_storage.setOnClickListener(this); + cb_camera_reverse.setOnClickListener(this); + cb_device_light.setOnClickListener(this); + cb_device_alarm.setOnClickListener(this); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_detail_title)); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + //不为空 列表页跳转 + fromWhere = arguments.getString(MethodConst.ParamConst.fromList); + if (deviceListBean == null) { + return; + } + deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 1) { + //多通道 + if (MethodConst.ParamConst.fromList.equals(fromWhere)) { + //设备详情 + tvDeviceName.setText(deviceListBean.name); + tvDeviceVersion.setText(deviceListBean.version); + rlDeployment.setVisibility(View.GONE); + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + //通道详情 + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + getDeviceLocalCache(); + rlDetailVersion.setVisibility(View.GONE); + rlCurWifi.setVisibility(View.GONE); + rlDetele.setVisibility(View.GONE); + } + } else if (deviceListBean.channels != null && deviceListBean.channels.size() == 1) { + //单通道 + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + getDeviceLocalCache(); + tvDeviceVersion.setText(deviceListBean.version); + if (deviceListBean.deviceSource == 2) { + rlDetele.setVisibility(View.GONE); + } + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + //多通道但是没有挂载通道 + //设备详情 + tvDeviceName.setText(deviceListBean.name); + tvDeviceVersion.setText(deviceListBean.version); + rlDeployment.setVisibility(View.GONE); + if (deviceListBean.ability.contains("WLAN")) { + rlCurWifi.setVisibility(View.VISIBLE); + //设备才能获取WIFI + getCurrentWifiInfo(); + } else { + rlCurWifi.setVisibility(View.GONE); + } + + } + if (deviceListBean.channels != null && deviceListBean.channels.size() == 0) { + if ("offline".equals(deviceListBean.status)) { + rlCurWifi.setVisibility(View.GONE); + } else { + rlDetailVersion.setOnClickListener(this); + } + } else { + if (deviceListBean.channels != null && "offline".equals(deviceListBean.channels.get(deviceListBean.checkedChannel).status)) { + rlCurWifi.setVisibility(View.GONE); + } else { + rlDetailVersion.setOnClickListener(this); + } + } + + + deviceType = getActivity().getIntent().getExtras().get("deviceType").toString(); + deviceId = getActivity().getIntent().getExtras().get("deviceId").toString(); + devicePosition = getActivity().getIntent().getExtras().get("addressId").toString(); + tv_device_address.setText(AddressNameUtil.getAddressName(devicePosition)); + + if (deviceType.equals(CAMERA_TAG)) { + + } else { + ll_fanren.setVisibility(View.GONE); + } + } + + /** + * 获取设备缓存信息 + */ + private void getDeviceLocalCache() { + DeviceLocalCacheData deviceLocalCacheData = new DeviceLocalCacheData(); + deviceLocalCacheData.setDeviceId(deviceListBean.deviceId); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + deviceLocalCacheData.setChannelId(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + } + DeviceLocalCacheService deviceLocalCacheService = ClassInstanceManager.newInstance().getDeviceLocalCacheService(); + deviceLocalCacheService.findLocalCache(deviceLocalCacheData, this); + } + + private void getCurrentWifiInfo() { + //设备才能获取WIFI + DialogUtils.show(getActivity()); + deviceDetailService.currentDeviceWifi(deviceListBean.deviceId, new IGetDeviceInfoCallBack.IDeviceCurrentWifiInfoCallBack() { + @Override + public void deviceCurrentWifiInfo(CurWifiInfo curWifiInfo) { + DialogUtils.dismiss(); + if (!isAdded() || curWifiInfo == null) { + return; + } + rlCurWifi.setVisibility(View.VISIBLE); + if (curWifiInfo.isLinkEnable()) { + wifiInfo = curWifiInfo; + tvCurrentWifi.setText(wifiInfo.getSsid()); + } + } + + @Override + public void onError(Throwable throwable) { + DialogUtils.dismiss(); + } + }); + + //获取设备指示灯状态 + breathingLightStatus(); + //获取摄像头翻转状态 + frameReverseStatus(); + //获取报警消息提醒 + getAlarmStatus(); + } + + private synchronized void breathingLightStatus() { + Business.getInstance().breathingLightStatus(deviceListBean.deviceId, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final int arg1 = msg.arg1; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (arg1 == 1) { + cb_device_light.setChecked(true); + } else { + cb_device_light.setChecked(false); + } + } + }); + + } else { + } + } + }); + } + + private synchronized void frameReverseStatus() { + Business.getInstance().frameReverseStatus(deviceListBean.deviceId, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final int obj = msg.arg1; + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (obj == 1) { + cb_camera_reverse.setChecked(true); + } else { + cb_camera_reverse.setChecked(false); + } + } + }); + } else { + + } + } + }); + } + + private void getAlarmStatus() { + + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + public void gotoModifyNamePage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailNameFragment fragment = DeviceDetailNameFragment.newInstance(); + fragment.setArguments(arguments); + fragment.setModifyNameListener(this); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + public void gotoUpdatePage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailVersionFragment fragment = DeviceDetailVersionFragment.newInstance(); + fragment.setArguments(arguments); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + public void gotoDeploymentPage(FragmentActivity fragmentActivity) { + if (fragmentActivity == null || fragmentActivity.getSupportFragmentManager() == null) { + return; + } + DeviceDetailDeploymentFragment fragment = DeviceDetailDeploymentFragment.newInstance(); + fragment.setArguments(arguments); + FragmentTransaction transaction = fragmentActivity.getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.rl_device_detail) { + gotoModifyNamePage(getActivity()); + } else if (id == R.id.rl_cur_wifi) { + DHDevice device = new DHDevice(); + device.setDeviceId(deviceListBean.deviceId); + device.setName(deviceListBean.name); + device.setStatus(deviceListBean.status); + LCDeviceEngine.newInstance().deviceOnlineChangeNet(getActivity(), device, wifiInfo); + } else if (id == R.id.rl_deployment) { + gotoDeploymentPage(getActivity()); + } else if (id == R.id.rl_detail_version) { + gotoUpdatePage(getActivity()); + } else if (id == R.id.rl_detele) { + /*//解绑设备 + deviceDetailActivity.rlLoading.setVisibility(View.VISIBLE); + DeviceDetailService deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + *//* DeviceUnBindData deviceUnBindData = new DeviceUnBindData(); + deviceUnBindData.data.deviceId = deviceListBean.deviceId; + deviceDetailService.unBindDevice(deviceUnBindData, this);*//* + deviceDetailService.deletePermission(deviceListBean.deviceId, null, this);*/ +// subsetDelete(); + ConfirmDialog dialog = new ConfirmDialog(getContext(), new Callback() { + @Override + public void callback(int position1) { + switch (position1) { + case 0: + break; + case 1: + unBindDevice(); + break; + } + } + }); + dialog.setContent(R.string.sure_delete_device); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn(R.string.sure); + dialog.setCancelable(false); + dialog.show(); + } else if (id == R.id.tv_device_address) { + Intent intent2; + intent2 = new Intent(getActivity(), ModifyRoomActivity.class); + intent2.putExtra("deviceId", deviceId); + intent2.putExtra("ziId", ""); + intent2.putExtra("deviceType", deviceType); + intent2.putExtra("deviceModel", "0"); + intent2.putExtra("deviceAddress", devicePosition); + intent2.putExtra("addressId", devicePosition); + startActivityForResult(intent2, GET_SWITCHER_CHANGE_INFO); + } else if (id == R.id.rl_device_storage) { + Intent intent = new Intent(getContext(), RecoverSDCardActivity.class); + intent.putExtra("UUID", deviceListBean.deviceId); + startActivity(intent); + } + switch (id) { + case R.id.cb_camera_reverse: + if (cb_camera_reverse.isChecked()) { + modifyFrameReverseStatus("reverse"); + } else { + modifyFrameReverseStatus("normal"); + } + break; + case R.id.cb_device_light: + if (cb_device_light.isChecked()) { + modifyBreathingLight("on"); + } else { + modifyBreathingLight("off"); + } + break; + case R.id.cb_device_alarm: + if (cb_device_alarm.isChecked()) { + modifyAlarmStatus("1"); + } else { + modifyAlarmStatus("0"); + } + break; + } + } + + @Override + public void unBindDevice(boolean result) { + if (!isAdded()) { + return; + } + DeviceUnBindData deviceUnBindData = new DeviceUnBindData(); + deviceUnBindData.data.deviceId = deviceListBean.deviceId; + deviceDetailService.unBindDevice(deviceUnBindData, this); + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + Toast.makeText(getContext(), getResources().getString(R.string.lc_demo_device_unbind_success), Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(); + intent.putExtra(DeviceConstant.IntentKey.DHDEVICE_UNBIND, true); + deviceDetailActivity.setResult(RESULT_OK, intent); + deviceDetailActivity.finish(); + } + + @Override + public void deviceCache(DeviceLocalCacheData deviceLocalCacheData) { + if (!isAdded()) { + return; + } + BitmapDrawable bitmapDrawable = MediaPlayHelper.picDrawable(deviceLocalCacheData.getPicPath()); + if (bitmapDrawable != null) { + ivDevicePic.setImageDrawable(bitmapDrawable); + } + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()) { + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + LogUtil.errorLog(TAG, "error", throwable); + if (!"null point".equals(throwable.getMessage()) && isAdded()) { + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == DEVICE_SETTING_WIFI_LIST && resultCode == RESULT_OK && data != null) { + CurWifiInfo curWifiInfo = (CurWifiInfo) data.getSerializableExtra(DeviceConstant.IntentKey.DEVICE_CURRENT_WIFI_INFO); + if (curWifiInfo != null) { + wifiInfo = curWifiInfo; + tvCurrentWifi.setText(wifiInfo.getSsid()); + } + } + switch (requestCode) { + case GET_SWITCHER_CHANGE_INFO: + case MODIFY_DEVICE_NAME: + if (data != null && data.getExtras().get("addressId") != null) { + String addressId = data.getExtras().get("addressId").toString(); + tv_device_address.setText(AddressNameUtil.getAddressName(addressId)); + } + break; + } + } + + private void modifyFrameReverseStatus(String state) { + Business.getInstance().modifyFrameReverseStatus(state, deviceListBean.deviceId, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + getContext(), + "修改成功", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + getContext(), + "修改失败", + Toast.LENGTH_SHORT).show(); + + } + } + }); + } + + private void modifyBreathingLight(String state) { + Business.getInstance().modifyBreathingLight(state, deviceListBean.deviceId, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + getContext(), + "修改成功", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + getContext(), + "修改失败", + Toast.LENGTH_SHORT).show(); + + } + } + }); + } + + private void modifyAlarmStatus(String state) { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + // map.put("deviceId", "4K0586CPAJ58121"); + map.put("deviceId", deviceListBean.deviceId); + map.put("alarmStatus", state); + netWorkUtil.requestPostByAsynewApi(MODIFY_ALARM_STATUS, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("modifyAlarmStatus", "onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText( + getContext(), + "修改报警消息提醒成功", + Toast.LENGTH_SHORT).show(); + } + }); + } else { + + } + } + + @Override + public void onFail(String message) { + + } + }); + } + + @Override + public void deviceName(String newName) { + tvDeviceName.setText(newName); + //多通道设备详情 + if (deviceListBean.channels.size() == 0 || (deviceListBean.channels.size() > 1 && MethodConst.ParamConst.fromList.equals(fromWhere))) { + deviceListBean.name = newName; + } else { + deviceListBean.channels.get(deviceListBean.checkedChannel).channelName = newName; + } + if (modifyNameListener != null) { + modifyNameListener.deviceName(newName); + } + } + + private void unBindDevice() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", deviceId); + netWorkUtil.requestPostByAsynewApi(UNBIND_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("unBindDevice", "onSuccess()" + respone); + BaseVersion5Entity obj = JSON.parseObject(respone, BaseVersion5Entity.class); + if (1 == obj.getFlag()) { + EventBus.getDefault().post( + new EventBusEntity("关闭")); + EventBus.getDefault().post( + new ChooseHomeEvent("2")); + getActivity().finish(); + } else { + Message msg = mHandler.obtainMessage(SEND_UPDATEVOICE_CONTROL_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(SEND_UPDATEVOICE_CONTROL_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void subsetDelete() { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", deviceId); + map.put("deviceModel", "0"); + map.put("deviceType", deviceType); + map.put("ziId", ""); + util.requestPostByAsyBody(NetWorkUrl.SUBSET_DELETE, map, "{}", new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("subsetDelete", "ShareDeviceActivity onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + getActivity().finish(); + } + }); + } else { + + } + } + + @Override + public void onFail(String message) { + + } + }); + } + + //handler + private static class UIHandle extends Handler { + WeakReference weakReference; + + public UIHandle(DeviceDetailMainFragment activity) { + weakReference = new WeakReference(activity); + } + + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + DeviceDetailMainFragment activity = weakReference.get(); + activity.callBackUiThread(msg); + } + } + + private void callBackUiThread(Message msg) { + switch (msg.what) { + case SEND_UPDATEVOICE_CONTROL_FAIL: + ToastUtil.show(getContext(), (String) msg.obj); + break; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailModifyNameFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailModifyNameFragment.java new file mode 100644 index 0000000..8d08a40 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailModifyNameFragment.java @@ -0,0 +1,185 @@ +package com.lechange.demo.ui; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceDetailService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceModifyNameData; +import com.mm.android.deviceaddmodule.helper.DeviceAddHelper; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.mm.android.deviceaddmodule.mobilecommon.utils.NameLengthFilter; +import com.mm.android.deviceaddmodule.mobilecommon.utils.WordInputFilter; +import com.mm.android.deviceaddmodule.mobilecommon.widget.ClearEditText; +import com.yonsz.z1.R; +import com.yonsz.z1.mine.mydevice.DeviceDetailActivity; + +public class DeviceDetailModifyNameFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IModifyDeviceCallBack { + private static final String TAG = DeviceDetailModifyNameFragment.class.getSimpleName(); + private Bundle arguments; + private ClearEditText newName; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private DeviceDetailLCActivity deviceDetailActivity; + private final int MAXLETHER = 40; + private IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener; + private String name; + private String fromWhere; + + public static DeviceDetailModifyNameFragment newInstance() { + DeviceDetailModifyNameFragment fragment = new DeviceDetailModifyNameFragment(); + return fragment; + } + + public void setModifyNameListener(IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener) { + this.modifyNameListener = modifyNameListener; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + arguments = getArguments(); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + //不为空 列表页跳转 + fromWhere = arguments.getString(MethodConst.ParamConst.fromList); + if (deviceListBean == null) { + return; + } + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.VISIBLE); + deviceDetailActivity.llOperate.setOnClickListener(this); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_modify_name, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_detail_title)); + initView(view); + } + + private void initView(View view) { + newName = view.findViewById(R.id.et_new_name); + if (deviceListBean.channels.size() > 1) { + //多通道 + if (MethodConst.ParamConst.fromList.equals(fromWhere)) { + newName.setText(deviceListBean.name); + } else { + newName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + } + } else if (deviceListBean.channels.size() == 1) { + newName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + } else { + newName.setText(deviceListBean.name); + } + if (!TextUtils.isEmpty(newName.getText().toString())) { + newName.setSelection(newName.getText().toString().length()); + } + newName.setFilters(new InputFilter[]{new WordInputFilter(WordInputFilter.REX_NAME), new NameLengthFilter(MAXLETHER)}); + newName.addTextChangedListener(mTextWatcher); + } + + private final TextWatcher mTextWatcher = new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int arg1, int arg2, int arg3) { + String devName = s.toString().trim(); + if (!TextUtils.isEmpty(devName)) { + deviceDetailActivity.llOperate.setEnabled(true); + newName.removeTextChangedListener(mTextWatcher); + String filterDevName = DeviceAddHelper.strDeviceNameFilter(devName); + if (!filterDevName.equals(devName)) { + newName.setText(filterDevName); + newName.setSelection(filterDevName.length()); + } + newName.addTextChangedListener(mTextWatcher); + } else { + deviceDetailActivity.llOperate.setEnabled(false); + } + } + + @Override + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + } + + @Override + public void afterTextChanged(Editable arg0) { + } + }; + + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onClick(View v) { + //修改名称 + deviceDetailActivity.rlLoading.setVisibility(View.VISIBLE); + if (newName == null || newName.getText().toString().trim() == null || newName.getText().toString().trim().isEmpty()) { + return; + } + name = newName.getText().toString().trim(); + DeviceDetailService deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + DeviceModifyNameData deviceModifyNameData = new DeviceModifyNameData(); + deviceModifyNameData.data.name = name; + deviceModifyNameData.data.deviceId = deviceListBean.deviceId; + if (deviceListBean.channels.size() > 1 && !MethodConst.ParamConst.fromList.equals(fromWhere)) { + //多通道 + deviceModifyNameData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + } + deviceDetailService.modifyDeviceName(deviceModifyNameData, this); + } + + @Override + public void deviceModify(boolean result) { + if (!isAdded()) { + return; + } + deviceDetailActivity.llOperate.setVisibility(View.GONE); + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + Toast.makeText(getContext(), getResources().getString(R.string.lc_demo_device_modify_success), Toast.LENGTH_SHORT).show(); + if (modifyNameListener != null) { + modifyNameListener.deviceName(name); + } + //多通道设备详情 + if (deviceListBean.channels.size() == 0 || (deviceListBean.channels.size() > 1 && MethodConst.ParamConst.fromList.equals(fromWhere))) { + deviceListBean.name = name; + } else { + deviceListBean.channels.get(deviceListBean.checkedChannel).channelName = name; + } + getActivity().getSupportFragmentManager().popBackStack(); + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()) { + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + LogUtil.errorLog(TAG, "error", throwable); + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailNameFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailNameFragment.java new file mode 100644 index 0000000..7208d61 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailNameFragment.java @@ -0,0 +1,128 @@ +package com.lechange.demo.ui; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.yonsz.z1.R; + +public class DeviceDetailNameFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IModifyDeviceName { + private static final String TAG = DeviceDetailNameFragment.class.getSimpleName(); + private Bundle arguments; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private DeviceDetailLCActivity deviceDetailActivity; + private TextView tvDeviceName; + private IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener; + private String fromWhere; + + public static DeviceDetailNameFragment newInstance() { + DeviceDetailNameFragment fragment = new DeviceDetailNameFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + arguments = getArguments(); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + //不为空 列表页跳转 + fromWhere = arguments.getString(MethodConst.ParamConst.fromList); + if (deviceListBean == null) { + return; + } + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.GONE); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_detail_name, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_detail_title)); + initView(view); + } + + private void initView(View view) { + view.findViewById(R.id.rl_device_modify).setOnClickListener(this); + tvDeviceName = view.findViewById(R.id.tv_device_name); + RelativeLayout rlDeviceType = view.findViewById(R.id.rl_detail_type); + RelativeLayout rlDeviceSerial = view.findViewById(R.id.rl_device_serial); + TextView tvDeviceType = view.findViewById(R.id.tv_device_type); + TextView tvDeviceSerial = view.findViewById(R.id.tv_device_serial); + if (deviceListBean.channels!=null&&deviceListBean.channels.size() > 1) { + //多通道 + if (MethodConst.ParamConst.fromList.equals(fromWhere)) { + tvDeviceName.setText(deviceListBean.name); + tvDeviceType.setText(deviceListBean.deviceModel); + tvDeviceSerial.setText(deviceListBean.deviceId); + }else { + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + rlDeviceType.setVisibility(View.GONE); + rlDeviceSerial.setVisibility(View.GONE); + } + } else if (deviceListBean.channels!=null&&deviceListBean.channels.size() == 1){ + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + tvDeviceType.setText(deviceListBean.deviceModel); + tvDeviceSerial.setText(deviceListBean.deviceId); + }else { + tvDeviceName.setText(deviceListBean.name); + tvDeviceType.setText(deviceListBean.deviceModel); + tvDeviceSerial.setText(deviceListBean.deviceId); + } + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onClick(View v) { + if (getActivity() == null || getActivity().getSupportFragmentManager() == null) { + return; + } + DeviceDetailModifyNameFragment fragment = DeviceDetailModifyNameFragment.newInstance(); + fragment.setModifyNameListener(this); + fragment.setArguments(arguments); + FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction(); + transaction.hide(this).add(R.id.fr_content, fragment).addToBackStack(null); + transaction.commitAllowingStateLoss(); + } + + public void setModifyNameListener(IGetDeviceInfoCallBack.IModifyDeviceName modifyNameListener) { + this.modifyNameListener = modifyNameListener; + } + + @Override + public void deviceName(String newName) { + tvDeviceName.setText(newName); + //多通道设备详情 + if (deviceListBean.channels.size() == 0 ||(deviceListBean.channels.size() > 1 && MethodConst.ParamConst.fromList.equals(fromWhere))) { + deviceListBean.name = newName; + } else { + deviceListBean.channels.get(deviceListBean.checkedChannel).channelName = newName; + } + if (modifyNameListener != null) { + modifyNameListener.deviceName(newName); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceDetailVersionFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceDetailVersionFragment.java new file mode 100644 index 0000000..60dc97a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceDetailVersionFragment.java @@ -0,0 +1,170 @@ +package com.lechange.demo.ui; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceDetailService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceVersionListData; +import com.lechange.demo.dialog.DeviceUpdateDialog; +import com.lechange.demo.view.LcProgressBar; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.mine.mydevice.DeviceDetailActivity; + +public class DeviceDetailVersionFragment extends Fragment implements IGetDeviceInfoCallBack.IDeviceVersionCallBack, View.OnClickListener , IGetDeviceInfoCallBack.IDeviceUpdateCallBack { + private static final String TAG = DeviceDetailVersionFragment.class.getSimpleName(); + private Bundle arguments; + private LcProgressBar pgUpodate; + private TextView tvVersionTip; + private LinearLayout llNewVersion; + private TextView tvNewVersionTip; + private TextView tvNewVersion; + private TextView tvDeviceCurrentVersion; + private DeviceDetailLCActivity deviceDetailActivity; + private DeviceDetailService deviceDetailService; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + + public static DeviceDetailVersionFragment newInstance() { + DeviceDetailVersionFragment fragment = new DeviceDetailVersionFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.llOperate.setVisibility(View.GONE); + arguments = getArguments(); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_version, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + DeviceDetailLCActivity deviceDetailActivity = (DeviceDetailLCActivity) getActivity(); + deviceDetailActivity.tvTitle.setText(getResources().getString(R.string.lc_demo_device_version_title)); + initView(view); + initData(); + } + + private void initView(View view) { + tvDeviceCurrentVersion = view.findViewById(R.id.tv_device_current_version); + tvNewVersion = view.findViewById(R.id.tv_new_version); + tvNewVersionTip = view.findViewById(R.id.tv_new_version_tip); + llNewVersion = view.findViewById(R.id.ll_new_version); + tvVersionTip = view.findViewById(R.id.tv_version_tip); + pgUpodate = view.findViewById(R.id.pg_upodate); + pgUpodate.setOnClickListener(this); + } + + private void initData() { + //获取设备版本信息 + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + if (deviceListBean == null) { + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.VISIBLE); + deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + DeviceVersionListData deviceVersionListData = new DeviceVersionListData(); + deviceVersionListData.data.deviceIds = deviceListBean.deviceId; + deviceDetailService.deviceVersionList(deviceVersionListData, this); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void deviceVersion(DeviceVersionListData.Response responseData) { + if (!isAdded()){ + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + if (responseData.data == null || responseData.data.deviceVersionList == null || responseData.data.deviceVersionList.size() == 0) { + return; + } + DeviceVersionListData.ResponseData.DeviceVersionListBean deviceVersionListBean = responseData.data.deviceVersionList.get(0); + if (deviceVersionListBean == null) { + return; + } + tvDeviceCurrentVersion.setText(deviceVersionListBean.version); + if (deviceVersionListBean.getUpgradeInfo() == null) { + //已是最新版本 + llNewVersion.setVisibility(View.GONE); + pgUpodate.setVisibility(View.GONE); + tvVersionTip.setVisibility(View.VISIBLE); + tvVersionTip.setText(getResources().getString(R.string.lc_demo_device_version_new_tip)); + } else { + //需要更新设备 + llNewVersion.setVisibility(View.VISIBLE); + pgUpodate.setVisibility(View.VISIBLE); + tvVersionTip.setVisibility(View.GONE); + tvNewVersion.setText(deviceVersionListBean.getUpgradeInfo().getVersion()); + tvNewVersionTip.setText(deviceVersionListBean.getUpgradeInfo().getDescription()); + } + } + + @Override + public void deviceUpdate(boolean result) { + if (!isAdded()){ + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + Toast.makeText(getContext(), getResources().getString(R.string.lc_demo_device_update_success), Toast.LENGTH_SHORT).show(); + deviceDetailActivity.finish(); + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()){ + return; + } + deviceDetailActivity.rlLoading.setVisibility(View.GONE); + LogUtil.errorLog(TAG, "error", throwable); + pgUpodate.setText(getResources().getString(R.string.lc_demo_device_update)); + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.pg_upodate) { + DeviceUpdateDialog deviceUpdateDialog = new DeviceUpdateDialog(getContext()); + deviceUpdateDialog.setOnOkClickLisenter(new DeviceUpdateDialog.OnOkClickLisenter() { + @Override + public void OnOK() { + deviceDetailActivity.rlLoading.setVisibility(View.VISIBLE); + pgUpodate.setText(getResources().getString(R.string.lc_demo_device_updateing)); + if(deviceDetailService==null){ + deviceDetailService = ClassInstanceManager.newInstance().getDeviceDetailService(); + } + deviceDetailService.upgradeDevice(deviceListBean.deviceId, DeviceDetailVersionFragment.this); + } + }); + deviceUpdateDialog.show(); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceLocalRecordListFragment.java b/app/src/main/java/com/lechange/demo/ui/DeviceLocalRecordListFragment.java new file mode 100644 index 0000000..253ccda --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceLocalRecordListFragment.java @@ -0,0 +1,303 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceRecordService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.LocalRecordsData; +import com.common.openapi.entity.RecordListData; +import com.common.openapi.entity.RecordsData; +import com.lechange.demo.adapter.DeviceRecordListAdapter; +import com.lechange.demo.tools.DateHelper; +import com.lechange.demo.tools.DialogUtils; +import com.lechange.demo.view.LcPullToRefreshRecyclerView; +import com.lechange.pulltorefreshlistview.Mode; +import com.lechange.pulltorefreshlistview.PullToRefreshBase; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.mm.android.deviceaddmodule.mobilecommon.utils.TimeUtils; +import com.mm.android.deviceaddmodule.mobilecommon.utils.UIUtils; +import com.yonsz.z1.R; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +public class DeviceLocalRecordListFragment extends Fragment implements View.OnClickListener, IGetDeviceInfoCallBack.IDeviceLocalRecordCallBack, PullToRefreshBase.OnRefreshListener2 { + private static final String TAG = DeviceLocalRecordListFragment.class.getSimpleName(); + private Bundle arguments; + private String searchDate; + private long searchDate1; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private RecyclerView recyclerView; + private TextView tvMonthDay; + private long oneDay = 24 * 60 * 60 * 1000; + private List recordListDataList = new ArrayList<>(); + private DeviceRecordListAdapter deviceRecordListAdapter; + private DeviceRecordService deviceRecordService = ClassInstanceManager.newInstance().getDeviceRecordService(); + private static DeviceLocalRecordListFragment fragment; + private DeviceRecordListActivity deviceRecordListActivity; + private LcPullToRefreshRecyclerView deviceList; + private int pageSize = 30; + private int pageIndex = 1; + private String time = ""; + private TextView tvToday; + private ImageView mNextDayTv; + public static DeviceLocalRecordListFragment newInstance() { + fragment = new DeviceLocalRecordListFragment(); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + arguments = getArguments(); + searchDate = DateHelper.dateFormat(new Date(System.currentTimeMillis())); + searchDate1 = DateHelper.parseMills(searchDate + " 00:00:00"); + deviceRecordListActivity = (DeviceRecordListActivity) getActivity(); + deviceRecordListActivity.llEdit.setVisibility(View.GONE); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_device_cloud_list, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(view); + if (arguments == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) arguments.getSerializable(MethodConst.ParamConst.deviceDetail); + if (deviceListBean == null) { + return; + } + initData(); + } + + private void initView(View view) { + view.findViewById(R.id.iv_day_pre).setOnClickListener(this); + mNextDayTv =view.findViewById(R.id.iv_day_next); + tvMonthDay = view.findViewById(R.id.tv_month_day); + deviceList = view.findViewById(R.id.record_list); + tvToday = view.findViewById(R.id.tv_today); + deviceList.setOnRefreshListener(this); + mNextDayTv.setOnClickListener(this); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + refreshMode(Mode.PULL_FROM_START); + refreshState(true); + } + }, 200); + recyclerView = deviceList.getRefreshableView(); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView.setLayoutManager(linearLayoutManager); + } + + private void refreshState(boolean refresh) { + if (refresh) { + deviceList.setRefreshing(true); + } else { + deviceList.onRefreshComplete(); + } + } + + private void refreshMode(Mode mode) { + deviceList.setMode(mode); + } + + private void initData() { + tvMonthDay.setText(searchDate); + mCalendar.setTime(TimeUtils.stringToDate(searchDate,"yyyy-MM-dd HH:mm:ss")); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + } + + protected Calendar mCalendar = Calendar.getInstance(); + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.iv_day_pre) { + searchDate1 = searchDate1 - oneDay; + searchDate = DateHelper.dateFormat(new Date(searchDate1)); + tvMonthDay.setText(searchDate); + mCalendar.setTime(new Date(searchDate1)); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + initLocalRecord(false); + } else if (id == R.id.iv_day_next) { + searchDate1 = searchDate1 + oneDay; + searchDate = DateHelper.dateFormat(new Date(searchDate1)); + tvMonthDay.setText(searchDate); + mCalendar.setTime(new Date(searchDate1)); + UIUtils.setEnabledEX(TimeUtils.isBeforeToday(mCalendar), mNextDayTv); + initLocalRecord(false); + } + } + + + + @Override + public void deviceLocalRecord(LocalRecordsData.Response result) { + if (!isAdded()){ + return; + } + tvToday.setVisibility(View.GONE); + recyclerView.setVisibility(View.VISIBLE); + DialogUtils.dismiss(); + refreshState(false); + if (result != null && result.data != null && result.data.records != null && result.data.records.size() > 0) { + if (result.data.records.size() >= pageSize) { + refreshMode(Mode.BOTH); + } else { + refreshMode(Mode.PULL_FROM_START); + } + recordListDataList = dealLocalRecord(result); + } else { + if (pageIndex == 1){ + tvToday.setVisibility(View.VISIBLE); + recyclerView.setVisibility(View.GONE); + } + refreshMode(Mode.PULL_FROM_START); + } + showList(); + } + + @Override + public void onError(Throwable throwable) { + if (!isAdded()){ + return; + } + LogUtil.errorLog(TAG, "error", throwable); + DialogUtils.dismiss(); + refreshState(false); + refreshMode(Mode.PULL_FROM_START); + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + pageIndex = 1; + time = ""; + recordListDataList.clear(); + showList(); + } + + private void initLocalRecord(boolean isLoadMore) { + if (isLoadMore) { + pageIndex = pageIndex + pageSize; + } else { + pageIndex = 1; + time = ""; + recordListDataList.clear(); + } + DialogUtils.show(getActivity()); + getLocalData(); + /* deviceRecordService.querySDUse(deviceListBean.deviceId, new IGetDeviceInfoCallBack.ICommon() { + + @Override + public void onCommonBack(String response) { + if (!"empty".equals(response)){ + getLocalData(); + }else{ + DialogUtils.dismiss(); + refreshState(false); + tvToday.setVisibility(View.VISIBLE); + tvToday.setText(getActivity().getResources().getString(R.string.lc_demo_device_local_sd)); + } + } + + @Override + public void onError(Throwable throwable) { + Toast.makeText(getActivity(),throwable.getMessage(),Toast.LENGTH_SHORT).show(); + } + });*/ + } + + private void getLocalData(){ + LocalRecordsData localRecordsData = new LocalRecordsData(); + localRecordsData.data.deviceId = deviceListBean.deviceId; + localRecordsData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + localRecordsData.data.beginTime = searchDate + " 00:00:00"; + localRecordsData.data.endTime = searchDate + " 23:59:59"; + localRecordsData.data.type = "All"; + localRecordsData.data.queryRange = pageIndex + "-" + (pageIndex + pageSize - 1); + deviceRecordService.queryLocalRecords(localRecordsData, this); + } + + private void showList() { + if (deviceRecordListAdapter == null) { + deviceRecordListAdapter = new DeviceRecordListAdapter(getContext(), recordListDataList); + recyclerView.setAdapter(deviceRecordListAdapter); + } else { + deviceRecordListAdapter.notifyDataSetChanged(); + } + deviceRecordListAdapter.setEditClickListener(new DeviceRecordListAdapter.EditClickListener() { + @Override + public void edit(int outPosition, int innerPosition) { + LogUtil.debugLog(TAG, outPosition + "..." + innerPosition); + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + bundle.putSerializable(MethodConst.ParamConst.recordData, recordListDataList.get(outPosition).recordsData.get(innerPosition)); + bundle.putInt(MethodConst.ParamConst.recordType, MethodConst.ParamConst.recordTypeLocal); + Intent intent = new Intent(getContext(), DeviceRecordPlayActivity.class); + intent.putExtras(bundle); + startActivity(intent); + } + }); + } + + private List dealLocalRecord(LocalRecordsData.Response result) { + for (LocalRecordsData.ResponseData.RecordsBean recordsBean : result.data.records) { + String innerTime = recordsBean.beginTime.substring(11, 13); + RecordsData a = new RecordsData(); + a.recordType = 1; + a.recordId = recordsBean.recordId; + a.channelID = recordsBean.channelID; + a.beginTime = recordsBean.beginTime; + a.endTime = recordsBean.endTime; + a.fileLength = recordsBean.fileLength; + a.type = recordsBean.type; + if (!innerTime.equals(time)) { + RecordListData r = new RecordListData(); + r.period = innerTime + ":00"; + r.recordsData = new ArrayList<>(); + r.recordsData.add(a); + recordListDataList.add(r); + time = innerTime; + } else { + RecordListData b = recordListDataList.get(recordListDataList.size() - 1); + b.recordsData.add(a); + } + } + LogUtil.debugLog(TAG, recordListDataList.size() + ""); + return recordListDataList; + } + + @Override + public void onPullDownToRefresh(PullToRefreshBase pullToRefreshBase) { + initLocalRecord(false); + + } + + @Override + public void onPullUpToRefresh(PullToRefreshBase pullToRefreshBase) { + initLocalRecord(true); + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceOnlineMediaPlayActivity.java b/app/src/main/java/com/lechange/demo/ui/DeviceOnlineMediaPlayActivity.java new file mode 100644 index 0000000..5a1c5ed --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceOnlineMediaPlayActivity.java @@ -0,0 +1,1515 @@ +package com.lechange.demo.ui; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.drawable.BitmapDrawable; +import android.hardware.SensorManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.widget.PopupWindowCompat; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Gravity; +import android.view.OrientationEventListener; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceLocalCacheService; +import com.common.openapi.DeviceRecordService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.CloudRecordsData; +import com.common.openapi.entity.ControlMovePTZData; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.DeviceLocalCacheData; +import com.common.openapi.entity.LocalRecordsData; +import com.common.openapi.entity.RecordsData; +import com.lechange.common.log.Logger; +import com.lechange.demo.adapter.MediaPlayRecordAdapter; +import com.lechange.demo.dialog.EncryptKeyInputDialog; +import com.lechange.demo.handler.ActivityHandler; +import com.lechange.demo.tools.DateHelper; +import com.lechange.demo.tools.DeviceAbilityHelper; +import com.lechange.demo.tools.MediaPlayHelper; +import com.lechange.demo.view.Direction; +import com.lechange.demo.view.LcCloudRudderView; +import com.lechange.demo.view.LcPopupWindow; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.listener.LCOpenSDK_TalkerListener; +import com.lechange.opensdk.media.LCOpenSDK_ParamReal; +import com.lechange.opensdk.media.LCOpenSDK_ParamTalk; +import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; +import com.lechange.opensdk.media.LCOpenSDK_Talk; +import com.mm.android.deviceaddmodule.LCDeviceEngine; +import com.mm.android.deviceaddmodule.device_wifi.DeviceConstant; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.mine.mydevice.DeviceDetailActivity; +import com.yonsz.z1.utils.SharedpreferencesUtil; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import de.greenrobot.event.EventBus; + +import static com.yonsz.z1.net.Constans.CLOSE_THIS_ACTIVITY; + +public class DeviceOnlineMediaPlayActivity extends AppCompatActivity implements View.OnClickListener, IGetDeviceInfoCallBack.IDeviceCacheCallBack { + private static final String TAG = DeviceOnlineMediaPlayActivity.class.getSimpleName(); + + private LCOpenSDK_PlayWindow mPlayWin = new LCOpenSDK_PlayWindow(); + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private Bundle bundle; + private FrameLayout frLiveWindow, frLiveWindowContent; + private TextView tvNoVideo, tvDeviceName, tvCloudVideo, tvLocalVideo, tvLoadingMsg, tvPixel; + private RecyclerView rcvVideoList; + private LinearLayout llVideoContent, llVideo, llSpeak, llScreenShot, llCloudStage, llFullScreen, llSound, llPlayStyle, llPlayPause, llDetail, llBack, llVideo1, llSpeak1, llScreenShot1, llCloudStage1; + private ImageView ivPalyPause, ivPlayStyle, ivSound, ivCloudStage, ivScreenShot, ivSpeak, ivVideo, ivCloudStage1, ivScreenShot1, ivSpeak1, ivVideo1; + private ProgressBar pbLoading; + private RelativeLayout rlLoading; + private LcCloudRudderView rudderView; + private boolean cloudvideo = true; + private boolean isShwoRudder = false; + private boolean showHD = true;//显示HD和SD的切换 + private AudioTalkerListener audioTalkerListener = new AudioTalkerListener(); + + private VideoMode videoMode = VideoMode.MODE_HD; + private SoundStatus soundStatus = SoundStatus.PLAY; + private SoundStatus soundStatusPre = SoundStatus.PLAY; + private SpeakStatus speakStatus = SpeakStatus.STOP; + private RecordStatus recordStatus = RecordStatus.STOP; + private PlayStatus playStatus = PlayStatus.ERROR; + private LinearLayoutManager linearLayoutManager; + private MediaPlayRecordAdapter mediaPlayRecordAdapter; + private List recordsDataList = new ArrayList<>(); + private List cloudRecordsDataList; + private List localRecordsDataList; + private String cloudRecordsDataTip = ""; + private String localRecordsDataTip = ""; + private DeviceRecordService deviceRecordService = ClassInstanceManager.newInstance().getDeviceRecordService(); + private Direction mPTZPreDirection = null; + private int mCurrentOrientation; + private LinearLayout llController; + private FrameLayout frRecord; + private RelativeLayout rlTitle; + private ImageView ivChangeScreen; + private EncryptKeyInputDialog encryptKeyInputDialog; + private String encryptKey; + private boolean supportPTZ; + private String videoPath = null; + // 屏幕方向改变监听器 + private OrientationEventListener mOrientationEventListener; + + private int mVideoViewCurrentOrientationRequest = NO_ORIENTATION_REQUEST; + private LcPopupWindow lcPopupWindow; + private int imageSize = -1;//视频播放分辨率 + private int bateMode; + + + public enum PlayStatus { + PLAY, PAUSE, ERROR + } + + public enum LoadStatus { + LOADING, LOAD_SUCCESS, LOAD_ERROR + } + + public enum SoundStatus { + PLAY, STOP, NO_SUPPORT + } + + public enum SpeakStatus { + PLAY, STOP, NO_SUPPORT, OPENING + } + + public enum VideoMode { + MODE_HD, MODE_SD + } + + public enum RecordStatus { + START, STOP + } + + private Handler mHandler; + + public void onEventMainThread(EventBusEntity event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + if (msg.equals("关闭")) { + finish(); + } + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + mHandler = new ActivityHandler(this) { + @Override + public void handleMsg(Message msg) { + switch (msg.what) { + case MSG_REQUEST_ORIENTATION: + requestedOrientation(msg.arg1, false); + break; + default: + break; + } + // handlePlayMessage(msg); + } + + }; + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + mCurrentOrientation = Configuration.ORIENTATION_PORTRAIT; + initOrientationEventListener(); + setContentView(R.layout.activity_device_online_media_play); + initView(); + initData(); + operatePTZ(); + } + + protected void requestedOrientation(int requestedOrientation, boolean isForce) { + + if (!isForce) { + + if (mVideoViewCurrentOrientationRequest == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { + + /* + * // 如果是开启全屏开关,禁止竖屏 if (requestedOrientation == + * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == + * ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) { return; } + */ + mVideoViewCurrentOrientationRequest = NO_ORIENTATION_REQUEST; + + } else { + + if (mVideoViewCurrentOrientationRequest == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { + + if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { + + // 如果监听器发出的请求是横屏,表示屏幕处于横屏,直接返回; + mVideoViewCurrentOrientationRequest = NO_ORIENTATION_REQUEST; + return; + } + + if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { + + // 如果监听器发出的请求和当前开关方向保持一致时,表示屏幕已经恢复到制定的竖屏,将开关请求状态重置; + mVideoViewCurrentOrientationRequest = NO_ORIENTATION_REQUEST; + return; + } + + // 如果监听器发出的请求与当前开关方向不一致时,表示屏幕已经转到其他方向,将开关请求状态重置,并发出相应的请求; + mVideoViewCurrentOrientationRequest = NO_ORIENTATION_REQUEST; + } + + // 如果开关没有发出请求,或者开关请求状态已经重置,则直接发出相应请求; + + } + + } else { + mVideoViewCurrentOrientationRequest = requestedOrientation; + } + + try { + setRequestedOrientation(requestedOrientation); + } catch (Exception e) { + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + mCurrentOrientation = newConfig.orientation; + super.onConfigurationChanged(newConfig); + switchScreenDirection(); + } + + private void operatePTZ() { + rudderView.setRudderListener(new LcCloudRudderView.RudderListener() { + @Override + public void onSteeringWheelChangedBegin() { + + } + + @Override + public void onSteeringWheelChangedContinue(Direction direction) { + if (direction == null && mPTZPreDirection != null) { + controlPTZ(mPTZPreDirection, 200, true); + mPTZPreDirection = null; + } else if (direction != mPTZPreDirection) { + // 方向不同才更新云台指示图标 + mPTZPreDirection = direction; + controlPTZ(mPTZPreDirection, 30000, false); + } + } + + @Override + public void onSteeringWheelChangedSingle(Direction direction) { + controlPTZ(direction, 200, false); + } + + @Override + public void onSteeringWheelChangedEnd() { + } + }); + } + + private void controlPTZ(Direction em, long time, boolean stop) { + String operation = ""; + if (em == Direction.Left) { + operation = "2"; + } else if (em == Direction.Right) { + operation = "3"; + } else if (em == Direction.Up) { + operation = "0"; + } else if (em == Direction.Down) { + operation = "1"; + } + if (stop) { + operation = "10"; + } + ControlMovePTZData controlMovePTZData = new ControlMovePTZData(); + controlMovePTZData.data.deviceId = deviceListBean.deviceId; + controlMovePTZData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + controlMovePTZData.data.operation = operation; + controlMovePTZData.data.duration = time; + deviceRecordService.controlMovePTZ(controlMovePTZData); + } + + private void initCloudRecord() { + if ((cloudRecordsDataTip != null && !cloudRecordsDataTip.isEmpty()) || cloudRecordsDataList != null) { + if (cloudRecordsDataList != null) { + showRecordList(cloudRecordsDataList); + } else { + showRecordListTip(cloudRecordsDataTip); + } + } else { + getCloudRecord(); + /* deviceRecordService.queryCloudUse(deviceListBean.deviceId, deviceListBean.channels.get(deviceListBean.checkedChannel).channelId, new IGetDeviceInfoCallBack.ICommon() { + + @Override + public void onCommonBack(Integer response) { + if (response==-1||response==0){ + cloudRecordsDataTip = getResources().getString(R.string.lc_demo_device_cloud_not_open); + showRecordListTip(cloudRecordsDataTip); + }else{ + getCloudRecord(); + } + + } + + @Override + public void onError(Throwable throwable) { + Toast.makeText(DeviceOnlineMediaPlayActivity.this,throwable.getMessage(),Toast.LENGTH_SHORT).show(); + } + });*/ + } + } + + + private void getCloudRecord() { + if (deviceListBean.channels.size() == 0) { + return; + } + CloudRecordsData cloudRecordsData = new CloudRecordsData(); + cloudRecordsData.data.deviceId = deviceListBean.deviceId; + cloudRecordsData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + cloudRecordsData.data.beginTime = DateHelper.dateFormat(new Date(System.currentTimeMillis())) + " 00:00:00"; + cloudRecordsData.data.endTime = DateHelper.dateFormat(new Date(System.currentTimeMillis())) + " 23:59:59"; + cloudRecordsData.data.count = 6; + deviceRecordService.getCloudRecords(cloudRecordsData, new IGetDeviceInfoCallBack.IDeviceCloudRecordCallBack() { + @Override + public void deviceCloudRecord(CloudRecordsData.Response result) { + List cloudRecords = result.data.records; + if (cloudRecords != null && cloudRecords.size() > 0) { + cloudRecordsDataList = new ArrayList<>(); + for (CloudRecordsData.ResponseData.RecordsBean recordsBean : cloudRecords) { + RecordsData recordsData = RecordsData.parseCloudData(recordsBean); + cloudRecordsDataList.add(recordsData); + } + showRecordList(cloudRecordsDataList); + } else { + queryCloudUseState(deviceListBean.deviceId, deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + } + } + + @Override + public void onError(Throwable throwable) { + cloudRecordsDataTip = throwable.getMessage(); + showRecordListTip(cloudRecordsDataTip); + } + }); + } + + /** + * 查询套餐使用情况 + * + * @param deviceId + * @param channelId + */ + private void queryCloudUseState(String deviceId, String channelId) { + deviceRecordService.queryCloudUse(deviceId, channelId, new IGetDeviceInfoCallBack.ICommon() { + @Override + public void onCommonBack(Integer response) { + switch (response) { + case -1://未开通 + cloudRecordsDataTip = getResources().getString(R.string.lc_demo_device_cloud_state_not_opened); + break; + case 0://过期 + cloudRecordsDataTip = getResources().getString(R.string.lc_demo_device_cloud_state_expired); + break; + case 1://使用中 + cloudRecordsDataTip = getResources().getString(R.string.lc_demo_device_more_video); + break; + case 2://暂停 + cloudRecordsDataTip = getResources().getString(R.string.lc_demo_device_cloud_state_suspended); + break; + } + showRecordListTip(cloudRecordsDataTip); + } + + @Override + public void onError(Throwable throwable) { + cloudRecordsDataTip = throwable.getMessage(); + showRecordListTip(cloudRecordsDataTip); + } + }); + } + + private void showRecordList(List list) { + rcvVideoList.setVisibility(View.VISIBLE); + tvNoVideo.setVisibility(View.GONE); + recordsDataList.clear(); + for (RecordsData a : list) { + recordsDataList.add(a); + } + if (mediaPlayRecordAdapter == null) { + mediaPlayRecordAdapter = new MediaPlayRecordAdapter(recordsDataList, DeviceOnlineMediaPlayActivity.this); + rcvVideoList.setAdapter(mediaPlayRecordAdapter); + } else { + mediaPlayRecordAdapter.notifyDataSetChanged(); + } + //加载更多 + mediaPlayRecordAdapter.setLoadMoreClickListener(new MediaPlayRecordAdapter.LoadMoreClickListener() { + @Override + public void loadMore() { + gotoRecordList(); + } + }); + //进入视频片段播放页 + mediaPlayRecordAdapter.setOnItemClickListener(new MediaPlayRecordAdapter.OnItemClickListener() { + @Override + public void click(int recordType, int position) { + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + bundle.putSerializable(MethodConst.ParamConst.recordData, recordsDataList.get(position)); + bundle.putInt(MethodConst.ParamConst.recordType, recordsDataList.get(position).recordType == 0 ? MethodConst.ParamConst.recordTypeCloud : MethodConst.ParamConst.recordTypeLocal); + Intent intent = new Intent(DeviceOnlineMediaPlayActivity.this, DeviceRecordPlayActivity.class); + intent.putExtras(bundle); + startActivity(intent); + } + }); + } + + private void gotoRecordList() { + if (cloudvideo) { + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + bundle.putInt(MethodConst.ParamConst.recordType, MethodConst.ParamConst.recordTypeCloud); + Intent intent = new Intent(DeviceOnlineMediaPlayActivity.this, DeviceRecordListActivity.class); + intent.putExtras(bundle); + startActivity(intent); + } else { + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + bundle.putInt(MethodConst.ParamConst.recordType, MethodConst.ParamConst.recordTypeLocal); + Intent intent = new Intent(DeviceOnlineMediaPlayActivity.this, DeviceRecordListActivity.class); + intent.putExtras(bundle); + startActivity(intent); + } + } + + private void showRecordListTip(String txt) { + rcvVideoList.setVisibility(View.GONE); + tvNoVideo.setVisibility(View.VISIBLE); + tvNoVideo.setText(txt); + } + + private void initLocalRecord() { + if ((localRecordsDataTip != null && !localRecordsDataTip.isEmpty()) || localRecordsDataList != null) { + if (localRecordsDataList != null) { + showRecordList(localRecordsDataList); + } else { + showRecordListTip(localRecordsDataTip); + } + } else { + getLocalRecord(); + /* deviceRecordService.querySDUse(deviceListBean.deviceId, new IGetDeviceInfoCallBack.ICommon() { + @Override + public void onCommonBack(String response) { + if (!"empty".equals(response)){ + getLocalRecord(); + }else{ + localRecordsDataTip = getResources().getString(R.string.lc_demo_device_local_sd); + showRecordListTip(localRecordsDataTip); + } + } + @Override + public void onError(Throwable throwable) { + Toast.makeText(DeviceOnlineMediaPlayActivity.this,throwable.getMessage(),Toast.LENGTH_SHORT).show(); + } + });*/ + + } + } + + private void getLocalRecord() { + LocalRecordsData localRecordsData = new LocalRecordsData(); + localRecordsData.data.deviceId = deviceListBean.deviceId; + localRecordsData.data.channelId = deviceListBean.channels.get(deviceListBean.checkedChannel).channelId; + localRecordsData.data.beginTime = DateHelper.dateFormat(new Date(System.currentTimeMillis())) + " 00:00:00"; + localRecordsData.data.endTime = DateHelper.dateFormat(new Date(System.currentTimeMillis())) + " 23:59:59"; + localRecordsData.data.type = "All"; + localRecordsData.data.queryRange = "1-6"; + deviceRecordService.queryLocalRecords(localRecordsData, new IGetDeviceInfoCallBack.IDeviceLocalRecordCallBack() { + @Override + public void deviceLocalRecord(LocalRecordsData.Response result) { + List localRecords = result.data.records; + if (localRecords != null && localRecords.size() > 0) { + localRecordsDataList = new ArrayList<>(); + for (LocalRecordsData.ResponseData.RecordsBean recordsBean : localRecords) { + RecordsData recordsData = RecordsData.parseLocalData(recordsBean); + localRecordsDataList.add(recordsData); + } + showRecordList(localRecordsDataList); + } else { + localRecordsDataTip = getResources().getString(R.string.lc_demo_device_more_video); + showRecordListTip(localRecordsDataTip); + } + } + + @Override + public void onError(Throwable throwable) { + localRecordsDataTip = throwable.getMessage(); + showRecordListTip(localRecordsDataTip); + } + }); + } + + private void initView() { + frLiveWindow = findViewById(R.id.fr_live_window); + frLiveWindowContent = findViewById(R.id.fr_live_window_content); + tvCloudVideo = findViewById(R.id.tv_cloud_video); + tvLocalVideo = findViewById(R.id.tv_local_video); + llBack = findViewById(R.id.ll_back); + tvDeviceName = findViewById(R.id.tv_device_name); + llDetail = findViewById(R.id.ll_detail); + llPlayPause = findViewById(R.id.ll_paly_pause); + llPlayStyle = findViewById(R.id.ll_play_style); + llSound = findViewById(R.id.ll_sound); + llFullScreen = findViewById(R.id.ll_fullscreen); + llCloudStage = findViewById(R.id.ll_cloudstage); + llScreenShot = findViewById(R.id.ll_screenshot); + llSpeak = findViewById(R.id.ll_speak); + llVideo = findViewById(R.id.ll_video); + llVideoContent = findViewById(R.id.ll_video_content); + rcvVideoList = findViewById(R.id.rcv_video_list); + tvNoVideo = findViewById(R.id.tv_no_video); + rudderView = findViewById(R.id.rudder); + ivPalyPause = findViewById(R.id.iv_paly_pause); + ivPlayStyle = findViewById(R.id.iv_play_style); + tvPixel = findViewById(R.id.tv_play_pixel); + ivSound = findViewById(R.id.iv_sound); + ivCloudStage = findViewById(R.id.iv_cloudStage); + ivScreenShot = findViewById(R.id.iv_screen_shot); + ivSpeak = findViewById(R.id.iv_speak); + ivVideo = findViewById(R.id.iv_video); + + llCloudStage1 = findViewById(R.id.ll_cloudstage1); + llScreenShot1 = findViewById(R.id.ll_screenshot1); + llSpeak1 = findViewById(R.id.ll_speak1); + llVideo1 = findViewById(R.id.ll_video1); + ivCloudStage1 = findViewById(R.id.iv_cloudStage1); + ivScreenShot1 = findViewById(R.id.iv_screen_shot1); + ivSpeak1 = findViewById(R.id.iv_speak1); + ivVideo1 = findViewById(R.id.iv_video1); + + rlLoading = findViewById(R.id.rl_loading); + pbLoading = findViewById(R.id.pb_loading); + tvLoadingMsg = findViewById(R.id.tv_loading_msg); + llController = findViewById(R.id.ll_controller); + frRecord = findViewById(R.id.fr_record); + rlTitle = findViewById(R.id.rl_title); + ivChangeScreen = findViewById(R.id.iv_change_screen); + linearLayoutManager = new LinearLayoutManager(DeviceOnlineMediaPlayActivity.this); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + rcvVideoList.setLayoutManager(linearLayoutManager); + initCommonClickListener(); + // 初始化播放窗口 + switchScreenDirection(); + mPlayWin.initPlayWindow(this, frLiveWindowContent, 0, false); + setWindowListener(mPlayWin); + mPlayWin.openTouchListener();//开启收拾监听 + } + + private void switchScreenDirection() { + if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) { + RelativeLayout.LayoutParams mLayoutParams = new RelativeLayout.LayoutParams(frLiveWindow.getLayoutParams()); + DisplayMetrics metric = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + mLayoutParams.addRule(RelativeLayout.BELOW, R.id.rl_title); + frLiveWindow.setLayoutParams(mLayoutParams); + MediaPlayHelper.quitFullScreen(DeviceOnlineMediaPlayActivity.this); + llController.setVisibility(View.VISIBLE); + rlTitle.setVisibility(View.VISIBLE); + llSpeak1.setVisibility(View.GONE); + llCloudStage1.setVisibility(View.GONE); + llVideo1.setVisibility(View.GONE); + llScreenShot1.setVisibility(View.GONE); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(frRecord + .getLayoutParams()); + layoutParams.addRule(RelativeLayout.BELOW, R.id.ll_controller); + frRecord.setLayoutParams(layoutParams); + FrameLayout.LayoutParams layoutParams3 = new FrameLayout.LayoutParams(rudderView.getLayoutParams()); + layoutParams3.gravity = Gravity.CENTER; + rudderView.setLayoutParams(layoutParams3); + switchCloudRudder(false); + } else if (mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE) { + DisplayMetrics metric = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metric); + RelativeLayout.LayoutParams mLayoutParams = new RelativeLayout.LayoutParams(metric.widthPixels, metric.heightPixels); + mLayoutParams.setMargins(0, 0, 0, 0); + mLayoutParams.removeRule(RelativeLayout.BELOW); + frLiveWindow.setLayoutParams(mLayoutParams); + MediaPlayHelper.setFullScreen(DeviceOnlineMediaPlayActivity.this); + llController.setVisibility(View.GONE); + rlTitle.setVisibility(View.GONE); + llSpeak1.setVisibility(View.VISIBLE); + llCloudStage1.setVisibility(View.VISIBLE); + llVideo1.setVisibility(View.VISIBLE); + llScreenShot1.setVisibility(View.VISIBLE); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(frRecord + .getLayoutParams()); + layoutParams.removeRule(RelativeLayout.BELOW); + frRecord.setLayoutParams(layoutParams); + FrameLayout.LayoutParams layoutParams3 = new FrameLayout.LayoutParams(rudderView.getLayoutParams()); + layoutParams3.gravity = Gravity.CENTER_VERTICAL; + rudderView.setLayoutParams(layoutParams3); + switchCloudRudder(false); + } + } + + private void initData() { + bundle = getIntent().getExtras(); + if (bundle == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) bundle.getSerializable(MethodConst.ParamConst.deviceDetail); + switchVideoList(true); + if (deviceListBean.channels.size() == 0) { + return; + } + getDeviceLocalCache(); + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + + /*if (deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions != null && deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions.size() > 0) { + showHD = false; + bateMode = deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions.get(0).streamType; + imageSize = deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions.get(0).imageSize; + tvPixel.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions.get(0).name); + } else { + showHD = true; + } + lcPopupWindow = new LcPopupWindow(DeviceOnlineMediaPlayActivity.this, deviceListBean.channels.get(deviceListBean.checkedChannel).resolutions); + lcPopupWindow.getContentView().measure(lcPopupWindow.makeDropDownMeasureSpec(lcPopupWindow.getWidth()), + lcPopupWindow.makeDropDownMeasureSpec(lcPopupWindow.getHeight() + ));*/ + } + + /** + * 获取设备缓存信息 + */ + private void getDeviceLocalCache() { + DeviceLocalCacheData deviceLocalCacheData = new DeviceLocalCacheData(); + deviceLocalCacheData.setDeviceId(deviceListBean.deviceId); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + deviceLocalCacheData.setChannelId(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + } + DeviceLocalCacheService deviceLocalCacheService = ClassInstanceManager.newInstance().getDeviceLocalCacheService(); + deviceLocalCacheService.findLocalCache(deviceLocalCacheData, this); + } + + + @Override + public void deviceCache(DeviceLocalCacheData deviceLocalCacheData) { + BitmapDrawable bitmapDrawable = MediaPlayHelper.picDrawable(deviceLocalCacheData.getPicPath()); + if (bitmapDrawable != null) { + rlLoading.setBackground(bitmapDrawable); + } + } + + @Override + public void onError(Throwable throwable) { + + } + + @Override + protected void onResume() { + super.onResume(); + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_loading), deviceListBean.deviceId); + } + + @Override + protected void onPause() { + super.onPause(); + stop(); + recordStatus = RecordStatus.STOP; + } + + private void initAbility(boolean loadSuccess) { + String deviceAbility = deviceListBean.ability; + String channelAbility = deviceListBean.ability; +// String channelAbility = deviceListBean.channels.get(deviceListBean.checkedChannel).ability; + //云台 + supportPTZ = DeviceAbilityHelper.isHasAbility(deviceAbility, channelAbility, "PT", "PTZ") && loadSuccess; + cloudStageClickListener(supportPTZ); + //对讲 + speakClickListener(DeviceAbilityHelper.isHasAbility(deviceAbility, channelAbility, "AudioTalkV1", "AudioTalk") && loadSuccess); + } + + private void switchVideoList(boolean b) { + this.cloudvideo = b; + tvCloudVideo.setSelected(cloudvideo); + tvLocalVideo.setSelected(!cloudvideo); + if (cloudvideo) { + initCloudRecord(); + } else { + initLocalRecord(); + } + } + + private void initCommonClickListener() { + llBack.setOnClickListener(this); + llDetail.setOnClickListener(this); + tvCloudVideo.setOnClickListener(this); + tvLocalVideo.setOnClickListener(this); + tvNoVideo.setOnClickListener(this); + llFullScreen.setOnClickListener(this); + } + + private void featuresClickListener(boolean loadSuccess) { + llPlayPause.setOnClickListener(loadSuccess ? this : null); + llPlayStyle.setOnClickListener(loadSuccess ? this : null); + + llScreenShot.setOnClickListener(loadSuccess ? this : null); + llScreenShot1.setOnClickListener(loadSuccess ? this : null); + llVideo.setOnClickListener(loadSuccess ? this : null); + llVideo1.setOnClickListener(loadSuccess ? this : null); + llSound.setOnClickListener(loadSuccess ? this : null); + ivPalyPause.setImageDrawable(loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause_disable)); + if (showHD) { + ivPlayStyle.setVisibility(View.VISIBLE); + tvPixel.setVisibility(View.GONE); + ivPlayStyle.setImageDrawable(videoMode == VideoMode.MODE_HD ? + (loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_hd) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_hd_disable)) : + (loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_sd) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_hd_disable))); + } else { + ivPlayStyle.setVisibility(View.GONE); + tvPixel.setVisibility(View.VISIBLE); + } + + ivScreenShot.setImageDrawable(loadSuccess + ? getDrawable(R.drawable.lc_demo_photo_capture_selector) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_screenshot_disable)); + ivVideo.setImageDrawable(loadSuccess + ? getDrawable(R.mipmap.lc_demo_livepreview_icon_video) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_video_disable)); + + ivScreenShot1.setImageDrawable(loadSuccess + ? getDrawable(R.mipmap.live_video_icon_h_screenshot) + : getDrawable(R.mipmap.live_video_icon_h_screenshot_disable)); + ivVideo1.setImageDrawable(loadSuccess + ? getDrawable(R.mipmap.live_video_icon_h_video_off) + : getDrawable(R.mipmap.live_video_icon_h_video_off_disable)); + ivSound.setImageDrawable(loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off_disable)); + //媒体声 + if (soundStatus != SoundStatus.PLAY) { + return; + } + if (openAudio()) { + soundStatus = SoundStatus.PLAY; + ivSound.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_on)); + } + } + + private void cloudStageClickListener(boolean isSupport) { + llCloudStage.setOnClickListener(isSupport ? this : null); + ivCloudStage.setImageDrawable(isSupport + ? getDrawable(R.mipmap.lc_demo_livepreview_icon_cloudstage) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_cloudstage_disable)); + llCloudStage1.setOnClickListener(isSupport ? this : null); + ivCloudStage1.setImageDrawable(isSupport + ? getDrawable(R.mipmap.live_video_icon_h_cloudterrace_off) + : getDrawable(R.mipmap.live_video_icon_h_cloudterrace_off_disable)); + } + + private void speakClickListener(boolean isSupport) { + ivSpeak.setOnClickListener(isSupport ? this : null); + ivSpeak.setImageDrawable(isSupport + ? getDrawable(R.mipmap.lc_demo_livepreview_icon_speak) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_speak_disable)); + ivSpeak1.setOnClickListener(isSupport ? this : null); + ivSpeak1.setImageDrawable(isSupport + ? getDrawable(R.mipmap.live_video_icon_h_talk_off) + : getDrawable(R.mipmap.live_video_icon_h_talk_off_disable)); + } + + private void setWindowListener(LCOpenSDK_PlayWindow playWin) { + playWin.setWindowListener(new LCOpenSDK_EventListener() { + //手势缩放开始事件 + @Override + public void onZoomBegin(int index) { + super.onZoomBegin(index); + LogUtil.debugLog(TAG, "onZoomBegin: index= " + index); + } + + //手势缩放中事件 + @Override + public void onZooming(int index, float dScale) { + super.onZooming(index, dScale); + LogUtil.debugLog(TAG, "onZooming: index= " + index + " , dScale= " + dScale); + mPlayWin.doScale(dScale); + } + + //缩放结束事件 + @Override + public void onZoomEnd(int index, ZoomType zoomType) { + super.onZoomEnd(index, zoomType); + LogUtil.debugLog(TAG, "onZoomEnd: index= " + index + " , zoomType= " + zoomType); + } + + //窗口单击事件 + @Override + public void onControlClick(int index, float dx, float dy) { + super.onControlClick(index, dx, dy); + LogUtil.debugLog(TAG, "onControlClick: index= " + index + " , dx= " + dx + " , dy= " + dy); + } + + //窗口双击事件 + @Override + public void onWindowDBClick(int index, float dx, float dy) { + super.onWindowDBClick(index, dx, dy); + LogUtil.debugLog(TAG, "onWindowDBClick: index= " + index + " , dx= " + dx + " , dy= " + dy); + } + + //滑动开始事件 + @Override + public boolean onSlipBegin(int index, Direction direction, float dx, float dy) { + LogUtil.debugLog(TAG, "onSlipBegin: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + return super.onSlipBegin(index, direction, dx, dy); + } + + //滑动中事件 + @Override + public void onSlipping(int index, Direction direction, float prex, float prey, float dx, float dy) { + super.onSlipping(index, direction, prex, prey, dx, dy); + mPlayWin.doTranslate(dx, dy); + LogUtil.debugLog(TAG, "onSlipping: index= " + index + " , direction= " + direction + " , prex= " + prex + " , prey= " + prey + " , dx= " + dx + " , dy= " + dy); + } + + //滑动结束事件 + @Override + public void onSlipEnd(int index, Direction direction, float dx, float dy) { + super.onSlipEnd(index, direction, dx, dy); + mPlayWin.doTranslateEnd(); + LogUtil.debugLog(TAG, "onSlipEnd: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + } + + //长按开始回调 + @Override + public void onWindowLongPressBegin(int index, Direction direction, float dx, float dy) { + super.onWindowLongPressBegin(index, direction, dx, dy); + LogUtil.debugLog(TAG, "onWindowLongPressBegin: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + } + + //长按事件结束 + @Override + public void onWindowLongPressEnd(int index) { + super.onWindowLongPressEnd(index); + LogUtil.debugLog(TAG, "onWindowLongPressEnd: index= " + index); + } + + /** + * 播放事件回调 + * resultSource: 0--RTSP 1--HLS 5--DHHTTP 99--OPENAPI + */ + @Override + public void onPlayerResult(int index, String code, int resultSource) { + //mPlayWin.setSEnhanceMode(4);//设置降噪等级最大 + super.onPlayerResult(index, code, resultSource); + LogUtil.debugLog(TAG, "onPlayerResult: index= " + index + " , code= " + code + " , resultSource= " + resultSource); + boolean failed = false; + if (resultSource == 99) { + //code -1000 HTTP交互出错或超时 + failed = true; + } else { + if (resultSource == 5 && (!(code.equals("1000") || code.equals("0") || code.equals("4000")))) { + // code 1000-开启播放成功 0-开始拉流 + failed = true; + if (code.equals("1000005")) { + inputEncryptKey(); + } + } else if (resultSource == 0 && (code.equals("0") || code.equals("1") || code.equals("3") || code.equals("7"))) { + // code + // 0-组帧失败,错误状态 + // 1-内部要求关闭,如连接断开等,错误状态 + // 3-RTSP鉴权失败,错误状态 + // 7-秘钥错误 + failed = true; + if (code.equals("7")) { + inputEncryptKey(); + } + } + } + if (failed) { + loadingStatus(LoadStatus.LOAD_ERROR, getResources().getString(R.string.lc_demo_device_video_play_error) + ":" + code + "." + resultSource, ""); + playStatus = PlayStatus.ERROR; + } + } + + //分辨率改变事件 + @Override + public void onResolutionChanged(int index, int width, int height) { + super.onResolutionChanged(index, width, height); + LogUtil.debugLog(TAG, "onResolutionChanged: index= " + index + " , width= " + width + " , height= " + height); + } + + //播放开始回调 + @Override + public void onPlayBegan(int index) { + super.onPlayBegan(index); + LogUtil.debugLog(TAG, "onPlayBegan: index= " + index); + loadingStatus(LoadStatus.LOAD_SUCCESS, "", ""); + playStatus = PlayStatus.PLAY; + } + + //接收数据回调 + @Override + public void onReceiveData(int index, int len) { + super.onReceiveData(index, len); + LogUtil.debugLog(TAG, "onReceiveData: index= " + index + " , len= " + len); + } + + //接收帧流回调 + @Override + public void onStreamCallback(int index, byte[] bytes, int len) { + super.onStreamCallback(index, bytes, len); + LogUtil.debugLog(TAG, "onStreamCallback: index= " + index + " , len= " + len); + } + + //播放结束事件 + @Override + public void onPlayFinished(int index) { + super.onPlayFinished(index); + LogUtil.debugLog(TAG, "onPlayFinished: index= " + index); + } + + //播放时间信息回调 + @Override + public void onPlayerTime(int index, long time) { + super.onPlayerTime(index, time); + LogUtil.debugLog(TAG, "onPlayerTime: index= " + index + " , time= " + time); + } + }); + } + + /** + * 输入秘钥 + */ + private void inputEncryptKey() { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (encryptKeyInputDialog == null) { + encryptKeyInputDialog = new EncryptKeyInputDialog(DeviceOnlineMediaPlayActivity.this); + } + encryptKeyInputDialog.show(); + encryptKeyInputDialog.setOnClick(new EncryptKeyInputDialog.OnClick() { + @Override + public void onSure(String txt) { + encryptKey = txt; + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_change), txt); + } + }); + } + }); + } + + /** + * 播放状态 + * + * @param loadStatus 播放状态 + * @param msg + */ + private void loadingStatus(final LoadStatus loadStatus, final String msg, final String psk) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (loadStatus == LoadStatus.LOADING) { + //先关闭 + stop(); + //开始播放 + play(psk); + rlLoading.setVisibility(View.VISIBLE); + pbLoading.setVisibility(View.VISIBLE); + tvLoadingMsg.setText(msg); + } else if (loadStatus == LoadStatus.LOAD_SUCCESS) { + //播放成功 + rlLoading.setVisibility(View.GONE); + rudderView.enable(true); + initAbility(true); + featuresClickListener(true); + } else { + //播放失败 + stop(); + rlLoading.setVisibility(View.VISIBLE); + pbLoading.setVisibility(View.GONE); + tvLoadingMsg.setText(msg); + initAbility(false); + featuresClickListener(false); + } + } + }); + } + + /** + * 开始播放 + */ + public void play(String psk) { + + if (showHD) { + bateMode = videoMode == VideoMode.MODE_HD ? 0 : 1; + } + if (deviceListBean.channels.size() == 0) { + return; + } + LCOpenSDK_ParamReal paramReal = new LCOpenSDK_ParamReal( + SharedpreferencesUtil.get("accessToken", ""), + deviceListBean.deviceId, + Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId), + psk, + deviceListBean.playToken, + bateMode, + true, true, imageSize + ); + mPlayWin.playRtspReal(paramReal); + + } + + /** + * 停止播放 + */ + public void stop() { + captureLastPic(); + stopRecord();// 关闭录像 + closeAudio();// 关闭音频 + stopTalk();//关闭对讲 + rudderView.enable(false); + mPlayWin.stopRtspReal(true);// 关闭视频 + } + + /** + * 保存最后一帧做封面 + */ + private void captureLastPic() { + if (playStatus == PlayStatus.ERROR) { + return; + } + String capturePath; + try { + capturePath = capture(false); + } catch (Throwable e) { + capturePath = null; + } + if (capturePath == null) { + return; + } + DeviceLocalCacheService deviceLocalCacheService = ClassInstanceManager.newInstance().getDeviceLocalCacheService(); + DeviceLocalCacheData deviceLocalCacheData = new DeviceLocalCacheData(); + deviceLocalCacheData.setPicPath(capturePath); + deviceLocalCacheData.setDeviceName(deviceListBean.name); + deviceLocalCacheData.setDeviceId(deviceListBean.deviceId); + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + deviceLocalCacheData.setChannelId(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + deviceLocalCacheData.setChannelName(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + } + deviceLocalCacheService.addLocalCache(deviceLocalCacheData); + } + + /** + * 开始录像 + */ + public boolean startRecord() { + // 录像的路径 + + String channelName = null; + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + channelName = deviceListBean.channels.get(deviceListBean.checkedChannel).channelName; + } else { + channelName = deviceListBean.name; + } + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + videoPath = MediaPlayHelper.getCaptureAndVideoPath(MediaPlayHelper.DHFilesType.DHVideo, channelName); + LogUtil.debugLog(TAG, "videopath:::----start" + videoPath); + //MediaScannerConnection.scanFile(this, new String[]{videoPath}, null, null); + // 开始录制 1 + int ret = mPlayWin.startRecord(videoPath, 1, 0x7FFFFFFF); + return ret == 0; + } + + /** + * 关闭录像 + */ + public boolean stopRecord() { + return mPlayWin.stopRecord() == 0; + } + + /** + * 截图 + */ + public String capture(boolean notify) { + String captureFilePath = null; + String channelName = null; + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + channelName = deviceListBean.channels.get(deviceListBean.checkedChannel).channelName; + } else { + channelName = deviceListBean.name; + } + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + captureFilePath = MediaPlayHelper.getCaptureAndVideoPath(notify ? MediaPlayHelper.DHFilesType.DHImage : MediaPlayHelper.DHFilesType.DHImageCache, channelName); + int ret = mPlayWin.snapShot(captureFilePath); + if (ret == 0) { + if (notify) { + // 扫描到相册中 + MediaPlayHelper.updatePhotoAlbum(captureFilePath); + // MediaScannerConnection.scanFile(this, new String[]{captureFilePath}, null, null); + } + } else { + captureFilePath = null; + } + return captureFilePath; + } + + /** + * 打开声音 + */ + public boolean openAudio() { + return mPlayWin.playAudio() == 0; + } + + /** + * 关闭声音 + */ + public boolean closeAudio() { + return mPlayWin.stopAudio() == 0; + } + + /** + * 开始对讲 多通道通道号参数传入对应的通道号,单通道传-1 + */ + public void startTalk() { + closeAudio(); + soundStatus = SoundStatus.STOP; + speakStatus = SpeakStatus.OPENING; + ivSound.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off_disable)); + llSound.setClickable(false);//声音按钮不允许点击 + LCOpenSDK_Talk.setListener(audioTalkerListener);//对讲前先设备监听 + int channelId = -1; + + if (Integer.parseInt(deviceListBean.channelNum) > 1) { + /* if(null != deviceListBean.channels.get(deviceListBean.checkedChannel).channelId && !"".equals(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId)) { + channelId = Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + } else { + stopTalk(); + Logger.e(TAG, "server returned NVR device channelId is null or empty charators"); + return; + }*/ + channelId = Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId); + Logger.d(TAG, "deviceCatalog = " + deviceListBean.catalog + ", routing device talk..."); + } + Logger.d(TAG, "playTalk, channelId = " + channelId); + LCOpenSDK_ParamTalk paramTalk = new LCOpenSDK_ParamTalk( + SharedpreferencesUtil.get("accessToken", ""), + deviceListBean.deviceId, + channelId, + TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey, + deviceListBean.playToken, + true, "talk" + ); + LCOpenSDK_Talk.playTalk(paramTalk); + } + + /** + * 停止对讲 + */ + public void stopTalk() { + soundStatus = soundStatusPre; + if (SoundStatus.PLAY == soundStatus) { + ivSound.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_on)); + openAudio(); + } else { + ivSound.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off)); + } + speakStatus = SpeakStatus.STOP; + ivSpeak.setImageDrawable(getDrawable(R.mipmap.lc_demo_livepreview_icon_speak)); + ivSpeak1.setImageDrawable(getDrawable(R.mipmap.live_video_icon_h_talk_off)); + + LCOpenSDK_Talk.stopTalk(); + LCOpenSDK_Talk.setListener(null);//停止对讲后对讲监听置为空 + llSound.setClickable(true); + } + + class AudioTalkerListener extends LCOpenSDK_TalkerListener { + public AudioTalkerListener() { + super(); + } + + @Override + public void onTalkResult(String error, int type) { + super.onTalkResult(error, type); + boolean talkResult = false; + if (type == 99 || error.equals("-1000") || error.equals("0") || error.equals("1") || error.equals("3")) { + talkResult = false; + } else if (error.equals("4")) { + talkResult = true; + } + final boolean finalTalkResult = talkResult; + runOnUiThread(new Runnable() { + @Override + public void run() { + if (!finalTalkResult) { + stopTalk(); + // 提示对讲打开失败 + Toast.makeText(DeviceOnlineMediaPlayActivity.this, R.string.lc_demo_device_talk_open_failed, Toast.LENGTH_SHORT).show(); + speakStatus = SpeakStatus.STOP; + ivSpeak.setImageDrawable(getDrawable(R.mipmap.lc_demo_livepreview_icon_speak)); + ivSpeak1.setImageDrawable(getDrawable(R.mipmap.live_video_icon_h_talk_off)); + } else { + // 提示对讲打开成功 + Toast.makeText(DeviceOnlineMediaPlayActivity.this, R.string.lc_demo_device_talk_open_success, Toast.LENGTH_SHORT).show(); + speakStatus = SpeakStatus.PLAY; + ivSpeak.setImageDrawable(getDrawable(R.mipmap.lc_demo_livepreview_icon_speak_ing)); + ivSpeak1.setImageDrawable(getDrawable(R.mipmap.live_video_icon_h_talk_on)); + + } + } + }); + } + + @Override + public void onTalkPlayReady() { + super.onTalkPlayReady(); + } + + @Override + public void onAudioRecord(byte[] bytes, int i, int i1, int i2, int i3) { + super.onAudioRecord(bytes, i, i1, i2, i3); + } + + @Override + public void onAudioReceive(byte[] bytes, int i, int i1, int i2, int i3) { + super.onAudioReceive(bytes, i, i1, i2, i3); + } + + @Override + public void onDataLength(int i) { + super.onDataLength(i); + } + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.ll_back) { + //返回 + finish(); + } else if (id == R.id.ll_fullscreen) { + //横竖屏切换 + if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + mCurrentOrientation = Configuration.ORIENTATION_LANDSCAPE; + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + mCurrentOrientation = Configuration.ORIENTATION_PORTRAIT; + } + ivChangeScreen.setImageDrawable(mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ? getResources().getDrawable(R.mipmap.live_btn_smallscreen) : getResources().getDrawable(R.mipmap.video_fullscreen)); + } else if (id == R.id.ll_detail) { + Bundle bundle = new Bundle(); + bundle.putSerializable(MethodConst.ParamConst.deviceDetail, deviceListBean); + Intent intent = new Intent(DeviceOnlineMediaPlayActivity.this, DeviceDetailLCActivity.class); + intent.putExtras(bundle); + intent.putExtra("addressId", getIntent().getExtras().get("addressId").toString()); + intent.putExtra("id", getIntent().getExtras().get("id").toString()); + intent.putExtra("deviceId", getIntent().getExtras().get("deviceId").toString()); + intent.putExtra("deviceType", getIntent().getExtras().get("deviceType").toString()); + startActivityForResult(intent, 0); + } else if (id == R.id.ll_paly_pause) { + //播放暂停 + if (playStatus == PlayStatus.PLAY) { + stop(); + initAbility(false); + featuresClickListener(false); + llPlayPause.setOnClickListener(this); + } else { + getDeviceLocalCache(); + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_loading), TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey); + } + playStatus = (playStatus == PlayStatus.PLAY) ? PlayStatus.PAUSE : PlayStatus.PLAY; + ivPalyPause.setImageDrawable(playStatus == PlayStatus.PLAY ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_play)); + } else if (id == R.id.ll_play_style) { + if (showHD) { + //视频清晰度切换 + videoMode = (videoMode == VideoMode.MODE_HD) ? VideoMode.MODE_SD : VideoMode.MODE_HD; + ivPlayStyle.setImageDrawable(videoMode == VideoMode.MODE_HD ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_hd) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_sd)); + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_change), TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey); + } else { + int offsetX = llPlayStyle.getWidth() / 3 * 2; + int offsetY = -(lcPopupWindow.getContentView().getMeasuredHeight() + 10); + PopupWindowCompat.showAsDropDown(lcPopupWindow, llPlayStyle, offsetX, offsetY, Gravity.START); + lcPopupWindow.setPixelRecycleListener(new LcPopupWindow.onRecyclerViewItemClickListener() { + @Override + public void onItemClick(RecyclerView parent, View view, int position, String name, int image_size, int streamType) { + tvPixel.setText(name); + lcPopupWindow.dismiss(); + imageSize = image_size; + bateMode = streamType; + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_change), TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey); + } + }); + } + + + } else if (id == R.id.ll_sound) { + //媒体声 如果是开启去关闭,反之 + if (soundStatus == SoundStatus.NO_SUPPORT) { + return; + } + boolean result = false; + if (soundStatus == SoundStatus.PLAY) { + result = closeAudio(); + } else { + result = openAudio(); + } + if (!result) { + return; + } + soundStatus = (soundStatus == SoundStatus.PLAY) ? SoundStatus.STOP : SoundStatus.PLAY; + ivSound.setImageDrawable(soundStatus == SoundStatus.PLAY ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_on) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off)); + } else if (id == R.id.ll_cloudstage || id == R.id.ll_cloudstage1) { + //云台和录像列表切换 + switchCloudRudder(!isShwoRudder); + } else if (id == R.id.ll_screenshot || id == R.id.ll_screenshot1) { + //截图 + if (capture(true) != null) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_capture_success), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_capture_failed), Toast.LENGTH_SHORT).show(); + } + } else if (id == R.id.iv_speak || id == R.id.iv_speak1) { + //对讲 如果是打开状态去关闭,反之 + if (speakStatus == SpeakStatus.NO_SUPPORT || speakStatus == SpeakStatus.OPENING) { + return; + } + if (speakStatus == SpeakStatus.STOP) { + soundStatusPre = soundStatus; + startTalk(); + } else { + Toast.makeText(DeviceOnlineMediaPlayActivity.this, R.string.lc_demo_device_talk_close_success, Toast.LENGTH_SHORT).show(); + stopTalk(); + + } + } else if (id == R.id.ll_video || id == R.id.ll_video1) { + //录像 如果是关闭状态去打开,反之 + if (recordStatus == RecordStatus.STOP) { + if (startRecord()) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_record_begin), Toast.LENGTH_SHORT).show(); + } else { + return; + } + } else { + if (stopRecord()) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_record_stop), Toast.LENGTH_SHORT).show(); + LogUtil.debugLog(TAG, "videopath:::" + videoPath); + MediaPlayHelper.updatePhotoVideo(videoPath); + } else { + return; + } + } + recordStatus = (recordStatus == RecordStatus.START) ? RecordStatus.STOP : RecordStatus.START; + ivVideo.setImageDrawable(recordStatus == RecordStatus.START + ? getDrawable(R.mipmap.lc_demo_livepreview_icon_video_ing) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_video)); + ivVideo1.setImageDrawable(recordStatus == RecordStatus.START + ? getDrawable(R.mipmap.live_video_icon_h_video_on) + : getDrawable(R.mipmap.live_video_icon_h_video_off)); + } else if (id == R.id.tv_cloud_video) { + //切换至云录像 + switchVideoList(true); + } else if (id == R.id.tv_local_video) { + //切换至设备录像 + switchVideoList(false); + } else if (id == R.id.tv_no_video) { + //暂无录像切换 + gotoRecordList(); + } + } + + private void switchCloudRudder(boolean isShow) { + this.isShwoRudder = isShow; + if (isShow) { + ivCloudStage.setImageDrawable(getDrawable(R.mipmap.lc_demo_livepreview_icon_cloudstage_click)); + ivCloudStage1.setImageDrawable(getDrawable(R.mipmap.live_video_icon_h_cloudterrace_on)); + llVideoContent.setVisibility(View.GONE); + rudderView.setVisibility(View.VISIBLE); + } else { + ivCloudStage.setImageDrawable(supportPTZ + ? getDrawable(R.mipmap.lc_demo_livepreview_icon_cloudstage) + : getDrawable(R.mipmap.lc_demo_livepreview_icon_cloudstage_disable)); + ivCloudStage1.setImageDrawable(supportPTZ + ? getDrawable(R.mipmap.live_video_icon_h_cloudterrace_off) + : getDrawable(R.mipmap.live_video_icon_h_cloudterrace_off_disable)); + llVideoContent.setVisibility(mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT ? View.VISIBLE : View.GONE); + rudderView.setVisibility(View.GONE); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mPlayWin.uninitPlayWindow();// 销毁底层资源 + uninitOrientationEventListener(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK && data != null) { + boolean unBind = data.getBooleanExtra(DeviceConstant.IntentKey.DHDEVICE_UNBIND, false); + if (unBind) { + finish(); + } + } + if (resultCode == 100 && data != null) { + String name = data.getStringExtra(DeviceConstant.IntentKey.DHDEVICE_NEW_NAME); + tvDeviceName.setText(name); + deviceListBean.channels.get(deviceListBean.checkedChannel).channelName = name; + } + } + + + public static final int NO_ORIENTATION_REQUEST = -1; + + public static final int MSG_REQUEST_ORIENTATION = 1; + + + private void initOrientationEventListener() { + + mOrientationEventListener = new MediaPlayOrientationEventListener(this, + SensorManager.SENSOR_DELAY_NORMAL, mHandler); + + if (mOrientationEventListener.canDetectOrientation()) { + mOrientationEventListener.enable(); + } else { + mOrientationEventListener.disable(); + } + } + + + private void uninitOrientationEventListener() { + if (mOrientationEventListener != null) { + mOrientationEventListener.disable(); + mOrientationEventListener = null; + } + } + + + static class MediaPlayOrientationEventListener extends OrientationEventListener { + + private WeakReference mWRHandler; + + private int mOrientationEventListenerLastOrientationRequest = NO_ORIENTATION_REQUEST; + + public MediaPlayOrientationEventListener(Context context, int rate, Handler handler) { + super(context, rate); + mWRHandler = new WeakReference(handler); + } + + @Override + public void onOrientationChanged(int orientation) { + + int requestedOrientation = createOrientationRequest(orientation); + if (requestedOrientation != NO_ORIENTATION_REQUEST + && mOrientationEventListenerLastOrientationRequest != requestedOrientation) { + + Handler handler = mWRHandler.get(); + + if (handler != null) { + handler.removeMessages(MSG_REQUEST_ORIENTATION); + Message msg = handler.obtainMessage(MSG_REQUEST_ORIENTATION); + msg.arg1 = requestedOrientation; + handler.sendMessageDelayed(msg, 200); + mOrientationEventListenerLastOrientationRequest = requestedOrientation; + } + } + } + + private int createOrientationRequest(int rotation) { + int requestedOrientation = NO_ORIENTATION_REQUEST; + + if (rotation == -1) { + + } else if (rotation < 10 || rotation > 350) {// 手机顶部向上 + + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + + } else if (rotation < 100 && rotation > 80) {// 手机左边向上 + + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; + + } else if (rotation < 190 && rotation > 170) {// 手机底边向上 + + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; + + } else if (rotation < 280 && rotation > 260) {// 手机右边向上 + + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + } + + return requestedOrientation; + } + + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceRecordListActivity.java b/app/src/main/java/com/lechange/demo/ui/DeviceRecordListActivity.java new file mode 100644 index 0000000..0f5ea51 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceRecordListActivity.java @@ -0,0 +1,110 @@ +package com.lechange.demo.ui; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.common.openapi.MethodConst; +import com.yonsz.z1.R; + +public class DeviceRecordListActivity extends AppCompatActivity implements View.OnClickListener { + + private static final String TAG = DeviceRecordListActivity.class.getSimpleName(); + private TextView tvCloudRecord; + private TextView tvLocalRecord; + private Bundle bundle; + private DeviceCloudRecordListFragment deviceCloudRecordListFragment = DeviceCloudRecordListFragment.newInstance(); + private DeviceLocalRecordListFragment deviceLocalRecordListFragment = DeviceLocalRecordListFragment.newInstance(); + private FragmentManager supportFragmentManager; + private Fragment currentFragment; + public LinearLayout llEdit; + public LinearLayout llAll; + public LinearLayout llBack; + public TextView tvEdit; + private int recordType; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_device_record_list); + supportFragmentManager = getSupportFragmentManager(); + initView(); + initData(); + } + + private void initData() { + bundle = getIntent().getExtras(); + recordType = bundle.getInt(MethodConst.ParamConst.recordType); + if (recordType == MethodConst.ParamConst.recordTypeCloud ? showFragment(deviceCloudRecordListFragment) : showFragment(deviceLocalRecordListFragment)) { + tvCloudRecord.setSelected(recordType == MethodConst.ParamConst.recordTypeCloud); + tvLocalRecord.setSelected(recordType == MethodConst.ParamConst.recordTypeLocal); + } + } + + private void initView() { + findViewById(R.id.ll_back).setOnClickListener(this); + llBack = findViewById(R.id.ll_back); + llEdit = findViewById(R.id.ll_edit); + llAll = findViewById(R.id.ll_all); + tvEdit = findViewById(R.id.tv_edit); + tvCloudRecord = findViewById(R.id.tv_cloud_record); + tvLocalRecord = findViewById(R.id.tv_local_record); + tvCloudRecord.setOnClickListener(this); + tvLocalRecord.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.ll_back) { + finish(); + } else if (id == R.id.tv_cloud_record) { + if (showFragment(deviceCloudRecordListFragment)) { + tvCloudRecord.setSelected(true); + tvLocalRecord.setSelected(false); + } + } else if (id == R.id.tv_local_record) { + if (showFragment(deviceLocalRecordListFragment)) { + tvCloudRecord.setSelected(false); + tvLocalRecord.setSelected(true); + } + } + } + + private boolean showFragment(Fragment fragment) { + if (currentFragment != fragment) { + FragmentTransaction transaction = supportFragmentManager.beginTransaction(); + if (currentFragment != null) { + transaction.hide(currentFragment); + } + currentFragment = fragment; + fragment.setArguments(bundle); + if (!fragment.isAdded()) { + transaction.add(R.id.fr_content, fragment).show(fragment).commit(); + } else { + transaction.show(fragment).commit(); + } + return true; + } + return false; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK && data != null) { + boolean delete = data.getBooleanExtra("data", false); + if (delete && deviceCloudRecordListFragment != null) { + deviceCloudRecordListFragment.deleteCloudRecord(); + } + } + } +} diff --git a/app/src/main/java/com/lechange/demo/ui/DeviceRecordPlayActivity.java b/app/src/main/java/com/lechange/demo/ui/DeviceRecordPlayActivity.java new file mode 100644 index 0000000..54357a8 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/ui/DeviceRecordPlayActivity.java @@ -0,0 +1,1000 @@ +package com.lechange.demo.ui; + +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.drawable.Drawable; +import android.media.MediaScannerConnection; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.common.openapi.ClassInstanceManager; +import com.common.openapi.DeviceRecordService; +import com.common.openapi.IGetDeviceInfoCallBack; +import com.common.openapi.MethodConst; +import com.common.openapi.entity.DeleteCloudRecordsData; +import com.common.openapi.entity.DeviceDetailListData; +import com.common.openapi.entity.RecordsData; +import com.lechange.demo.dialog.EncryptKeyInputDialog; +import com.lechange.demo.tools.DateHelper; +import com.lechange.demo.tools.DialogUtils; +import com.lechange.demo.tools.MediaPlayHelper; +import com.lechange.demo.view.LcProgressBar; +import com.lechange.demo.view.RecoderSeekBar; +import com.lechange.opensdk.listener.LCOpenSDK_DownloadListener; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.media.LCOpenSDK_Download; +import com.lechange.opensdk.media.LCOpenSDK_ParamCloudRecord; +import com.lechange.opensdk.media.LCOpenSDK_ParamDeviceRecord; +import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; +import com.mm.android.deviceaddmodule.LCDeviceEngine; +import com.mm.android.deviceaddmodule.mobilecommon.dialog.LCAlertDialog; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; +import com.yonsz.z1.R; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class DeviceRecordPlayActivity extends AppCompatActivity implements View.OnClickListener, IGetDeviceInfoCallBack.IDeviceDeleteRecordCallBack { + private static final String TAG = DeviceRecordPlayActivity.class.getSimpleName(); + private FrameLayout frLiveWindow, frLiveWindowContent; + private TextView tvDeviceName, tvLoadingMsg, recordStartTime, recordEndTime; + private LinearLayout llFullScreen, llSound, llPlayStyle, llPlayPause, llDelete, llBack, llScreenshot, llVideo; + private ImageView ivPalyPause, ivPlayStyle, ivSound, ivScreenShot, ivVideo; + private ProgressBar pbLoading; + private RelativeLayout rlLoading; + private LcProgressBar pgDownload; + private DeviceDetailListData.ResponseData.DeviceListBean deviceListBean; + private Bundle bundle; + private LCOpenSDK_PlayWindow mPlayWin = new LCOpenSDK_PlayWindow(); + private RecordsData recordsData; + //1 云录像 2 设备录像 + private int recordType; + private RecoderSeekBar recordSeekbar; + private int progress; + private String beginTime; + + private SoundStatus soundStatus = SoundStatus.PLAY; + private PlayStatus playStatus = PlayStatus.PAUSE; + private RecordStatus recordStatus = RecordStatus.STOP; + private DownloadStatus downloadStatus = DownloadStatus.UNBEGIN; + //倍速位置 + private int speedPosition = 0; + //倍速数组 + private int[] speed = {1, 4, 8, 16}; + //倍速图片 + private Drawable[] speedImage = new Drawable[4]; + private DeviceRecordService deviceRecordService = ClassInstanceManager.newInstance().getDeviceRecordService(); + private String totalMb; + private ImageView ivChangeScreen; + private LinearLayout llOperate; + private RelativeLayout rlTitle; + private EncryptKeyInputDialog encryptKeyInputDialog; + private String encryptKey; + private String path; + private LCAlertDialog mLCAlertDialog; + private int passcode; + + public enum LoadStatus { + LOADING, LOAD_SUCCESS, LOAD_ERROR + } + + public enum SoundStatus { + PLAY, STOP, NO_SUPPORT + } + + public enum PlayStatus { + PLAY, PAUSE, ERROR, STOP + } + + public enum RecordStatus { + START, STOP + } + + public enum DownloadStatus { + UNBEGIN, ING, FINISH, ERROR + } + + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCurrentOrientation = getResources().getConfiguration().orientation; + setContentView(R.layout.activity_device_record_play); + initView(); + initData(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) { + LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(frLiveWindow.getLayoutParams()); + DisplayMetrics metric = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + frLiveWindow.setLayoutParams(mLayoutParams); + MediaPlayHelper.quitFullScreen(DeviceRecordPlayActivity.this); + llOperate.setVisibility(View.VISIBLE); + if (recordType == MethodConst.ParamConst.recordTypeLocal) { + pgDownload.setVisibility(View.GONE); + } else { + pgDownload.setVisibility(View.VISIBLE); + } + rlTitle.setVisibility(View.VISIBLE); + } else if (mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE) { + DisplayMetrics metric = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metric); + LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(metric.widthPixels, metric.heightPixels); + mLayoutParams.setMargins(0, 0, 0, 0); + frLiveWindow.setLayoutParams(mLayoutParams); + MediaPlayHelper.setFullScreen(DeviceRecordPlayActivity.this); + llOperate.setVisibility(View.GONE); + pgDownload.setVisibility(View.GONE); + rlTitle.setVisibility(View.GONE); + } + } + + private void initData() { + speedImage[0] = getResources().getDrawable(R.mipmap.play_module_video_1x); + speedImage[1] = getResources().getDrawable(R.mipmap.play_module_video_4x); + speedImage[2] = getResources().getDrawable(R.mipmap.play_module_video_8x); + speedImage[3] = getResources().getDrawable(R.mipmap.play_module_video_16x); + bundle = getIntent().getExtras(); + if (bundle == null) { + return; + } + deviceListBean = (DeviceDetailListData.ResponseData.DeviceListBean) bundle.getSerializable(MethodConst.ParamConst.deviceDetail); + recordsData = (RecordsData) bundle.getSerializable(MethodConst.ParamConst.recordData); + recordType = bundle.getInt(MethodConst.ParamConst.recordType); + tvDeviceName.setText(deviceListBean.channels.get(deviceListBean.checkedChannel).channelName); + if (recordType == MethodConst.ParamConst.recordTypeLocal) { + llDelete.setVisibility(View.GONE); + pgDownload.setVisibility(View.GONE); + totalMb = byte2mb(Long.parseLong(recordsData.fileLength + "")); + } else { + totalMb = byte2mb(Long.parseLong(recordsData.size)); + } + //初始化时间 + initSeekBarAndTime(); + //初始化控件 + initCommonClickListener(); + //播放视频 + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_loading), deviceListBean.deviceId); + } + + @Override + protected void onPause() { + super.onPause(); + pauseAsync(); + playStatus = PlayStatus.PAUSE; + ivPalyPause.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_play)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stop(); + mPlayWin.uninitPlayWindow();// 销毁底层资源 + } + + private void playVideo(String psk) { + if (recordType == MethodConst.ParamConst.recordTypeCloud) { + //云录像 + LCOpenSDK_ParamCloudRecord paramCloudRecord = new LCOpenSDK_ParamCloudRecord( + LCDeviceEngine.newInstance().accessToken, + deviceListBean.deviceId, + Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId), + psk, + deviceListBean.playToken, + recordsData.recordRegionId, + 1000, + 0, + 24 * 3600 + ); + + mPlayWin.playCloud(paramCloudRecord); + } else if (recordType == MethodConst.ParamConst.recordTypeLocal) { + //设备录像 + LCOpenSDK_ParamDeviceRecord paramDeviceRecord = new LCOpenSDK_ParamDeviceRecord( + LCDeviceEngine.newInstance().accessToken, + deviceListBean.deviceId, + Integer.parseInt(deviceListBean.channels.get(deviceListBean.checkedChannel).channelId), + psk, + deviceListBean.playToken, + recordsData.recordId, + DateHelper.parseMills(recordsData.beginTime), + DateHelper.parseMills(recordsData.endTime), + 0, + 0, + true + ); + + mPlayWin.playRtspPlayback(paramDeviceRecord); + } + } + + private void stop() { + stopPlayWindow(); + //禁止拖动 + setCanSeekChanged(false); + } + + /** + * 单独关闭播放 注意:组件要求必须要主线程调用 + */ + private void stopPlayWindow() { + closeAudio();// 关闭音频 + if (recordType == MethodConst.ParamConst.recordTypeCloud) { + mPlayWin.stopCloud(true); + } else { + mPlayWin.stopRtspPlayback(true);// 关闭视频 + } + } + + /** + * 设置拖动进度条是否能使用 + */ + public void setCanSeekChanged(boolean canSeek) { + recordSeekbar.setCanTouchAble(canSeek); + } + + /** + * 开始录像 + */ + public boolean startRecord() { + // 录像的路径 + String videoPath = null; + String channelName = null; + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + channelName = deviceListBean.channels.get(deviceListBean.checkedChannel).channelName; + } else { + channelName = deviceListBean.name; + } + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + videoPath = MediaPlayHelper.getCaptureAndVideoPath(MediaPlayHelper.DHFilesType.DHVideo, channelName); + MediaScannerConnection.scanFile(this, new String[]{videoPath}, null, null); + // 开始录制 1 + int ret = mPlayWin.startRecord(videoPath, 1, 0x7FFFFFFF); + return ret == 0; + } + + /** + * 关闭录像 + */ + public boolean stopRecord() { + return mPlayWin.stopRecord() == 0; + } + + /** + * 截图 + */ + public String capture() { + String captureFilePath = null; + String channelName = null; + if (deviceListBean.channels != null && deviceListBean.channels.size() > 0) { + channelName = deviceListBean.channels.get(deviceListBean.checkedChannel).channelName; + } else { + channelName = deviceListBean.name; + } + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + captureFilePath = MediaPlayHelper.getCaptureAndVideoPath(MediaPlayHelper.DHFilesType.DHImage, channelName); + int ret = mPlayWin.snapShot(captureFilePath); + if (ret == 0) { + // 扫描到相册中 + MediaScannerConnection.scanFile(this, new String[]{captureFilePath}, null, null); + } else { + captureFilePath = null; + } + return captureFilePath; + } + + private void initView() { + frLiveWindow = findViewById(R.id.fr_live_window); + frLiveWindowContent = findViewById(R.id.fr_live_window_content); + llBack = findViewById(R.id.ll_back); + tvDeviceName = findViewById(R.id.tv_device_name); + llDelete = findViewById(R.id.ll_delete); + llPlayPause = findViewById(R.id.ll_paly_pause); + llPlayStyle = findViewById(R.id.ll_play_style); + llSound = findViewById(R.id.ll_sound); + llFullScreen = findViewById(R.id.ll_fullscreen); + ivPalyPause = findViewById(R.id.iv_paly_pause); + ivPlayStyle = findViewById(R.id.iv_play_style); + ivSound = findViewById(R.id.iv_sound); + rlLoading = findViewById(R.id.rl_loading); + pbLoading = findViewById(R.id.pb_loading); + tvLoadingMsg = findViewById(R.id.tv_loading_msg); + recordStartTime = findViewById(R.id.record_startTime); + recordSeekbar = findViewById(R.id.record_seekbar); + recordEndTime = findViewById(R.id.record_endTime); + llScreenshot = findViewById(R.id.ll_screenshot); + llVideo = findViewById(R.id.ll_video); + ivScreenShot = findViewById(R.id.iv_screen_shot); + ivVideo = findViewById(R.id.iv_video); + pgDownload = findViewById(R.id.pg_download); + ivChangeScreen = findViewById(R.id.iv_change_screen); + llOperate = findViewById(R.id.ll_operate); + rlTitle = findViewById(R.id.rl_title); + pgDownload.setText(getResources().getString(R.string.lc_demo_device_record_download)); + // 初始化播放窗口 + LinearLayout.LayoutParams mLayoutParams = (LinearLayout.LayoutParams) frLiveWindow + .getLayoutParams(); + DisplayMetrics metric = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + frLiveWindow.setLayoutParams(mLayoutParams); + mPlayWin.initPlayWindow(this, frLiveWindowContent, 0, false); + setWindowListener(mPlayWin); + mPlayWin.openTouchListener();//开启收拾监听 + } + + private void initCommonClickListener() { + llBack.setOnClickListener(this); + llFullScreen.setOnClickListener(this); + if (recordType == MethodConst.ParamConst.recordTypeCloud) { + llDelete.setOnClickListener(this); + pgDownload.setOnClickListener(this); + LCOpenSDK_Download.setListener(new CloudDownloadListener()); + } + } + + private void featuresClickListener(boolean loadSuccess) { + llPlayStyle.setOnClickListener(loadSuccess ? this : null); + llPlayPause.setOnClickListener(loadSuccess ? this : null); + llSound.setOnClickListener(loadSuccess ? this : null); + ivScreenShot.setOnClickListener(loadSuccess ? this : null); + ivVideo.setOnClickListener(loadSuccess ? this : null); + ivPalyPause.setImageDrawable(loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause_disable)); + ivSound.setImageDrawable(loadSuccess ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off_disable)); + ivScreenShot.setImageDrawable(loadSuccess ? getDrawable(R.drawable.lc_demo_photo_capture_selector) : getDrawable(R.mipmap.lc_demo_livepreview_icon_screenshot_disable)); + ivVideo.setImageDrawable(loadSuccess ? getDrawable(R.mipmap.lc_demo_livepreview_icon_video) : getDrawable(R.mipmap.lc_demo_livepreview_icon_video_disable)); + //媒体声 + if (soundStatus != SoundStatus.PLAY) { + return; + } + if (openAudio()) { + soundStatus = SoundStatus.PLAY; + ivSound.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_on)); + } + } + + private void initSeekBarAndTime() { + String startTime = recordsData.beginTime.substring(11); + String endTime = recordsData.endTime.substring(11); + recordSeekbar.setMax((int) ((DateHelper.parseMills(recordsData.endTime) - DateHelper.parseMills(recordsData.beginTime)) / 1000)); + recordSeekbar.setProgress(0); + recordStartTime.setText(startTime); + recordEndTime.setText(endTime); + } + + + private void setSeekBarListener() { + recordSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + if (recordSeekbar.getMax() - DeviceRecordPlayActivity.this.progress <= 2) { + seek(recordSeekbar.getMax() >= 2 ? recordSeekbar.getMax() - 2 : 0); + } else { + seek(DeviceRecordPlayActivity.this.progress); + } + + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean byUser) { + if (byUser) { + DeviceRecordPlayActivity.this.progress = progress; + } + } + }); + } + + /** + * 继续播放(异步) + */ + public void resumeAsync() { + mPlayWin.resumeAsync(); + } + + /** + * 暂停播放(异步) + */ + public void pauseAsync() { + mPlayWin.pauseAsync(); + } + + public boolean openAudio() { + return mPlayWin.playAudio() == 0; + } + + public boolean closeAudio() { + return mPlayWin.stopAudio() == 0; + } + + public void seek(int index) { + long seekTime = DateHelper.parseMills(recordsData.beginTime) / 1000 + index; + //先暂存时间记录 + beginTime = DateHelper.getTimeHMS(seekTime * 1000); + this.progress = index; + recordSeekbar.setProgress(index); + recordStartTime.setText(this.beginTime); + mPlayWin.seek(index); + } + + private int mCurrentOrientation; + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.ll_back) { + if (downloadStatus == DownloadStatus.ING) { + LCAlertDialog.Builder builder = new LCAlertDialog.Builder(this); + builder.setTitle(R.string.lc_demo_device_delete_exit); + builder.setMessage(R.string.lc_demo_device_delete_exit_tip); + builder.setCancelButton(com.mm.android.deviceaddmodule.R.string.common_cancel, null); + builder.setConfirmButton(com.mm.android.deviceaddmodule.R.string.common_confirm, + new LCAlertDialog.OnClickListener() { + @Override + public void onClick(LCAlertDialog dialog, int which, boolean isChecked) { + stopDownLoad(); + finish(); + } + }); + mLCAlertDialog = builder.create(); + mLCAlertDialog.show(getSupportFragmentManager(), "exit"); + return; + } + finish(); + } else if (id == R.id.ll_fullscreen) { + //横竖屏切换 + if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + mCurrentOrientation = Configuration.ORIENTATION_LANDSCAPE; + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + mCurrentOrientation = Configuration.ORIENTATION_PORTRAIT; + } + ivChangeScreen.setImageDrawable(mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE ? getResources().getDrawable(R.mipmap.live_btn_smallscreen) : getResources().getDrawable(R.mipmap.video_fullscreen)); + } else if (id == R.id.pg_download) { + //下载 + if (downloadStatus == DownloadStatus.ING || downloadStatus == DownloadStatus.FINISH) { + return; + } + pgDownloadProgress( + getResources().getString(R.string.lc_demo_device_record_download_begin), + 0, + 100, + getResources().getColor(R.color.lc_demo_color_ffffff)); + downloadStatus = DownloadStatus.ING; + startDownload(); + } else if (id == R.id.ll_play_style) { + if (speedPosition == 3) { + speedPosition = 0; + } else { + speedPosition = speedPosition + 1; + } + ivPlayStyle.setImageDrawable(speedImage[speedPosition]); + mPlayWin.setPlaySpeed(speed[speedPosition]); + } else if (id == R.id.ll_delete) { + LCAlertDialog.Builder builder = new LCAlertDialog.Builder(this); + builder.setTitle(R.string.lc_demo_device_delete_sure); + builder.setMessage(""); + builder.setCancelButton(com.mm.android.deviceaddmodule.R.string.common_cancel, null); + builder.setConfirmButton(com.mm.android.deviceaddmodule.R.string.common_confirm, + new LCAlertDialog.OnClickListener() { + @Override + public void onClick(LCAlertDialog dialog, int which, boolean isChecked) { + //删除 + DialogUtils.show(DeviceRecordPlayActivity.this); + DeleteCloudRecordsData deleteCloudRecordsData = new DeleteCloudRecordsData(); + List recordRegionIds = new ArrayList<>(); + recordRegionIds.add(recordsData.recordRegionId); + deleteCloudRecordsData.data.recordRegionIds = recordRegionIds; + deviceRecordService.deleteCloudRecords(deleteCloudRecordsData, DeviceRecordPlayActivity.this); + } + }); + mLCAlertDialog = builder.create(); + mLCAlertDialog.show(getSupportFragmentManager(), "delete"); + } else if (id == R.id.ll_paly_pause) { + //播放暂停 重新播放 + if (playStatus == PlayStatus.PLAY) { + pauseAsync(); + featuresClickListener(false); + llPlayPause.setOnClickListener(this); + playStatus = (playStatus == PlayStatus.PLAY) ? PlayStatus.PAUSE : PlayStatus.PLAY; + ivPalyPause.setImageDrawable(playStatus == PlayStatus.PLAY ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_play)); + } else if (playStatus == PlayStatus.PAUSE) { + resumeAsync(); + featuresClickListener(true); + llPlayPause.setOnClickListener(this); + playStatus = (playStatus == PlayStatus.PLAY) ? PlayStatus.PAUSE : PlayStatus.PLAY; + ivPalyPause.setImageDrawable(playStatus == PlayStatus.PLAY ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_pause) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_play)); + } else { + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_change), TextUtils.isEmpty(encryptKey) ? deviceListBean.deviceId : encryptKey); + } + } else if (id == R.id.ll_sound) { + //媒体声 如果是开启去关闭,反之 + if (soundStatus == SoundStatus.NO_SUPPORT) { + return; + } + boolean result = false; + if (soundStatus == SoundStatus.PLAY) { + result = closeAudio(); + } else { + result = openAudio(); + } + if (!result) { + return; + } + soundStatus = (soundStatus == SoundStatus.PLAY) ? SoundStatus.STOP : SoundStatus.PLAY; + ivSound.setImageDrawable(soundStatus == SoundStatus.PLAY ? getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_on) : getDrawable(R.mipmap.lc_demo_live_video_icon_h_sound_off)); + } else if (id == R.id.iv_screen_shot) { + //截图 + if (capture() != null) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_capture_success), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_capture_failed), Toast.LENGTH_SHORT).show(); + } + } else if (id == R.id.iv_video) { + if (playStatus != PlayStatus.PLAY) { + return; + } + //录像 如果是关闭状态去打开,反之 + if (recordStatus == RecordStatus.STOP) { + if (startRecord()) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_record_begin), Toast.LENGTH_SHORT).show(); + } else { + return; + } + } else { + if (stopRecord()) { + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_record_stop), Toast.LENGTH_SHORT).show(); + } else { + return; + } + } + recordStatus = (recordStatus == RecordStatus.START) ? RecordStatus.STOP : RecordStatus.START; + ivVideo.setImageDrawable(recordStatus == RecordStatus.START ? getDrawable(R.mipmap.lc_demo_livepreview_icon_video_ing) : getDrawable(R.mipmap.lc_demo_livepreview_icon_video)); + } + } + + private void setWindowListener(LCOpenSDK_PlayWindow playWin) { + playWin.setWindowListener(new LCOpenSDK_EventListener() { + //手势缩放开始事件 + @Override + public void onZoomBegin(int index) { + super.onZoomBegin(index); + LogUtil.debugLog(TAG, "onZoomBegin: index= " + index); + } + + //手势缩放中事件 + @Override + public void onZooming(int index, float dScale) { + super.onZooming(index, dScale); + LogUtil.debugLog(TAG, "onZooming: index= " + index + " , dScale= " + dScale); + mPlayWin.doScale(dScale); + } + + //缩放结束事件 + @Override + public void onZoomEnd(int index, ZoomType zoomType) { + super.onZoomEnd(index, zoomType); + LogUtil.debugLog(TAG, "onZoomEnd: index= " + index + " , zoomType= " + zoomType); + } + + //窗口单击事件 + @Override + public void onControlClick(int index, float dx, float dy) { + super.onControlClick(index, dx, dy); + LogUtil.debugLog(TAG, "onControlClick: index= " + index + " , dx= " + dx + " , dy= " + dy); + } + + //窗口双击事件 + @Override + public void onWindowDBClick(int index, float dx, float dy) { + super.onWindowDBClick(index, dx, dy); + LogUtil.debugLog(TAG, "onWindowDBClick: index= " + index + " , dx= " + dx + " , dy= " + dy); + } + + //滑动开始事件 + @Override + public boolean onSlipBegin(int index, Direction direction, float dx, float dy) { + LogUtil.debugLog(TAG, "onSlipBegin: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + return super.onSlipBegin(index, direction, dx, dy); + } + + //滑动中事件 + @Override + public void onSlipping(int index, Direction direction, float prex, float prey, float dx, float dy) { + super.onSlipping(index, direction, prex, prey, dx, dy); + LogUtil.debugLog(TAG, "onSlipping: index= " + index + " , direction= " + direction + " , prex= " + prex + " , prey= " + prey + " , dx= " + dx + " , dy= " + dy); + } + + //滑动结束事件 + @Override + public void onSlipEnd(int index, Direction direction, float dx, float dy) { + super.onSlipEnd(index, direction, dx, dy); + LogUtil.debugLog(TAG, "onSlipEnd: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + } + + //长按开始回调 + @Override + public void onWindowLongPressBegin(int index, Direction direction, float dx, float dy) { + super.onWindowLongPressBegin(index, direction, dx, dy); + LogUtil.debugLog(TAG, "onWindowLongPressBegin: index= " + index + " , direction= " + direction + " , dx= " + dx + " , dy= " + dy); + } + + //长按事件结束 + @Override + public void onWindowLongPressEnd(int index) { + super.onWindowLongPressEnd(index); + LogUtil.debugLog(TAG, "onWindowLongPressEnd: index= " + index); + } + + /** + * 播放事件回调 + * resultSource: 0--RTSP 1--HLS 5--DHHTTP 99--OPENAPI + */ + @Override + public void onPlayerResult(int index, String code, int resultSource) { + super.onPlayerResult(index, code, resultSource); + LogUtil.debugLog(TAG, "onPlayerResult: index= " + index + " , code= " + code + " , resultSource= " + resultSource); + boolean failed = false; + + if (resultSource == 99) { + //code -1000 HTTP交互出错或超时 + failed = true; + } else if (resultSource == 1) { + //云录像 + if (code.equals("0") || code.equals("4") || code.equals("7") || code.equals("11") || code.equals("14")) { + failed = true; + } + if (code.equals("11")) { + showInputKey(); + } + if (code.equals("14")) { + passcode = 1; + showInputKey(); + } + } else if (resultSource == 0) { + //设备录像 + if (code.equals("0") || code.equals("1") || code.equals("3") || code.equals("7")) { + failed = true; + } + if (code.equals("7")) { + showInputKey(); + } + } else if (resultSource == 5) { + //设备录像 + if (!(code.equals("1000") || code.equals("0") || code.equals("2000") || code.equals("4000"))) { + failed = true; + } + if (code.equals("1000005")) { + showInputKey(); + } + } + if (failed) { + loadingStatus(LoadStatus.LOAD_ERROR, getResources().getString(R.string.lc_demo_device_video_play_error) + ":" + code + "." + resultSource, ""); + } + } + + //分辨率改变事件 + @Override + public void onResolutionChanged(int index, int width, int height) { + super.onResolutionChanged(index, width, height); + LogUtil.debugLog(TAG, "onResolutionChanged: index= " + index + " , width= " + width + " , height= " + height); + } + + //播放开始回调 + @Override + public void onPlayBegan(int index) { + super.onPlayBegan(index); + LogUtil.debugLog(TAG, "onPlayBegan: index= " + index); + loadingStatus(LoadStatus.LOAD_SUCCESS, "", ""); + } + + //接收数据回调 + @Override + public void onReceiveData(int index, int len) { + super.onReceiveData(index, len); + // LogUtil.debugLog(TAG, "onReceiveData: index= " + index + " , len= " + len); + } + + //接收帧流回调 + @Override + public void onStreamCallback(int index, byte[] bytes, int len) { + super.onStreamCallback(index, bytes, len); + LogUtil.debugLog(TAG, "onStreamCallback: index= " + index + " , len= " + len); + } + + //播放结束事件 + @Override + public void onPlayFinished(int index) { + super.onPlayFinished(index); + LogUtil.debugLog(TAG, "onPlayFinished: index= " + index); + runOnUiThread(new Runnable() { + @Override + public void run() { + stop(); + playStatus = PlayStatus.STOP; + featuresClickListener(false); + speedPosition = 0; + ivPlayStyle.setImageDrawable(speedImage[0]); + llPlayPause.setOnClickListener(DeviceRecordPlayActivity.this); + ivPalyPause.setImageDrawable(getDrawable(R.mipmap.lc_demo_live_video_icon_h_play)); + } + }); + } + + //播放时间信息回调 + @Override + public void onPlayerTime(int index, final long current) { + super.onPlayerTime(index, current); + LogUtil.debugLog(TAG, "onPlayerTime: index= " + index + " , time= " + current); + + long startTime = DateHelper.parseMills(recordsData.beginTime) / 1000; + DeviceRecordPlayActivity.this.progress = (int) (current - startTime); + LogUtil.debugLog(TAG, "onPlayerTime: progress= " + DeviceRecordPlayActivity.this.progress); + runOnUiThread(new Runnable() { + @Override + public void run() { + recordSeekbar.setProgress(DeviceRecordPlayActivity.this.progress); + DeviceRecordPlayActivity.this.beginTime = DateHelper.getTimeHMS(current * 1000); + recordStartTime.setText(DeviceRecordPlayActivity.this.beginTime); + } + }); + + } + + + }); + } + + private void showInputKey() { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (encryptKeyInputDialog == null) { + encryptKeyInputDialog = new EncryptKeyInputDialog(DeviceRecordPlayActivity.this); + } + encryptKeyInputDialog.show(); + if (1 == passcode) { + encryptKeyInputDialog.setText(getText(R.string.lc_demo_device_encrypt_device_password_tip).toString()); + } else { + encryptKeyInputDialog.setText(getText(R.string.lc_demo_device_encrypt_key_tip).toString()); + } + encryptKeyInputDialog.setOnClick(new EncryptKeyInputDialog.OnClick() { + @Override + public void onSure(String txt) { + encryptKey = txt; + loadingStatus(LoadStatus.LOADING, getResources().getString(R.string.lc_demo_device_video_play_change), txt); + } + }); + } + }); + } + + private void showInputKeyEx() { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (encryptKeyInputDialog == null) { + encryptKeyInputDialog = new EncryptKeyInputDialog(DeviceRecordPlayActivity.this); + } + encryptKeyInputDialog.show(); + if (1 == passcode) { + encryptKeyInputDialog.setText(getText(R.string.lc_demo_device_encrypt_device_password_tip).toString()); + } else { + encryptKeyInputDialog.setText(getText(R.string.lc_demo_device_encrypt_key_tip).toString()); + } + encryptKeyInputDialog.setOnClick(new EncryptKeyInputDialog.OnClick() { + @Override + public void onSure(String txt) { + encryptKey = txt; + path = MediaPlayHelper.getDownloadVideoPath(0, recordsData.recordId, DateHelper.parseMills(recordsData.beginTime)); + LCOpenSDK_Download.startDownload(0, + path, + LCDeviceEngine.newInstance().accessToken, + recordsData.recordRegionId, + recordsData.deviceId, + String.valueOf(0), + txt, + 1000, + 5000); + } + }); + } + }); + } + + /** + * 播放状态 + * + * @param loadStatus 播放状态 + * @param msg + */ + private void loadingStatus(final LoadStatus loadStatus, final String msg, final String psk) { + runOnUiThread(new Runnable() { + @Override + public void run() { + if (loadStatus == LoadStatus.LOADING) { + //先关闭 + stop(); + //开始播放 + playVideo(psk); + rlLoading.setVisibility(View.VISIBLE); + pbLoading.setVisibility(View.VISIBLE); + tvLoadingMsg.setText(msg); + //禁止拖动 + setCanSeekChanged(false); + + } else if (loadStatus == LoadStatus.LOAD_SUCCESS) { + //播放成功 + rlLoading.setVisibility(View.GONE); + //允许拖动 + setCanSeekChanged(true); + //SeekBar监听 + setSeekBarListener(); + playStatus = PlayStatus.PLAY; + //mPlayWin.setSEnhanceMode(4);//设置降噪等级最大 + featuresClickListener(true); + } else { + //播放失败 + stop(); + rlLoading.setVisibility(View.VISIBLE); + pbLoading.setVisibility(View.GONE); + tvLoadingMsg.setText(msg); + //禁止拖动 + setCanSeekChanged(false); + playStatus = PlayStatus.ERROR; + featuresClickListener(false); + } + } + }); + } + + private void startDownload() { + path = MediaPlayHelper.getDownloadVideoPath(0, recordsData.recordId, DateHelper.parseMills(recordsData.beginTime)); + LCOpenSDK_Download.startDownload(0, + path, + LCDeviceEngine.newInstance().accessToken, + recordsData.recordRegionId, + recordsData.deviceId, + String.valueOf(0), + recordsData.deviceId, + 1000, + 5000); + } + + private void stopDownLoad() { + LCOpenSDK_Download.stopDownload(0); + //更新數據到相冊 + MediaPlayHelper.updatePhotoVideo(path); + } + + private int downloadProgress; + + private class CloudDownloadListener extends LCOpenSDK_DownloadListener { + @Override + public void onDownloadReceiveData(int index, final int dataLen) { + LogUtil.debugLog(TAG, "CloudDownloadListener----" + "index=" + index + ", dataLen=" + dataLen); + if (downloadStatus == DownloadStatus.ING) { + downloadProgress = downloadProgress + dataLen; + runOnUiThread(new Runnable() { + @Override + public void run() { + pgDownloadProgress( + getResources().getString(R.string.lc_demo_device_record_download_begin) + byte2mb(downloadProgress) + "MB/" + totalMb + "M", + (int) ((float) downloadProgress / (float) Long.parseLong(recordsData.size) * 100), + 100, + getResources().getColor(R.color.lc_demo_color_ffffff)); + + } + }); + } + } + + @Override + public void onDownloadState(int index, String code, int type) { + LogUtil.debugLog(TAG, "CloudDownloadListener----" + "index=" + index + ", code=" + code + ", type=" + type); + if (type == 99 || code.equals("0") || code.equals("4") || code.equals("7") || code.equals("8")) { + //下载出错 + downloadStatus = DownloadStatus.ERROR; + runOnUiThread(new Runnable() { + @Override + public void run() { + pgDownloadProgress(getResources().getString(R.string.lc_demo_device_record_download_error), + 0, + 0, + getResources().getColor(R.color.lc_demo_color_FF4F4F)); + downloadProgress = 0; + } + }); + } + if (code.equals("14")) { + passcode = 1; + } + if (code.equals("11") || code.equals("14")) { + //下载出错 + downloadStatus = DownloadStatus.ERROR; + showInputKeyEx(); + } + if (type == 1 && code.equals("1")) { + //开始下载 + downloadStatus = DownloadStatus.ING; + } + + if (type == 1 && code.equals("2")) { + //下载完成 + downloadStatus = DownloadStatus.FINISH; + // MediaScannerConnection.scanFile(DeviceRecordPlayActivity.this, new String[]{path}, null, null); + MediaPlayHelper.updatePhotoVideo(path); + runOnUiThread(new Runnable() { + @Override + public void run() { + pgDownloadProgress(getResources().getString(R.string.lc_demo_device_record_download_finish), + 100, + 100, + getResources().getColor(R.color.lc_demo_color_ffffff)); + downloadProgress = 0; + } + }); + } + } + } + + private void pgDownloadProgress(String tip, int progress, int secondProgress, int textColor) { + pgDownload.setText(tip); + pgDownload.setProgress(progress); + pgDownload.setSecondaryProgress(secondProgress); + pgDownload.setTextColor(textColor); + } + + @Override + public void deleteDeviceRecord() { + DialogUtils.dismiss(); + Toast.makeText(this, getResources().getString(R.string.lc_demo_device_record_delete_success), Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(); + intent.putExtra("data", true); + setResult(RESULT_OK, intent); + finish(); + } + + @Override + public void onError(Throwable throwable) { + DialogUtils.dismiss(); + Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_SHORT).show(); + } + + private String byte2mb(long b) { + double mb = (double) b / 1024 / 1024; + DecimalFormat decimalFormat = new DecimalFormat("0.00"); + return decimalFormat.format(mb); + } +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/ContainerAdapter.java b/app/src/main/java/com/lechange/demo/videoplay/ContainerAdapter.java new file mode 100644 index 0000000..af20bd8 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/ContainerAdapter.java @@ -0,0 +1,102 @@ +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.support.constraint.ConstraintLayout; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; +import com.yonsz.z1.R; + +import java.util.List; + +public class ContainerAdapter extends RecyclerView.Adapter { + private String TAG = getClass().getSimpleName(); + private LCOpenSDK_EventListener videoPlayerListener; + private List mData; + private Context mContext; + + private ConstraintLayout.LayoutParams layoutParams; + + public ContainerAdapter(Context mContext, List datas) { + this.mData = datas; + this.mContext = mContext; + } + + @Override + public ContainerHoler onCreateViewHolder(ViewGroup parent, int viewType) { + View rootView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_container, parent, false); + ContainerHoler containerHoler = new ContainerHoler(rootView); + layoutParams = new ConstraintLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParams.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID; + return containerHoler; + } + + @Override + public void onBindViewHolder(final ContainerHoler holder, int position) { + // final VideoBean videoBean = mData.get(position); + // holder.pqVideoPlayer.setId(videoBean.getId()); + // holder.pqVideoPlayer.setFocus(videoBean.isSelect()); + // holder.pqVideoPlayer.setVideoPlayerListener(videoPlayerListener); + // holder.pqVideoPlayer.setPqVideoOnclickListener(new PqVideoPlayer.PqVideoOnclickListener() { + // @Override + // public void onClick() { + // refreshSelect(videoBean); + // } + // }); + /*pqVideoPlayer.setVideoPlayerListener(videoPlayerListener); + pqVideoPlayer.setPqVideoOnclickListener(new PqVideoPlayer.PqVideoOnclickListener() { + @Override + public void onClick() { + refreshSelect(pqVideoPlayer); + } + });*/ + holder.setViews(position); + } + + private void refreshSelect(LCOpenSDK_PlayWindow videoBean) { + Log.d(TAG, "refreshSelect: "); + /*for (LCOpenSDK_PlayWindow vb : mData) { + vb.setFocus(vb == videoBean); + }*/ + // notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mData.size(); + } + + public void setVideoPlayerListener(LCOpenSDK_EventListener videoPlayerListener) { + this.videoPlayerListener = videoPlayerListener; + } + + public class ContainerHoler extends RecyclerView.ViewHolder { + // private PqVideoPlayer pqVideoPlayer; + private ViewGroup constraintLayout; + private FrameLayout frame_content; + + public ContainerHoler(View itemView) { + super(itemView); + // pqVideoPlayer = itemView.findViewById(R.id.pq_video_player); + constraintLayout = (ConstraintLayout) itemView.findViewById(R.id.container); + } + + public void setViews(final int position) { + final VideoPlayOnlineFragment pqVideoPlayer = mData.get(position); + /*constraintLayout.addView(pqVideoPlayer, 0, layoutParams); + getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, pqVideoPlayer) + .commitAllowingStateLoss();*/ + // constraintLayout.addView(pqVideoPlayer, 0, layoutParams); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayer.java b/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayer.java new file mode 100644 index 0000000..5390205 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayer.java @@ -0,0 +1,688 @@ +/* +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.SurfaceTexture; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.TextureView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yonsz.z1.R; +import com.yonsz.z1.utils.DensityUtil; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +*/ +/** + * 描述:自定义播放器 + * + * @author :chezi008 on 2017/11/21 15:41 + * 邮箱:chezi008@163.com + *//* + + +public class PqVideoPlayer extends RelativeLayout implements View.OnClickListener, PqVideoPlayerZoomIn.PqZoomOutVideoListener { + + public static final int HANDLER_SET_STATUS_DEAULT = 0; + public static final int HANDLER_SET_STATUS_PLAYING = 1; + public static final int HANDLER_UPDATE_BPS = 2; + public static final int HANDLER_UPDATE_LOSS_FRAME = 3; + private static final int CORE_POOL_SIZE = 5; + private static final int MAXIMUM_POOL_SIZE = 10; + private static final int KEEP_ALIVE_TIME = 60000; + */ +/** + * 默认边框大小 + *//* + + private final int DEFAULT_BORDER_SIZE = 1; + private final int DEFALUT_BORDER_COLOR = Color.parseColor("#00000000"); + //自定义属性 1、选中时候边框大小 2、选中边框颜色 + //3、默认背景色 4、选中背景色 + // 5、资源添加icon + */ +/** + * 默认背景 + *//* + + private final int DEFAULT_BG_COLOR = Color.parseColor("#6b7e9e"); + private final int DEFAULT_BG_SELECT_COLOR = Color.parseColor("#FFFFFF"); + */ +/** + * 默认添加资源图片 + *//* + + private final int DEFAULT_RES_ICON = R.mipmap.vp_ic_res_add; + private final int DEFAULT_FULL_SCREEN_ICON = R.mipmap.vp_ic_full_screen; + private final int DEFAULT_STOP_ICON = R.mipmap.vp_ic_stop_play; + private ArrayBlockingQueue mArrayBlockingQueue; + private String TAG = getClass().getSimpleName(); + */ +/** + * 选中边框 + *//* + + private int mBorderSize, mBorderColor; + private int mBgColor, mBgSelectColor; + private int mResIcon, mFullIcon, mStopIcon; + + private RelativeLayout mRlBorderBg, mRlVideoBg, mTextureParent, mRlBottomBar; + private TextureView mTextureView; + private SurfaceTexture mSurfaceTexture; + private TextureView.SurfaceTextureListener mSurfaceTextureListener; + + private ProgressBar mProcessBar; + private TextView mTvPath, mTvLoss; + private ImageView ivResAdd; + + */ +/** + * 解码器 + *//* + + private PqVideoDecoder mVideoDecoder; + */ +/** + * 线程池 + *//* + + private ThreadPoolExecutor mExecutorService; + private ScheduledExecutorService mScheduledExecutorService; + private Runnable mScheduleRunable; + private H264ReadRunable mH264ReadRunable; + + private boolean isFullScreen, isFoucsed, isZoomIn; + */ +/** + * 码流统计 + *//* + + private Handler mMainHandler; + + private VideoPlayerListener videoPlayerListener; + private PqVideoOnclickListener mPqVideoOnclickListener; + + private PlayerViewState curState; + private long[] mHits = new long[2]; + + public PqVideoPlayer(Context context) { + this(context, null); + } + + + public PqVideoPlayer(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PqVideoPlayer); + mBorderSize = ta.getInt(R.styleable.PqVideoPlayer_vp_border_size, DEFAULT_BORDER_SIZE); + mBorderColor = ta.getColor(R.styleable.PqVideoPlayer_vp_border_color, DEFALUT_BORDER_COLOR); + mBgColor = ta.getColor(R.styleable.PqVideoPlayer_vp_bg_default_color, DEFAULT_BG_COLOR); + mBgSelectColor = ta.getColor(R.styleable.PqVideoPlayer_vp_bg_select_color, DEFAULT_BG_SELECT_COLOR); + mResIcon = ta.getResourceId(R.styleable.PqVideoPlayer_vp_res_icon, DEFAULT_RES_ICON); + mFullIcon = ta.getResourceId(R.styleable.PqVideoPlayer_vp_fullscreen_icon, DEFAULT_FULL_SCREEN_ICON); + mStopIcon = ta.getResourceId(R.styleable.PqVideoPlayer_vp_stop_icon, DEFAULT_STOP_ICON); + + initVirable(); + initView(); + } + + public void setVideoPlayerListener(VideoPlayerListener videoPlayerListener) { + this.videoPlayerListener = videoPlayerListener; + } + + public void setPqVideoOnclickListener(PqVideoOnclickListener mPqVideoOnclickListener) { + this.mPqVideoOnclickListener = mPqVideoOnclickListener; + } + + private void initVirable() { + mArrayBlockingQueue = new ArrayBlockingQueue(MAXIMUM_POOL_SIZE); + mExecutorService = new ThreadPoolExecutor(CORE_POOL_SIZE, + MAXIMUM_POOL_SIZE, + KEEP_ALIVE_TIME, + TimeUnit.MILLISECONDS, mArrayBlockingQueue); + mScheduledExecutorService = new ScheduledThreadPoolExecutor(1); + + if (mMainHandler == null) { + mMainHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case HANDLER_SET_STATUS_DEAULT: + setDefaultUI(); + break; + case HANDLER_SET_STATUS_PLAYING: + setPlayerViewState(PlayerViewState.Playying); + break; + case HANDLER_UPDATE_BPS: + // if (videoPlayerFullScreenListener != null) { + // videoPlayerFullScreenListener.onGetBps((String) msg.obj); + // } + break; + //播放器丢包率更新 + case HANDLER_UPDATE_LOSS_FRAME: + mTvLoss.setText((String) msg.obj); + // if (videoPlayerFullScreenListener != null) { + // videoPlayerFullScreenListener.onGetLossFrame((String) msg.obj); + // } + break; + default: + break; + } + } + }; + } + } + + */ +/** + * 初始化视图 + *//* + + private void initView() { + //设置屏幕常亮 + setKeepScreenOn(true); + //添加选中的边框 + LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mRlBorderBg = new RelativeLayout(getContext()); + mRlBorderBg.setBackgroundColor(mBorderColor); + mRlBorderBg.setPadding(mBorderSize, mBorderSize, mBorderSize, mBorderSize); + addView(mRlBorderBg, layoutParams); + //添加播放器背景 + layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mRlVideoBg = new RelativeLayout(getContext()); + mRlVideoBg.setBackgroundColor(mBgColor); + mRlBorderBg.addView(mRlVideoBg, layoutParams); + + //添加播放器显示界面 + layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mTextureParent = new RelativeLayout(getContext()); + mTextureParent.setBackgroundColor(Color.BLACK); + mTextureParent.setVisibility(GONE); + mRlVideoBg.addView(mTextureParent, layoutParams); + + //添加添加资源图标 + layoutParams = new LayoutParams(DensityUtil.sp2px(getContext(), 35), + DensityUtil.sp2px(getContext(), 35)); + layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); + ivResAdd = new ImageView(getContext()); + ivResAdd.setImageResource(mResIcon); + ivResAdd.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + ivResAdd.setId(R.id.iv_res_add); + ivResAdd.setOnClickListener(this); + mRlVideoBg.addView(ivResAdd, layoutParams); + //添加progres + mProcessBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyle); + mRlVideoBg.addView(mProcessBar, layoutParams); + mProcessBar.setVisibility(GONE); + + // addTextureView(); + + //添加播放器控制栏 + //底部白色背景 + LayoutParams layoutParamsInner = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + mRlBottomBar = new RelativeLayout(getContext()); + mRlBottomBar.setBackgroundColor(Color.WHITE); + mRlBottomBar.getBackground().setAlpha(128); + mRlBottomBar.setGravity(CENTER_VERTICAL); + layoutParamsInner.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + mRlVideoBg.addView(mRlBottomBar, layoutParamsInner); + mRlBottomBar.setVisibility(GONE); + //全屏 + int btnWidth = DensityUtil.sp2px(getContext(), 25); + int btnPadding = DensityUtil.sp2px(getContext(), 3); + LayoutParams layoutParamsFullScreen = new LayoutParams(btnWidth, btnWidth); + layoutParamsFullScreen.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + ImageView ivFull = new ImageView(getContext()); + ivFull.setId(R.id.btnFullScreen); + + ivFull.setPadding(btnPadding, btnPadding, btnPadding, btnPadding); + ivFull.setImageResource(mFullIcon); + ivFull.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + ivFull.setOnClickListener(this); + mRlBottomBar.addView(ivFull, layoutParamsFullScreen); + //停止 + LayoutParams layoutParamsStopVideo = new LayoutParams(btnWidth, btnWidth); + layoutParamsStopVideo.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + ImageView ivStop = new ImageView(getContext()); + ivStop.setId(R.id.btnStop); + ivStop.setPadding(btnPadding, btnPadding, btnPadding, btnPadding); + ivStop.setImageResource(mStopIcon); + ivStop.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + ivStop.setOnClickListener(this); + mRlBottomBar.addView(ivStop, layoutParamsStopVideo); + + //设备路径信息 + LinearLayout llPath = new LinearLayout(getContext()); + llPath.setId(R.id.tvDeviceInfo); + mTvPath = new TextView(getContext()); + mTvPath.setTextColor(Color.WHITE); + mTvPath.setTextSize(8); + mTvPath.setSingleLine(true); + mTvPath.setText("轮播字"); + mTvPath.setEllipsize(TextUtils.TruncateAt.MARQUEE); + mTvPath.setMarqueeRepeatLimit(-1); + mTvPath.setSelected(true); + llPath.addView(mTvPath); + + LayoutParams layoutParamsDevicePathTextView = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParamsDevicePathTextView.setMargins(btnPadding, btnPadding, btnPadding, btnPadding); + layoutParamsDevicePathTextView.addRule(RIGHT_OF, R.id.btnStop); + layoutParamsDevicePathTextView.addRule(RelativeLayout.LEFT_OF, R.id.tvLossFrame); + layoutParamsDevicePathTextView.addRule(CENTER_VERTICAL); + mRlBottomBar.addView(llPath, layoutParamsDevicePathTextView); + + //丢包率 + mTvLoss = new TextView(getContext()); + mTvLoss.setId(R.id.tvLossFrame); + mTvLoss.setTextColor(Color.WHITE); + mTvLoss.setTextSize(8); + mTvLoss.setLines(1); + mTvLoss.setText("0.00%"); + LayoutParams rlLoss = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + rlLoss.setMargins(btnPadding, btnPadding, btnPadding, btnPadding); + rlLoss.addRule(RelativeLayout.LEFT_OF, R.id.btnFullScreen); + rlLoss.addRule(CENTER_VERTICAL); + mRlBottomBar.addView(mTvLoss, rlLoss); + + setPlayerViewState(PlayerViewState.Default); + // setPlayerViewState(PlayerViewState.Playying); + } + + private void initTextureView() { + if (mTextureView == null) { + mTextureView = new VideoTextureView(getContext()); + mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + Log.d(TAG, "onSurfaceTextureAvailable: "); + //检查解码器是否初始化 + if (!initDecoder(surface)) { + Log.d(TAG, "onSurfaceTextureAvailable: init decoder failed!"); + return; + } + if (mH264ReadRunable != null) { + Log.d(TAG, "onSurfaceTextureAvailable: 读取视频流"); + mExecutorService.execute(mH264ReadRunable); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + Log.d(TAG, "onSurfaceTextureDestroyed: "); + // stopDecoder(); + mSurfaceTexture = surface; + if (isZoomIn) { + videoPlayerListener.onChangeSurface(surface); + } + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + + } + }); + + } + } + + */ +/** + * 添加显示画面 + *//* + + private void addTextureView() { + Log.d(TAG, "addTextureView: ----------->"); + LayoutParams textureParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + textureParams.addRule(RelativeLayout.CENTER_IN_PARENT); + if (mTextureParent.getChildCount() > 0) { + throw new IllegalStateException("已经添加了显示控件!"); + } + //不能添加空控件 播放器setPlaying的时候会添加 + mTextureParent.addView(mTextureView, textureParams); + mTextureParent.setVisibility(VISIBLE); + } + + */ +/** + * 停止解码器 + *//* + + private void stopDecoder() { + if (mVideoDecoder != null) { + mVideoDecoder.stop(); + } + } + + */ +/** + * 移除显示画面 + *//* + + private void removeTextureView() { + mTextureParent.setVisibility(GONE); + if (mTextureParent.getChildCount() > 0) { + mTextureParent.removeView(mTextureView); + // mTextureView = null; + } + } + + private void resetTextureView() { + mTextureParent.setVisibility(GONE); + if (mTextureParent.getChildCount() > 0) { + mTextureParent.removeView(mTextureView); + mTextureView = null; + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.iv_res_add) { + //播放 + if (mH264ReadRunable == null) { + mH264ReadRunable = new H264ReadRunable(); + mH264ReadRunable.setH264ReadListener(new H264ReadRunable.H264ReadListener() { + @Override + public void onFrameData(byte[] datas) { + mVideoDecoder.feedData(datas, 0, datas.length); + } + + @Override + public void onStopRead() { + stopVideoPlayer(true); + } + }); + } + setPlayerViewState(PlayerViewState.Playying); + } else if (v.getId() == R.id.btnFullScreen) { + //全屏 + startFullScreen(); + } else if (v.getId() == R.id.btnStop) { + //停止 + Log.d(TAG, "onClick:btnStop "); + stopVideoPlayer(true); + } + setSelectStyle(); + } + + */ +/** + * 开启全屏 + *//* + + public void startFullScreen() { + isFullScreen = true; + FullScreenActivity.start(getContext()); + } + + */ +/** + * 退出全屏模式 + *//* + + public void exitFullScreen() { + isFullScreen = false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // gestureDetector.onTouchEvent(event); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + doubleClick_2(); + mPqVideoOnclickListener.onClick(); + return true; + case MotionEvent.ACTION_UP: + return true; + } + return super.onTouchEvent(event); + } + + private void doubleClick_2() { + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + //获取手机开机时间 + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[mHits.length - 1] - mHits[0] < 500) { + */ +/**双击的业务逻辑*//* + + Log.d(TAG, "doubleClick_2: 双击"); + onZoomViewExchange(); + } + } + + private void onZoomViewExchange() { + if (mTextureView != null) { + mSurfaceTextureListener = mTextureView.getSurfaceTextureListener(); + } + isZoomIn = true; + removeTextureView(); + videoPlayerListener.onZoomInView(PqVideoPlayer.this); + } + + */ +/** + * 设置选中的状态 + *//* + + private void setSelectStyle() { + isFoucsed = true; + //背景为黑色,且出现选中边框 + mRlVideoBg.setBackgroundColor(Color.BLACK); + mRlBorderBg.setBackgroundColor(mBgSelectColor); + } + + private void setDefultStyle() { + isFoucsed = false; + mRlVideoBg.setBackgroundColor(mBgColor); + mRlBorderBg.setBackgroundColor(mBorderColor); + } + + */ +/** + * 设置时候获取焦点 + * + * @param focus + *//* + + public void setFocus(boolean focus) { + if (focus) { + setSelectStyle(); + } else { + setDefultStyle(); + } + } + + */ +/** + * 开始播放视频 + *//* + + public void startVideoPlayer() { + setPlayerViewState(PlayerViewState.Playying); + //设置轮播字幕 + // mTvPath.setText(mParams.getVideoName()); + } + + public void stopVideoPlayer(boolean isClear) { + //停止视频解码器 + stopDecoder(); + //移除显示画面 + mMainHandler.sendEmptyMessage(HANDLER_SET_STATUS_DEAULT); + // setPlayerViewState(PlayerViewState.Default); + if (isClear) { + // mParams.getSessionParams().requestId = null; + } + } + + */ +/** + * 显示加载动画 + *//* + + public void showProgressbar() { + setPlayerViewState(PlayerViewState.Waiting); + //定时器 15s还没来自动关闭 + if (mScheduleRunable == null) { + mScheduleRunable = new Runnable() { + @Override + public void run() { + if (mProcessBar.getVisibility() == VISIBLE) { + mMainHandler.sendEmptyMessage(HANDLER_SET_STATUS_DEAULT); + } + } + }; + } + mScheduledExecutorService.schedule(mScheduleRunable, 15000, TimeUnit.MILLISECONDS); + } + + + private void setPlayerViewState(PlayerViewState state) { + curState = state; + Log.d(TAG, "setPlayerViewState: " + curState); + switch (state) { + case Default: + //默认背景 + mRlVideoBg.setBackgroundColor(mBgColor); + ivResAdd.setVisibility(VISIBLE); + //隐藏textureView + resetTextureView(); + //隐藏dialog + mProcessBar.setVisibility(GONE); + //隐藏底部控制栏 + mRlBottomBar.setVisibility(GONE); + break; + case Waiting: + //背景设为黑色 + mRlVideoBg.setBackgroundColor(Color.BLACK); + //隐藏资源图标 + ivResAdd.setVisibility(GONE); + //显示dialog + mProcessBar.setVisibility(VISIBLE); + break; + case Playying: + //隐藏dialog + mProcessBar.setVisibility(GONE); + //隐藏资源 + ivResAdd.setVisibility(GONE); + initTextureView(); + addTextureView(); + //显示底部控制栏 + mRlBottomBar.setVisibility(VISIBLE); + break; + case Control: + break; + } + } + + + private boolean initDecoder(SurfaceTexture surface) { + Log.d(TAG, "initDecoder: "); + if (mVideoDecoder == null) { + mVideoDecoder = new PqVideoDecoder(); + } + boolean initSuccess = mVideoDecoder.init(surface, + 1280, + 720); + + return initSuccess; + } + + + private void setDefaultUI() { + //判断当前是否是播放状态 + if (mRlBottomBar.getVisibility() == VISIBLE || mProcessBar.getVisibility() == VISIBLE) { + //停止视频解码器 + stopDecoder(); + //移除显示画面 + setPlayerViewState(PlayerViewState.Default); + setSelectStyle(); + } + } + + @Override + public void onZoomIn() { + onResume(); + setVisibility(VISIBLE); + isZoomIn = false; + } + + public void onResume() { + if (curState == PlayerViewState.Playying) { + setSurfaceTexture(); + } + } + + private void setSurfaceTexture() { + if (null == mTextureView.getSurfaceTexture()) { + Log.d(TAG, "setSurfaceTexture: "); + mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); + mTextureView.setSurfaceTexture(mSurfaceTexture); + } + addTextureView(); + } + + public SurfaceTexture getSurfaceTexture() { + return mTextureView.getSurfaceTexture(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), + getDefaultSize(0, heightMeasureSpec)); + + int childWidthSize = getMeasuredWidth(); + // 高度和宽度一样 + heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec( + childWidthSize, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + public interface VideoPlayerListener { + */ +/** + * 双击放大 + * + * @param videoPlayer + *//* + + void onZoomInView(PqVideoPlayer videoPlayer); + + */ +/** + * 渲染画面被交换 + * + * @param surfaceTexture + *//* + + void onChangeSurface(SurfaceTexture surfaceTexture); + + } + + public interface PqVideoOnclickListener { + void onClick(); + } +} +*/ diff --git a/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayerZoomIn.java b/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayerZoomIn.java new file mode 100644 index 0000000..b260336 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/PqVideoPlayerZoomIn.java @@ -0,0 +1,194 @@ +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.SurfaceTexture; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.TextureView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.yonsz.z1.R; +import com.yonsz.z1.utils.DensityUtil; + +public class PqVideoPlayerZoomIn extends FrameLayout implements View.OnClickListener { + private String TAG = getClass().getSimpleName(); + private RelativeLayout mTextureParent, mRlBottomBar; + private TextureView mTextureView; + private ImageView ivResAdd; + private TextView mTvPath, mTvLoss; + private PqZoomOutVideoListener mPqZoomOutVideoListener; + private SurfaceTexture mSurfaceTexture; + private long[] mHits = new long[2]; + private float[] mHorizontals = new float[2]; + + public PqVideoPlayerZoomIn(@NonNull Context context) { + this(context, null); + } + + public PqVideoPlayerZoomIn(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public PqVideoPlayerZoomIn(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(); + } + + private void initView() { + //设置屏幕常亮 + setKeepScreenOn(true); + setBackgroundColor(getResources().getColor(R.color.colorPrimary)); + addTextureParent(); + // addTextureView(); + addResIconView(); + // addBottomView(); + } + + private void addTextureParent() { + //先添加其父容器 + LayoutParams parentParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + parentParams.gravity = Gravity.CENTER; + + mTextureParent = new RelativeLayout(getContext()); + mTextureParent.setBackgroundColor(Color.BLACK); + mTextureParent.setVisibility(VISIBLE); + addView(mTextureParent, parentParams); + } + + private void addResIconView() { + //添加添加资源图标 + LayoutParams layoutParams = new LayoutParams(DensityUtil.sp2px(getContext(), 35), + DensityUtil.sp2px(getContext(), 35)); + layoutParams.gravity = Gravity.CENTER; + ivResAdd = new ImageView(getContext()); + ivResAdd.setImageResource(R.mipmap.vp_ic_res_add); + ivResAdd.setScaleType(ImageView.ScaleType.CENTER_INSIDE); +// ivResAdd.setId(R.id.iv_res_add); + ivResAdd.setOnClickListener(this); + addView(ivResAdd, layoutParams); + } + + private void addTextureView() { + //添加渲染视图 + if (mTextureView == null) { + mTextureView = new VideoTextureView(getContext()); + mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + Log.d(TAG, "onSurfaceTextureAvailable: "); + if (mSurfaceTexture != null) { + mTextureView.setSurfaceTexture(mSurfaceTexture); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + Log.d(TAG, "onSurfaceTextureDestroyed: "); + mSurfaceTexture = surface; + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + + } + }); + } + + if (mTextureParent.getChildCount() > 0) { + throw new IllegalStateException("已经添加了一个子控件了!"); + } + RelativeLayout.LayoutParams LinlayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, + RelativeLayout.LayoutParams.MATCH_PARENT); + LinlayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); + mTextureParent.addView(mTextureView, LinlayoutParams); + } + + public void setSurfaceView(SurfaceTexture surfaceView) { + Log.d(TAG, "setSurfaceView: "); + addTextureView(); + mTextureView.setSurfaceTexture(surfaceView); + } + + public void setPqZoomOutVideoListener(PqZoomOutVideoListener mPqZoomOutVideoListener) { + this.mPqZoomOutVideoListener = mPqZoomOutVideoListener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + Log.i("TAG", "onTouchEvent--ACTION_DOWN" + event.getX()); + mHorizontals[0] = event.getX(); + doubleClick_2(); + return true; + case MotionEvent.ACTION_UP: + Log.i("TAG", "onTouchEvent--ACTION_UP" + event.getX()); + mHorizontals[1] = event.getX(); + changeLeftOrRight(); + return true; + } + return super.onTouchEvent(event); + } + + private void changeLeftOrRight() { + if (mHorizontals[0] > mHorizontals[1]) { + if ((mHorizontals[0] - mHorizontals[1]) > 200) { + Log.i("TAG", "onTouchEvent" + "下一个" + (mHorizontals[0] - mHorizontals[1])); + Toast.makeText(getContext(), "下一个", Toast.LENGTH_SHORT).show(); + } + } else { + if ((mHorizontals[1] - mHorizontals[0]) > 200) { + Log.i("TAG", "onTouchEven" + "上一个"); + Toast.makeText(getContext(), "上一个", Toast.LENGTH_SHORT).show(); + } + } + } + + private void doubleClick_2() { + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + //获取手机开机时间 + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[mHits.length - 1] - mHits[0] < 500) { + /**双击的业务逻辑*/ + Log.d(TAG, "doubleClick_2: 双击"); + onZoomViewExchange(); + } + } + + private void onZoomViewExchange() { + mTextureParent.removeView(mTextureView); + mPqZoomOutVideoListener.onZoomIn(); + setVisibility(GONE); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + /*case R.id.iv_res_add: + break;*/ + } + } + + public interface PqZoomOutVideoListener { + void onZoomIn(); + } + +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoContainerFragment.java b/app/src/main/java/com/lechange/demo/videoplay/VideoContainerFragment.java new file mode 100644 index 0000000..3f9631c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoContainerFragment.java @@ -0,0 +1,169 @@ +package com.lechange.demo.videoplay; + +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v4.app.Fragment; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.yonsz.z1.R; +import com.yonsz.z1.fragment.BaseFragment; +import com.yonsz.z1.version4.fragment.MyFragmentPagerAdapter; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +public class VideoContainerFragment extends BaseFragment { + private View fragView; + private String TAG = getClass().getSimpleName(); + private UIHandle mHandler; + private RecyclerView rv_list; + private PqVideoPlayerZoomIn pqZoomOutVideoPlayer; + private VideoPlayOnlineFragment mCurPqVideoPlayer; + private GridLayoutManager mGridLayoutManager; + private ContainerAdapter containerAdapter; + private List videoIdList; + private MyFragmentPagerAdapter myFragmentPagerAdapter; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mHandler = new UIHandle(this); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + fragView = View.inflate(getActivity(), R.layout.activity_video_container, null); + initView(fragView); + return fragView; + } + + + private void initView(View fragView) { + videoIdList = new ArrayList<>(); + + for (int i = 0; i < 4; i++) { + VideoPlayOnlineFragment pqVideoPlayer = new VideoPlayOnlineFragment(); + Bundle b = new Bundle(); + String resId = getActivity().getIntent().getStringExtra("UUID"); + b.putString("RESID", resId); + pqVideoPlayer.setArguments(b); + videoIdList.add(pqVideoPlayer); + } + + rv_list = (RecyclerView) fragView.findViewById(R.id.rv_list); + pqZoomOutVideoPlayer = (PqVideoPlayerZoomIn) fragView.findViewById(R.id.pq_video); + + containerAdapter = new ContainerAdapter(getContext(), videoIdList); + myFragmentPagerAdapter = new MyFragmentPagerAdapter(getFragmentManager()) { + @Override + public int getCount() { + return 4; + } + + @Override + public Fragment getItem(int position) { + return videoIdList.get(position); + } + + @Override + public long getItemId(int position) { + return videoIdList.get(position).getId(); + } + }; + /*containerAdapter.setVideoPlayerListener(new PqVideoPlayer.VideoPlayerListener() { + @Override + public void onZoomInView(PqVideoPlayer videoPlayer) { + mCurPqVideoPlayer = videoPlayer; + videoPlayer.setVisibility(View.GONE); + pqZoomOutVideoPlayer.setVisibility(View.VISIBLE); + pqZoomOutVideoPlayer.setPqZoomOutVideoListener(videoPlayer); + } + + @Override + public void onChangeSurface(SurfaceTexture surfaceTexture) { + pqZoomOutVideoPlayer.setSurfaceView(surfaceTexture); + } + + });*/ + mGridLayoutManager = new VideoGridLayoutManager(getContext(), 2); + rv_list.setLayoutManager(mGridLayoutManager); + rv_list.setAdapter(containerAdapter); + + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() { + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + Log.d(TAG, "getMovementFlags: "); + int dragFlags; + int swipeFlags; + if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { + dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | + ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; + swipeFlags = 0; + } else { + dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; + swipeFlags = 0; + } + return makeMovementFlags(dragFlags, swipeFlags); + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + Log.d(TAG, "onMove: "); + int fromPosition = viewHolder.getAdapterPosition(); + int toPosition = target.getAdapterPosition(); + if (fromPosition < toPosition) { + for (int i = fromPosition; i < toPosition; i++) { + Collections.swap(videoIdList, i, i + 1); + } + } else { + for (int i = fromPosition; i < toPosition; i--) { + Collections.swap(videoIdList, i, i - 1); + } + } + containerAdapter.notifyItemMoved(fromPosition, toPosition); + return true; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + Log.d(TAG, "onSwiped: "); + } + }); + itemTouchHelper.attachToRecyclerView(rv_list); + } + + private void callBackUiThread(Message msg) { + + } + + //handler + private static class UIHandle extends Handler { + WeakReference weakReference; + + public UIHandle(VideoContainerFragment activity) { + weakReference = new WeakReference(activity); + } + + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + VideoContainerFragment activity = weakReference.get(); + activity.callBackUiThread(msg); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoGridLayoutManager.java b/app/src/main/java/com/lechange/demo/videoplay/VideoGridLayoutManager.java new file mode 100644 index 0000000..cd6405a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoGridLayoutManager.java @@ -0,0 +1,27 @@ +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.util.AttributeSet; + + +public class VideoGridLayoutManager extends GridLayoutManager { + public VideoGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public VideoGridLayoutManager(Context context, int spanCount) { + super(context, spanCount); + } + + public VideoGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { + super(context, spanCount, orientation, reverseLayout); + } + + @Override + public boolean canScrollVertically() { +// super.canScrollVertically() + return false; + } + +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoPlayFragment.java b/app/src/main/java/com/lechange/demo/videoplay/VideoPlayFragment.java new file mode 100644 index 0000000..a6a2c92 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoPlayFragment.java @@ -0,0 +1,251 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayFragment.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.videoplay; + +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.hardware.SensorManager; +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.OrientationEventListener; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.media.LCOpenSDK_PlayWindow; + + +/** + * 描述:视频播放组件基类 作者: lc + */ +public class VideoPlayFragment extends Fragment{ + private final static String tag = "MediaPlayFragment"; + //底层返回值 + protected static final int retOK = 0; + protected static final int retNG = -1; + + public interface BackHandlerInterface { + public void setSelectedFragment(VideoPlayFragment backHandledFragment); + } + protected LCOpenSDK_EventListener listener; + protected LCOpenSDK_PlayWindow mPlayWin = new LCOpenSDK_PlayWindow(); + protected Handler mHander = new Handler(); + // 屏幕方向改变监听器 + private OrientationEventListener mOrientationListener; + + // 统计当前累计总流量,单位:字节 + //protected long mTotalFlow; + protected ViewGroup mSurfaceParentView; + protected ProgressDialog mProgressDialog; //播放加载使用 + protected TextView mReplayTip; + + public enum ORIENTATION {isPortRait, isLandScape, isNone} + protected ORIENTATION mOrientation = ORIENTATION.isNone; //禁止横竖屏标志 + + protected static final String AUDIO_TALK_ERROR = "-1000"; //实时对讲初始化失败 + + + //吐司类工具 + protected void toast(int resId) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT).show(); + } + } + protected void toast(String content) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast.makeText(getActivity(), content, Toast.LENGTH_SHORT).show(); + } + } + public void toastWithImg(String content, int imgId) { + if (getActivity() != null && !getActivity().isFinishing()) { + Toast toast = Toast.makeText(getActivity(), content, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastView = (LinearLayout) toast.getView(); + ImageView imageCodeProject = new ImageView(getActivity()); + imageCodeProject.setImageResource(imgId); + toastView.addView(imageCodeProject, 0); + toast.show(); + } + } + + //播放失败提示器 + protected void showErrorTip(int resId){ + mReplayTip.setVisibility(View.VISIBLE); + mReplayTip.setText(resId); + } + protected void showErrorTip(String res){ + mReplayTip.setVisibility(View.VISIBLE); + mReplayTip.setText(res); + } + + //播放缓冲提示器 + protected void showLoading(int res) { + mReplayTip.setVisibility(View.GONE); + mProgressDialog.setStart(getString(res)); //开启播放加载控件 + } + protected void showLoading(String res) { + mReplayTip.setVisibility(View.GONE); + mProgressDialog.setStart(res); //开启播放加载控件 + } + + @Override + public void onStart() { + super.onStart(); + //将自己的实例传出去 + if (!(getActivity() instanceof BackHandlerInterface)) { + throw new ClassCastException("Hosting activity must implement BackHandlerInterface"); + } else { + ((BackHandlerInterface)getActivity()).setSelectedFragment(this); + } + } + + @Override + public void onDestroyView() + { + super.onDestroyView(); + mOrientationListener.disable(); + mOrientationListener = null; + } + + /** + * 描述:开启屏幕方向监听 + */ + protected final void startListener() { + if (getActivity() == null || getActivity().isFinishing()) { + return; + } + mOrientationListener = new OrientationEventListener(getActivity(), SensorManager.SENSOR_DELAY_NORMAL) { + @Override + public void onOrientationChanged(int rotation) { + // 设置竖屏 + if (getActivity() == null || getActivity().isFinishing()) { + return; + } + requestedOrientation(rotation); + } + }; + if (mOrientationListener.canDetectOrientation()) { + mOrientationListener.enable(); + } else { + mOrientationListener.disable(); + } + + } + /** + * 描述:改变屏幕方向 + */ + private void requestedOrientation(int rotation) { + if (rotation < 10 || rotation > 350) {// 手机顶部向上 + setPortOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else if (rotation < 100 && rotation > 80) {// 手机右边向上 + setLandOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + } else if (rotation < 190 && rotation > 170) {// 手机低边向上 + setPortOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); + } else if (rotation < 280 && rotation > 260) {// 手机左边向上 + setLandOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + } + + private void setPortOrientation(int type) { + switch(mOrientation){ + case isNone: + getActivity().setRequestedOrientation(type); + break; + case isPortRait: + mOrientation = ORIENTATION.isNone; + break; + default: + break; + } + } + + private void setLandOrientation(int type) { + switch(mOrientation){ + case isNone: + getActivity().setRequestedOrientation(type); + break; + case isLandScape: + mOrientation = ORIENTATION.isNone; + break; + default: + break; + } + } + + /** + * @see Fragment#onConfigurationChanged(Configuration) + * 描述:屏幕方向改变时重新绘制界面 + */ + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + initWindow(newConfig); + initSurFace(newConfig); + resetViews(newConfig); + } + + /** + * 描述:初始化playWindow + */ + protected void initWindow(Configuration mConfiguration) { + LayoutParams mLayoutParams = (LayoutParams) mSurfaceParentView.getLayoutParams(); + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.heightPixels; // 屏幕高度(像素) + mLayoutParams.setMargins(0, 0, 0, 0); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + } + mSurfaceParentView.setLayoutParams(mLayoutParams); + } + + /** + * 描述:初始化全屏或非全屏 + */ + private void initSurFace(Configuration mConfiguration) { + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + if (getActivity() instanceof MediaPlayActivity) { + ((MediaPlayActivity) getActivity()).toggleTitle(false); + } + MediaPlayHelper.setFullScreen(getActivity()); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + if (getActivity() instanceof MediaPlayActivity) { + ((MediaPlayActivity) getActivity()).toggleTitle(true); + } + MediaPlayHelper.quitFullScreen(getActivity()); + } + } + + /** + * 重置View,子类实现 + */ + protected void resetViews(Configuration mConfiguration) {} + + public boolean onBackPressed() { + return false; + } +} + diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoPlayOnlineFragment.java b/app/src/main/java/com/lechange/demo/videoplay/VideoPlayOnlineFragment.java new file mode 100644 index 0000000..7358870 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoPlayOnlineFragment.java @@ -0,0 +1,1023 @@ +/* + * 项目名: YYS + * 文件名: MediaPlayOnlineFragment.java + * 版权声明: + * 本系统的所有内容,包括源码、页面设计,文字、图像以及其他任何信息, + * 如未经特殊说明,其版权均属大华技术股份有限公司所有。 + * Copyright (c) 2015 大华技术股份有限公司 + * 版权所有 + */ +package com.lechange.demo.videoplay; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.media.MediaScannerConnection; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.demo.business.Business; +import com.lechange.demo.business.Business.PlayerResultCode; +import com.lechange.demo.business.Business.RetObject; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.business.entity.ChannelPTZInfo; +import com.lechange.demo.business.util.MediaPlayHelper; +import com.lechange.demo.business.util.MediaPlayHelper.DHFilesType; +import com.lechange.demo.common.ProgressDialog; +import com.lechange.demo.localvideo.RecordListActivity; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.lechange.opensdk.listener.LCOpenSDK_EventListener; +import com.lechange.opensdk.listener.LCOpenSDK_TalkerListener; +import com.lechange.opensdk.media.LCOpenSDK_Talk; +import com.qw.soul.permission.SoulPermission; +import com.qw.soul.permission.bean.Permission; +import com.qw.soul.permission.bean.Permissions; +import com.qw.soul.permission.callbcak.CheckRequestPermissionsListener; +import com.yonsz.z1.R; +import com.yonsz.z1.utils.NetWorkSpeedUtils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * 描述:实时视频监控 作者: lc + */ +public class VideoPlayOnlineFragment extends VideoPlayFragment implements + OnClickListener, View.OnLongClickListener { + + protected static final int MediaMain = 0; // 主码流 + protected static final int MediaAssist = 1; // 辅码流 + protected static final int RECORDER_TYPE_DAV = 3; // 录制格式DAV + protected static final int RECORDER_TYPE_MP4 = 4; // 录制格式MP4 + private static final String TAG = "MediaPlayOnlineFragment"; + /** + * 描述:开始录制 + */ + String path = null; + // 状态值 + private int bateMode = MediaAssist; + private AudioTalkStatus mOpenTalk = AudioTalkStatus.talk_close; // 语音对讲状态 + private boolean isRecord = false; // 正在录制 + private boolean isOpenSound = false; // 声音打开 + private boolean isPlaying; // 正在播放 + private boolean IsPTZOpen = false; // 云台打开 + private ChannelInfo channelInfo; + private LinearLayout mLiveMenu; + private TextView mLiveMode; + private ImageView mLivePtz; + private RelativeLayout rl_live_ptz; + private ImageView mLiveSound; + private ImageView mLiveScale; + private ImageView mLiveStop; + private LinearLayout mLiveUseLayout; + private LinearLayout mLiveBack; + private ImageView mLiveScreenshot; + private ImageView mLiveTalk; + private ImageView mLiveRecord; + private TextView netSpeedTv; + private ImageView iv_top, iv_down, iv_left, iv_right; + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case 100: + netSpeedTv.setText(msg.obj.toString()); + break; + } + super.handleMessage(msg); + } + }; + + private ImageView list_device_localvideo; + private ImageView list_device_cloudvideo; + + /** + * @param savedInstanceState + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle b = getArguments(); + if (b != null) { + String channelId = b.getString("RESID"); + channelInfo = Business.getInstance().getChannel(channelId); + } + if (channelInfo == null) { + toast("设备不存在"); + getActivity().setResult(-1); + getActivity().finish(); + } + } + + /** + * ViewGroup, Bundle) 描述: + * + * @return + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View mView = inflater.inflate(R.layout.fragment_media_live, container, + false); + // 必须赋值,父类需要使用到 + mSurfaceParentView = (ViewGroup) mView.findViewById(R.id.live_window); + // 初始化窗口大小 + LayoutParams mLayoutParams = (LayoutParams) mSurfaceParentView + .getLayoutParams(); + DisplayMetrics metric = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric); + mLayoutParams.width = metric.widthPixels; // 屏幕宽度(像素) + mLayoutParams.height = metric.widthPixels * 9 / 16; + mLayoutParams.setMargins(0, 0, 0, 0); + mSurfaceParentView.setLayoutParams(mLayoutParams); + + mPlayWin.initPlayWindow(this.getActivity(), + (ViewGroup) mView.findViewById(R.id.live_window_content), 0, true); + + mProgressDialog = (ProgressDialog) mView + .findViewById(R.id.live_play_load); + mReplayTip = (TextView) mView.findViewById(R.id.live_play_pressed); + + iv_top = (ImageView) mView.findViewById(R.id.iv_top); + iv_down = (ImageView) mView.findViewById(R.id.iv_down); + iv_left = (ImageView) mView.findViewById(R.id.iv_left); + iv_right = (ImageView) mView.findViewById(R.id.iv_right); + list_device_localvideo = (ImageView) mView.findViewById(R.id.list_device_localvideo); + list_device_cloudvideo = (ImageView) mView.findViewById(R.id.list_device_cloudvideo); + netSpeedTv = (TextView) mView.findViewById(R.id.tv_net_speed); + mLiveMenu = (LinearLayout) mView.findViewById(R.id.live_menu); + mLiveMode = (TextView) mView.findViewById(R.id.live_mode); + mLivePtz = (ImageView) mView.findViewById(R.id.live_ptz); + rl_live_ptz = (RelativeLayout) mView.findViewById(R.id.rl_live_ptz); + mLiveSound = (ImageView) mView.findViewById(R.id.live_sound); + mLiveUseLayout = (LinearLayout) mView.findViewById(R.id.live_use_layout); + mLiveBack = (LinearLayout) mView.findViewById(R.id.live_video_back_layout); + mLiveScale = (ImageView) mView.findViewById(R.id.live_scale); + mLiveStop = (ImageView) mView.findViewById(R.id.live_stop); + mLiveScreenshot = (ImageView) mView.findViewById(R.id.live_screenshot); + mLiveTalk = (ImageView) mView.findViewById(R.id.live_talk); + mLiveRecord = (ImageView) mView.findViewById(R.id.live_record); + + mReplayTip.setOnClickListener(this); + mLiveMode.setOnClickListener(this); + mLivePtz.setOnClickListener(this); + mLiveSound.setOnClickListener(this); + mLiveScale.setOnClickListener(this); + mLiveStop.setOnClickListener(this); + mLiveScreenshot.setOnClickListener(this); + mLiveTalk.setOnClickListener(this); + mLiveRecord.setOnClickListener(this); + list_device_localvideo.setOnClickListener(this); + list_device_cloudvideo.setOnClickListener(this); + iv_top.setOnClickListener(this); + iv_down.setOnClickListener(this); + iv_left.setOnClickListener(this); + iv_right.setOnClickListener(this); + iv_top.setOnLongClickListener(this); + iv_down.setOnLongClickListener(this); + iv_left.setOnLongClickListener(this); + iv_right.setOnLongClickListener(this); + + new NetWorkSpeedUtils(getContext(), mHandler).startShowNetSpeed(); + return mView; + + } + + /** + * 描述:MediaPlayActivity创建完毕 + * + * @param savedInstanceState + */ + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + listener = new MyBaseWindowListener(); + mPlayWin.setWindowListener(listener); + mPlayWin.openTouchListener(); + + // 开启横竖屏切换 + startListener(); + + // int ability = channelInfo.getAbility(); + // if ((ability & ChannelInfo.Ability.AudioTalk) == 0) { + // if (getActivity().getResources().getConfiguration().orientation == + // Configuration.ORIENTATION_LANDSCAPE) { + // mLiveTalk.setOnClickListener(new OnClickListener() { + // @Override + // public void onClick(View v) { + // toast(R.string.video_monitor_unsupport_audio_talk); + // } + // }); + // } else if + // (getActivity().getResources().getConfiguration().orientation == + // Configuration.ORIENTATION_PORTRAIT) { + // mLiveTalk.setOnClickListener(new OnClickListener() { + // @Override + // public void onClick(View v) { + // toast(R.string.video_monitor_unsupport_audio_talk); + // } + // }); + // } + // } + } + + @Override + public void onResume() { + // TODO Auto-generated method stub + super.onResume(); + play(0); + } + + @Override + public void onPause() { + super.onPause(); + // 停止实时视频,无效资源号 + stop(-1); + // 关闭语音对讲 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + } + + @Override + public void onDestroyView() { + // TODO Auto-generated method stub + super.onDestroyView(); + mPlayWin.uninitPlayWindow();// 销毁底层资源 + } + + /** + * 描述:实现个性化界面 + * + * @param mConfiguration + */ + @Override + protected void resetViews(Configuration mConfiguration) { + super.resetViews(mConfiguration); + if (mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 横屏 + mLiveUseLayout.setVisibility(View.GONE); + mLiveBack.setVisibility(View.GONE); + mLiveScale.setTag("LANDSCAPE"); + mLiveScale.setImageResource(R.drawable.live_btn_smallscreen); + } else if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { + mLiveUseLayout.setVisibility(View.VISIBLE); + mLiveBack.setVisibility(View.VISIBLE); + mLiveScale.setTag("PORTRAIT"); + mLiveScale.setImageResource(R.drawable.live_btn_fullscreen); + } + } + + private void sendCloudOrder(final Cloud mCloud, final boolean longclick) { + if (IsPTZOpen && isPlaying) { + // super.sendCloudOrder(mCloud, longclick); + Log.d(TAG, "-----is longclick:" + longclick); + ChannelPTZInfo.Operation operation = ChannelPTZInfo.Operation.Move; + ChannelPTZInfo.Direction direction = null; + switch (mCloud) { + case up: + direction = ChannelPTZInfo.Direction.Up; + Log.d(TAG, "-----Up"); + break; + case down: + direction = ChannelPTZInfo.Direction.Down; + Log.d(TAG, "-----Down"); + break; + case left:// 手势向左, 摄像头向右转 + direction = ChannelPTZInfo.Direction.Left; + Log.d(TAG, "-----case left"); + break; + case right: + direction = ChannelPTZInfo.Direction.Right; + Log.d(TAG, "-----case right"); + break; + case zoomin: + direction = ChannelPTZInfo.Direction.ZoomIn; + Log.d(TAG, "-----ZoomIn"); + break; + case zoomout: + direction = ChannelPTZInfo.Direction.ZoomOut; + Log.d(TAG, "-----ZoomOut"); + break; + case stop: + Log.d(TAG, "-----stop"); + operation = ChannelPTZInfo.Operation.Stop; + // direction = ChannelPTZInfo.Direction.Down; + break; + default: + break; + } + ChannelPTZInfo ptzInfo = new ChannelPTZInfo(operation, direction); + ptzInfo.setDuration(ChannelPTZInfo.Duration.Short); + if (longclick) { + ptzInfo.setDuration(ChannelPTZInfo.Duration.Long); + } + + Business.getInstance().AsynControlPtz(channelInfo.getUuid(), + ptzInfo, new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isAdded() || getActivity() == null) { + Log.d(TAG, "*******page not exits"); + return; + } + // Log.d(TAG, + // "-----control callback what:"+msg.what); + RetObject retObject = (RetObject) msg.obj; + if (msg.what == 0) { + Log.d(TAG, "-----control result: true"); + } else + toast(retObject.mMsg); + } + }); + } + } + + /** + * 描述:开始播放 + */ + public void play(int strRes) { + // if (isPlaying) { + stop(-1); + // } + if (strRes > 0) { + showLoading(strRes); + } else { + showLoading(R.string.common_loading); + } + mPlayWin.playRtspReal( + Business.getInstance().getToken(), + channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo + .getEncryptKey() : channelInfo.getDeviceCode(), + channelInfo.getIndex(), bateMode, true);//最后一个参数为true,表示使用长连接 + } + + /** + * 描述:停止播放 + */ + public void stop(final int res) { + // 关闭播放加载控件 + mProgressDialog.setStop(); + + if (isRecord) { + stopRecord();// 关闭录像 + } + + if (isOpenSound) { + closeAudio();// 关闭音频 + isOpenSound = false; + mLiveSound.setImageResource(R.drawable.live_btn_sound_off); + } + mPlayWin.stopRtspReal(false);// 关闭视频 + isPlaying = false; + + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + if (res > 0) + showErrorTip(res); + } + } + }); + } + } + + /** + * 描述:抓拍图像 + */ + public String capture() { + String captureFilePath = null; + // 判断SD卡是否已存在 + // SD卡容量检查 + // FIXME 检查设备是否在线 + // 抓图 + String channelName = null; + if (channelInfo != null) { + channelName = channelInfo.getName(); + } else { + channelName = ""; + } + + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + + captureFilePath = MediaPlayHelper.getCaptureAndVideoPath( + DHFilesType.DHImage, channelName); + int ret = mPlayWin.snapShot(captureFilePath); + if (ret == retOK) { + // 扫描到相册中 + MediaScannerConnection.scanFile(getActivity(), + new String[]{captureFilePath}, null, null); + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_success, + Toast.LENGTH_SHORT).show(); + } else { + captureFilePath = null; + Toast.makeText(getActivity(), + R.string.video_monitor_image_capture_failed, + Toast.LENGTH_SHORT).show(); + } + return captureFilePath; + } + + public boolean startRecord() { + if (!isPlaying) { + toast(R.string.video_monitor_video_record_failed); + return false; + } + // 判断SD卡是否已存在 + // SD卡容量检查 + + // FIXME 要做 ~~~~检查设备是否在线 + + // 录像的路径 + String channelName = null; + if (channelInfo != null) { + channelName = channelInfo.getName(); + } else { + channelName = ""; + } + + // 去除通道中在目录中的非法字符 + channelName = channelName.replace("-", ""); + + path = MediaPlayHelper.getCaptureAndVideoPath(DHFilesType.DHVideo, + channelName); + int recordType = 1; + long spaceRemain = 0x7FFFFFFF; //保留字段 + // 开始录制 1 + int ret = mPlayWin.startRecord(path, recordType, spaceRemain); + if (ret != retOK) { + toast(R.string.video_monitor_video_record_failed); + return false; + } + + return true; + } + + /** + * 关闭录像 + */ + public void stopRecord() { + mPlayWin.stopRecord(); + isRecord = false; + toast(getString(R.string.video_monitor_video_record_success)); + mLiveRecord.setImageResource(R.drawable.icon_videotape_nor); + + MediaScannerConnection.scanFile(getActivity(), new String[]{path}, + null, null); + } + + /** + * 打开声音 + */ + public boolean openAudio() { + return mPlayWin.playAudio() == retOK; + } + + /** + * 关闭声音 + */ + public boolean closeAudio() { + return mPlayWin.stopAudio() == retOK; + } + + /** + * 描述:开始对讲 + */ + public void startTalk() { + if (!isPlaying) { + toast(R.string.video_monitor_talk_open_error); + return; + } + + toastWithImg(getString(R.string.video_monitor_media_talk), + R.drawable.live_pic_talkback); + + // 替换图片 + mLiveTalk.setImageResource(R.drawable.icon_dialogue_pre); + mOpenTalk = AudioTalkStatus.talk_opening; + // 关闭扬声器 默认为关 + if (isOpenSound) { + closeAudio(); + mLiveSound.setImageResource(R.drawable.live_btn_sound_off); + } + mLiveSound.setClickable(false); + LCOpenSDK_Talk.setListener(new AudioTalkerListener()); + LCOpenSDK_Talk.playTalk( + Business.getInstance().getToken(), + channelInfo.getDeviceCode(), + channelInfo.getEncryptKey() != null ? channelInfo + .getEncryptKey() : channelInfo.getDeviceCode(), true);//对讲使用长连接 + } + + /** + * 描述:停止对讲 + */ + public void stopTalk() { + Log.d("playAudio", "stopTalk press"); + toast(R.string.video_monitor_media_talk_close); + // 替换图片 + mLiveTalk.setImageResource(R.drawable.icon_dialogue_nor); + LCOpenSDK_Talk.stopTalk(); + // 解决gc回收问题 + LCOpenSDK_Talk.setListener(null); + mOpenTalk = AudioTalkStatus.talk_close; + // 开启扬声器 + if (isOpenSound && isPlaying) { + openAudio(); + mLiveSound.setImageResource(R.drawable.live_btn_sound_on); + } + mLiveSound.setClickable(true); + } + + @Override + public void onClick(View view) { + // TODO Auto-generated method stub + switch (view.getId()) { + case R.id.live_ptz: + if (!isPlaying) { + return; + } + if ((channelInfo.getAbility() & ChannelInfo.Ability.PTZ) != 0) { + if (IsPTZOpen) { + // 测试专用 + // mPlayWin.setStreamCallback(0); + IsPTZOpen = false; + mLivePtz.setImageResource(R.drawable.icon_control_nor); + rl_live_ptz.setVisibility(View.GONE); + } else { + // 测试专用 + // mPlayWin.setStreamCallback(1); + IsPTZOpen = true; + mLivePtz.setImageResource(R.drawable.icon_control_pre); + rl_live_ptz.setVisibility(View.VISIBLE); + } + } else { + toast(R.string.toast_device_ability_no_ptz); + } + break; + case R.id.live_scale: + if ("LANDSCAPE".equals(mLiveScale.getTag())) { + mOrientation = ORIENTATION.isPortRait; + getActivity().setRequestedOrientation( + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else { + mOrientation = ORIENTATION.isLandScape; + getActivity().setRequestedOrientation( + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + break; + case R.id.live_stop: + if (isPlaying) { + // 停止实时视频,无效资源号 + stop(-1); + // 关闭语音对讲 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + } else { + play(0); + } + break; + case R.id.live_mode: + // if(isPlaying) //播放是个异步的,多次点击会使停止播放顺序乱掉 + if (mOpenTalk == AudioTalkStatus.talk_opening) { + stopTalk(); + } + // 高清切换到流畅 + if (bateMode == MediaMain) { + bateMode = MediaAssist; + mLiveMode.setText("流畅"); + play(R.string.video_monitor_change_stream_normal); + }// 流畅切换到高清 + else if (bateMode == MediaAssist) { + bateMode = MediaMain; + mLiveMode.setText("高清"); + play(R.string.video_monitor_change_stream_hd); + } + break; + case R.id.live_talk: + switch (mOpenTalk) { + case talk_open: + case talk_opening: + stopTalk(); + break; + case talk_close: + SoulPermission.getInstance().checkAndRequestPermissions( + Permissions.build(Manifest.permission.RECORD_AUDIO), + //if you want do noting or no need all the callbacks you may use SimplePermissionsAdapter instead + new CheckRequestPermissionsListener() { + @Override + public void onAllPermissionOk(Permission[] allPermissions) { + startTalk(); + } + + @Override + public void onPermissionDenied(Permission[] refusedPermissions) { + Toast.makeText(getContext(), "此功能需要开启麦克风权限", Toast.LENGTH_LONG).show(); + } + }); + break; + default: + break; + } + break; + case R.id.live_sound: + if (mOpenTalk != AudioTalkStatus.talk_close || !isPlaying) { + toast(R.string.video_monitor_load_talk_sound_error); + } else { + if (isOpenSound) { + boolean result = closeAudio(); + if (result) { + mLiveSound + .setImageResource(R.drawable.live_btn_sound_off); + toast(R.string.video_monitor_sound_close); + isOpenSound = false; + } + } else { + boolean result = openAudio(); + if (result) { + mLiveSound + .setImageResource(R.drawable.live_btn_sound_on); + toast(R.string.video_monitor_sound_open); + isOpenSound = true; + } + } + } + break; + case R.id.live_screenshot: + mLiveScreenshot + .setImageResource(R.drawable.icon_photograph_pre); + capture(); + mLiveScreenshot + .setImageResource(R.drawable.icon_photograph_nor); + break; + case R.id.live_record: + if (!isRecord) { + boolean result = startRecord(); + if (result) { + toastWithImg( + getString(R.string.video_monitor_media_record), + R.drawable.live_pic_record); + isRecord = true; + mLiveRecord + .setImageResource(R.drawable.icon_videotape_pre); + } + } else { + stopRecord(); + } + break; + case R.id.live_play_pressed: + play(-1); + break; + case R.id.list_device_cloudvideo: + Intent intent = new Intent(getContext(), RecordListActivity.class); + intent.putExtra("UUID", getActivity().getIntent().getExtras().get("UUID").toString()); + intent.putExtra("MEDIA_TITLE", R.string.cloud_records_name); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_CLOUD_RECORD); + startActivity(intent); + break; + case R.id.list_device_localvideo: + Intent intent1 = new Intent(getContext(), RecordListActivity.class); + intent1.putExtra("UUID", getActivity().getIntent().getExtras().get("UUID").toString()); + intent1.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_REMOTE_RECORD); + intent1.putExtra("MEDIA_TITLE", R.string.local_records_name); + startActivity(intent1); + break; + case R.id.iv_top: + sendCloudOrder(Cloud.up, false); + break; + case R.id.iv_down: + sendCloudOrder(Cloud.down, false); + break; + case R.id.iv_left: + sendCloudOrder(Cloud.left, false); + break; + case R.id.iv_right: + sendCloudOrder(Cloud.right, false); + break; + default: + break; + } + } + + @Override + public boolean onLongClick(View v) { + switch (v.getId()) { + case R.id.iv_top: + sendCloudOrder(Cloud.up, false); + break; + case R.id.iv_down: + sendCloudOrder(Cloud.down, false); + break; + case R.id.iv_left: + sendCloudOrder(Cloud.left, false); + break; + case R.id.iv_right: + sendCloudOrder(Cloud.right, false); + break; + } + return false; + } + + public enum Cloud { + up, down, left, right, leftUp, rightUp, leftDown, RightDown, zoomin, zoomout, stop + } + + private enum AudioTalkStatus { + talk_close, talk_opening, talk_open + } + + class MyBaseWindowListener extends LCOpenSDK_EventListener { + @Override + public void onPlayerResult(int index, String code, int type) { + if (type == Business.RESULT_SOURCE_OPENAPI) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_play_error); + } + } + }); + } + } else { + if (code.equals(PlayerResultCode.STATE_PACKET_FRAME_ERROR) + || code.equals(PlayerResultCode.STATE_RTSP_TEARDOWN_ERROR) + || code.equals(PlayerResultCode.STATE_RTSP_AUTHORIZATION_FAIL) + || code.equals(PlayerResultCode.STATE_RTSP_KEY_MISMATCH)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + stop(R.string.video_monitor_play_error); + } + } + }); + } + } + } + } + + @Override + public void onPlayBegan(int index) { + // TODO Auto-generated method stub + // 显示码率 + // if (mHander != null) { + // mHander.post(MediaPlayOnlineFragment.this); + // } + isPlaying = true; + // 建立码流,自动开启音频 + if (mHander != null) { + mHander.post(new Runnable() { + @Override + public void run() { + if (isAdded()) { + // showLoading(R.string.video_monitor_data_cache); + onClick(mLiveSound); + } + } + }); + } + // 关闭播放加载控件 + mProgressDialog.setStop(); + } + + // public void onReceiveData(int len) { + // // 流量统计 + // mTotalFlow += len; + // } + @Override + public void onStreamCallback(int index, byte[] data, int len) { + // Log.d(TAG, "LCOpenSDK_EventListener::onStreamCallback-size : " + + // len); + try { + String path = Environment.getExternalStorageDirectory() + .getPath() + "/streamCallback.ts"; + FileOutputStream fout = new FileOutputStream(path, true); + fout.write(data); + fout.close(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Override + public void onWindowLongPressBegin(int index, Direction dir, float dx, + float dy) { + sendCloudOrder(direction2Cloud(dir), true); + } + + @Override + public void onWindowLongPressEnd(int index) { + sendCloudOrder(Cloud.stop, false); + } + + // 电子缩放 + @Override + public void onZooming(int index, float dScale) { + if (IsPTZOpen == false) { + mPlayWin.doScale(dScale); + } + + } + + // 云台缩放 + @Override + public void onZoomEnd(int index, ZoomType zoom) { + Log.d(TAG, "onZoomEnd" + zoom); + if (IsPTZOpen == false) { + return; + } + // TODO Auto-generated method stub + sendCloudOrder(zoom == ZoomType.ZOOM_IN ? Cloud.zoomin + : Cloud.zoomout, false); + } + + // 滑动开始 + @Override + public boolean onSlipBegin(int index, Direction dir, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin "); + } + sendCloudOrder(direction2Cloud(dir), false); + return true; + } + + // 滑动中 + @Override + public void onSlipping(int index, Direction dir, float prex, + float prey, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin onFlinging"); + mPlayWin.doTranslate(dx, dy); + } + } + + // 滑动结束 + @Override + public void onSlipEnd(int index, Direction dir, float dx, float dy) { + if (IsPTZOpen == false && mPlayWin.getScale() > 1) { + Log.d(TAG, "onflingBegin onFlingEnd"); + return; + } + + // sendCloudOrder(Cloud.stop, false); + } + + private Cloud direction2Cloud(Direction dir) { + Cloud cloud = null; + switch (dir) { + case Up: + cloud = Cloud.up; + break; + case Down: + cloud = Cloud.down; + break; + case Left: + cloud = Cloud.left; + break; + case Right: + cloud = Cloud.right; + break; + case Left_up: + cloud = Cloud.leftUp; + break; + case Left_down: + cloud = Cloud.leftDown; + break; + case Right_up: + cloud = Cloud.rightUp; + break; + case Right_down: + cloud = Cloud.RightDown; + break; + default: + break; + } + return cloud; + } + + public void onWindowDBClick(int index, float dx, float dy) { + // TODO Auto-generated method stub + switch (mLiveMenu.getVisibility()) { + case View.GONE: + mLiveMenu.setVisibility(View.VISIBLE); + break; + case View.VISIBLE: + mLiveMenu.setVisibility(View.GONE); + break; + default: + break; + } + } + + } + + class AudioTalkerListener extends LCOpenSDK_TalkerListener { + /** + * 描述:对讲状态获取 + */ + @Override + public void onTalkResult(String error, int type) { + // TODO Auto-generated method stub + if (type == Business.RESULT_SOURCE_OPENAPI + || error.equals(AUDIO_TALK_ERROR) + || error.equals(PlayerResultCode.STATE_PACKET_FRAME_ERROR) + || error.equals(PlayerResultCode.STATE_RTSP_TEARDOWN_ERROR) + || error.equals(PlayerResultCode.STATE_RTSP_AUTHORIZATION_FAIL)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + // 提示对讲打开失败 + toast(R.string.video_monitor_talk_open_error); + stopTalk();// 关闭播放 + } + } + }); + } + } else if (error.equals(PlayerResultCode.STATE_RTSP_PLAY_READY)) { + if (mHander != null) { + mHander.post(new Runnable() { + public void run() { + if (isAdded()) { + // 提示对讲打开成功 + toast(R.string.video_monitor_media_talk_ready); + } + } + }); + } + mOpenTalk = AudioTalkStatus.talk_open; + } + + } + + @Override + public void onTalkPlayReady() { + // TODO Auto-generated method stub + + } + + @Override + public void onAudioRecord(byte[] pData, int length, int audioFormat, int sampleRate, int sampleDepth) { + super.onAudioRecord(pData, length, audioFormat, sampleRate, sampleDepth); + BufferedOutputStream bufferedOutputStream; + FileOutputStream fileOutputStream; + String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/AudioFile.pcm"; + File file = new File(filePath); + if (file.exists()) { + try { + fileOutputStream = new FileOutputStream(file, true); + bufferedOutputStream = new BufferedOutputStream(fileOutputStream); + try { + bufferedOutputStream.write(pData); + bufferedOutputStream.flush(); + bufferedOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + + } + } else { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public void onAudioReceive(byte[] pData, int length, int audioFormat, int sampleRate, int sampleDepth) { + super.onAudioReceive(pData, length, audioFormat, sampleRate, sampleDepth); + } + + } +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoRecycler.java b/app/src/main/java/com/lechange/demo/videoplay/VideoRecycler.java new file mode 100644 index 0000000..e1c006a --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoRecycler.java @@ -0,0 +1,54 @@ +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +import com.yonsz.z1.R; + + +public class VideoRecycler extends RecyclerView { + + public VideoRecycler(Context context) { + this(context, null); + } + + public VideoRecycler(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public VideoRecycler(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + private void initView() { + setBackgroundColor(getResources().getColor(R.color.colorAccent)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int width = 0; + int height = 0; + + width = widthSize; + switch (heightMode) { + case MeasureSpec.EXACTLY: + height = heightSize; + break; + default: + height = widthSize; + break; + } + if (height > heightSize) { + height = heightSize; + } + setMeasuredDimension(width, height); + } +} diff --git a/app/src/main/java/com/lechange/demo/videoplay/VideoTextureView.java b/app/src/main/java/com/lechange/demo/videoplay/VideoTextureView.java new file mode 100644 index 0000000..b8e335c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/videoplay/VideoTextureView.java @@ -0,0 +1,55 @@ +package com.lechange.demo.videoplay; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.TextureView; + +public class VideoTextureView extends TextureView { + public String TAG = getClass().getSimpleName(); + + public VideoTextureView(Context context) { + this(context, null); + } + + public VideoTextureView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + int width = 0; + int height = 0; + // Log.d(TAG, "onMeasure: widthMode-->" + widthMode + "heightMode-->" + heightMode); + // if (widthMode == MeasureSpec.EXACTLY) { + // // Parent has told us how big to be. So be it. + // width = widthSize; + // } else if (widthMode == MeasureSpec.AT_MOST) { + // width = 200; + // } else { + // width = widthSize; + // Log.d(TAG, "onMeasure: width else"); + // } + width = widthSize; + height = width * 3 / 4; + if (height > heightSize) { + height = heightSize; + } + + // if (heightMode == MeasureSpec.EXACTLY) { + // // Parent has told us how big to be. So be it. + // height = heightSize; + // } else if (widthMode == MeasureSpec.AT_MOST) { + // height = width * 3 / 4; + // } else { + // height = heightSize; + // } + // Log.d(TAG, "onMeasure: width-->" + width + "height-->" + height); + setMeasuredDimension(width, height); + } + +} diff --git a/app/src/main/java/com/lechange/demo/view/Direction.java b/app/src/main/java/com/lechange/demo/view/Direction.java new file mode 100644 index 0000000..aa879f5 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/Direction.java @@ -0,0 +1,9 @@ +package com.lechange.demo.view; + +/** + * 云台移动方向 8个方向 + */ + +public enum Direction { + Up, Down, Left, Right, Left_up, Left_down, Right_up, Right_down +} diff --git a/app/src/main/java/com/lechange/demo/view/LcCloudRudderView.java b/app/src/main/java/com/lechange/demo/view/LcCloudRudderView.java new file mode 100644 index 0000000..14ca4c6 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/LcCloudRudderView.java @@ -0,0 +1,437 @@ +package com.lechange.demo.view; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import com.yonsz.z1.R; + + +/** + * 云台控制面板 + */ +@SuppressLint("DrawAllocation") +public class LcCloudRudderView extends View { + private Point mRockerPosition; + private final Point mCtrlPoint = new Point(100, 100); + private float mSolidRudderRadius = 60; + private float mChangeRudderRadius = 60; + private int mWheelRadius = 100; + private RudderListener listener = null; + private int mDownState; + private int firstX, firstY; + private int dCtrlPointx, dCtrlPointy; + private static Bitmap mBigCircleBg; + private static Bitmap mBigCircleBg_h; + private static Bitmap mSmallCircleBg; + private static Bitmap mBigCircleLandScapeBg; + private static Bitmap mBigCircleLandScapeBg_h; + private static Bitmap mSmallCircleLandScapeBg; + private float mAngle; + private boolean mShowDirectPic; + private boolean mCanTouch = true; + private boolean mLandScapeOnly = false; + //支持四方向 + private boolean mSupportFourDirection=true; + + + public LcCloudRudderView(Context context) { + super(context); + init(); + } + + public LcCloudRudderView(Context context, AttributeSet attrs) { + super(context, attrs); + setAttribute(context, attrs); + init(); + } + + private void setAttribute(Context context, AttributeSet attrs) { + if (attrs != null) { + TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LcCloudRudderView); + mLandScapeOnly = array.getBoolean(R.styleable.LcCloudRudderView_landscape_only, false); + array.recycle(); + } + } + + private void init() { + setBackgroundColor(Color.TRANSPARENT); + this.setKeepScreenOn(true); + mCanTouch = true; + Paint mPaint = new Paint(); + mPaint.setColor(Color.GREEN); + mPaint.setAntiAlias(true); + mRockerPosition = new Point(mCtrlPoint); + setFocusable(true); + setFocusableInTouchMode(true); + + if (mBigCircleBg == null) { + mBigCircleBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_cloudstage_direction_default); + } + + if (mBigCircleBg_h == null) { + mBigCircleBg_h = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_cloudstage_direction_up); + } + + if (mSmallCircleBg == null) { + mSmallCircleBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_cloudstage_direction_button); + } + if (mBigCircleLandScapeBg == null) { + mBigCircleLandScapeBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_video_cloudstage_direction_default); + } + + if (mBigCircleLandScapeBg_h == null) { + mBigCircleLandScapeBg_h = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_video_cloudstage_direction_up); + } + + if (mSmallCircleLandScapeBg == null) { + mSmallCircleLandScapeBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_video_cloudstage_direction_button); + } + mSolidRudderRadius = (float) (mSmallCircleBg.getHeight() / 2.0); + } + + /** + * 重置云台背景图,为了区分4方向和8方向 + */ + public void resetCircleBg() { + if (mSupportFourDirection) { + if (mBigCircleBg != null) { + mBigCircleBg.recycle(); + mBigCircleBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_cloudstage_direction_default_four); + } + if (mBigCircleLandScapeBg != null) { + mBigCircleLandScapeBg.recycle(); + mBigCircleLandScapeBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_video_cloudstage_direction_default_four); + } + } else { + if (mBigCircleBg != null) { + mBigCircleBg.recycle(); + mBigCircleBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_cloudstage_direction_default); + } + if (mBigCircleLandScapeBg != null) { + mBigCircleLandScapeBg.recycle(); + mBigCircleLandScapeBg = BitmapFactory.decodeResource(getResources(), R.mipmap.play_module_video_cloudstage_direction_default); + } + } + invalidate(); + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Bitmap bigCirclebg = mLandScapeOnly ? mBigCircleLandScapeBg : mBigCircleBg; + if (bigCirclebg == null || bigCirclebg.isRecycled()) { + return; + } + + try { + canvas.save(); + canvas.translate(mCtrlPoint.x, mCtrlPoint.y); + canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + + Paint paint = new Paint(); + paint.setAntiAlias(true); + Rect srcRect = new Rect(0, 0, bigCirclebg.getWidth(), bigCirclebg.getHeight()); + RectF dstRcctF = new RectF(-mWheelRadius, -mWheelRadius, mWheelRadius, mWheelRadius); + canvas.drawBitmap(bigCirclebg, srcRect, dstRcctF, paint); + canvas.restore(); + + if (mShowDirectPic) { + + Bitmap bigCircleBg_h = mLandScapeOnly ? mBigCircleLandScapeBg_h : mBigCircleBg_h; + canvas.save(); + canvas.translate(mCtrlPoint.x, mCtrlPoint.y); + canvas.rotate(mAngle); + Rect srcRect2 = new Rect(0, 0, bigCircleBg_h.getWidth(), bigCircleBg_h.getHeight()); + RectF dstRcctF2 = new RectF(-mWheelRadius, -mWheelRadius, mWheelRadius, mWheelRadius); + canvas.drawBitmap(bigCircleBg_h, srcRect2, dstRcctF2, paint); + canvas.restore(); + } + + Bitmap smallCircleBg = mLandScapeOnly ? mSmallCircleLandScapeBg : mSmallCircleBg; + Rect srcRect3 = new Rect(0, 0, smallCircleBg.getWidth(), smallCircleBg.getHeight()); + RectF dstRcctF3 = new RectF(mRockerPosition.x - mChangeRudderRadius, mRockerPosition.y - mChangeRudderRadius, mRockerPosition.x + mChangeRudderRadius, mRockerPosition.y + mChangeRudderRadius); + canvas.drawBitmap(smallCircleBg, srcRect3, dstRcctF3, paint); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + + } + } + + + public void setRudderListener(RudderListener rockerListener) { + listener = rockerListener; + } + + public boolean isSupportFourDirection() { + return mSupportFourDirection; + } + + /** + * 设置是否支持四方向云台 + * + * @param supportFourDirection + */ + public void setSupportFourDirection(boolean supportFourDirection) { + this.mSupportFourDirection = supportFourDirection; + resetCircleBg(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!mCanTouch) { + return true; + } + int len = (int) Math.sqrt(Math.pow(mCtrlPoint.x - event.getX(), 2) + Math.pow(mCtrlPoint.y - event.getY(), 2)); + switch (event.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + if (len < mWheelRadius / 2) { + if (listener != null) { + listener.onSteeringWheelChangedBegin(); + } + mDownState = 1; + firstX = (int) event.getX(); + firstY = (int) event.getY(); + dCtrlPointx = firstX - mCtrlPoint.x; + dCtrlPointy = firstY - mCtrlPoint.y; + } else if (len >= (mWheelRadius / 2) && len <= mWheelRadius) { + if (listener != null) { + listener.onSteeringWheelChangedBegin(); + } + mDownState = 2; + mShowDirectPic = true; + firstX = (int) event.getX(); + firstY = (int) event.getY(); + dCtrlPointx = firstX - mCtrlPoint.x; + dCtrlPointy = firstY - mCtrlPoint.y; + float radian = getRadian(mCtrlPoint, new Point((int) event.getX(), (int) event.getY())); + int angle = LcCloudRudderView.this.getAngleConvert(radian); + Direction direction = directConvert(angle); + if (listener != null) { + listener.onSteeringWheelChangedSingle(direction); + } + } + invalidate(); + break; + case MotionEvent.ACTION_MOVE: + if (mDownState == 1) { + int dragLen = (int) Math.sqrt(Math.pow(firstX - event.getX(), 2) + Math.pow(firstY - event.getY(), 2)); + if (dragLen <= mWheelRadius - mChangeRudderRadius / 2) { + mRockerPosition.set((int) event.getX() - dCtrlPointx, (int) event.getY() - dCtrlPointy); + } else { + int cutRadius = (int) (mWheelRadius - mChangeRudderRadius / 2); + float radian = getRadian(mCtrlPoint, new Point((int) event.getX() - (firstX - mCtrlPoint.x), (int) event.getY() - (firstY - mCtrlPoint.y))); + mRockerPosition = new Point(mCtrlPoint.x + (int) (cutRadius * Math.cos(radian)), mCtrlPoint.y + (int) (cutRadius * Math.sin(radian))); + + } + float radian = getRadian(mCtrlPoint, new Point((int) event.getX(), (int) event.getY())); + int angle = LcCloudRudderView.this.getAngleConvert(radian); + Direction direction = directConvert(angle); + if (dragLen >= (mWheelRadius / 2)) {//超过 边界再发送命令 + mShowDirectPic = true; + if (listener != null) { + listener.onSteeringWheelChangedContinue(direction); + } + } else {//未超过边界,发送停止命令,图标不显示按下 + mShowDirectPic = false; + if (listener != null) { + listener.onSteeringWheelChangedContinue(null); + } + } + } else if (mDownState == 2) { + if (listener != null) { + if (len >= (mWheelRadius / 2) && len <= mWheelRadius) { + mShowDirectPic = true; + float radian = getRadian(mCtrlPoint, new Point((int) event.getX(), (int) event.getY())); + int angle = LcCloudRudderView.this.getAngleConvert(radian); + directConvert(angle); + } else { + mShowDirectPic = false; + } + } + + } + invalidate(); + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (mDownState == 1) { + mShowDirectPic = false; + mRockerPosition = new Point(mCtrlPoint); + if (listener != null) { + listener.onSteeringWheelChangedContinue(null); + listener.onSteeringWheelChangedEnd(); + } + + } else if (mDownState == 2) { + mShowDirectPic = false; + float radian = getRadian(mCtrlPoint, new Point((int) event.getX(), (int) event.getY())); + int angle = LcCloudRudderView.this.getAngleConvert(radian); + Direction direction = directConvert(angle); + mRockerPosition = new Point(mCtrlPoint); + if (listener != null) { + //listener.onSteeringWheelChangedSingle(direction); + listener.onSteeringWheelChangedEnd(); + } + } + firstX = 0; + firstY = 0; + mDownState = 0; + invalidate(); + break; + default: + break; + } + return true; + } + + private static float getRadian(Point a, Point b) { + float lenA = b.x - a.x; + float lenB = b.y - a.y; + float lenC = (float) Math.sqrt(lenA * lenA + lenB * lenB); + float ang = (float) Math.acos(lenA / lenC); + ang = ang * (b.y < a.y ? -1 : 1); + return ang; + } + + private Direction directConvert(int angle) { + Direction direction = Direction.Left; + if (mSupportFourDirection) { + if (angle <= 45 || angle > 315) { + direction = Direction.Right; + mAngle = 90; + } else if (angle > 45 && angle <= 135) { + direction = Direction.Up; + mAngle = 0; + } else if (angle > 135 && angle <= 225) { + direction = Direction.Left; + mAngle = 270; + } else if (angle > 225 && angle <= 315) { + direction = Direction.Down; + mAngle = 180; + } + + } else { + + if (angle <= 22.5 || angle > 337.5) { + direction = Direction.Right; + mAngle = 90; + } else if (angle > 22.5 && angle <= 67.5) { + direction = Direction.Right_up; + mAngle = 45; + } else if (angle > 67.5 && angle <= 112.5) { + direction = Direction.Up; + mAngle = 0; + } else if (angle > 112.5 && angle <= 157.5) { + direction = Direction.Left_up; + mAngle = 315; + } else if (angle > 157.5 && angle <= 202.5) { + direction = Direction.Left; + mAngle = 270; + } else if (angle > 202.5 && angle <= 247.5) { + direction = Direction.Left_down; + mAngle = 225; + } else if (angle > 247.5 && angle <= 292.5) { + direction = Direction.Down; + mAngle = 180; + } else if (angle > 292.5 && angle <= 337.5) { + direction = Direction.Right_down; + mAngle = 135; + } + } + + return direction; + } + + private int getAngleConvert(float radian) { + int tmp = (int) Math.round(radian / Math.PI * 180); + if (tmp < 0) { + return -tmp; + } else { + return 180 + (180 - tmp); + } + } + + public interface RudderListener { + void onSteeringWheelChangedBegin(); + + void onSteeringWheelChangedContinue(Direction direction); + + void onSteeringWheelChangedSingle(Direction direction); + + void onSteeringWheelChangedEnd(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + int len = Math.min(w, h) / 2; + mWheelRadius = (int) (len - mSolidRudderRadius / 2); + mChangeRudderRadius = mWheelRadius * 17 / 40; + + mCtrlPoint.set(w / 2, h / 2); + mRockerPosition.set(w / 2, h / 2); + postInvalidate(); + } + + public void enable(boolean enabled) { + if (mCanTouch && !enabled) { + mShowDirectPic = false; + mRockerPosition = new Point(mCtrlPoint); + invalidate(); + if (listener != null) { + listener.onSteeringWheelChangedContinue(null); + listener.onSteeringWheelChangedEnd(); + } + } + setEnabled(enabled); + setAlpha(enabled ? 1f : 0.5f); + mCanTouch = enabled; + } + + public void unit() { + Bitmap bigCirclebg = mLandScapeOnly ? mBigCircleLandScapeBg : mBigCircleBg; + Bitmap bigCircleBg_h = mLandScapeOnly ? mBigCircleLandScapeBg_h : mBigCircleBg_h; + Bitmap smallCircleBg = mLandScapeOnly ? mSmallCircleLandScapeBg : mSmallCircleBg; + if (bigCirclebg != null) { + bigCirclebg.recycle(); + if (mLandScapeOnly) { + mBigCircleLandScapeBg = null; + } else { + mBigCircleBg = null; + } + } + if (bigCircleBg_h != null) { + bigCircleBg_h.recycle(); + if (mLandScapeOnly) { + mBigCircleLandScapeBg_h = null; + } else { + mBigCircleBg_h = null; + } + } + if (smallCircleBg != null) { + smallCircleBg.recycle(); + if (mLandScapeOnly) { + mSmallCircleLandScapeBg = null; + } else { + mSmallCircleBg = null; + } + } + listener = null; + } +} diff --git a/app/src/main/java/com/lechange/demo/view/LcPopupWindow.java b/app/src/main/java/com/lechange/demo/view/LcPopupWindow.java new file mode 100644 index 0000000..b9b8227 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/LcPopupWindow.java @@ -0,0 +1,63 @@ +package com.lechange.demo.view; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; + +import com.common.openapi.entity.DeviceDetailListData; +import com.lechange.demo.adapter.PixelListAdapter; +import com.yonsz.z1.R; + +import java.util.List; + +/** + * 显示支持分辨率的弹框 + */ +public class LcPopupWindow extends PopupWindow { + + private RecyclerView pixelRecycle; +// private ArrayList mData = new ArrayList<>(); + private PixelListAdapter mPixelAdapter; + + public LcPopupWindow(Context context, List dataList) { + super(context); + setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); + setOutsideTouchable(true); + setFocusable(true); + setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + View contentView = LayoutInflater.from(context).inflate(R.layout.view_pixel_popwindow, + null, false); + pixelRecycle = contentView.findViewById(R.id.pixel_recycle); + pixelRecycle.setLayoutManager(new LinearLayoutManager(context)); + mPixelAdapter = new PixelListAdapter(context,dataList); + pixelRecycle.setAdapter(mPixelAdapter); + setContentView(contentView); + } + + public void setPixelRecycleListener(onRecyclerViewItemClickListener listener){ + mPixelAdapter.setOnItemClickListener(listener); + } + + @SuppressWarnings("ResourceType") + public int makeDropDownMeasureSpec(int measureSpec) { + int mode; + if (measureSpec == ViewGroup.LayoutParams.WRAP_CONTENT) { + mode = View.MeasureSpec.UNSPECIFIED; + } else { + mode = View.MeasureSpec.EXACTLY; + } + return View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(measureSpec), mode); + } + + public interface onRecyclerViewItemClickListener{ + void onItemClick(RecyclerView parent, View view, int position, String name, int imageSize, int streamType); + } + +} diff --git a/app/src/main/java/com/lechange/demo/view/LcProgressBar.java b/app/src/main/java/com/lechange/demo/view/LcProgressBar.java new file mode 100644 index 0000000..bcc5542 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/LcProgressBar.java @@ -0,0 +1,68 @@ +package com.lechange.demo.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.widget.ProgressBar; + +import com.yonsz.z1.R; + + +public class LcProgressBar extends ProgressBar { + + private final Paint progressPaint = new Paint(); + private Context context; + private String content = getResources().getString(R.string.lc_demo_device_update); + private int textColor = getResources().getColor(R.color.lc_demo_color_0B8C0D); + + public LcProgressBar(Context context) { + this(context, null); + } + + public LcProgressBar(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + init(); + } + + private void init() { + progressPaint.setStrokeWidth(4); + progressPaint.setStyle(Paint.Style.FILL); + progressPaint.setColor(textColor); + progressPaint.setTextSize(dip2Px(context.getResources().getDimensionPixelSize(R.dimen.x12))); + progressPaint.setTextAlign(Paint.Align.CENTER); + progressPaint.setAntiAlias(true); + } + + private int dip2Px(int dip) { + float density = context.getResources().getDisplayMetrics().density; + int px = (int) (dip * density + 0.5f); + return px; + } + + @Override + protected synchronized void onDraw(Canvas canvas) { + super.onDraw(canvas); + Rect rect = new Rect(); + progressPaint.getTextBounds(this.content, 0, this.content.length(), rect); + int x = (getWidth() / 2) ; + int y = (getHeight() / 2) - rect.centerY(); + canvas.drawText(this.content, x, y, this.progressPaint); + } + + public void setText(String text) { + this.content = text; + postInvalidate(); + } + public void setTextColor(int color) { + this.textColor = color; + progressPaint.setColor(textColor); + postInvalidate(); + } +} diff --git a/app/src/main/java/com/lechange/demo/view/LcPullToRefreshRecyclerView.java b/app/src/main/java/com/lechange/demo/view/LcPullToRefreshRecyclerView.java new file mode 100644 index 0000000..ae71ac2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/LcPullToRefreshRecyclerView.java @@ -0,0 +1,87 @@ +package com.lechange.demo.view; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; + +import com.lechange.pulltorefreshlistview.Mode; +import com.lechange.pulltorefreshlistview.Orientation; +import com.lechange.pulltorefreshlistview.PullToRefreshBase; + +public class LcPullToRefreshRecyclerView extends PullToRefreshBase { + public LcPullToRefreshRecyclerView(Context context) { + super(context); + } + + public LcPullToRefreshRecyclerView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LcPullToRefreshRecyclerView(Context context, Mode mode) { + super(context, mode); + } + + @Override + public Orientation getPullToRefreshScrollDirection() { + return Orientation.VERTICAL; + } + + @Override + protected RecyclerView createRefreshableView(Context context, AttributeSet attrs) { + RecyclerView recyclerView = new RecyclerView(context); + return recyclerView; + } + + + @Override + protected boolean isReadyForPullStart() { + return isFirstItemVisible(); + } + + public boolean isFirstItemVisible() { + final RecyclerView.Adapter adapter = getRefreshableView().getAdapter(); + + //如果未设置Adapter或者Adpter没有数据可以下拉刷新 + if(null == adapter || adapter.getItemCount() == 0){ + return true; + }else{ + if(getFristVisiblePosition() == 0){ + return mRefreshableView.getChildAt(0).getTop() >= mRefreshableView.getTop(); + } + } + + return false; + } + + public int getFristVisiblePosition() { + View firstVisibleChild = mRefreshableView.getChildAt(0); + return firstVisibleChild != null ? mRefreshableView.getChildPosition(firstVisibleChild) : -1; + } + + @Override + protected boolean isReadyForPullEnd() { + return isLastItemVisible(); + } + + public boolean isLastItemVisible() { + final RecyclerView.Adapter adapter = getRefreshableView().getAdapter(); + + //如果未设置Adapter或者Adpter没有数据可以下拉刷新 + if(null == adapter || adapter.getItemCount() == 0){ + return true; + }else{ + if(getLastVisiblePosition() == adapter.getItemCount() - 1){ + return mRefreshableView.getChildAt(mRefreshableView.getChildCount() - 1).getBottom() <= mRefreshableView.getBottom(); + } + } + + return false; + } + + public int getLastVisiblePosition() { + View lastVisibleChild = mRefreshableView.getChildAt(mRefreshableView.getChildCount() - 1); + return lastVisibleChild != null ? mRefreshableView.getChildPosition(lastVisibleChild) : -1; + } + +} diff --git a/app/src/main/java/com/lechange/demo/view/RecoderSeekBar.java b/app/src/main/java/com/lechange/demo/view/RecoderSeekBar.java new file mode 100644 index 0000000..a398043 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/RecoderSeekBar.java @@ -0,0 +1,34 @@ +package com.lechange.demo.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +public class RecoderSeekBar extends android.support.v7.widget.AppCompatSeekBar { + + private boolean canTouchAble = true; + + public RecoderSeekBar(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public RecoderSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RecoderSeekBar(Context context) { + super(context); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!canTouchAble) { + return true; + } + return super.onTouchEvent(event); + } + + public void setCanTouchAble(boolean canTouchAble) { + this.canTouchAble = canTouchAble; + } +} diff --git a/app/src/main/java/com/lechange/demo/view/SpacesItemDecoration.java b/app/src/main/java/com/lechange/demo/view/SpacesItemDecoration.java new file mode 100644 index 0000000..9512d00 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/view/SpacesItemDecoration.java @@ -0,0 +1,23 @@ +package com.lechange.demo.view; + +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +public class SpacesItemDecoration extends RecyclerView.ItemDecoration { + private int space; + + public SpacesItemDecoration(int space) { + this.space = space; + } + + @Override + public void getItemOffsets(Rect outRect, View view, + RecyclerView parent, RecyclerView.State state) { + + // Add top margin only for the first item to avoid double space between items + if (parent.getChildPosition(view) != 0){ + outRect.left = space; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/AddCompleteAndRenameActivity.java b/app/src/main/java/com/lechange/demo/yonsz/AddCompleteAndRenameActivity.java new file mode 100644 index 0000000..ef687b2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/AddCompleteAndRenameActivity.java @@ -0,0 +1,345 @@ +package com.lechange.demo.yonsz; + +import android.os.Bundle; +import android.os.Message; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUrl; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.utils.ToastUtil; +import com.yonsz.z1.view.TitleView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_FAIL; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_SUCCESS; + +/** + * Created by Administrator on 2019/2/27. + */ + + +public class AddCompleteAndRenameActivity extends BaseActivity implements CompoundButton.OnCheckedChangeListener { + private TitleView mTitleView; + private Button nextConfig; + + private CheckBox[] timeCheckBox = new CheckBox[14]; + private List positionIds = new ArrayList<>(); + private CompoundButton lastTimeCheckBox; + private String deviceAddress = "1"; + private List condition = new ArrayList<>(); + private String addressId; + private TextView deviceName; + private ImageView cleanIv; + + public void onEventMainThread(EventBusEntity event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_modify_camera_name); + initView(); + initListener(); + } + + private void initView() { + addressId = deviceAddress; + cleanIv = (ImageView) findViewById(R.id.iv_clean); + cleanIv.setOnClickListener(this); + deviceName = (TextView) findViewById(R.id.edit_device_name); + nextConfig = (Button) findViewById(R.id.bt_sure_config); + nextConfig.setOnClickListener(this); + mTitleView = (TitleView) findViewById(R.id.title_switcher_two); + mTitleView.setHead(R.string.add_device); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + + positionIds.add(R.id.cb_position0); + positionIds.add(R.id.cb_position1); + positionIds.add(R.id.cb_position2); + positionIds.add(R.id.cb_position3); + positionIds.add(R.id.cb_position4); + positionIds.add(R.id.cb_position5); + positionIds.add(R.id.cb_position6); + positionIds.add(R.id.cb_position7); + positionIds.add(R.id.cb_position8); + positionIds.add(R.id.cb_position9); + positionIds.add(R.id.cb_position10); + positionIds.add(R.id.cb_position11); + positionIds.add(R.id.cb_position12); + positionIds.add(R.id.cb_position13); + for (int i = 0; i < positionIds.size(); i++) { + timeCheckBox[i] = (CheckBox) findViewById(positionIds.get(i)); + timeCheckBox[i].setOnCheckedChangeListener(this); + } + + switch (deviceAddress) { + case "0": + timeCheckBox[13].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position13); + condition.add("13"); + break; + case "1": + timeCheckBox[0].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position0); + condition.add("0"); + break; + case "2": + timeCheckBox[1].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position1); + condition.add("1"); + break; + case "3": + timeCheckBox[2].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position2); + condition.add("2"); + break; + case "4": + timeCheckBox[3].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position3); + condition.add("3"); + break; + case "5": + timeCheckBox[4].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position4); + condition.add("4"); + break; + case "6": + timeCheckBox[5].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position5); + condition.add("5"); + break; + case "7": + timeCheckBox[6].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position6); + condition.add("6"); + break; + case "8": + timeCheckBox[7].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position7); + condition.add("7"); + break; + case "9": + timeCheckBox[8].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position8); + condition.add("8"); + break; + case "10": + timeCheckBox[9].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position9); + condition.add("9"); + break; + case "11": + timeCheckBox[10].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position10); + condition.add("10"); + break; + case "12": + timeCheckBox[11].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position11); + condition.add("11"); + break; + case "13": + timeCheckBox[12].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position12); + condition.add("12"); + break; + } + + // deviceName.setText(AddressNameUtil.getAddressName(localAddAddressId) + "摄像头"); + deviceName.setText("摄像头"); + } + + private void modifyDevice(String addressId) { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + /*if (addressId.equals("13")) { + map.put("addressId", "0"); + } else { + map.put("addressId", String.valueOf(Integer.valueOf(addressId) + 1)); + }*/ + // map.put("addressId", localAddAddressId); + map.put("deviceId", getIntent().getExtras().get("deviceSN").toString()); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + map.put("deviceName", deviceName.getText().toString().trim()); + util.requestPostByAsynewApi(NetWorkUrl.MODIFY_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("updateBlindEntityName", "ShareDeviceActivity onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + private void initListener() { + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.bt_sure_config: + modifyDevice(addressId); + break; + case R.id.iv_clean: + deviceName.setText(""); + break; + } + } + + @Override + public void callBackUiThread(Message msg) { + switch (msg.what) { + case UPDATE_BLINDENTITY_NAME_SUCCESS: + Toast.makeText(AddCompleteAndRenameActivity.this, "添加成功", Toast.LENGTH_SHORT).show(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + finish(); + } + }, 2000); + break; + case UPDATE_BLINDENTITY_NAME_FAIL: + ToastUtil.show(this, (String) msg.obj); + break; + } + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + int id = buttonView.getId(); + //如果是时间筛选 + if (positionIds.contains(id)) { + if (isChecked) { + if (lastTimeCheckBox != null) { + lastTimeCheckBox.setChecked(false); + } + lastTimeCheckBox = buttonView; + } else { + boolean isForceCheck = true; + for (int i = 0; i < timeCheckBox.length; i++) { + if (timeCheckBox[i].isChecked()) { + isForceCheck = false; + } + } + if (isForceCheck) { + buttonView.setChecked(true); + } + } + } + switch (id) { + case R.id.cb_position0: + if (isChecked) + addressId = "0"; + break; + case R.id.cb_position1: + if (isChecked) + addressId = "1"; + break; + case R.id.cb_position2: + if (isChecked) + addressId = "2"; + break; + case R.id.cb_position3: + if (isChecked) + addressId = "3"; + break; + case R.id.cb_position4: + if (isChecked) + addressId = "4"; + break; + case R.id.cb_position5: + if (isChecked) + addressId = "5"; + break; + case R.id.cb_position6: + if (isChecked) + addressId = "6"; + break; + case R.id.cb_position7: + if (isChecked) + addressId = "7"; + break; + case R.id.cb_position8: + if (isChecked) + addressId = "8"; + break; + case R.id.cb_position9: + if (isChecked) + addressId = "9"; + break; + case R.id.cb_position10: + if (isChecked) + addressId = "10"; + break; + case R.id.cb_position11: + if (isChecked) + addressId = "11"; + break; + case R.id.cb_position12: + if (isChecked) + addressId = "12"; + break; + case R.id.cb_position13: + if (isChecked) + addressId = "13"; + break; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/CameraDetailActivity.java b/app/src/main/java/com/lechange/demo/yonsz/CameraDetailActivity.java new file mode 100644 index 0000000..753c783 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/CameraDetailActivity.java @@ -0,0 +1,603 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.entity.ChannelInfo; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.createfamily.floor.ChooseRoomInFloorActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.AddressNameUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.utils.ToastUtil; +import com.yonsz.z1.version5.ModifyRoomActivity; +import com.yonsz.z1.view.TitleView; + +import java.util.HashMap; + +import de.greenrobot.event.EventBus; + +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.CHECK_USER_BIND_FAIL; +import static com.yonsz.z1.net.Constans.FIND_DEVICES_FAIL; +import static com.yonsz.z1.net.Constans.FIND_DEVICES_SUCCESS; +import static com.yonsz.z1.net.Constans.GET_SWITCHER_CHANGE_INFO; +import static com.yonsz.z1.net.Constans.MODIFY_ALARM_STATUS_SUCCESS; +import static com.yonsz.z1.net.Constans.MODIFY_DEVICE_NAME; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; +import static com.yonsz.z1.net.NetWorkUrl.DEVICE_LIST; +import static com.yonsz.z1.net.NetWorkUrl.MODIFY_ALARM_STATUS; +import static com.yonsz.z1.net.NetWorkUrl.UNBIND_DEVICE; +import static com.yonsz.z1.version5.MainFragment5.isRefreshCamera; + +/** + * Created by Administrator on 2019/2/27. + */ + +public class CameraDetailActivity extends BaseActivity { + private TitleView mTitleView; + private TextView deleteDevice; + private RelativeLayout rl_device_storage, rl_alarm; + private String mChannelUUID = null; + private CheckBox cb_camera_reverse, cb_device_light, cb_device_check, cb_device_alarm; + private TextView tv_wifi_name, tv_device_name, tv_device_version; + private ImageView iv_last_pic; + private LinearLayout ll_device_detail_top; + private ChannelInfo channel; + private TextView tv_device_address; + private String devicePosition = "1"; + private String deviceCode; + + public void onEventMainThread(ChooseHomeEvent event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + if (msg.equals("1") || msg.equals("3") || msg.equals("2") || msg.equals("5")) { + + } else { + tv_device_name.setText(msg); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_camera_detail); + initView(); + initListener(); + } + + private void initView() { + mChannelUUID = getIntent().getStringExtra("UUID"); // 获取通道的UUID + ll_device_detail_top = (LinearLayout) findViewById(R.id.ll_device_detail_top); + tv_device_name = (TextView) findViewById(R.id.tv_device_name); + tv_device_version = (TextView) findViewById(R.id.tv_device_version); + iv_last_pic = (ImageView) findViewById(R.id.iv_last_pic); + tv_wifi_name = (TextView) findViewById(R.id.tv_wifi_name); + cb_camera_reverse = (CheckBox) findViewById(R.id.cb_camera_reverse); + cb_device_light = (CheckBox) findViewById(R.id.cb_device_light); + cb_device_check = (CheckBox) findViewById(R.id.cb_device_check); + cb_device_alarm = (CheckBox) findViewById(R.id.cb_device_alarm); + rl_device_storage = (RelativeLayout) findViewById(R.id.rl_device_storage); + rl_alarm = (RelativeLayout) findViewById(R.id.rl_alarm); + deleteDevice = (TextView) findViewById(R.id.tv_delete_device); + tv_device_address = (TextView) findViewById(R.id.tv_device_address); + mTitleView = (TitleView) findViewById(R.id.title_device_detail); + mTitleView.setHead("设备详情"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + //获取设备基本信息 + channel = Business.getInstance().getChannel(mChannelUUID); + // String deviceName = channel.getDeviceName(); + // final String backgroudImgURL = channel.getBackgroudImgURL(); + deviceCode = channel.getDeviceCode(); + if (channel.getDeviceName().contains("的")) { + devicePosition = channel.getDeviceName().substring(0, channel.getDeviceName().indexOf("的")); + tv_device_address.setText(devicePosition); + } + tv_device_name.setText(channel.getName()); + tv_device_version.setText(channel.getDeviceModel()); + /*if (backgroudImgURL != null && backgroudImgURL.length() > 0) { + //下载 注:由于有些请求的图片是经过加密处理的,所以需要使用带有解密功能的接口,默认密码为设备序列号 + ImageHelper.loadCacheImage(backgroudImgURL, deviceCode, deviceCode, new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + if (backgroudImgURL.hashCode() == msg.what && msg.obj != null) { + // mBgDevice.setBackgroundDrawable((Drawable) msg.obj); + iv_last_pic.setImageDrawable((Drawable) msg.obj); + } + } + }); + }*/ + /*new AsyncTask() { + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected Object doInBackground(Object[] objects) { + //获取当前网络 + currentDeviceWifi(); + //获取设备指示灯状态 + breathingLightStatus(); + //获取摄像头翻转状态 + frameReverseStatus(); + return null; + } + + @Override + protected void onProgressUpdate(Object[] values) { + super.onProgressUpdate(values); + } + + @Override + protected void onPostExecute(Object o) { + super.onPostExecute(o); + } + }.execute();*/ + //获取当前网络 + getLcDeviceList(); + } + + private void initListener() { + rl_device_storage.setOnClickListener(this); + cb_camera_reverse.setOnClickListener(this); + cb_device_light.setOnClickListener(this); + cb_device_check.setOnClickListener(this); + cb_device_alarm.setOnClickListener(this); + deleteDevice.setOnClickListener(this); + ll_device_detail_top.setOnClickListener(this); + tv_device_address.setOnClickListener(this); + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.rl_device_storage: + Intent intent = new Intent(CameraDetailActivity.this, RecoverSDCardActivity.class); + intent.putExtra("UUID", mChannelUUID); + startActivity(intent); + break; + case R.id.cb_camera_reverse: + if (cb_camera_reverse.isChecked()) { + modifyFrameReverseStatus("reverse"); + } else { + modifyFrameReverseStatus("normal"); + } + break; + case R.id.cb_device_light: + if (cb_device_light.isChecked()) { + modifyBreathingLight("on"); + } else { + modifyBreathingLight("off"); + } + break; + case R.id.cb_device_check: + if (cb_device_check.isChecked()) { + modifyAlarmPlan(true); + } else { + modifyAlarmPlan(false); + } + break; + case R.id.cb_device_alarm: + if (cb_device_alarm.isChecked()) { + modifyAlarmStatus("1"); + } else { + modifyAlarmStatus("0"); + } + break; + case R.id.tv_delete_device: + ConfirmDialog dialog = new ConfirmDialog(this, new Callback() { + @Override + public void callback(int position) { + switch (position) { + case 0: + break; + case 1: + unBindDevice(); + break; + } + } + }); + dialog.setContent("是否删除摄像头?"); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn(R.string.sure); + dialog.setCancelable(false); + dialog.show(); + break; + case R.id.ll_device_detail_top: + Intent intent1 = new Intent(CameraDetailActivity.this, CameraNameDetailActivity.class); + intent1.putExtra("UUID", mChannelUUID); + startActivity(intent1); + break; + case R.id.tv_device_address: + Intent intent2; + + if (null != homeListEntity && !TextUtils.isEmpty(homeListEntity.getData().get(deviceNumListPosition).getFloorList())) { + intent2 = new Intent(this, ChooseRoomInFloorActivity.class); + intent2.putExtra("floorList", homeListEntity.getData().get(deviceNumListPosition).getFloorList()); + intent2.putExtra("houseTypeName", "房间选择"); + intent2.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + + intent2.putExtra("deviceId", channel.getDeviceCode()); + intent2.putExtra("ziId", ""); + intent2.putExtra("deviceType", "102"); + intent2.putExtra("deviceModel", "0"); + intent2.putExtra("addressId", AddressNameUtil.getAddressId(devicePosition)); + intent2.putExtra("deviceAddress", AddressNameUtil.getAddressId(devicePosition)); + startActivityForResult(intent2, MODIFY_DEVICE_NAME); + } else { + /*intent = new Intent(getActivity(), ModifyRoomActivity.class); + intent.putExtra("ziId", ziId); + intent.putExtra("deviceType", "000"); + intent.putExtra("deviceModel", "0"); + intent.putExtra("addressId", AddressNameUtil.getAddressId(devicePositionTv.getText().toString())); + intent.putExtra("deviceId", ziId); + startActivityForResult(intent, MODIFY_DEVICE_NAME);*/ + + intent2 = new Intent(CameraDetailActivity.this, ModifyRoomActivity.class); + intent2.putExtra("deviceAddress", AddressNameUtil.getAddressId(devicePosition)); + intent2.putExtra("deviceId", channel.getDeviceCode()); + + intent2.putExtra("ziId", ""); + intent2.putExtra("deviceType", CAMERA_TAG); + intent2.putExtra("deviceModel", "0"); + intent2.putExtra("addressId", AddressNameUtil.getAddressId(devicePosition)); + startActivityForResult(intent2, GET_SWITCHER_CHANGE_INFO); + } + + break; + } + } + + private void modifyAlarmStatus(String state) { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + // map.put("deviceId", "4K0586CPAJ58121"); + map.put("deviceId", channel.getDeviceCode()); + map.put("alarmStatus", state); + netWorkUtil.requestPostByAsynewApi(MODIFY_ALARM_STATUS, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("modifyAlarmStatus", "onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(MODIFY_ALARM_STATUS_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + android.os.Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void unBindDevice() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + // map.put("deviceId", "4K0586CPAJ58121"); + map.put("deviceId", channel.getDeviceCode()); + netWorkUtil.requestPostByAsynewApi(UNBIND_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + + /*mChannelInfoList.remove(mChannelInfoList.get(lechengPosition)); + mHorizontalAdapter.notifyDataSetChanged();*/ + // getLcDeviceList(); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + isRefreshCamera = true; + Log.i("unBindDevice", "onSuccess()" + respone); + EventBus.getDefault().post( + new EventBusEntity("关闭")); + EventBus.getDefault().post( + new ChooseHomeEvent("2")); + finish(); + } else { + Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + android.os.Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void currentDeviceWifi() { + Business.getInstance().currentDeviceWifi(mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final String obj = (String) msg.obj; + runOnUiThread(new Runnable() { + @Override + public void run() { + tv_wifi_name.setText(obj); + //获取设备指示灯状态 + breathingLightStatus(); + } + }); + } else { + /*Toast.makeText( + CameraDetailActivity.this, + R.string.toast_storagestrategy_update_failed, + Toast.LENGTH_SHORT).show();*/ + + } + } + }); + } + + private void breathingLightStatus() { + Business.getInstance().breathingLightStatus(mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final int arg1 = msg.arg1; + runOnUiThread(new Runnable() { + @Override + public void run() { + if (arg1 == 1) { + cb_device_light.setChecked(true); + } else { + cb_device_light.setChecked(false); + } + //获取摄像头翻转状态 + frameReverseStatus(); + } + }); + + } else { + /*Toast.makeText( + CameraDetailActivity.this, + R.string.toast_storagestrategy_update_failed, + Toast.LENGTH_SHORT).show();*/ + + } + } + }); + } + + /** + * 修改动检计划状态 + * + * @param enable 动检计划开启与否 + */ + private void modifyAlarmPlan(final boolean enable) { + Business.getInstance().modifyAlarmStatus(enable, mChannelUUID, + new Handler() { + + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText(CameraDetailActivity.this, + R.string.toast_alarmplan_modifyalarmstatus_success, + Toast.LENGTH_LONG).show(); + if (enable) { + rl_alarm.setVisibility(View.VISIBLE); + } else { + rl_alarm.setVisibility(View.GONE); + } + } else { + Toast.makeText(CameraDetailActivity.this, + R.string.toast_alarmplan_modifyalarmstatus_failed, + Toast.LENGTH_LONG).show(); + } + } + + }); + } + + + private void modifyBreathingLight(String state) { + Business.getInstance().modifyBreathingLight(state, mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + CameraDetailActivity.this, + "修改成功", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + CameraDetailActivity.this, + "修改失败", + Toast.LENGTH_SHORT).show(); + + } + } + }); + } + + private void frameReverseStatus() { + Business.getInstance().frameReverseStatus(mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final int obj = msg.arg1; + runOnUiThread(new Runnable() { + @Override + public void run() { + if (obj == 1) { + cb_camera_reverse.setChecked(true); + } else { + cb_camera_reverse.setChecked(false); + } + getAlarmStatus(); + } + }); + } else { + + } + } + }); + } + + private void getAlarmStatus() { + Business.getInstance().getAlarmStatus(mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + final int obj = msg.arg1; + runOnUiThread(new Runnable() { + @Override + public void run() { + if (obj == 1) { + cb_device_check.setChecked(true); + rl_alarm.setVisibility(View.VISIBLE); + } else { + cb_device_check.setChecked(false); + rl_alarm.setVisibility(View.GONE); + } + } + }); + } else { + + } + } + }); + } + + private void modifyFrameReverseStatus(String state) { + Business.getInstance().modifyFrameReverseStatus(state, mChannelUUID, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + CameraDetailActivity.this, + "修改成功", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + CameraDetailActivity.this, + "修改失败", + Toast.LENGTH_SHORT).show(); + + } + } + }); + } + + @Override + public void callBackUiThread(Message msg) { + switch (msg.what) { + case FIND_DEVICES_SUCCESS: + LcListEntity obj = (LcListEntity) msg.obj; + for (int i = 0; i < obj.getData().size(); i++) { + if (deviceCode.equals(obj.getData().get(i).getDeviceId())) { + tv_device_version.setText(obj.getData().get(i).getVersion()); + if (obj.getData().get(i).getAlarmStatus().equals("1")) { + cb_device_alarm.setChecked(true); + } else { + cb_device_alarm.setChecked(false); + } + } + } + currentDeviceWifi(); + break; + case CHECK_USER_BIND_FAIL: + ToastUtil.show(this, (String) msg.obj); + break; + case MODIFY_ALARM_STATUS_SUCCESS: + ToastUtil.show(this, "修改报警消息提醒成功"); + break; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case GET_SWITCHER_CHANGE_INFO: + case MODIFY_DEVICE_NAME: + if (data != null && data.getExtras().get("addressId") != null) { + String addressId = data.getExtras().get("addressId").toString(); + tv_device_address.setText(AddressNameUtil.getAddressName(addressId)); + // addressId = data.getExtras().get("addressId").toString(); + } + break; + } + } + + private synchronized void getLcDeviceList() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + netWorkUtil.requestPostByAsynewApi(DEVICE_LIST, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("findDevices", "onSuccess()" + respone); + LcListEntity obj = JSON.parseObject(respone, LcListEntity.class); + if (1 == obj.getFlag()) { + android.os.Message msg = mHandler.obtainMessage(FIND_DEVICES_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + android.os.Message msg = mHandler.obtainMessage(FIND_DEVICES_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + android.os.Message msg = mHandler.obtainMessage(FIND_DEVICES_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/CameraNameDetailActivity.java b/app/src/main/java/com/lechange/demo/yonsz/CameraNameDetailActivity.java new file mode 100644 index 0000000..2f40ee2 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/CameraNameDetailActivity.java @@ -0,0 +1,171 @@ +package com.lechange.demo.yonsz; + +import android.content.ClipboardManager; +import android.content.Context; +import android.os.Bundle; +import android.os.Message; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.lechange.demo.business.Business; +import com.lechange.demo.business.entity.ChannelInfo; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.ChooseHomeEvent; +import com.yonsz.z1.listener.NoDoubleClickListener; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.mine.aboutversion.customview.RenameNameDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback1; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUrl; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.view.TitleView; + +import java.util.HashMap; + +import de.greenrobot.event.EventBus; + +import static com.yonsz.z1.UniKongApp.getActivity; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_FAIL; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_SUCCESS; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; + +/** + * Created by Administrator on 2019/3/12. + */ + +public class CameraNameDetailActivity extends BaseActivity { + private TitleView mTitleView; + private String mChannelUUID; + private ChannelInfo channel; + private TextView tv_device_name, tv_device_type, tv_device_code, tv_device_code_copy; + private ImageView ImageView01_name_edit; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_camera_name); + initView(); + } + + private void initView() { + mChannelUUID = getIntent().getStringExtra("UUID"); // 获取通道的UUID + channel = Business.getInstance().getChannel(mChannelUUID); + mTitleView = (TitleView) findViewById(R.id.title_camera_name); + mTitleView.setHead("设备详情"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + tv_device_name = (TextView) findViewById(R.id.tv_device_name); + tv_device_type = (TextView) findViewById(R.id.tv_device_type); + tv_device_code = (TextView) findViewById(R.id.tv_device_code); + tv_device_code_copy = (TextView) findViewById(R.id.tv_device_code_copy); + ImageView01_name_edit = (ImageView) findViewById(R.id.ImageView01_name_edit); + tv_device_name.setText(channel.getName()); + tv_device_type.setText(channel.getDeviceModel()); + tv_device_code.setText(channel.getDeviceCode()); + tv_device_code_copy.setOnClickListener(new NoDoubleClickListener() { + @Override + protected void onNoDoubleClick(View v) { + ClipboardManager cmb = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); + cmb.setText(tv_device_code.getText()); //将内容放入粘贴管理器,在别的地方长按选择"粘贴"即可 + cmb.getText();//获取粘贴信息 + Toast.makeText(CameraNameDetailActivity.this, "复制成功!", Toast.LENGTH_SHORT).show(); + } + }); + ImageView01_name_edit.setOnClickListener(new NoDoubleClickListener() { + @Override + protected void onNoDoubleClick(View v) { + RenameNameDialog dialog = new RenameNameDialog(CameraNameDetailActivity.this, new Callback1() { + @Override + public void callback(int position, String positioName) { + switch (position) { + case 0: + break; + case 1: + if (TextUtils.isEmpty(positioName.trim())) { + return; + } + modifyDevice(positioName); + break; + } + } + }); + dialog.setOldName(channel.getName()); + dialog.setContent("修改摄像机名称"); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn(R.string.save); + dialog.setCancelable(false); + dialog.show(); + } + }); + + } + + private void modifyDevice(final String deviceName) { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", channel.getDeviceCode()); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + map.put("deviceName", deviceName); + util.requestPostByAsynewApi(NetWorkUrl.MODIFY_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("updateBlindEntityName", "ShareDeviceActivity onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_SUCCESS); + msg.obj = deviceName; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + @Override + public void callBackUiThread(Message msg) { + switch (msg.what) { + case UPDATE_BLINDENTITY_NAME_SUCCESS: + String obj = (String) msg.obj; + tv_device_name.setText(obj); + channel.setDeviceName(obj); + EventBus.getDefault().post( + new ChooseHomeEvent(obj)); + EventBus.getDefault().post( + new ChooseHomeEvent("2")); + break; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/CustomSnapHelper.java b/app/src/main/java/com/lechange/demo/yonsz/CustomSnapHelper.java new file mode 100644 index 0000000..511bedf --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/CustomSnapHelper.java @@ -0,0 +1,87 @@ +package com.lechange.demo.yonsz; + +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.LinearSnapHelper; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yonsz.z1.listener.OnRecyclerScrollListener; + +/** + * Created by loonggg on 2017/2/6. + */ + +public class CustomSnapHelper extends LinearSnapHelper { + private OrientationHelper mHorizontalHelper; + private OnRecyclerScrollListener mRecyclerScrollListener; + + @Override + public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) { + int[] out = new int[2]; + //判断支持水平滚动,修改水平方向的位置,是修改的out[0]的值 + if (layoutManager.canScrollHorizontally()) { + out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager)); + } else { + out[0] = 0; + } + return out; + } + + private int distanceToStart(View targetView, OrientationHelper helper) { + return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding(); + } + + @Override + public View findSnapView(RecyclerView.LayoutManager layoutManager) { + return findStartView(layoutManager, getHorizontalHelper(layoutManager)); + } + + private View findStartView(RecyclerView.LayoutManager layoutManager, + OrientationHelper helper) { + + if (layoutManager instanceof LinearLayoutManager) { + int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); + int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); + if (firstChild == RecyclerView.NO_POSITION) { + return null; + } + //这行的作用是如果是最后一个,翻到最后一条,解决显示不全的问题 + /*if (lastChild == layoutManager.getItemCount() - 1) { + return layoutManager.findViewByPosition(lastChild); + }*/ + + View child = layoutManager.findViewByPosition(firstChild); + if (mRecyclerScrollListener != null) { + if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2 && helper.getDecoratedEnd(child) > 0) { + mRecyclerScrollListener.onScroll(firstChild); + + } else { + mRecyclerScrollListener.onScroll(firstChild + 1); + + } + } + //获取偏左显示的Item + if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2 + && helper.getDecoratedEnd(child) > 0) { + return child; + } else { + return layoutManager.findViewByPosition(firstChild + 1); + } + } + + return super.findSnapView(layoutManager); + } + + public void setmOnItemScrollListener(OnRecyclerScrollListener mRecyclerScrollListener) { + this.mRecyclerScrollListener = mRecyclerScrollListener; + } + + private OrientationHelper getHorizontalHelper( + RecyclerView.LayoutManager layoutManager) { + if (mHorizontalHelper == null) { + mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager); + } + return mHorizontalHelper; + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/LcDataListEntity.java b/app/src/main/java/com/lechange/demo/yonsz/LcDataListEntity.java new file mode 100644 index 0000000..a835a8c --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/LcDataListEntity.java @@ -0,0 +1,173 @@ +package com.lechange.demo.yonsz; + +import com.common.openapi.entity.DeviceDetailListData; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2019/3/2. + */ + +public class LcDataListEntity { + + /** + * data : [{"addressId":"3","deviceId":"4K0586CPAJ58121","deviceModel":"deviceModel","deviceProvider":"lc","deviceType":1,"houseId":"de37c4cef269487ab09af03fd5bbc721","id":1,"thirdDeviceAccountId":2,"userId":"c8971e8ea0654c429c89cb486d259357"}] + * flag : 1 + * msg : success + */ + + private int flag; + private String msg; + private List data; + + public int getFlag() { + return flag; + } + + public void setFlag(int flag) { + this.flag = flag; + } + + public String getMsg() { + return msg == null ? "" : msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public List getData() { + if (data == null) { + return new ArrayList<>(); + } + return data; + } + + public void setData(List data) { + this.data = data; + } + + public static class DataBean { + /** + * addressId : 3 + * deviceId : 4K0586CPAJ58121 + * deviceModel : deviceModel + * deviceProvider : lc + * deviceType : 1 + * houseId : de37c4cef269487ab09af03fd5bbc721 + * id : 1 + * thirdDeviceAccountId : 2 + * userId : c8971e8ea0654c429c89cb486d259357 + */ + + private String addressId; + private String deviceId; + private String deviceModel; + private String deviceProvider; + private int deviceType; + private String houseId; + private int id; + private int thirdDeviceAccountId; + private String userId; + private String deviceName; + private String version; + private String alarmStatus; + + public String getAlarmStatus() { + return alarmStatus == null ? "" : alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public String getVersion() { + return version == null ? "" : version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getDeviceName() { + return deviceName == null ? "" : deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getAddressId() { + return addressId == null ? "" : addressId; + } + + public void setAddressId(String addressId) { + this.addressId = addressId; + } + + public String getDeviceId() { + return deviceId == null ? "" : deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceModel() { + return deviceModel == null ? "" : deviceModel; + } + + public void setDeviceModel(String deviceModel) { + this.deviceModel = deviceModel; + } + + public String getDeviceProvider() { + return deviceProvider == null ? "" : deviceProvider; + } + + public void setDeviceProvider(String deviceProvider) { + this.deviceProvider = deviceProvider; + } + + public int getDeviceType() { + return deviceType; + } + + public void setDeviceType(int deviceType) { + this.deviceType = deviceType; + } + + public String getHouseId() { + return houseId == null ? "" : houseId; + } + + public void setHouseId(String houseId) { + this.houseId = houseId; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getThirdDeviceAccountId() { + return thirdDeviceAccountId; + } + + public void setThirdDeviceAccountId(int thirdDeviceAccountId) { + this.thirdDeviceAccountId = thirdDeviceAccountId; + } + + public String getUserId() { + return userId == null ? "" : userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/LcListEntity.java b/app/src/main/java/com/lechange/demo/yonsz/LcListEntity.java new file mode 100644 index 0000000..395ccfb --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/LcListEntity.java @@ -0,0 +1,171 @@ +package com.lechange.demo.yonsz; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2019/3/2. + */ + +public class LcListEntity { + + /** + * data : [{"addressId":"3","deviceId":"4K0586CPAJ58121","deviceModel":"deviceModel","deviceProvider":"lc","deviceType":1,"houseId":"de37c4cef269487ab09af03fd5bbc721","id":1,"thirdDeviceAccountId":2,"userId":"c8971e8ea0654c429c89cb486d259357"}] + * flag : 1 + * msg : success + */ + + private int flag; + private String msg; + private List data; + + public int getFlag() { + return flag; + } + + public void setFlag(int flag) { + this.flag = flag; + } + + public String getMsg() { + return msg == null ? "" : msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public List getData() { + if (data == null) { + return new ArrayList<>(); + } + return data; + } + + public void setData(List data) { + this.data = data; + } + + public static class DataBean { + /** + * addressId : 3 + * deviceId : 4K0586CPAJ58121 + * deviceModel : deviceModel + * deviceProvider : lc + * deviceType : 1 + * houseId : de37c4cef269487ab09af03fd5bbc721 + * id : 1 + * thirdDeviceAccountId : 2 + * userId : c8971e8ea0654c429c89cb486d259357 + */ + + private String addressId; + private String deviceId; + private String deviceModel; + private String deviceProvider; + private int deviceType; + private String houseId; + private int id; + private int thirdDeviceAccountId; + private String userId; + private String deviceName; + private String version; + private String alarmStatus; + + public String getAlarmStatus() { + return alarmStatus == null ? "" : alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public String getVersion() { + return version == null ? "" : version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getDeviceName() { + return deviceName == null ? "" : deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getAddressId() { + return addressId == null ? "" : addressId; + } + + public void setAddressId(String addressId) { + this.addressId = addressId; + } + + public String getDeviceId() { + return deviceId == null ? "" : deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceModel() { + return deviceModel == null ? "" : deviceModel; + } + + public void setDeviceModel(String deviceModel) { + this.deviceModel = deviceModel; + } + + public String getDeviceProvider() { + return deviceProvider == null ? "" : deviceProvider; + } + + public void setDeviceProvider(String deviceProvider) { + this.deviceProvider = deviceProvider; + } + + public int getDeviceType() { + return deviceType; + } + + public void setDeviceType(int deviceType) { + this.deviceType = deviceType; + } + + public String getHouseId() { + return houseId == null ? "" : houseId; + } + + public void setHouseId(String houseId) { + this.houseId = houseId; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getThirdDeviceAccountId() { + return thirdDeviceAccountId; + } + + public void setThirdDeviceAccountId(int thirdDeviceAccountId) { + this.thirdDeviceAccountId = thirdDeviceAccountId; + } + + public String getUserId() { + return userId == null ? "" : userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/LcModifyNameActivity.java b/app/src/main/java/com/lechange/demo/yonsz/LcModifyNameActivity.java new file mode 100644 index 0000000..e885279 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/LcModifyNameActivity.java @@ -0,0 +1,332 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Message; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.alibaba.fastjson.JSON; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.EventBusEntity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUrl; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.version4.fragment.CurtainFragment; +import com.yonsz.z1.view.TitleView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static com.yonsz.z1.net.Constans.GET_SWITCHER_CHANGE_INFO; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_FAIL; +import static com.yonsz.z1.net.Constans.UPDATE_BLINDENTITY_NAME_SUCCESS; +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; + +/** + * Created by Administrator on 2019/3/16. + */ + +public class LcModifyNameActivity extends BaseActivity implements CompoundButton.OnCheckedChangeListener { + private TitleView mTitleView; + private Button nextConfig; + + private CheckBox[] timeCheckBox = new CheckBox[14]; + private List positionIds = new ArrayList<>(); + private CompoundButton lastTimeCheckBox; + private String deviceAddress = "0"; + private List condition = new ArrayList<>(); + private String addressId; + private TextView tv_curtain_step_two; + + public void onEventMainThread(EventBusEntity event) { + String msg = event.getMsg(); + Log.e("nettyUtil", msg); + finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_curtain_two); + initView(); + initListener(); + } + + private void initView() { + deviceAddress = getIntent().getExtras().get("deviceAddress").toString(); + addressId = deviceAddress; + tv_curtain_step_two = (TextView) findViewById(R.id.tv_curtain_step_two); + tv_curtain_step_two.setVisibility(View.GONE); + nextConfig = (Button) findViewById(R.id.bt_sure_config); + nextConfig.setOnClickListener(this); + nextConfig.setText("确定"); + nextConfig.setVisibility(View.VISIBLE); + mTitleView = (TitleView) findViewById(R.id.title_switcher_two); + mTitleView.setHead("修改摄像头位置信息"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + + positionIds.add(R.id.cb_position0); + positionIds.add(R.id.cb_position1); + positionIds.add(R.id.cb_position2); + positionIds.add(R.id.cb_position3); + positionIds.add(R.id.cb_position4); + positionIds.add(R.id.cb_position5); + positionIds.add(R.id.cb_position6); + positionIds.add(R.id.cb_position7); + positionIds.add(R.id.cb_position8); + positionIds.add(R.id.cb_position9); + positionIds.add(R.id.cb_position10); + positionIds.add(R.id.cb_position11); + positionIds.add(R.id.cb_position12); + positionIds.add(R.id.cb_position13); + for (int i = 0; i < positionIds.size(); i++) { + timeCheckBox[i] = (CheckBox) findViewById(positionIds.get(i)); + timeCheckBox[i].setOnCheckedChangeListener(this); + } + + switch (deviceAddress) { + case "0": + timeCheckBox[13].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position13); + condition.add("13"); + break; + case "1": + timeCheckBox[0].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position0); + condition.add("0"); + break; + case "2": + timeCheckBox[1].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position1); + condition.add("1"); + break; + case "3": + timeCheckBox[2].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position2); + condition.add("2"); + break; + case "4": + timeCheckBox[3].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position3); + condition.add("3"); + break; + case "5": + timeCheckBox[4].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position4); + condition.add("4"); + break; + case "6": + timeCheckBox[5].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position5); + condition.add("5"); + break; + case "7": + timeCheckBox[6].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position6); + condition.add("6"); + break; + case "8": + timeCheckBox[7].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position7); + condition.add("7"); + break; + case "9": + timeCheckBox[8].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position8); + condition.add("8"); + break; + case "10": + timeCheckBox[9].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position9); + condition.add("9"); + break; + case "11": + timeCheckBox[10].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position10); + condition.add("10"); + break; + case "12": + timeCheckBox[11].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position11); + condition.add("11"); + break; + case "13": + timeCheckBox[12].setChecked(true); + lastTimeCheckBox = (CompoundButton) findViewById(R.id.cb_position12); + condition.add("12"); + break; + } + } + + private void modifyDevice() { + NetWorkUtil util = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("deviceId", getIntent().getExtras().get("deviceId").toString()); + map.put("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + if (addressId.equals("13")) { + map.put("addressId", "0"); + } else { + map.put("addressId", String.valueOf(Integer.valueOf(addressId) + 1)); + } + util.requestPostByAsynewApi(NetWorkUrl.MODIFY_DEVICE, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("updateBlindEntityName", "ShareDeviceActivity onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_SUCCESS); + msg.obj = addressId; + mHandler.sendMessage(msg); + } else { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + Message msg = mHandler.obtainMessage(UPDATE_BLINDENTITY_NAME_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void initListener() { + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.bt_sure_config: + modifyDevice(); + break; + } + } + + @Override + public void callBackUiThread(Message msg) { + switch (msg.what) { + case UPDATE_BLINDENTITY_NAME_SUCCESS: + Intent intent = new Intent(LcModifyNameActivity.this, CurtainFragment.class); + if (addressId.equals("13")) { + intent.putExtra("addressId", 0); + } else { + intent.putExtra("addressId", Integer.valueOf(addressId) + 1); + } + setResult(GET_SWITCHER_CHANGE_INFO, intent); + finish(); + break; + } + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + int id = buttonView.getId(); + //如果是时间筛选 + if (positionIds.contains(id)) { + if (isChecked) { + if (lastTimeCheckBox != null) { + lastTimeCheckBox.setChecked(false); + } + lastTimeCheckBox = buttonView; + } else { + boolean isForceCheck = true; + for (int i = 0; i < timeCheckBox.length; i++) { + if (timeCheckBox[i].isChecked()) { + isForceCheck = false; + } + } + if (isForceCheck) { + buttonView.setChecked(true); + } + } + } + switch (id) { + case R.id.cb_position0: + if (isChecked) + addressId = "0"; + break; + case R.id.cb_position1: + if (isChecked) + addressId = "1"; + break; + case R.id.cb_position2: + if (isChecked) + addressId = "2"; + break; + case R.id.cb_position3: + if (isChecked) + addressId = "3"; + break; + case R.id.cb_position4: + if (isChecked) + addressId = "4"; + break; + case R.id.cb_position5: + if (isChecked) + addressId = "5"; + break; + case R.id.cb_position6: + if (isChecked) + addressId = "6"; + break; + case R.id.cb_position7: + if (isChecked) + addressId = "7"; + break; + case R.id.cb_position8: + if (isChecked) + addressId = "8"; + break; + case R.id.cb_position9: + if (isChecked) + addressId = "9"; + break; + case R.id.cb_position10: + if (isChecked) + addressId = "10"; + break; + case R.id.cb_position11: + if (isChecked) + addressId = "11"; + break; + case R.id.cb_position12: + if (isChecked) + addressId = "12"; + break; + case R.id.cb_position13: + if (isChecked) + addressId = "13"; + break; + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/LechengChannelAdapter.java b/app/src/main/java/com/lechange/demo/yonsz/LechengChannelAdapter.java new file mode 100644 index 0000000..b4f4bd4 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/LechengChannelAdapter.java @@ -0,0 +1,174 @@ +package com.lechange.demo.yonsz; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Handler; +import android.os.Message; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.lechange.demo.business.Business; +import com.lechange.demo.business.entity.ChannelInfo; +import com.lechange.demo.mediaplay.MediaPlayActivity; +import com.yonsz.z1.R; + +import java.util.List; + +/** + * Created by Administrator on 2019/2/27. + */ + +public class LechengChannelAdapter extends RecyclerView.Adapter { + + private List mChannelInfoList; + private Context mContext; + + public LechengChannelAdapter(Context mContext, List mChannelInfoList) { + super(); + this.mContext = mContext; + this.mChannelInfoList = mChannelInfoList; + } + + @Override + public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_device_list_item, + parent, false); + return new LechengChannelAdapter.MessageViewHolder(view); + } + + @Override + public void onBindViewHolder(LechengChannelAdapter.MessageViewHolder holder, int position) { + holder.setViews(position); + } + + @Override + public int getItemCount() { + return mChannelInfoList != null ? mChannelInfoList.size() : 0; + } + + @Override + public long getItemId(int position) { + return super.getItemId(position); + } + + private void unBindDevice(final ChannelInfo info) { + Business.getInstance().unBindDevice(info.getDeviceCode(), new Handler() { + @Override + public void handleMessage(Message msg) { + Business.RetObject retObject = (Business.RetObject) msg.obj; + if (msg.what == 0) { + Toast.makeText(mContext, R.string.toast_device_delete_success, Toast.LENGTH_SHORT).show(); + mChannelInfoList.remove(info); + notifyDataSetChanged(); + } else { + Toast.makeText(mContext, retObject.mMsg, Toast.LENGTH_SHORT).show(); + } + + } + }); + } + + class MessageViewHolder extends RecyclerView.ViewHolder { + /*private TextView mChannelName; + private ImageView mDelete;*/ + // private RelativeLayout mBgDevice; + private ImageView mLiveVideo; + /*private ImageView mLocalVideo; + private ImageView mCloudVideo; + private ImageView mMessage; + private ImageView mSetting;*/ + private LinearLayout mListShade; + private ChannelInfo mInfo; + private ImageView iv; + + public MessageViewHolder(View convertView) { + super(convertView); + /*mChannelName = (TextView) convertView.findViewById(R.id.list_channel_name); + mDelete = (ImageView) convertView.findViewById(R.id.list_device_delete);*/ + // mBgDevice = (RelativeLayout) convertView.findViewById(R.id.list_bg_device); + mLiveVideo = (ImageView) convertView.findViewById(R.id.list_device_livevideo); + /*mLocalVideo = (ImageView) convertView.findViewById(R.id.list_device_localvideo); + mCloudVideo = (ImageView) convertView.findViewById(R.id.list_device_cloudvideo); + mMessage = (ImageView) convertView.findViewById(R.id.list_device_message); + mSetting = (ImageView) convertView.findViewById(R.id.list_device_setting);*/ + mListShade = (LinearLayout) convertView.findViewById(R.id.list_shade); + iv = (ImageView) itemView.findViewById(R.id.imageView); + } + + public void setViews(final int position) { + //修改数据信息(含加密标识符) + mInfo = mChannelInfoList.get(position); + /*if (mInfo.getBackgroudImgURL() != null && mInfo.getBackgroudImgURL().length() > 0) { + //下载 注:由于有些请求的图片是经过加密处理的,所以需要使用带有解密功能的接口,默认密码为设备序列号 + ImageHelper.loadCacheImage(mInfo.getBackgroudImgURL(), mInfo.getDeviceCode(), mInfo.getDeviceCode(), new Handler() { + @Override + public void handleMessage(Message msg) { + // TODO Auto-generated method stub + super.handleMessage(msg); + if (mInfo.getBackgroudImgURL().hashCode() == msg.what && msg.obj != null) { + // mBgDevice.setBackgroundDrawable((Drawable) msg.obj); + iv.setImageDrawable((Drawable) msg.obj); + } + } + }); + }*/ + //"在线" : "离线" + if (mInfo.getState() == ChannelInfo.ChannelState.Online) { + mListShade.setVisibility(View.GONE); + } else { + mListShade.setVisibility(View.VISIBLE); + } + mLiveVideo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + // 启动实时视频 + final EditText et = new EditText(mContext); + if (mInfo.getEncryptMode() == 1 && mInfo.getEncryptKey() == null) { + new AlertDialog.Builder(mContext).setTitle(R.string.alarm_message_keyinput_dialog_title) + .setIcon(android.R.drawable.ic_dialog_info).setView(et) + .setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO Auto-generated method stub + mInfo.setEncryptKey(et.getText().toString()); + Intent intent = new Intent(mContext, MediaPlayActivity.class); + if (TextUtils.isEmpty(mInfo.getUuid())) { + return; + } + intent.putExtra("UUID", mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_ONLINE); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.getApplicationContext().startActivity(intent); + } + }) + .setNegativeButton(R.string.dialog_negative, null).show(); + } else { + Intent intent = new Intent(mContext, MediaPlayActivity.class); + if (TextUtils.isEmpty(mInfo.getUuid())) { + return; + } + intent.putExtra("UUID", mInfo.getUuid()); + intent.putExtra("TYPE", MediaPlayActivity.IS_VIDEO_ONLINE); + /*ArrayList UUIDStringList = new ArrayList<>(); + for (int i = 0; i < mChannelInfoList.size(); i++) { + UUIDStringList.add(mChannelInfoList.get(i).getUuid()); + } + intent.putStringArrayListExtra("UUIDStringList", UUIDStringList); + intent.putExtra("position", position);*/ + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.getApplicationContext().startActivity(intent); + } + } + }); + } + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/LechengLoginActivity.java b/app/src/main/java/com/lechange/demo/yonsz/LechengLoginActivity.java new file mode 100644 index 0000000..0d2a7f4 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/LechengLoginActivity.java @@ -0,0 +1,302 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.lechange.demo.business.Business; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.database.entity.SimpleEntty; +import com.yonsz.z1.database.entity.entity4.CheckBindEntity; +import com.yonsz.z1.devicea2.safedevice.ScanCodeActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.login.PhoneAreaActivity; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.net.NetWorkUtil; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.utils.ToastUtil; +import com.yonsz.z1.view.TitleView; + +import java.util.HashMap; + +import static com.yonsz.z1.net.Constans.CHECK_USER_BIND_FAIL; +import static com.yonsz.z1.net.Constans.CHECK_USER_BIND_SUCCESS; +import static com.yonsz.z1.net.Constans.GET_CODE_FAIL; +import static com.yonsz.z1.net.Constans.GET_CODE_SUCCESS; +import static com.yonsz.z1.net.Constans.GET_PHONE_AREA; +import static com.yonsz.z1.net.Constans.UPDATE_SEC; +import static com.yonsz.z1.net.Constans.USER_BIND_SMS_FAIL; +import static com.yonsz.z1.net.Constans.USER_BIND_SMS_SUCCESS; +import static com.yonsz.z1.net.NetWorkUrl.USER_BIND; +import static com.yonsz.z1.net.NetWorkUrl.USER_BIND_SMS; + +/** + * Created by Administrator on 2017/5/26. + */ +public class LechengLoginActivity extends BaseActivity { + private EditText mUserPhone; + private EditText mUserCode; + private TextView mGetCode; + private int sec = 60; + private TitleView mTitleView; + private Button btNext; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_lecheng_login); + initView(); + initListener(); + } + + + private void initView() { + mUserPhone = (EditText) findViewById(R.id.edit_username); + mUserCode = (EditText) findViewById(R.id.edit_code); + mGetCode = (TextView) findViewById(R.id.tv_getcode); + btNext = (Button) findViewById(R.id.bt_forgetpw_next); + btNext.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_9cc6f6)); + mTitleView = (TitleView) findViewById(R.id.title_forgetpw); + mTitleView.setHead(R.string.login); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + mUserPhone.setText(SharedpreferencesUtil.get(Constans.USERPHONE, "").toString()); + } + + private void initListener() { + btNext.setOnClickListener(this); + mGetCode.setOnClickListener(this); + mUserCode.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + int i = s.length(); + if (i != 0) { + btNext.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_398dee)); + } else { + btNext.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_9cc6f6)); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.bt_forgetpw_next: + // checkUserCode(mUserPhone.getText().toString().trim(), mUserCode.getText().toString()); + // checkSms(); + userBind(); + break; + case R.id.tv_getcode: + // getUserSms(); + //发送短信验证码 + userBindSms(); + break; + case R.id.ll_phone_area: + Intent intent1 = new Intent(LechengLoginActivity.this, PhoneAreaActivity.class); + intent1.putExtra("type", "forgetPw"); + startActivityForResult(intent1, GET_PHONE_AREA); + break; + } + } + + public void checkSms() { + String smsCode = mUserCode.getText().toString().trim(); + if (smsCode.length() == 0) { + Toast.makeText(getApplicationContext(), R.string.toast_userbind_no_idcode, Toast.LENGTH_LONG).show(); + return; + } + Business.getInstance().checkUserSms(mUserPhone.getText().toString().trim(), smsCode, new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Intent intent = new Intent(LechengLoginActivity.this, ScanCodeActivity.class); + intent.putExtra("ziId", "LechengLoginActivity"); + intent.putExtra("deviceAddress", "LechengLoginActivity"); + intent.putExtra("houseId", getIntent().getExtras().get("houseId").toString()); + startActivity(intent); + finish(); + } else { + String result = (String) msg.obj; + ToastUtil.show(LechengLoginActivity.this, result); + } + } + + }); + } + + /** + * 获取短信验证码 + */ + public void getUserSms() { + Business.getInstance().getUserSms(mUserPhone.getText().toString().trim(), new Handler() { + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + ToastUtil.show(LechengLoginActivity.this, R.string.notice_sms); + mGetCode.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_9cc6f6)); + mGetCode.setEnabled(false); + mGetCode.setText(getResources().getString(R.string.sec, sec)); + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + } else { + String result = (String) msg.obj; + ToastUtil.show(LechengLoginActivity.this, result); + } + } + + }); + } + + @Override + public void callBackUiThread(Message msg) { + switch (msg.what) { + case GET_CODE_SUCCESS: + ToastUtil.show(this, R.string.notice_sms); + // mSure.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_27_50)); + // mSure.setClickable(true); + mGetCode.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_9cc6f6)); + mGetCode.setEnabled(false); + mGetCode.setText(getResources().getString(R.string.sec, sec)); + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + break; + case GET_CODE_FAIL: + ToastUtil.show(this, (String) msg.obj != null ? ((String) msg.obj) : + getResources().getString(R.string.sms_fail)); + break; + case UPDATE_SEC: + if (sec > 2) { + sec--; + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + mGetCode.setText(getResources().getString(R.string.sec, sec - 1)); + } else { + mGetCode.setText(R.string.get_code); + mGetCode.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_398dee)); + mGetCode.setEnabled(true); + sec = 60; + } + break; + case CHECK_USER_BIND_SUCCESS: + CheckBindEntity bindEntity = (CheckBindEntity) msg.obj; + Business.getInstance().setToken(bindEntity.getData().getUserToken()); + Intent intent = new Intent(LechengLoginActivity.this, ScanCodeActivity.class); + intent.putExtra("ziId", "LechengLoginActivity"); + intent.putExtra("deviceAddress", "LechengLoginActivity"); + intent.putExtra("houseId", getIntent().getExtras().get("houseId").toString()); + startActivity(intent); + finish(); + break; + case CHECK_USER_BIND_FAIL: + ToastUtil.show(this, (String) msg.obj); + break; + case USER_BIND_SMS_FAIL: + ToastUtil.show(this, (String) msg.obj); + break; + case USER_BIND_SMS_SUCCESS: + ToastUtil.show(LechengLoginActivity.this, R.string.notice_sms); + mGetCode.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_9cc6f6)); + mGetCode.setEnabled(false); + mGetCode.setText(getResources().getString(R.string.sec, sec)); + mHandler.sendEmptyMessageDelayed(UPDATE_SEC, 1000); + break; + } + } + + private void userBind() { + String smsCode = mUserCode.getText().toString().trim(); + if (smsCode.length() == 0) { + Toast.makeText(getApplicationContext(), R.string.toast_userbind_no_idcode, Toast.LENGTH_LONG).show(); + return; + } + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("phone", mUserPhone.getText().toString().trim()); + map.put("smsCode", smsCode); + netWorkUtil.requestPostByAsynewApi(USER_BIND, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("userBind", "onSuccess()" + respone); + CheckBindEntity obj = JSON.parseObject(respone, CheckBindEntity.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(CHECK_USER_BIND_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + android.os.Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + android.os.Message msg = mHandler.obtainMessage(CHECK_USER_BIND_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } + + private void userBindSms() { + NetWorkUtil netWorkUtil = NetWorkUtil.instans(); + HashMap map = new HashMap<>(); + map.put("phone", mUserPhone.getText().toString().trim()); + netWorkUtil.requestPostByAsynewApi(USER_BIND_SMS, map, new NetWorkUtil.ReqCallBack() { + @Override + public void onSuccess(String respone) { + Log.i("userBindSms", "onSuccess()" + respone); + SimpleEntty obj = JSON.parseObject(respone, SimpleEntty.class); + if (1 == obj.getFlag()) { + Message msg = mHandler.obtainMessage(USER_BIND_SMS_SUCCESS); + msg.obj = obj; + mHandler.sendMessage(msg); + } else { + android.os.Message msg = mHandler.obtainMessage(USER_BIND_SMS_FAIL); + msg.obj = obj.getMsg(); + mHandler.sendMessage(msg); + } + } + + @Override + public void onFail(String message) { + android.os.Message msg = mHandler.obtainMessage(USER_BIND_SMS_FAIL); + msg.obj = message; + mHandler.sendMessage(msg); + } + }); + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/RecoverSDCardActivity.java b/app/src/main/java/com/lechange/demo/yonsz/RecoverSDCardActivity.java new file mode 100644 index 0000000..6c3a4d4 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/RecoverSDCardActivity.java @@ -0,0 +1,103 @@ +package com.lechange.demo.yonsz; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.lechange.demo.business.Business; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.listener.NoDoubleClickListener; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.mine.aboutversion.customview.ConfirmDialog; +import com.yonsz.z1.mine.aboutversion.feature.Callback; +import com.yonsz.z1.view.TitleView; + +/** + * Created by Administrator on 2019/3/12. + */ + +public class RecoverSDCardActivity extends BaseActivity { + private TitleView mTitleView; + private TextView tv_recover_sdcard; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_recover_sdcard); + initView(); + } + + private void initView() { + tv_recover_sdcard = (TextView) findViewById(R.id.tv_recover_sdcard); + mTitleView = (TitleView) findViewById(R.id.title_recover_sdcard); + mTitleView.setHead("本地存储"); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + tv_recover_sdcard.setOnClickListener(new NoDoubleClickListener() { + @Override + protected void onNoDoubleClick(View v) { + ConfirmDialog dialog = new ConfirmDialog(RecoverSDCardActivity.this, new Callback() { + @Override + public void callback(int position) { + switch (position) { + case 0: + break; + case 1: + recoverSDCard(); + break; + } + } + }); + dialog.setContent("格式化将会清空存储卡内所有数据,且该操作一旦开始不可以取消"); + dialog.setCancleBtn(R.string.cancel); + dialog.setSureBtn("格式化"); + dialog.setCancelable(false); + dialog.show(); + } + }); + } + + private void recoverSDCard() { + Business.getInstance().recoverSDCard(getIntent().getExtras().get("UUID").toString(), new Handler() { + + @Override + public void handleMessage(Message msg) { + if (0 == msg.what) { + Toast.makeText( + RecoverSDCardActivity.this, + "格式化完成", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + RecoverSDCardActivity.this, + "格式化失败", + Toast.LENGTH_SHORT).show(); + + } + } + }); + } + + @Override + public void callBackUiThread(Message msg) { + + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/ResetLechengActivity.java b/app/src/main/java/com/lechange/demo/yonsz/ResetLechengActivity.java new file mode 100644 index 0000000..cd73324 --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/ResetLechengActivity.java @@ -0,0 +1,183 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Message; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.lechange.demo.manager.DeviceAddActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.view.TitleView; + +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.GATE_WAY; + +/** + * Created by Administrator on 2019/2/26. + */ + +public class ResetLechengActivity extends BaseActivity { + private TitleView mTitleView; + private Button startConfig; + private CheckBox selectUnnorReveal, selectUnnorReveal1; + private String configWifiType; + private TextView apSmartTv, tv_gateway; + private TextView tv_ap_smart_declare, tv_ap_smart_declare1; + private RelativeLayout rl_camera, rl_gateway; + private LinearLayout ll_camera, ll_gateway; + private String devType = "0"; + private ImageView iv_gateway_pic; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_reset_lecheng); + initView(); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + private void initView() { + if (null != getIntent().getExtras().get("deviceModel")) { + devType = getIntent().getExtras().get("deviceModel").toString(); + } + configWifiType = getIntent().getExtras().get("configWifiType").toString(); + iv_gateway_pic = (ImageView) findViewById(R.id.iv_gateway_pic); + selectUnnorReveal = (CheckBox) findViewById(R.id.iv_select_unnor_reveal); + selectUnnorReveal1 = (CheckBox) findViewById(R.id.iv_select_unnor_reveal1); + rl_camera = (RelativeLayout) findViewById(R.id.rl_camera); + rl_gateway = (RelativeLayout) findViewById(R.id.rl_gateway); + ll_camera = (LinearLayout) findViewById(R.id.ll_camera); + ll_gateway = (LinearLayout) findViewById(R.id.ll_gateway); + tv_gateway = (TextView) findViewById(R.id.tv_gateway); + mTitleView = (TitleView) findViewById(R.id.title_wifi_stepone); + mTitleView.setHead(R.string.add_device); + startConfig = (Button) findViewById(R.id.bt_start_config); + startConfig.setOnClickListener(this); + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_e3e3e3_5dp)); + startConfig.setClickable(false); + startConfig.setEnabled(false); + startConfig.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent; + if (devType.equals("1")) { + intent = new Intent(ResetLechengActivity.this, WifiHotspotActivity.class); + intent.putExtra("devId", getIntent().getExtras().get("deviceSN").toString()); + intent.putExtra("devType", devType); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("mPwd", getIntent().getExtras().get("password").toString());//将要连接的wifi的密码携带过去 + intent.putExtra("scCode", getIntent().getExtras().get("deviceCode").toString()); + } else { + intent = new Intent(ResetLechengActivity.this, DeviceAddActivity.class); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("password", getIntent().getExtras().get("password").toString()); + intent.putExtra("houseId", getIntent().getExtras().get("houseId").toString()); + intent.putExtra("deviceSN", getIntent().getExtras().get("deviceSN").toString()); + if (null != getIntent().getExtras().get("floor")) { + intent.putExtra("floor", getIntent().getExtras().get("floor").toString()); + } + if (configWifiType.equals(GATE_WAY)) { + intent.putExtra("deviceType", GATE_WAY); + } else { + intent.putExtra("deviceType", CAMERA_TAG); + } + if (null != getIntent().getExtras().get("deviceAddress")) { + intent.putExtra("deviceAddress", getIntent().getExtras().get("deviceAddress").toString()); + } + if (null != getIntent().getExtras().get("deviceCode")) { + intent.putExtra("deviceCode", getIntent().getExtras().get("deviceCode").toString()); + } + } + startActivity(intent); + finish(); + } + }); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + selectUnnorReveal.setOnClickListener(this); + selectUnnorReveal1.setOnClickListener(this); + apSmartTv = (TextView) findViewById(R.id.tv_ap_smart_top); + tv_ap_smart_declare = (TextView) findViewById(R.id.tv_ap_smart_declare); + tv_ap_smart_declare1 = (TextView) findViewById(R.id.tv_ap_smart_declare1); + if (devType.equals("1")) { + iv_gateway_pic.setImageResource(R.drawable.pic_add_gateway_g2); + tv_gateway.setText("已听到热点已开启提示"); + tv_ap_smart_declare.setText("长按配对键6s后松开,设备蓝灯慢闪后,听到 “设备热点已开启”后点击“下一步”"); + tv_ap_smart_declare1.setText("请确保该网关没有在乐橙等第三方app上添加过”"); + rl_gateway.setVisibility(View.VISIBLE); + rl_camera.setVisibility(View.GONE); + ll_camera.setVisibility(View.GONE); + ll_gateway.setVisibility(View.VISIBLE); + } else if (configWifiType.equals(GATE_WAY)) { + tv_ap_smart_declare.setText("长按配对键5s后松开,听到“开始无线配对”后点击“下一步”"); + tv_ap_smart_declare1.setText("请确保该网关没有在乐橙等第三方app上添加过”"); + rl_gateway.setVisibility(View.VISIBLE); + rl_camera.setVisibility(View.GONE); + ll_camera.setVisibility(View.GONE); + ll_gateway.setVisibility(View.VISIBLE); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_select_unnor_reveal: + if (selectUnnorReveal.isChecked()) { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_5dp)); + startConfig.setClickable(true); + startConfig.setEnabled(true); + } else { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_e3e3e3_5dp)); + startConfig.setClickable(false); + startConfig.setEnabled(false); + } + break; + case R.id.iv_select_unnor_reveal1: + if (selectUnnorReveal1.isChecked()) { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_5dp)); + startConfig.setClickable(true); + startConfig.setEnabled(true); + } else { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_e3e3e3_5dp)); + startConfig.setClickable(false); + startConfig.setEnabled(false); + } + break; + } + } + + @Override + public void callBackUiThread(Message msg) { + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/TimeOutActivity.java b/app/src/main/java/com/lechange/demo/yonsz/TimeOutActivity.java new file mode 100644 index 0000000..acb9d2e --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/TimeOutActivity.java @@ -0,0 +1,99 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Message; +import android.view.View; +import android.widget.TextView; + +import com.lechange.demo.manager.DeviceAddActivity; +import com.lechange.demo.manager.SoftAPActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.devicea2.safedevice.ScanCodeActivity; +import com.yonsz.z1.gateway.AddLCSafeActivity; +import com.yonsz.z1.listener.NoDoubleClickListener; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.view.TitleView; + +import static com.yonsz.z1.net.Constans.deviceNumListPosition; +import static com.yonsz.z1.net.Constans.homeListEntity; + +/** + * Created by Administrator on 2019/3/12. + */ + +public class TimeOutActivity extends BaseActivity { + private TitleView mTitleView; + private TextView bt_sure_config; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_time_out); + initView(); + } + + private void initView() { + mTitleView = (TitleView) findViewById(R.id.title_time_out); + bt_sure_config = (TextView) findViewById(R.id.bt_sure_config); + mTitleView.setHead(R.string.add_device); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + bt_sure_config.setOnClickListener(new NoDoubleClickListener() { + @Override + protected void onNoDoubleClick(View v) { + Intent intent; + if (getIntent().getExtras().get("from").toString().equals("LcnDeviceAddActivity")) { + intent = new Intent(TimeOutActivity.this, DeviceAddActivity.class); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("password", getIntent().getExtras().get("password").toString()); + intent.putExtra("houseId", getIntent().getExtras().get("houseId").toString()); + intent.putExtra("deviceSN", getIntent().getExtras().get("deviceSN").toString()); + intent.putExtra("deviceType", getIntent().getExtras().get("deviceType").toString()); + intent.putExtra("deviceCode", getIntent().getExtras().get("deviceCode").toString()); + } else if (getIntent().getExtras().get("from").toString().equals("SoftAPActivity")) { + intent = new Intent(TimeOutActivity.this, SoftAPActivity.class); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("pwd", getIntent().getExtras().get("pwd").toString()); + intent.putExtra("devId", getIntent().getExtras().get("devId").toString()); + intent.putExtra("scCode", getIntent().getExtras().get("scCode").toString()); + intent.putExtra("devType", getIntent().getExtras().get("devType").toString()); + intent.putExtra("from", "SoftAPActivity"); + } else { + intent = new Intent(TimeOutActivity.this, AddLCSafeActivity.class); + intent.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + intent.putExtra("from", "TimeOutActivity"); + intent.putExtra("deviceSN", getIntent().getExtras().get("deviceSN").toString()); + intent.putExtra("deviceCode", getIntent().getExtras().get("deviceCode").toString()); + intent.putExtra("deviceType", getIntent().getExtras().get("deviceType").toString()); + intent.putExtra("deviceModel", getIntent().getExtras().get("deviceModel").toString()); + intent.putExtra("parentThirdDeviceId", getIntent().getExtras().get("parentThirdDeviceId").toString()); + } + startActivity(intent); + finish(); + } + }); + } + + @Override + public void callBackUiThread(Message msg) { + + } +} diff --git a/app/src/main/java/com/lechange/demo/yonsz/WifiHotspotActivity.java b/app/src/main/java/com/lechange/demo/yonsz/WifiHotspotActivity.java new file mode 100644 index 0000000..cab48bd --- /dev/null +++ b/app/src/main/java/com/lechange/demo/yonsz/WifiHotspotActivity.java @@ -0,0 +1,197 @@ +package com.lechange.demo.yonsz; + +import android.content.Intent; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.Message; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.lechange.demo.manager.DeviceAddActivity; +import com.lechange.demo.manager.SoftAPActivity; +import com.yonsz.z1.R; +import com.yonsz.z1.activity.BaseActivity; +import com.yonsz.z1.device.deviceadd.ApConfigActivity; +import com.yonsz.z1.listener.OnTitleItemClickListener; +import com.yonsz.z1.net.Constans; +import com.yonsz.z1.utils.SharedpreferencesUtil; +import com.yonsz.z1.view.TitleView; + +import static com.yonsz.z1.net.Constans.CAMERA_TAG; +import static com.yonsz.z1.net.Constans.GATE_WAY; + +/** + * Created by Administrator on 2019/2/26. + */ + +public class WifiHotspotActivity extends BaseActivity { + private TitleView mTitleView; + private Button startConfig; + private CheckBox selectUnnorReveal, selectUnnorReveal1; + private TextView apSmartTv, tv_gateway; + private TextView tv_ap_smart_declare, tv_ap_smart_declare1; + private RelativeLayout rl_camera, rl_gateway; + private LinearLayout ll_camera, ll_gateway; + private String devType = "1"; + private ImageView iv_gateway_pic; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_wifi_hotspot); + initView(); + } + + @Override + public void onResume() { + super.onResume(); + if (getSSid().contains("G2")) { + Intent intent = new Intent(WifiHotspotActivity.this, SoftAPActivity.class); + intent.putExtra("devId", getIntent().getExtras().get("devId").toString()); + intent.putExtra("devType", devType); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("mPwd", getIntent().getExtras().get("mPwd").toString());//将要连接的wifi的密码携带过去 + intent.putExtra("scCode", getIntent().getExtras().get("scCode").toString()); + startActivity(intent); + finish(); + } + if (getSSid().contains("HF-LPT220")) { + Intent intent = new Intent(WifiHotspotActivity.this, ApConfigActivity.class); + intent.putExtra("ssid", getIntent().getExtras().get("ssid").toString()); + intent.putExtra("password", getIntent().getExtras().get("password").toString()); + intent.putExtra("houseId", SharedpreferencesUtil.get(Constans.HOUSEID, "")); + if (null != getIntent().getExtras().get("addressTypeCode")) { + intent.putExtra("addressTypeCode", getIntent().getExtras().get("addressTypeCode").toString()); + } + if (null != getIntent().getExtras().get("deviceAddress")) { + intent.putExtra("deviceAddress", getIntent().getExtras().get("deviceAddress").toString()); + } + if (null != getIntent().getExtras().get("floor")) { + intent.putExtra("floor", getIntent().getExtras().get("floor").toString()); + } + if (null != getIntent().getExtras().get("deviceCode")) { + intent.putExtra("deviceCode", getIntent().getExtras().get("deviceCode").toString()); + } + if (null != getIntent().getExtras().get("titleRemark")) { + intent.putExtra("titleRemark", getIntent().getExtras().get("titleRemark").toString()); + } + startActivity(intent); + finish(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + private void initView() { + if (null != getIntent().getExtras().get("devType")) { + devType = getIntent().getExtras().get("devType").toString(); + } + iv_gateway_pic = (ImageView) findViewById(R.id.pic_one); + /*selectUnnorReveal = (CheckBox) findViewById(R.id.iv_select_unnor_reveal); + selectUnnorReveal1 = (CheckBox) findViewById(R.id.iv_select_unnor_reveal1);*/ + rl_camera = (RelativeLayout) findViewById(R.id.rl_camera); + rl_gateway = (RelativeLayout) findViewById(R.id.rl_gateway); + ll_camera = (LinearLayout) findViewById(R.id.ll_camera); + ll_gateway = (LinearLayout) findViewById(R.id.ll_gateway); + tv_gateway = (TextView) findViewById(R.id.tv_gateway); + mTitleView = (TitleView) findViewById(R.id.title_wifi_stepone); + mTitleView.setHead(R.string.add_device); + startConfig = (Button) findViewById(R.id.bt_start_config); + startConfig.setOnClickListener(this); + startConfig.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(); + intent.setAction("android.net.wifi.PICK_WIFI_NETWORK"); + startActivity(intent); + } + }); + mTitleView.setTitleListener(new OnTitleItemClickListener() { + @Override + public void onBack() { + finish(); + } + + @Override + public void onFunction() { + + } + + @Override + public void onFunctionText() { + + } + }); + apSmartTv = (TextView) findViewById(R.id.tv_ap_smart_top); + tv_ap_smart_declare = (TextView) findViewById(R.id.tv_ap_smart_declare); + tv_ap_smart_declare1 = (TextView) findViewById(R.id.tv_ap_smart_declare1); + if (devType.equals("1")) { + tv_ap_smart_declare.setText("请将手机Wi-Fi连接到“G2-XXXX”后,返回此页面,热点密码" + getIntent().getExtras().get("scCode").toString()); + tv_ap_smart_declare1.setText("请确保该网关没有在乐橙等第三方app上添加过”"); + } + if (devType.equals("000")) { + tv_ap_smart_declare.setText("请将手机Wi-Fi连接到“HF-LPT220”后,返回App"); + iv_gateway_pic.setImageResource(R.drawable.pic_setup_apwifi); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_select_unnor_reveal: + /*if (selectUnnorReveal.isChecked()) { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_5dp)); + startConfig.setClickable(true); + startConfig.setEnabled(true); + } else { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_e3e3e3_5dp)); + startConfig.setClickable(false); + startConfig.setEnabled(false); + }*/ + break; + case R.id.iv_select_unnor_reveal1: + /* if (selectUnnorReveal1.isChecked()) { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_5dp)); + startConfig.setClickable(true); + startConfig.setEnabled(true); + } else { + startConfig.setBackgroundDrawable(getResources().getDrawable(R.drawable.btn_round_e3e3e3_5dp)); + startConfig.setClickable(false); + startConfig.setEnabled(false); + }*/ + break; + } + } + + @Override + public void callBackUiThread(Message msg) { + } + + private String getSSid() { + + WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); + if (wm != null) { + WifiInfo wi = wm.getConnectionInfo(); + if (wi != null) { + String ssid = wi.getSSID(); + if (ssid.length() > 2 && ssid.startsWith("\"") && ssid.endsWith("\"")) { + return ssid.substring(1, ssid.length() - 1); + } else { + return ssid; + } + } + } + + return ""; + } + +}