Merge branch 'dev_MogoAP_eagle-220_211207_8.0.17_merge' into dev_robotaxi-p-app_254_220228_2.5.4
# Conflicts: # core/function-impl/mogo-core-function-hmi/build.gradle # core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiFragment.kt # core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/carcorder/CarcorderPreviewView.kt # core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_carcorder_preview.xml # libraries/map-usbcamera/build.gradle # libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/UVCCameraHelper.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/CameraDialog.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/DeviceFilter.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/IFrameCallback.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/Size.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBVendorId.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/UVCCamera.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IAudioEncoder.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IVideoEncoder.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaAudioEncoder.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaSurfaceEncoder.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoBufferEncoder.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/RecordParams.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/AACEncodeConsumer.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java # libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/Mp4MediaMuxer.java # libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libUVCCamera.so # libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libjpeg-turbo1500.so # libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libusb100.so # libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libuvc.so # libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libUVCCamera.so # libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libjpeg-turbo1500.so # libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libusb100.so # libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libuvc.so # libraries/map-usbcamera/src/main/jniLibs/x86/libUVCCamera.so # libraries/map-usbcamera/src/main/jniLibs/x86/libjpeg-turbo1500.so # libraries/map-usbcamera/src/main/jniLibs/x86/libusb100.so # libraries/map-usbcamera/src/main/jniLibs/x86/libuvc.so # libraries/map-usbcamera/src/main/jniLibs/x86_64/libUVCCamera.so # libraries/map-usbcamera/src/main/jniLibs/x86_64/libjpeg-turbo1500.so # libraries/map-usbcamera/src/main/jniLibs/x86_64/libusb100.so # libraries/map-usbcamera/src/main/jniLibs/x86_64/libuvc.so
This commit is contained in:
@@ -24,6 +24,7 @@ import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotPlanningListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr;
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast;
|
||||
@@ -134,7 +135,7 @@ public class MogoOCHTaxiModelNew {
|
||||
|
||||
if (NetworkUtils.isConnected(mContext)) {
|
||||
// startOrStopOrderLoop(mOCHCarStatus == 1);
|
||||
if (FunctionBuildConfig.appIdentityMode == 0x00) {
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
queryCarStatus();
|
||||
}
|
||||
}
|
||||
@@ -821,7 +822,7 @@ public class MogoOCHTaxiModelNew {
|
||||
Logger.d( TAG, "onIntentReceived = %s", intentStr );
|
||||
if ( ConnectivityManager.CONNECTIVITY_ACTION.equals( intentStr ) ) {
|
||||
if ( NetworkUtils.isConnected( mContext ) ) {
|
||||
if (FunctionBuildConfig.appIdentityMode == 0x00) {
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
startOrStopOrderLoop(mOCHCarStatus == 1);
|
||||
queryCarStatus();
|
||||
}
|
||||
@@ -941,7 +942,7 @@ public class MogoOCHTaxiModelNew {
|
||||
mPrevAPStatus = state;
|
||||
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& FunctionBuildConfig.appIdentityMode == 0x01) {
|
||||
&& AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
|
||||
// 当美化模式(演示模式)开启时:且是乘客app、且未到终点时,维持自动驾驶icon开启状态
|
||||
if (!arriveAtEnd) {
|
||||
return;
|
||||
@@ -955,7 +956,7 @@ public class MogoOCHTaxiModelNew {
|
||||
mPrevAPStatus = state;
|
||||
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& FunctionBuildConfig.appIdentityMode == 0x01) {
|
||||
&& AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
|
||||
// 当美化模式(演示模式)开启时:且是乘客app、且未到终点时,维持自动驾驶icon开启状态
|
||||
if (!arriveAtEnd) {
|
||||
return;
|
||||
@@ -981,7 +982,7 @@ public class MogoOCHTaxiModelNew {
|
||||
@Override
|
||||
public void onAutopilotArriveAtStation(@Nullable AutopilotStationInfo data) {
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& FunctionBuildConfig.appIdentityMode == 0x01) {
|
||||
&& AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
|
||||
arriveAtEnd = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
|
||||
import com.mogo.eagle.core.function.call.map.CallerSmpManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.uicontroller.VisualAngleMode;
|
||||
@@ -133,7 +134,7 @@ public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presente
|
||||
@Override
|
||||
public void onClickImpl(View v) {
|
||||
// 如果能自动驾驶,就自动驾驶,不能就提示
|
||||
if (FunctionBuildConfig.appIdentityMode == 0x00) {
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
restartAutopilot();
|
||||
}
|
||||
// TODO: 2021/11/27 通过开启结果更新ui
|
||||
@@ -220,7 +221,7 @@ public abstract class BaseOchTaxiTabFragment<V extends IView, P extends Presente
|
||||
showNaviToStartStationFragment(false);
|
||||
});
|
||||
|
||||
if (FunctionBuildConfig.appIdentityMode == 0x01) {
|
||||
if (AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) {
|
||||
flStationPanelContainer.setVisibility(View.GONE);
|
||||
tvOperationStatus.setVisibility(View.GONE);
|
||||
mSettingBtn.setVisibility(View.GONE);
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.fragment.app.FragmentTransaction;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotRouteInfo;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||
import com.mogo.module.common.MogoApisHandler;
|
||||
import com.mogo.och.taxi.passenger.R;
|
||||
@@ -85,7 +86,7 @@ public class OCHTaxiFragment extends BaseOchTaxiTabFragment<OCHTaxiFragment, OCH
|
||||
switchVRFlatMode(false);
|
||||
}
|
||||
|
||||
if (FunctionBuildConfig.appIdentityMode == 0x00) {
|
||||
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
|
||||
tvOperationStatus.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
tvOperationStatus.setVisibility(View.GONE);
|
||||
|
||||
21
ZD_README/README_Utils.md
Normal file
21
ZD_README/README_Utils.md
Normal file
@@ -0,0 +1,21 @@
|
||||
### 项目说明
|
||||
|
||||
* ### 应用身份 相关 -> [AppIdentityModeUtils.java][AppIdentityModeUtils.java] -> [Demo][AppIdentityModeUtils.java]
|
||||
```
|
||||
|
||||
// 判断是否是 司机身份
|
||||
AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)
|
||||
|
||||
// 判断是否是 乘客身份
|
||||
AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)
|
||||
|
||||
|
||||
// 判断是否是 小巴车
|
||||
AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
|
||||
|
||||
// 判断是否是 出租车
|
||||
AppIdentityModeUtils.isTaxi(FunctionBuildConfig.appIdentityMode)
|
||||
|
||||
```
|
||||
|
||||
|
||||
182
app/build.gradle
182
app/build.gradle
@@ -5,9 +5,6 @@ apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'android-aspectjx'
|
||||
apply plugin: 'bugly'
|
||||
|
||||
if (!isAndroidTestBuild()) {
|
||||
apply plugin: 'apm-plugin'
|
||||
}
|
||||
|
||||
//apply ByteX宿主
|
||||
if (!isAndroidTestBuild()) {
|
||||
@@ -18,73 +15,78 @@ if (!isAndroidTestBuild()) {
|
||||
logLevel "DEBUG"
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAndroidTestBuild()) {
|
||||
apply plugin: 'bytex.threadOpt'
|
||||
thread_opt {
|
||||
enable true
|
||||
enableInDebug true
|
||||
rxJavaIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
rxJavaComputationReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
coroutineDefaultReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便使用systrace工具,在工程侧打点,便于分析工程侧性能问题
|
||||
*/
|
||||
apply plugin: 'bytex.systrace'
|
||||
systrace {
|
||||
/**
|
||||
* 交付时要关闭,会有性能损耗
|
||||
*/
|
||||
enable false
|
||||
enableInDebug false
|
||||
/**
|
||||
* - 是否使用[Trace.beginAsyncSection(String, int)/Trace.endAsyncSection(String, int)]进行打点
|
||||
* - 默认使用[Trace.beginSection(String)/Trace.endSection()]进行打点
|
||||
*/
|
||||
isTraceAsync false
|
||||
/**
|
||||
* - 是否在运行时只针对主线程打点,其它线程不打
|
||||
*/
|
||||
isOnlyMainThread false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类的静态构造方法打点
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreClinitMethod false
|
||||
|
||||
/**
|
||||
* - 是否忽略对类中的简单方法打点
|
||||
* 简单方法定义:
|
||||
* - 空方法
|
||||
* - get/set 方法
|
||||
* - 单独的方法,方法体内没有调用其它方法
|
||||
* - 默认不忽略
|
||||
*/
|
||||
isIgnoreSampleMethod false
|
||||
|
||||
/**
|
||||
* - 针对特定类集合,配置打点白名单,在此集合中的类中的所有方法不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForClass = []
|
||||
|
||||
/**
|
||||
* - 针对特定包名集合,配置打点白名单,所有类以此包名为前缀的类不打点
|
||||
* - 支持正则表达式
|
||||
*/
|
||||
whiteListForPackage = []
|
||||
apply plugin: 'chain.log.hook'
|
||||
hooklog{
|
||||
enableLoggerToServer true
|
||||
}
|
||||
}
|
||||
|
||||
//if (!isAndroidTestBuild()) {
|
||||
// apply plugin: 'apm-plugin'
|
||||
//}
|
||||
|
||||
//if (!isAndroidTestBuild()) {
|
||||
// apply plugin: 'bytex.threadOpt'
|
||||
// thread_opt {
|
||||
// enable true
|
||||
// enableInDebug true
|
||||
// rxJavaIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
// rxJavaComputationReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
// coroutineIoReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getIoPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
// coroutineDefaultReplacer 'com/mogo/eagle/core/utilcode/util/ThreadUtils@@getCpuPool@@()Ljava/util/concurrent/ExecutorService;'
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 方便使用systrace工具,在工程侧打点,便于分析工程侧性能问题
|
||||
// */
|
||||
// apply plugin: 'bytex.systrace'
|
||||
// systrace {
|
||||
// /**
|
||||
// * 交付时要关闭,会有性能损耗
|
||||
// */
|
||||
// enable false
|
||||
// enableInDebug false
|
||||
// /**
|
||||
// * - 是否使用[Trace.beginAsyncSection(String, int)/Trace.endAsyncSection(String, int)]进行打点
|
||||
// * - 默认使用[Trace.beginSection(String)/Trace.endSection()]进行打点
|
||||
// */
|
||||
// isTraceAsync false
|
||||
// /**
|
||||
// * - 是否在运行时只针对主线程打点,其它线程不打
|
||||
// */
|
||||
// isOnlyMainThread false
|
||||
//
|
||||
// /**
|
||||
// * - 是否忽略对类的静态构造方法打点
|
||||
// * - 默认不忽略
|
||||
// */
|
||||
// isIgnoreClinitMethod false
|
||||
//
|
||||
// /**
|
||||
// * - 是否忽略对类中的简单方法打点
|
||||
// * 简单方法定义:
|
||||
// * - 空方法
|
||||
// * - get/set 方法
|
||||
// * - 单独的方法,方法体内没有调用其它方法
|
||||
// * - 默认不忽略
|
||||
// */
|
||||
// isIgnoreSampleMethod false
|
||||
//
|
||||
// /**
|
||||
// * - 针对特定类集合,配置打点白名单,在此集合中的类中的所有方法不打点
|
||||
// * - 支持正则表达式
|
||||
// */
|
||||
// whiteListForClass = []
|
||||
//
|
||||
// /**
|
||||
// * - 针对特定包名集合,配置打点白名单,所有类以此包名为前缀的类不打点
|
||||
// * - 支持正则表达式
|
||||
// */
|
||||
// whiteListForPackage = []
|
||||
// }
|
||||
//}
|
||||
|
||||
/*apply plugin: 'chain.log.hook'
|
||||
hooklog{
|
||||
enableLoggerToServer true
|
||||
}*/
|
||||
bugly {
|
||||
appId = 'ac71228f85' // 注册时分配的App ID
|
||||
appKey = '3c736249-d6be-4066-b577-b7a6dc975cf7' // 注册时分配的App Key
|
||||
@@ -254,31 +256,31 @@ dependencies {
|
||||
androidTestImplementation rootProject.ext.dependencies.androidx_espresso_core
|
||||
}
|
||||
|
||||
if (!isAndroidTestBuild()) {
|
||||
ApmPlugin {
|
||||
// 是否进行插桩
|
||||
enable true
|
||||
// 是否在Debug包插桩,默认不插桩
|
||||
enableInDebug true
|
||||
// DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");
|
||||
// INFO 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin
|
||||
logLevel "DEBUG"
|
||||
// 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
|
||||
startSwitch = true
|
||||
// 页面响应开关:监控Activity的生命周期耗时
|
||||
pageLoadSwitch = true
|
||||
// 网络监控开关:监控okhttp3的网络请求
|
||||
okHttp3Switch = true
|
||||
// 白名单下的包进行插桩,需要填写要插装类所在的包名,支持前缀配置
|
||||
whiteList = [
|
||||
"com.mogo"
|
||||
]
|
||||
// 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
|
||||
blackList = [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
//if (!isAndroidTestBuild()) {
|
||||
// ApmPlugin {
|
||||
// // 是否进行插桩
|
||||
// enable true
|
||||
// // 是否在Debug包插桩,默认不插桩
|
||||
// enableInDebug true
|
||||
// // DEBUG("DEBUG"), INFO("INFO"), WARN("WARN"), ERROR("ERROR");
|
||||
// // INFO 级别Log会汇总所有被插桩处理的类供查看,路径 app/build/ByteX/ApmPlugin
|
||||
// logLevel "DEBUG"
|
||||
// // 启动分析开关:监控App启动耗时,需要同时开启pageLoadSwitch
|
||||
// startSwitch = true
|
||||
// // 页面响应开关:监控Activity的生命周期耗时
|
||||
// pageLoadSwitch = true
|
||||
// // 网络监控开关:监控okhttp3的网络请求
|
||||
// okHttp3Switch = true
|
||||
// // 白名单下的包进行插桩,需要填写要插装类所在的包名,支持前缀配置
|
||||
// whiteList = [
|
||||
// "com.mogo"
|
||||
// ]
|
||||
// // 黑名单包下类不进行插桩,可以配置包名和类名,没有可以填空
|
||||
// blackList = [
|
||||
//
|
||||
// ]
|
||||
// }
|
||||
//}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
def buildTime = new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08:00"))
|
||||
|
||||
@@ -29,7 +29,7 @@ project.android.productFlavors {
|
||||
// 构建的应用身份类型,司机|乘客
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0x02"
|
||||
// 连接的工控机IP地址
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.1.102\""
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.1.104\""
|
||||
// 构建的是否是演示(美化)模式
|
||||
buildConfigField 'boolean', 'IS_DEMO_MODE', 'true'
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ project.android.productFlavors {
|
||||
// GPS数据提供源: 0-Android系统,1-工控机,2-OBU
|
||||
buildConfigField 'int', 'GPS_PROVIDER', "1"
|
||||
|
||||
// 构建的应用身份类型,司机|乘客
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0x00"
|
||||
// 构建的应用身份类型,出租车0|小巴A-司机|乘客
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0xA0"
|
||||
// 连接的工控机IP地址
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.8.102\""
|
||||
// 构建的是否是演示(美化)模式
|
||||
|
||||
@@ -26,8 +26,8 @@ project.android.productFlavors {
|
||||
// GPS数据提供源: 0-Android系统,1-工控机,2-OBU
|
||||
buildConfigField 'int', 'GPS_PROVIDER', "1"
|
||||
|
||||
// 构建的应用身份类型,司机0|乘客1
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0x01"
|
||||
// 构建的应用身份类型,出租车0|小巴A-司机0|乘客1
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0xA1"
|
||||
// 连接的工控机IP地址
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.8.103\""
|
||||
// 构建的是否是演示(美化)模式
|
||||
|
||||
@@ -29,7 +29,7 @@ project.android.productFlavors {
|
||||
// GPS数据提供源: 0-Android系统,1-工控机,2-OBU
|
||||
buildConfigField 'int', 'GPS_PROVIDER', "1"
|
||||
|
||||
// 构建的应用身份类型,司机|乘客
|
||||
// 构建的应用身份类型,出租车0|小巴A-司机|乘客
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0x00"
|
||||
// 连接的工控机IP地址
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.1.102\""
|
||||
|
||||
@@ -28,7 +28,7 @@ project.android.productFlavors {
|
||||
// GPS数据提供源: 0-Android系统,1-工控机,2-OBU
|
||||
buildConfigField 'int', 'GPS_PROVIDER', "1"
|
||||
|
||||
// 构建的应用身份类型,司机0|乘客1
|
||||
// 构建的应用身份类型,出租车0|小巴A-司机0|乘客1
|
||||
buildConfigField 'int', 'APP_IDENTITY_MODE', "0x01"
|
||||
// 连接的工控机IP地址
|
||||
buildConfigField 'String', 'ADAS_CONNECT_IP', "\"192.168.1.103\""
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.mogo.functions.test
|
||||
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import com.mogo.eagle.core.function.hmi.ui.MoGoHmiFragment
|
||||
import com.mogo.eagle.core.function.main.MainLauncherActivity
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class TipToastLeakTest {
|
||||
|
||||
|
||||
lateinit var launch: ActivityScenario<MainLauncherActivity>
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
launch = ActivityScenario.launch(MainLauncherActivity::class.java)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test() = runBlocking(Dispatchers.Main) {
|
||||
val f = ensureMoGoHmiFragmentShow()
|
||||
var index = 0
|
||||
while (index < 50) {
|
||||
delay(TimeUnit.SECONDS.toMillis(4))
|
||||
TipToast.shortTip("toast-> $index" )
|
||||
index ++
|
||||
}
|
||||
delay(TimeUnit.SECONDS.toMillis(1))
|
||||
f.activity?.finish()
|
||||
delay(TimeUnit.SECONDS.toMillis(2))
|
||||
}
|
||||
|
||||
private suspend fun ensureMoGoHmiFragmentShow(): MoGoHmiFragment = suspendCancellableCoroutine {
|
||||
launch.onActivity { itx ->
|
||||
val executor = Executors.newSingleThreadScheduledExecutor()
|
||||
executor.scheduleAtFixedRate({
|
||||
var find =
|
||||
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
|
||||
while (find == null) {
|
||||
find =
|
||||
itx.supportFragmentManager.fragments.find { it is MoGoHmiFragment } as? MoGoHmiFragment
|
||||
|
||||
}
|
||||
while (!find.isResumed) {
|
||||
Thread.sleep(500)
|
||||
}
|
||||
it.resumeWith(Result.success(find))
|
||||
try {
|
||||
Thread.sleep(500)
|
||||
executor.shutdownNow()
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}, 50, 500, MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,7 @@ public class MogoApplication extends MainMoGoApplication {
|
||||
HmiBuildConfig.isShowPerspectiveSwitchView = false;
|
||||
HmiBuildConfig.isShowToolsView = false;
|
||||
HmiBuildConfig.isShowBadCaseView = false;
|
||||
HmiBuildConfig.isShowUpgradeTipsView = false;
|
||||
//业务端可以根据需要控制是否展示刹车和转向灯的ui
|
||||
// HmiBuildConfig.isShowBrakeLightView = false;
|
||||
// HmiBuildConfig.isShowTurnLightView = false;
|
||||
|
||||
@@ -35,9 +35,7 @@ buildscript {
|
||||
classpath 'com.volcengine:apm_insight_plugin:1.4.1'
|
||||
classpath 'com.mogo.cloud:thread_opt:1.0.1'
|
||||
classpath 'com.mogo.cloud:systrace:1.0.1'
|
||||
|
||||
// classpath "com.bytedance.android.byteX:base-plugin:0.3.0"
|
||||
// classpath "com.mogo.cloud:hook:${HOOK_LOG_VERSION}"
|
||||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
|
||||
|
||||
// classpath ("com.tencent.matrix:matrix-gradle-plugin:0.6.6") { changing = true }
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ ext {
|
||||
obusdk : "com.zhidao.enterprise.smartv2x:smartv2x:1.0.0.3",
|
||||
mogoobu : 'com.zhidao.support.obu:mogoobu:1.0.0.19',
|
||||
mogoami : 'com.zhidao.support.obu.ami:mogoami:1.0.0.10',
|
||||
adasHigh : 'com.zhidao.support.adas:high:1.2.1.2_bate21',
|
||||
adasHigh : 'com.zhidao.support.adas:high:1.2.1.2_bate25',
|
||||
|
||||
// google
|
||||
googlezxing : "com.google.zxing:core:3.3.3",
|
||||
@@ -222,6 +222,7 @@ ext {
|
||||
mogoaicloudtanlu : "com.mogo.cloud:tanlu:${MOGO_TANLU_VERSION}",
|
||||
mogoaicloudtrafficlive : "com.mogo.cloud:trafficlive:${MOGO_TRAFFICLIVE_VERSION}",
|
||||
mogoaicloudlocation : "com.mogo.cloud:location:${MOGO_LOCATION_VERSION}",
|
||||
mogoaicloudtelematic : "com.mogo.cloud:telematic:${MOGO_TELEMATIC_VERSION}",
|
||||
|
||||
//========================= 新架构的 Maven 版本管理 =========================
|
||||
mogo_core_function_autopilot : "com.mogo.eagle.core.function.impl:autopilot:${MOGO_CORE_FUNCTION_AUTOPILOT_VERSION}",
|
||||
@@ -237,13 +238,14 @@ ext {
|
||||
mogo_core_function_v2x : "com.mogo.eagle.core.function.impl:v2x:${MOGO_CORE_FUNCTION_V2X_VERSION}",
|
||||
mogo_core_function_api : "com.mogo.eagle.core.function:api:${MOGO_CORE_FUNCTION_API_VERSION}",
|
||||
mogo_core_function_call : "com.mogo.eagle.core.function:call:${MOGO_CORE_FUNCTION_CALL_VERSION}",
|
||||
mogo_core_function_carcorder : "com.mogo.eagle.core.function:carcorder:${MOGO_CORE_FUNCTION_CARCORDER_VERSION}",
|
||||
mogo_core_data : "com.mogo.eagle.core:data:${MOGO_CORE_DATA_VERSION}",
|
||||
mogo_core_res : "com.mogo.eagle.core:res:${MOGO_CORE_RES_VERSION}",
|
||||
mogo_core_utils : "com.mogo.eagle.core:utils:${MOGO_CORE_UTILS_VERSION}",
|
||||
mogo_core_network : "com.mogo.eagle.core:network:${MOGO_CORE_NETWORK_VERSION}",
|
||||
|
||||
//========================= V2X SDK =========================
|
||||
mogo_v2x : "com.mogo.v2x:v2x:${MOGO_V2X_SDK_VERSION}",
|
||||
mogo_v2x : "com.mogo.v2x:v2x:${MOGO_V2X_SDK_VERSION}",
|
||||
|
||||
life_cycle_scope : "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0",
|
||||
view_model_scope : "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0",
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
本模块用来编写鹰眼核型功能
|
||||
|
||||
- function-impl 目录下编写的都是对mogo-core-function-api定的功能实现,
|
||||
- mogo-core-function-check 程序及车辆检测模块
|
||||
- mogo-core-function-devatools 开发工具模块
|
||||
- mogo-core-function-hmi UI呈现及交互模块
|
||||
- mogo-core-function-main 主入口
|
||||
- mogo-core-function-map 地图相关的模块
|
||||
- mogo-core-function-monitoring 远距离监控查看,路测摄像头、前车直播
|
||||
- mogo-core-function-notice 云端公告、调度相关模块
|
||||
- mogo-core-function-obu-mogo 自研OBU预警模块
|
||||
- mogo-core-function-smp 小地图模块
|
||||
- mogo-core-function-v2x 自车+云端预警模块
|
||||
- check 程序及车辆检测模块
|
||||
- devatools 开发工具模块:日志采集、BadCase、
|
||||
- hmi UI呈现及交互模块
|
||||
- main 主入口(模块加载、后台服务启动、多进程启动等)
|
||||
- map 地图相关的模块
|
||||
- monitoring 行车超视距模块,路测摄像头、前车直播
|
||||
- notice 云端公告、调度相关模块
|
||||
- obu-mogo 自研OBU预警模块
|
||||
- smp 小地图模块
|
||||
- v2x 自车+云端预警模块
|
||||
|
||||
- mogo-core-data:定义基础业务所需要的数据结构
|
||||
|
||||
- mogo-core-function-res:这里只存放公共资源,图片,布局,动画等
|
||||
|
||||
- mogo-core-network:公共网络请求
|
||||
|
||||
- mogo-core-function-api:定义基础业务功能的接口
|
||||
|
||||
- mogo-core-function-call:定义基础业务暴露给外部调用的接口,对function-impl的二次封装,只将能对外调用的功能进行封装
|
||||
|
||||
- mogo-core-res:程序中涉及到的图片及布局资源,同一管理,并通过设置不同的目录指定是那个模块的资源
|
||||
- mogo-core-res:程序中涉及到的图片及布局资源,同一管理,并通过设置不同的目录指定是那个模块的资源,这里只存放公共资源,图片,布局,动画等
|
||||
|
||||
- mogo-core-utils:基于成熟的工具类开源框架下沉的,这里可以增添针对我们业务上的一些工具类
|
||||
|
||||
@@ -51,18 +51,20 @@ dependencies {
|
||||
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
|
||||
implementation rootProject.ext.dependencies.adasHigh
|
||||
implementation rootProject.ext.dependencies.mogochainbase
|
||||
implementation rootProject.ext.dependencies.mogoami
|
||||
implementation rootProject.ext.dependencies.mogoaicloudtelematic
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogo_core_data
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
implementation rootProject.ext.dependencies.moduleservice
|
||||
|
||||
implementation rootProject.ext.dependencies.mogo_core_data
|
||||
implementation rootProject.ext.dependencies.mogo_core_utils
|
||||
implementation rootProject.ext.dependencies.mogo_core_network
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_api
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_call
|
||||
implementation rootProject.ext.dependencies.adasHigh
|
||||
} else {
|
||||
implementation project(':modules:mogo-module-common')
|
||||
implementation project(':modules:mogo-module-service')
|
||||
@@ -72,6 +74,7 @@ dependencies {
|
||||
implementation project(':core:mogo-core-network')
|
||||
implementation project(':core:mogo-core-function-api')
|
||||
implementation project(':core:mogo-core-function-call')
|
||||
implementation project(':libraries:mogo-adas')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.Manifest.permission
|
||||
import android.content.Context
|
||||
import androidx.annotation.RequiresPermission
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlCmdParameter
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
@@ -21,10 +22,12 @@ import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.zhidao.support.adas.high.AdasManager
|
||||
import com.zhidao.support.adas.high.AdasOptions
|
||||
import com.zhidao.support.adas.high.bean.IPCUpgradeInfo
|
||||
import com.zhidao.support.adas.high.common.CupidLogUtils
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
/**
|
||||
* @author xiaoyuzhou
|
||||
* @date 2021/9/22 8:43 下午
|
||||
@@ -32,7 +35,7 @@ import java.util.concurrent.TimeUnit
|
||||
*/
|
||||
@Route(path = MogoServicePaths.PATH_AUTO_PILOT)
|
||||
class MoGoAutopilotProvider :
|
||||
IMoGoAutopilotProvider, IMoGoMapDataCollectProvider.OnMapCollectCmdListener {
|
||||
IMoGoAutopilotProvider, IMoGoMapDataCollectProvider.OnMapCollectCmdListener {
|
||||
private val TAG = "MoGoAutoPilotProvider"
|
||||
private var mContext: Context? = null
|
||||
|
||||
@@ -50,24 +53,121 @@ class MoGoAutopilotProvider :
|
||||
when (FunctionBuildConfig.appIdentityMode) {
|
||||
0x00 -> // 司机
|
||||
{
|
||||
// 注册地图采集功能
|
||||
CallerMapDataCollectorManager.registerOnMapCollectTaskListener(this)
|
||||
AdasManager.getInstance().create(context, FunctionBuildConfig.adasConnectIP)
|
||||
// "192.168.1.102"
|
||||
val options = AdasOptions.Builder()
|
||||
.setIPCIp(FunctionBuildConfig.adasConnectIP)
|
||||
.setClient(false)
|
||||
.build()
|
||||
|
||||
AdasManager.getInstance().create(context, options)
|
||||
// NSDNettyManager.getInstance().startNSDNettyServer(context, object : NettyServerListener<MogoProtocolMsg> {
|
||||
// override fun onMessageResponseServer(msg: MogoProtocolMsg?, channel: Channel?) {
|
||||
// Logger.d(TAG, "Receive client data is:${msg?.toString()}")
|
||||
// }
|
||||
//
|
||||
// override fun onStartServer() {
|
||||
// ToastUtils.showShort("司机端服务启动成功!")
|
||||
// Logger.d(TAG, "onStartServer")
|
||||
// }
|
||||
//
|
||||
// override fun onStopServer() {
|
||||
// ToastUtils.showLong("司机端服务停止!")
|
||||
// Logger.d(TAG, "onStopServer")
|
||||
// }
|
||||
//
|
||||
// override fun onChannelConnect(channel: Channel?) {
|
||||
// NSDNettyManager.getInstance().selectChannel(channel)
|
||||
// val socketAddress = channel?.remoteAddress().toString()
|
||||
// Logger.d(TAG, "Client ip is:${socketAddress}")
|
||||
// }
|
||||
//
|
||||
// override fun onChannelDisConnect(channel: Channel?) {
|
||||
// Logger.d(TAG, "onChannelDisConnect")
|
||||
// }
|
||||
// })
|
||||
}
|
||||
0x01 -> // 乘客
|
||||
{
|
||||
// 乘客端默认接收绘制全局路径+引导线
|
||||
//FunctionBuildConfig.isDemoMode = true
|
||||
//FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true
|
||||
AdasManager.getInstance().create(context, FunctionBuildConfig.adasConnectIP)
|
||||
// "192.168.1.102"
|
||||
val options = AdasOptions
|
||||
.Builder()
|
||||
.setClient(true)
|
||||
.build()
|
||||
AdasManager.getInstance().create(context, options)
|
||||
// NSDNettyManager.getInstance().searchAndConnectServer(context, MoGoAiCloudClientConfig.getInstance().sn, object : NettyClientListener<MogoProtocolMsg> {
|
||||
// override fun onMessageResponseClient(msg: MogoProtocolMsg?, sign: String?) {
|
||||
// Logger.d(TAG, "收到司机端的数据!")
|
||||
// // 乘客端收到adas数据直接解析,后续分发解析后的数据流程同司机端
|
||||
// msg?.let {
|
||||
// AdasManager.getInstance().parseIPCData(it.body)
|
||||
// Logger.d(TAG, "解析司机端数据完毕!")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onClientStatusConnectChanged(statusCode: Int, sign: String?) {
|
||||
// when (statusCode) {
|
||||
// ConnectState.STATUS_CONNECT_SUCCESS -> Logger.d(TAG, "乘客端连接司机端服务成功! sign is:${sign}")
|
||||
// else -> {
|
||||
// ToastUtils.showLong("和司机端连接异常!")
|
||||
// Logger.d(TAG, "client statusCode is:${statusCode}")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
//
|
||||
else -> // 默认采用UDP寻址方式
|
||||
AdasManager.getInstance().create(context)
|
||||
{
|
||||
val options = AdasOptions.Builder()
|
||||
.setClient(false)
|
||||
.setIPCIp(FunctionBuildConfig.adasConnectIP)
|
||||
.build()
|
||||
AdasManager.getInstance().create(context, options)
|
||||
}
|
||||
}
|
||||
//////////////////////////////////注意先后顺序,AdasManager.getInstance().create后才可以设置监听/////////////////////////////////////////////
|
||||
// 监听 adas 连接状态
|
||||
AdasManager.getInstance().setOnAdasConnectStatusListener(MoGoAdasMsgConnectStatusListenerImpl())
|
||||
// 监听ADAS-SDK获取到的工控机数据
|
||||
AdasManager.getInstance()
|
||||
.setOnAdasConnectStatusListener(MoGoAdasMsgConnectStatusListenerImpl())
|
||||
// 监听ADAS-SDK获取到的工控机数据(乘客也需注册)
|
||||
AdasManager.getInstance().setOnAdasListener(MoGoAdasListenerImpl())
|
||||
// // 司机端监听
|
||||
// if (FunctionBuildConfig.appIdentityMode == 0) {
|
||||
// AdasManager.getInstance().setOnMultiDeviceListener { bytes ->
|
||||
// Logger.d(
|
||||
// TAG,
|
||||
// "司机端接收到工控机吐出来的数据为:${Arrays.toString(bytes)}"
|
||||
// )
|
||||
// // 发送数据给乘客端
|
||||
// if (NSDNettyManager.getInstance().isServerStart) {
|
||||
// Logger.d(
|
||||
// TAG,
|
||||
// "司机端透传数据给乘客端!"
|
||||
// )
|
||||
// NSDNettyManager.getInstance().sendMsgToAllClients(MogoProtocolMsg(NORMAL_DATA, bytes.size, bytes))
|
||||
//// NSDNettyManager.getInstance().sendMogoProtocolMsgToClient(MogoProtocolMsg(NORMAL_DATA, bytes.size, bytes)) { channelFuture: ChannelFuture ->
|
||||
//// if (channelFuture.isSuccess) {
|
||||
//// Logger.d(
|
||||
//// TAG,
|
||||
//// "Send data to client is success."
|
||||
//// )
|
||||
//// } else {
|
||||
//// Logger.d(
|
||||
//// TAG,
|
||||
//// "Send data to client is failure."
|
||||
//// )
|
||||
//// }
|
||||
//// }
|
||||
// } else {
|
||||
// Logger.d(TAG, "司机端Server未启动!")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// 同步数据给工控机的服务
|
||||
AsyncDataToAutopilotServer.INSTANCE.initServer()
|
||||
// 同步是否开启美化模式
|
||||
@@ -87,7 +187,9 @@ class MoGoAutopilotProvider :
|
||||
@RequiresPermission(permission.INTERNET)
|
||||
override fun doInBackground(): String {
|
||||
// 保存本地 AutoPilot IP地址
|
||||
mContext?.let { SharedPrefsMgr.getInstance(it).putString(MoGoConfig.AUTOPILOT_IP, autoPilotIp) }
|
||||
mContext?.let {
|
||||
SharedPrefsMgr.getInstance(it).putString(MoGoConfig.AUTOPILOT_IP, autoPilotIp)
|
||||
}
|
||||
// 设置IP地址
|
||||
AdasManager.getInstance().setIPCIp(autoPilotIp)
|
||||
// 打开通讯连接
|
||||
@@ -134,7 +236,7 @@ class MoGoAutopilotProvider :
|
||||
|
||||
override fun recordPackage(): Boolean {
|
||||
return AdasManager.getInstance()
|
||||
.recordPackage(1, (System.currentTimeMillis() / 1000).toInt())
|
||||
.recordPackage(1, (System.currentTimeMillis() / 1000).toInt())
|
||||
}
|
||||
|
||||
override fun recordPackage(type: Int, id: Int): Boolean {
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
package com.mogo.eagle.core.function.autopilot.adapter;
|
||||
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ARRIVE;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_GUARDIAN;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_RECORD;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ROUTE;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_STATUS;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_WARN;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_STATE;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_ALIAS_CODE_ADAS_MESSAGE_RECT_DATA;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_LINK_ADAS;
|
||||
import static com.mogo.eagle.core.data.chain.ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_DATA;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -42,6 +54,8 @@ import com.zhidao.support.adas.high.bean.WarnMessageInfo;
|
||||
import com.zhidao.support.adas.high.bean.guardian.AutopilotGuardianInfo;
|
||||
import com.zhidao.support.adas.high.bean.record.AutopilotRecordResult;
|
||||
import com.zhidao.support.obu.ami.AmiClientManager;
|
||||
import com.zhjt.service.chain.ChainLog;
|
||||
import com.zhjt.service.chain.TracingConstants;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
@@ -57,7 +71,12 @@ import java.util.List;
|
||||
public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
private final String TAG = "OnAdasListenerAdapter";
|
||||
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_RECT_DATA,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onRectData(RectInfo rectInfo) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
@@ -66,6 +85,12 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_STATE,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onCarStateData(CarStateInfo carStateInfo) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
@@ -145,6 +170,12 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_STATUS,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void autopilotStatus(AutopilotStatus autopilotStatus) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
@@ -177,10 +208,16 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ARRIVE,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void autopilotArrive(AutopilotWayArrive autopilotWayArrive) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
Logger.d(TAG, "autopilotArrive : " + autopilotWayArrive);
|
||||
// Logger.d(TAG, "autopilotArrive : " + autopilotWayArrive);
|
||||
if (autopilotWayArrive != null) {
|
||||
AutopilotWayArrive.ResultBean result = autopilotWayArrive.getResult();
|
||||
if (result != null) {
|
||||
@@ -195,19 +232,30 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ROUTE,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onAutopilotRoute(AutopilotRoute route) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
Logger.d(TAG, "onAutopilotRoute : " + route.toString());
|
||||
// Logger.d(TAG, "onAutopilotRoute : " + route.toString());
|
||||
AutopilotRouteInfo autopilotRoute = AdasObjectConvertUtils.INSTANCE.fromAdasAutopilotRoute(route);
|
||||
CallerAutopilotPlanningListenerManager.INSTANCE.invokeAutopilotRotting(autopilotRoute);
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onAutopilotTrajectory(List<TrajectoryInfo> trajectoryList) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
Logger.d(TAG, "onAutopilotTrajectory : " + trajectoryList);
|
||||
// Logger.d(TAG, "onAutopilotTrajectory : " + trajectoryList);
|
||||
ArrayList<ADASTrajectoryInfo> trajectoryInfoArrayList = new ArrayList<>();
|
||||
if (trajectoryList != null && trajectoryList.size() > 0) {
|
||||
for (TrajectoryInfo trajectory : trajectoryList) {
|
||||
@@ -223,7 +271,7 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
adasTrajectoryInfo.setTheta(trajectory.getTheta());
|
||||
trajectoryInfoArrayList.add(adasTrajectoryInfo);
|
||||
}
|
||||
Log.e(TAG, "time:" + System.currentTimeMillis() + "trajectoryInfoArrayList:" + trajectoryInfoArrayList);
|
||||
// Log.e(TAG, "time:" + System.currentTimeMillis() + "trajectoryInfoArrayList:" + trajectoryInfoArrayList);
|
||||
}
|
||||
CallerAutopilotPlanningListenerManager.INSTANCE.invokeAutopilotTrajectory(trajectoryInfoArrayList);
|
||||
}
|
||||
@@ -234,6 +282,12 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
CallerAutoPilotStatusListenerManager.INSTANCE.invokeAutopilotSNRequest();
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_GUARDIAN,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onAutopilotGuardian(AutopilotGuardianInfo guardianInfo) {
|
||||
if (HdMapBuildConfig.isMapLoaded) {
|
||||
@@ -242,6 +296,12 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
}
|
||||
}
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_RECORD,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onAutopilotRecord(AutopilotRecordResult result) {
|
||||
if (result != null) {
|
||||
@@ -276,7 +336,12 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// @ChainLog(linkCode = CHAIN_LINK_ADAS,
|
||||
// linkChainLog = CHAIN_LINK_LOG_WEB_SOCKET_DATA,
|
||||
// endpoint = TracingConstants.Endpoint.PAD,
|
||||
// nodeAliasCode = CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_WARN,
|
||||
// paramIndexes = {0},
|
||||
// clientPkFileName = "sn")
|
||||
@Override
|
||||
public void onWarnMessage(WarnMessageInfo warnMessageInfo) {
|
||||
final AutopilotWarnMessage warnMessage = AdasObjectConvertUtils.INSTANCE.fromAdasObject(warnMessageInfo);
|
||||
|
||||
1
core/function-impl/mogo-core-function-carcorder/.gitignore
vendored
Normal file
1
core/function-impl/mogo-core-function-carcorder/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
75
core/function-impl/mogo-core-function-carcorder/build.gradle
Normal file
75
core/function-impl/mogo-core-function-carcorder/build.gradle
Normal file
@@ -0,0 +1,75 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-android-extensions'
|
||||
id 'kotlin-kapt'
|
||||
id 'com.alibaba.arouter'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
|
||||
//ARouter apt 参数
|
||||
kapt {
|
||||
useBuildCache = false
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.getName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
||||
implementation rootProject.ext.dependencies.coroutinescore
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.mogologlib
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
|
||||
implementation project(':libraries:map-usbcamera')
|
||||
|
||||
implementation rootProject.ext.dependencies.mogo_core_utils
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_api
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_call
|
||||
implementation rootProject.ext.dependencies.mogo_core_data
|
||||
}else {
|
||||
implementation project(':services:mogo-service-api')
|
||||
implementation project(':modules:mogo-module-common')
|
||||
|
||||
implementation project(':libraries:map-usbcamera')
|
||||
|
||||
implementation project(':core:mogo-core-utils')
|
||||
implementation project(':core:mogo-core-function-api')
|
||||
implementation project(':core:mogo-core-function-call')
|
||||
implementation project(':core:mogo-core-data')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.eagle.core.function.impl
|
||||
POM_ARTIFACT_ID=carcorder
|
||||
VERSION_CODE=1
|
||||
21
core/function-impl/mogo-core-function-carcorder/proguard-rules.pro
vendored
Normal file
21
core/function-impl/mogo-core-function-carcorder/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.eagle.core.function.carcorder">
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name=".service.CarcorderService"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:process=":uvcservice">
|
||||
<intent-filter>
|
||||
<action android:name="com.mogo.launcher.action.CARCORDER_SERVICE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.mogo.eagle.core.function.carcorder.service
|
||||
|
||||
import android.content.Intent
|
||||
import android.hardware.usb.UsbDevice
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.usbcamera.UVCCameraHelper
|
||||
import com.serenegiant.usb.IFrameCallback
|
||||
import com.serenegiant.usb.USBMonitor
|
||||
import com.serenegiant.usb.USBMonitor.OnDeviceConnectListener
|
||||
import com.serenegiant.usb.USBMonitor.UsbControlBlock
|
||||
import com.serenegiant.usb.UVCCamera
|
||||
import com.serenegiant.usb.common.BaseService
|
||||
import com.serenegiant.usb.encoder.MediaVideoBufferEncoder
|
||||
|
||||
/**
|
||||
* 行车记录仪服务
|
||||
* @author donghongyu
|
||||
*/
|
||||
class CarcorderService : BaseService() {
|
||||
private val DEBUG = true
|
||||
val TAG = CarcorderService::class.java.name
|
||||
|
||||
// 挂载的USB设备集合
|
||||
private var mDeviceList: List<UsbDevice>? = null
|
||||
|
||||
// USB 设备连接工具
|
||||
private var mUSBMonitor: USBMonitor? = null
|
||||
|
||||
// 用于接入UVC摄像机
|
||||
private var mUVCCamera: UVCCamera? = null
|
||||
|
||||
// 相机控制
|
||||
private var mCtrlBlock: UsbControlBlock? = null
|
||||
|
||||
/**
|
||||
* 配置相机基本按书
|
||||
*/
|
||||
private val previewWidth = 640
|
||||
private val previewHeight = 480
|
||||
|
||||
// Default using MJPEG
|
||||
// if your device is connected,but have no images
|
||||
// please try to change it to FRAME_FORMAT_YUYV
|
||||
val FRAME_FORMAT_MJPEG: Int = UVCCamera.FRAME_FORMAT_MJPEG
|
||||
val MODE_BRIGHTNESS = UVCCamera.PU_BRIGHTNESS
|
||||
val MODE_CONTRAST = UVCCamera.PU_CONTRAST
|
||||
private val mFrameFormat = UVCCameraHelper.FRAME_FORMAT_MJPEG
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (DEBUG) {
|
||||
Logger.d(TAG, "onCreate……")
|
||||
}
|
||||
if (mUSBMonitor == null) {
|
||||
mUSBMonitor = USBMonitor(applicationContext, mOnDeviceConnectListener)
|
||||
mUSBMonitor!!.register()
|
||||
mDeviceList = mUSBMonitor!!.deviceList
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (DEBUG) Log.d(TAG, "onDestroy:")
|
||||
if (mUSBMonitor != null) {
|
||||
mUSBMonitor!!.unregister()
|
||||
mUSBMonitor = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onRebind(intent: Intent) {
|
||||
if (DEBUG) Log.d(TAG, "onRebind:$intent")
|
||||
}
|
||||
|
||||
|
||||
override fun onUnbind(intent: Intent): Boolean {
|
||||
if (DEBUG) Log.d(TAG, "onUnbind:$intent")
|
||||
|
||||
if (DEBUG) Log.d(TAG, "onUnbind:finished")
|
||||
return true
|
||||
}
|
||||
|
||||
//**********************************************************************************************************************************
|
||||
private val mSync: Any = Any()
|
||||
|
||||
private val mVideoEncoder: MediaVideoBufferEncoder? = null
|
||||
|
||||
|
||||
/**
|
||||
* USB 设备连接监听
|
||||
*/
|
||||
private val mOnDeviceConnectListener: OnDeviceConnectListener = object : OnDeviceConnectListener {
|
||||
override fun onAttach(device: UsbDevice) {
|
||||
if (DEBUG) Log.d(TAG, "OnDeviceConnectListener#onAttach:${device.deviceName}---mDeviceList:${mDeviceList?.size}")
|
||||
mUSBMonitor!!.requestPermission(device)
|
||||
}
|
||||
|
||||
override fun onConnect(device: UsbDevice, ctrlBlock: UsbControlBlock, createNew: Boolean) {
|
||||
if (DEBUG) Log.d(TAG, "OnDeviceConnectListener#onConnect:${device.deviceName}")
|
||||
openCamera(device, ctrlBlock, createNew)
|
||||
}
|
||||
|
||||
override fun onDisconnect(device: UsbDevice, ctrlBlock: UsbControlBlock) {
|
||||
if (DEBUG) Log.d(TAG, "OnDeviceConnectListener#onDisconnect:${device.deviceName}")
|
||||
}
|
||||
|
||||
override fun onDettach(device: UsbDevice) {
|
||||
if (DEBUG) Log.d(TAG, "OnDeviceConnectListener#onDettach:${device.deviceName}")
|
||||
}
|
||||
|
||||
override fun onCancel(device: UsbDevice) {
|
||||
if (DEBUG) Log.d(TAG, "OnDeviceConnectListener#onCancel:${device.deviceName}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接相机
|
||||
*/
|
||||
private fun openCamera(device: UsbDevice, ctrlBlock: UsbControlBlock, createNew: Boolean) {
|
||||
if (mUVCCamera == null) {
|
||||
mUVCCamera = UVCCamera()
|
||||
mUVCCamera!!.open(ctrlBlock)
|
||||
mUVCCamera!!.setStatusCallback { statusClass, event, selector, statusAttribute, data ->
|
||||
if (DEBUG) Log.d(TAG, "IStatusCallback#onStatus(statusClass=${statusClass},event=${event},selector=${selector},statusAttribute=${statusAttribute},data=${data})")
|
||||
}
|
||||
|
||||
try {
|
||||
mUVCCamera!!.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.FRAME_FORMAT_MJPEG)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
try {
|
||||
mUVCCamera!!.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.DEFAULT_PREVIEW_MODE)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
mUVCCamera!!.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
mUVCCamera!!.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_YUV420SP)
|
||||
mUVCCamera!!.startPreview()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频帧回掉
|
||||
*/
|
||||
private val mIFrameCallback = IFrameCallback { frame ->
|
||||
if (DEBUG) Log.d(TAG, "IFrameCallback#onFrame:${frame}")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.mogo.eagle.core.function.carcorder.service
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.serenegiant.usb.common.BaseService
|
||||
|
||||
/**
|
||||
* 行车记录仪服务
|
||||
* @author donghongyu
|
||||
*/
|
||||
class LivePushService : BaseService() {
|
||||
private val DEBUG = true
|
||||
val TAG = LivePushService::class.java.name
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (DEBUG) {
|
||||
Logger.d(TAG, "onCreate……")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (DEBUG) Log.d(TAG, "onDestroy:")
|
||||
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onRebind(intent: Intent) {
|
||||
if (DEBUG) Log.d(TAG, "onRebind:$intent")
|
||||
}
|
||||
|
||||
|
||||
override fun onUnbind(intent: Intent): Boolean {
|
||||
if (DEBUG) Log.d(TAG, "onUnbind:$intent")
|
||||
|
||||
if (DEBUG) Log.d(TAG, "onUnbind:finished")
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -48,6 +48,7 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.mogologlib
|
||||
implementation rootProject.ext.dependencies.mogochainbase
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.zhjt.mogo_core_function_devatools">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
</manifest>
|
||||
@@ -1,29 +1,105 @@
|
||||
package com.zhjt.mogo_core_function_devatools
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_ADAS_INIT
|
||||
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_ADAS_MSG
|
||||
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_CONNECT_STATUS
|
||||
import com.mogo.eagle.core.data.chain.ChainConstant.Companion.CHAIN_LINK_LOG_WEB_SOCKET_DATA
|
||||
import com.mogo.eagle.core.data.chain.ChainLogParam
|
||||
import com.mogo.eagle.core.data.constants.MoGoConfig
|
||||
import com.mogo.eagle.core.data.constants.MogoServicePaths
|
||||
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.util.DeviceUtils
|
||||
import com.mogo.eagle.core.utilcode.util.Utils
|
||||
import com.zhidao.loglib.fw.FileWriteManager
|
||||
import com.zhidao.loglib.fw.FwBuild
|
||||
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchManager
|
||||
import com.zhjt.service.chain.core.ChainTraceStarter
|
||||
|
||||
@Route(path = MogoServicePaths.PATH_DEVA_TOOLS)
|
||||
class DevaToolsProvider : IDevaToolsProvider {
|
||||
|
||||
private val traceInfoCache = hashMapOf<Int, ChainLogParam>()
|
||||
private val fwBuildMap: MutableMap<Int, FwBuild> = HashMap()
|
||||
|
||||
override val functionName: String
|
||||
get() = "DevaToolsProvider"
|
||||
|
||||
override fun init(context: Context) {
|
||||
MogoLogCatchManager.init(context)
|
||||
logCheck(context)
|
||||
initTrace(context)
|
||||
}
|
||||
|
||||
private fun logCheck(context: Context) {
|
||||
val logger = SharedPrefsMgr.getInstance(context).getBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
val loggerTime = SharedPrefsMgr.getInstance(context).getLong(MoGoConfig.CATCH_LOG_TIME, 0)
|
||||
val logCatchDuration = (System.currentTimeMillis() - loggerTime) / 1000 / 60
|
||||
if (logger && loggerTime > 0) {
|
||||
val logTime: Int = if (10 - logCatchDuration < 1) {
|
||||
1
|
||||
} else {
|
||||
10 - logCatchDuration.toInt()
|
||||
}
|
||||
MogoLogCatchManager.startCatchLog(logTime)
|
||||
} else {
|
||||
Logger.d(
|
||||
functionName,
|
||||
"logCheck logger : $logger , logCatchDuration : $logCatchDuration"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun startLogCatch() {
|
||||
MogoLogCatchManager.startCatchLog()
|
||||
}
|
||||
|
||||
override fun startLogCatch(duration: Int) {
|
||||
MogoLogCatchManager.startCatchLog(duration)
|
||||
}
|
||||
|
||||
override fun stopLogCatch() {
|
||||
MogoLogCatchManager.stopCatchLog()
|
||||
}
|
||||
|
||||
private fun initTrace(context: Context) {
|
||||
// 初始化Trace抓取服务
|
||||
val pkgName = Utils.getApp().packageName
|
||||
ChainTraceStarter.start(pkgName, DeviceUtils.getMacAddress(), BuildConfig.DEBUG)
|
||||
|
||||
// Trace过程中进行日志抓取,对日志进行配置
|
||||
fwBuildMap[CHAIN_LINK_LOG_CONNECT_STATUS] =
|
||||
FwBuild(true, pkgName + CHAIN_LINK_LOG_ADAS_INIT, 5_000)
|
||||
fwBuildMap[CHAIN_LINK_LOG_WEB_SOCKET_DATA] =
|
||||
FwBuild(false, pkgName + CHAIN_LINK_LOG_ADAS_MSG, 500)
|
||||
|
||||
traceInfoCache[CHAIN_LINK_LOG_CONNECT_STATUS] = ChainLogParam(true, "ADAS连接状态")
|
||||
traceInfoCache[CHAIN_LINK_LOG_WEB_SOCKET_DATA] = ChainLogParam(false, "ADAS长链数据")
|
||||
FileWriteManager.getInstance()
|
||||
.init(context, MoGoAiCloudClientConfig.getInstance().sn, pkgName, fwBuildMap)
|
||||
}
|
||||
|
||||
override fun getTraceInfo(): HashMap<Int, ChainLogParam> {
|
||||
return traceInfoCache
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
override fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>) {
|
||||
map.forEach { (type, param) ->
|
||||
val fwBuild = this.fwBuildMap[type]
|
||||
fwBuild?.let {
|
||||
Logger.d(functionName, "param : ${param.des} , record : ${param.record}")
|
||||
it.isRecord = param.record
|
||||
}
|
||||
}
|
||||
FileWriteManager.getInstance().operateChainMap(fwBuildMap)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
MogoLogCatchManager.onDestroy()
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@ import android.os.Message
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
import com.mogo.eagle.core.data.constants.MoGoConfig
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsListenerManager
|
||||
import com.mogo.eagle.core.network.NetConfig
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.LogLevel
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.eagle.core.utilcode.util.TimeUtils
|
||||
import com.mogo.module.common.MogoApisHandler
|
||||
import com.mogo.service.cloud.socket.IMogoOnMessageListener
|
||||
import com.zhidao.loglib.bean.RemoteLogPushContent
|
||||
@@ -25,7 +26,6 @@ import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchConst.Companio
|
||||
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchConst.Companion.LOG_PUSH_TYPE
|
||||
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchConst.Companion.START_CATCH_LOG
|
||||
import com.zhjt.mogo_core_function_devatools.logcatch.MogoLogCatchConst.Companion.STOP_CATCH_LOG
|
||||
import java.io.File
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handler.Callback,
|
||||
@@ -47,7 +47,6 @@ object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handl
|
||||
MogoApisHandler.getInstance().apis
|
||||
.getSocketManagerApi(AbsMogoApplication.getApp().applicationContext)
|
||||
.registerOnMessageListener(LOG_PUSH_TYPE, this)
|
||||
manualContent.duration = 10
|
||||
manualContent.pkgName = context.packageName
|
||||
}
|
||||
|
||||
@@ -80,12 +79,13 @@ object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handl
|
||||
return false
|
||||
}
|
||||
|
||||
fun startCatchLog() {
|
||||
fun startCatchLog(duration:Int = 10) {
|
||||
if (catchingList.contains(MANUAL_CATCH_PKG_NAME)) {
|
||||
TipToast.shortTip("已经在抓取日志了,请稍后再试")
|
||||
} else {
|
||||
Logger.d(TAG, "开始抓取日志====")
|
||||
Logger.d(TAG, "开始抓取日志==== duration : $duration")
|
||||
manualContent.type = START_CATCH_LOG
|
||||
manualContent.duration = duration
|
||||
startCatchLog(manualContent)
|
||||
}
|
||||
}
|
||||
@@ -101,20 +101,28 @@ object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handl
|
||||
var delay = (content.duration).toLong()
|
||||
handler.removeMessages(MSG_TRY_CLOSE_LOG)
|
||||
if (delay <= 0) {
|
||||
// 如果push 下来的delay小于等于0,那就给个默认最大值一小时
|
||||
// 如果push 下来的delay小于等于0,那就给个默认值
|
||||
delay = 10
|
||||
}
|
||||
handler.sendEmptyMessageDelayed(MSG_TRY_CLOSE_LOG, delay * 1000L * 60)
|
||||
|
||||
openLoggerLevel()
|
||||
|
||||
logInfoManager = LogInfoManagerFactory.createPushLogInfoManager(
|
||||
mContext,
|
||||
MoGoAiCloudClientConfig.getInstance().sn + File.separator + TimeUtils.formatYMD(System.currentTimeMillis()),
|
||||
content, this
|
||||
MoGoAiCloudClientConfig.getInstance().sn,
|
||||
content,
|
||||
this
|
||||
)
|
||||
|
||||
logInfoManager?.start()
|
||||
logInfoManager?.registerLogOutListener { lineLog ->
|
||||
CallerDevaToolsListenerManager.invokeDevaToolsLogCatchLines(lineLog)
|
||||
}
|
||||
|
||||
SharedPrefsMgr.getInstance(mContext!!).putBoolean(MoGoConfig.CATCH_LOG, true)
|
||||
SharedPrefsMgr.getInstance(mContext!!)
|
||||
.putLong(MoGoConfig.CATCH_LOG_TIME, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
private fun stopCatchLog(content: RemoteLogPushContent) {
|
||||
@@ -125,6 +133,9 @@ object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handl
|
||||
logInfoManager?.stop()
|
||||
logInfoManager = null
|
||||
closeLoggerLevel()
|
||||
|
||||
SharedPrefsMgr.getInstance(mContext!!).putBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
SharedPrefsMgr.getInstance(mContext!!).putLong(MoGoConfig.CATCH_LOG_TIME, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +163,10 @@ object MogoLogCatchManager : IMogoOnMessageListener<RemoteLogPushContent>, Handl
|
||||
|
||||
override fun onClose(pkgName: String?) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
|
||||
SharedPrefsMgr.getInstance(mContext!!).putBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
SharedPrefsMgr.getInstance(mContext!!).putLong(MoGoConfig.CATCH_LOG_TIME, 0)
|
||||
|
||||
CallerDevaToolsListenerManager.invokeDevaToolsLogCatchClose()
|
||||
TipToast.shortTip("日志抓取默认计时结束")
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ dependencies {
|
||||
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
compileOnly rootProject.ext.dependencies.mogoserviceapi
|
||||
implementation project(':libraries:map-usbcamera')
|
||||
|
||||
implementation rootProject.ext.dependencies.mogo_core_res
|
||||
@@ -76,7 +76,7 @@ dependencies {
|
||||
implementation project(':core:mogo-core-res')
|
||||
implementation project(':core:mogo-core-data')
|
||||
implementation project(':core:mogo-core-utils')
|
||||
implementation project(':core:mogo-core-res')
|
||||
implementation project(':core:mogo-core-network')
|
||||
implementation project(':core:mogo-core-function-api')
|
||||
implementation project(':core:mogo-core-function-call')
|
||||
}
|
||||
|
||||
@@ -5,12 +5,16 @@ import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.transition.*
|
||||
import androidx.transition.AutoTransition
|
||||
import androidx.transition.TransitionManager
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.commons.mvp.MvpFragment
|
||||
@@ -37,7 +41,6 @@ import com.mogo.eagle.core.function.hmi.notification.WarningFloat
|
||||
import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator
|
||||
import com.mogo.eagle.core.function.hmi.notification.enums.SidePattern
|
||||
import com.mogo.eagle.core.function.hmi.ui.camera.CameraListView
|
||||
import com.mogo.eagle.core.function.hmi.ui.carcorder.CarcorderPreviewView
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeBannerView
|
||||
import com.mogo.eagle.core.function.hmi.ui.notice.NoticeNormalBannerView
|
||||
import com.mogo.eagle.core.function.hmi.ui.setting.DebugSettingView
|
||||
@@ -99,6 +102,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
private var onBadCaseShow: (() -> View)? = null
|
||||
private var onBadCaseHide: (() -> Unit)? = null
|
||||
|
||||
private var upgradeTipsView: (() -> View)? = null
|
||||
|
||||
companion object {
|
||||
private const val MSG_WHAT_DISMISS_BAD_CASE_ENTRY = 0x1010
|
||||
private val CASE_EXPIRE_DURATION = TimeUnit.HOURS.toMillis(4)
|
||||
@@ -117,7 +122,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
Log.d("QQQ", "-- step -- 1 --")
|
||||
var oldT = try {
|
||||
old?.timestamp?.takeIf { it.isNotBlank() }?.let {
|
||||
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time ?: 0L
|
||||
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
|
||||
?: 0L
|
||||
} ?: 0L
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
@@ -127,30 +133,31 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
var newT = try {
|
||||
it.receive()?.also { record = it }?.timestamp?.takeIf { it.isNotBlank() }?.let {
|
||||
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
|
||||
?: 0L
|
||||
?: 0L
|
||||
} ?: 0L
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
0L
|
||||
}
|
||||
|
||||
if (oldT == 0L || (newT > 0L && (newT - oldT > 0L) && (newT - oldT) < CASE_EXPIRE_DURATION)) {
|
||||
if (oldT == 0L || (newT > 0L && (newT - oldT > 0L) && (newT - oldT) < CASE_EXPIRE_DURATION)) {
|
||||
Log.d("QQQ", "-- step -- 2 --")
|
||||
record?.takeIf { it.key != old?.key && it.timestamp != old?.timestamp }?.also {
|
||||
Log.d("QQQ", "record: [$record] is displaying and consuming ~~~" )
|
||||
Log.d("QQQ", "record: [$record] is displaying and consuming ~~~")
|
||||
showBadCaseEntrance(it)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
while (oldT != 0L && newT != 0L && (newT - oldT) >= CASE_EXPIRE_DURATION) {
|
||||
Log.d("QQQ", "record: [$record] has been discarded, because it has been timeout." )
|
||||
Log.d("QQQ", "record: [$record] has been discarded, because it has been timeout.")
|
||||
oldT = newT
|
||||
newT = try {
|
||||
it.receive()?.also {
|
||||
record = it
|
||||
}?.timestamp?.takeIf { it.isNotBlank() }?.let {
|
||||
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time ?: 0L
|
||||
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).parse(it)?.time
|
||||
?: 0L
|
||||
} ?: 0L
|
||||
} catch (t: Throwable) {
|
||||
t.printStackTrace()
|
||||
@@ -158,7 +165,7 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
}
|
||||
}
|
||||
record?.takeIf { it.key != old?.key && it.timestamp != old?.timestamp }?.also {
|
||||
Log.d("QQQ", "record: [$record] is displaying for rest ..." )
|
||||
Log.d("QQQ", "record: [$record] is displaying for rest ...")
|
||||
showBadCaseEntrance(it)
|
||||
}
|
||||
} else {
|
||||
@@ -170,7 +177,7 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
it.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
Log.d("QQQ", "record: [$old] hasn't been consumed~~~~" )
|
||||
Log.d("QQQ", "record: [$old] hasn't been consumed~~~~")
|
||||
}
|
||||
} finally {
|
||||
delay(1000)
|
||||
@@ -232,10 +239,10 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
}
|
||||
}
|
||||
|
||||
ivCameraIcon?.setOnLongClickListener {
|
||||
/*ivCameraIcon?.setOnLongClickListener {
|
||||
activity?.let { it1 -> CarcorderPreviewView.show(it1) }
|
||||
true
|
||||
}
|
||||
}*/
|
||||
|
||||
ivToolsIcon?.setOnClickListener {
|
||||
if (toolsViewFloat == null) {
|
||||
@@ -265,6 +272,11 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*// TODO 这里后面需要改成独立进程通讯后台获取YUV
|
||||
view.postDelayed({
|
||||
activity?.let { CarcorderPreviewView.show(it) }
|
||||
}, 1000)*/
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@@ -352,21 +364,29 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
onBadCaseHide = onHide
|
||||
}
|
||||
|
||||
/**
|
||||
*注册工控机升级提示圆点View的回调
|
||||
* @param 提示圆点View
|
||||
*/
|
||||
override fun registerUpgradeTipsCallback(tipsView: () -> View) {
|
||||
upgradeTipsView = tipsView
|
||||
}
|
||||
|
||||
/**
|
||||
* 工控机重启返回结果
|
||||
* @param code
|
||||
* @param msg
|
||||
*/
|
||||
override fun showDockerRebootResult(code: Int, msg: String) {
|
||||
ThreadUtils.runOnUiThread{
|
||||
if(code>=-1){
|
||||
ThreadUtils.runOnUiThread {
|
||||
if (code >= -1) {
|
||||
//重启成功
|
||||
ToastUtils.showShort("重启成功")
|
||||
}else{
|
||||
} else {
|
||||
//重启失败
|
||||
msg?.let {
|
||||
ToastUtils.showShort(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,7 +398,7 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
if (autoPilotBadCaseView == null) {
|
||||
autoPilotBadCaseView = AutoPilotBadCaseView(it).also { itx ->
|
||||
val record =
|
||||
autoPilotBadCaseEntrance?.getTag(R.id.autopilot_badcase_record) as? AutoPilotRecordResult
|
||||
autoPilotBadCaseEntrance?.getTag(R.id.autopilot_badcase_record) as? AutoPilotRecordResult
|
||||
itx.tag = record
|
||||
itx.onDismiss {
|
||||
dismissBadCaseFloatView()
|
||||
@@ -389,12 +409,13 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
val params = mutableMapOf<String, String>()
|
||||
autoPilotBadCaseEntrance?.apply {
|
||||
params["carLicense"] =
|
||||
MoGoAiCloudClientConfig.getInstance().sn
|
||||
MoGoAiCloudClientConfig.getInstance().sn
|
||||
params["filename"] = record?.fileName ?: ""
|
||||
params["filesize"] = record?.total.toString()
|
||||
params["key"] = record?.key ?: ""
|
||||
params["reason"] = it.reason ?: ""
|
||||
params["duration"] = record?.duration?.toInt()?.toString() ?: ""
|
||||
params["duration"] = record?.duration?.toInt()?.toString()
|
||||
?: ""
|
||||
params["timestamp"] = record?.timestamp ?: ""
|
||||
}
|
||||
val response = post(params)
|
||||
@@ -409,9 +430,9 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
dismissBadCaseFloatView()
|
||||
dismiss?.invoke()
|
||||
CallerAutoPilotManager.recordCause(
|
||||
record?.key,
|
||||
record?.fileName,
|
||||
it.id, it.reason)
|
||||
record?.key,
|
||||
record?.fileName,
|
||||
it.id, it.reason)
|
||||
ToastUtils.showShort("接管反馈成功~")
|
||||
record?.also {
|
||||
it.consumed = true
|
||||
@@ -437,39 +458,39 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
}
|
||||
}
|
||||
autoPilotToolsFloat = WarningFloat.with(it)
|
||||
.setTag("BadCaseCollectFloat")
|
||||
.setLayout(autoPilotBadCaseView!!)
|
||||
.setSidePattern(SidePattern.LEFT)
|
||||
.setGravity(Gravity.LEFT, offsetY = 72)
|
||||
.setImmersionStatusBar(true)
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.enterAnim(view, params, windowManager, sidePattern)
|
||||
?.apply {
|
||||
interpolator = OvershootInterpolator()
|
||||
}
|
||||
.setTag("BadCaseCollectFloat")
|
||||
.setLayout(autoPilotBadCaseView!!)
|
||||
.setSidePattern(SidePattern.LEFT)
|
||||
.setGravity(Gravity.LEFT, offsetY = 72)
|
||||
.setImmersionStatusBar(true)
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.enterAnim(view, params, windowManager, sidePattern)
|
||||
?.apply {
|
||||
interpolator = OvershootInterpolator()
|
||||
}
|
||||
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.exitAnim(view, params, windowManager, sidePattern)
|
||||
?.setDuration(200)
|
||||
})
|
||||
.addWarningStatusListener(object : IMoGoWarningStatusListener {
|
||||
override fun onDismiss() {
|
||||
autoPilotToolsFloat = null
|
||||
autoPilotBadCaseView = null
|
||||
}
|
||||
})
|
||||
.show()
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.exitAnim(view, params, windowManager, sidePattern)
|
||||
?.setDuration(200)
|
||||
})
|
||||
.addWarningStatusListener(object : IMoGoWarningStatusListener {
|
||||
override fun onDismiss() {
|
||||
autoPilotToolsFloat = null
|
||||
autoPilotBadCaseView = null
|
||||
}
|
||||
})
|
||||
.show()
|
||||
} else {
|
||||
autoPilotToolsFloat?.show()
|
||||
}
|
||||
@@ -669,7 +690,8 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
if (floatWindow == null || TextUtils.isEmpty(showTag) || !floatWindow.isShow() || floatWindow.config.floatTag != tag) {
|
||||
val notificationView = V2XNotificationView(it)
|
||||
notificationView.setWarningIcon(EventTypeEnum.getWarningIcon(v2xType.toString()))
|
||||
val warningContent = alertContent ?: EventTypeEnum.getWarningContent(v2xType.toString())
|
||||
val warningContent = alertContent
|
||||
?: EventTypeEnum.getWarningContent(v2xType.toString())
|
||||
if (warningContent.isEmpty()) {
|
||||
Logger.e(TAG, "Show warningContent is null or empty!")
|
||||
return@launchWhenResumed
|
||||
@@ -680,48 +702,48 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
WarningFloat.dismiss(floatWindow.config.floatTag, true)
|
||||
}
|
||||
mWarningFloat = WarningFloat.with(it)
|
||||
.setTag(tag)
|
||||
.setLayout(notificationView)
|
||||
.setSidePattern(SidePattern.RESULT_TOP)
|
||||
.setCountDownTime(expireTime)
|
||||
.setGravity(Gravity.CENTER_HORIZONTAL, offsetY = 110)
|
||||
.setImmersionStatusBar(true)
|
||||
.isEnqueue(true)
|
||||
.addWarningStatusListener(listenerIMoGo)
|
||||
.addWarningStatusListener(object : IMoGoWarningStatusListener {
|
||||
override fun onShow() {
|
||||
// 创建弹窗成功才进行TTS播报
|
||||
Logger.d(
|
||||
"MoGoWarningFragment",
|
||||
"mWarningFloat = $mWarningFloat---ttsContent = $ttsContent"
|
||||
)
|
||||
if (mWarningFloat != null && !TextUtils.isEmpty(ttsContent) && playTts) {
|
||||
Logger.d("MoGoWarningFragment", "---> ttsContent = $ttsContent")
|
||||
AIAssist.getInstance(activity)
|
||||
.speakTTSVoice(ttsContent)
|
||||
}
|
||||
}
|
||||
})
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.enterAnim(view, params, windowManager, sidePattern)?.apply {
|
||||
interpolator = OvershootInterpolator()
|
||||
.setTag(tag)
|
||||
.setLayout(notificationView)
|
||||
.setSidePattern(SidePattern.RESULT_TOP)
|
||||
.setCountDownTime(expireTime)
|
||||
.setGravity(Gravity.CENTER_HORIZONTAL, offsetY = 110)
|
||||
.setImmersionStatusBar(true)
|
||||
.isEnqueue(true)
|
||||
.addWarningStatusListener(listenerIMoGo)
|
||||
.addWarningStatusListener(object : IMoGoWarningStatusListener {
|
||||
override fun onShow() {
|
||||
// 创建弹窗成功才进行TTS播报
|
||||
Logger.d(
|
||||
"MoGoWarningFragment",
|
||||
"mWarningFloat = $mWarningFloat---ttsContent = $ttsContent"
|
||||
)
|
||||
if (mWarningFloat != null && !TextUtils.isEmpty(ttsContent) && playTts) {
|
||||
Logger.d("MoGoWarningFragment", "---> ttsContent = $ttsContent")
|
||||
AIAssist.getInstance(activity)
|
||||
.speakTTSVoice(ttsContent)
|
||||
}
|
||||
}
|
||||
})
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.enterAnim(view, params, windowManager, sidePattern)?.apply {
|
||||
interpolator = OvershootInterpolator()
|
||||
}
|
||||
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.exitAnim(view, params, windowManager, sidePattern)?.setDuration(200)
|
||||
})
|
||||
.show()
|
||||
override fun exitAnim(
|
||||
view: View,
|
||||
params: WindowManager.LayoutParams,
|
||||
windowManager: WindowManager,
|
||||
sidePattern: SidePattern
|
||||
): Animator? =
|
||||
super.exitAnim(view, params, windowManager, sidePattern)?.setDuration(200)
|
||||
})
|
||||
.show()
|
||||
} else {
|
||||
val notification = floatWindow.config.layoutView as? V2XNotificationView
|
||||
if (alertContent?.isNotEmpty() == true) {
|
||||
@@ -1073,22 +1095,32 @@ class MoGoHmiFragment : MvpFragment<MoGoWarningContract.View?, WaringPresenter?>
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
override fun showAdUpgradeStatus(
|
||||
upgradeMode: Int,
|
||||
downloadStatus: Int,
|
||||
currentProgress: Int,
|
||||
totalProgress: Int,
|
||||
downloadVersion: String,
|
||||
upgradeStatus: Int
|
||||
upgradeMode: Int,
|
||||
downloadStatus: Int,
|
||||
currentProgress: Int,
|
||||
totalProgress: Int,
|
||||
downloadVersion: String,
|
||||
upgradeStatus: Int
|
||||
) {
|
||||
ThreadUtils.runOnUiThread{
|
||||
ThreadUtils.runOnUiThread {
|
||||
val tipsView = upgradeTipsView?.invoke()
|
||||
//如果工控机处于“下载中”、“可升级(下载完成)”、“升级中”、“升级失败”状态时,工具箱入口显示红色角标
|
||||
if(AdUpgradeStateHelper.showUpgradeTips(downloadStatus, upgradeStatus)){
|
||||
viewUpgradeTips.visibility = View.VISIBLE
|
||||
}else{
|
||||
viewUpgradeTips.visibility = View.GONE
|
||||
if (AdUpgradeStateHelper.showUpgradeTips(downloadStatus, upgradeStatus)) {
|
||||
if (HmiBuildConfig.isShowUpgradeTipsView){
|
||||
viewUpgradeTips?.visibility = View.VISIBLE
|
||||
}else{
|
||||
tipsView?.let {
|
||||
it.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewUpgradeTips?.visibility = View.GONE
|
||||
tipsView?.let {
|
||||
it.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
//将状态同步到工具箱
|
||||
toolsView?.showAdUpgradeStatus(upgradeMode,downloadStatus, currentProgress, totalProgress, downloadVersion, upgradeStatus)
|
||||
toolsView?.showAdUpgradeStatus(upgradeMode, downloadStatus, currentProgress, totalProgress, downloadVersion, upgradeStatus)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import android.widget.Toast
|
||||
import com.mogo.cloud.live.manager.ILiveStreamManager
|
||||
import com.mogo.cloud.live.manager.LiveStreamManagerImpl
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.function.hmi.notification.WarningFloat
|
||||
import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator
|
||||
@@ -39,6 +41,8 @@ class CarcorderPreviewView private constructor(
|
||||
private var isRequest = false
|
||||
private var isPreview = false
|
||||
|
||||
private var liveStreamManager: ILiveStreamManager? = null
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_carcorder_preview, this, true)
|
||||
}
|
||||
@@ -70,7 +74,7 @@ class CarcorderPreviewView private constructor(
|
||||
.setTag("CarcorderPreviewView")
|
||||
.setLayout(carcorderPreviewVie)
|
||||
.setSidePattern(SidePattern.RIGHT)
|
||||
.setGravity(Gravity.RIGHT, offsetY = 200)
|
||||
.setGravity(Gravity.RIGHT, offsetY = 250)
|
||||
.setImmersionStatusBar(true)
|
||||
.setAnimator(object : DefaultAnimator() {
|
||||
override fun enterAnim(
|
||||
@@ -160,6 +164,10 @@ class CarcorderPreviewView private constructor(
|
||||
Log.d(TAG, "onDisConnectDev")
|
||||
showShortMsg("相机断开连接")
|
||||
}
|
||||
|
||||
override fun onCancelDev(device: UsbDevice?) {
|
||||
Log.d(TAG, "onCancelDev:" + device?.deviceName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +182,14 @@ class CarcorderPreviewView private constructor(
|
||||
mCameraHelper?.setDefaultFrameFormat(UVCCameraHelper.FRAME_FORMAT_MJPEG)
|
||||
mCameraHelper?.initUSBMonitor(context as Activity, carcorderPreview, listener)
|
||||
|
||||
mCameraHelper?.setOnPreviewFrameListener { nv21Yuv -> Log.d(TAG, "onPreviewResult: " + nv21Yuv.size) }
|
||||
mCameraHelper?.setOnPreviewFrameListener { nv21Yuv ->
|
||||
Log.d(TAG, "onPreviewResult: " + nv21Yuv.size)
|
||||
//Log.i(TAG, "onVideoFrame byte length: " + bytesLength);
|
||||
if (liveStreamManager != null) {
|
||||
// 将摄像头采集的YUV数据推送到ZEGO
|
||||
liveStreamManager!!.notifyYUVData(nv21Yuv, 640, 480, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,6 +200,19 @@ class CarcorderPreviewView private constructor(
|
||||
if (mCameraHelper != null) {
|
||||
mCameraHelper!!.registerUSB()
|
||||
}
|
||||
// 初始化直播流管理
|
||||
// 初始化直播流管理
|
||||
liveStreamManager = LiveStreamManagerImpl.getInstance((context as Activity).application,
|
||||
MoGoAiCloudClientConfig.getInstance().sn, true)
|
||||
|
||||
// 设置状态回调
|
||||
liveStreamManager!!.setLiveStatusChangeCallback { status ->
|
||||
if (status == 0) {
|
||||
Logger.d(TAG, "直播中……")
|
||||
} else {
|
||||
Logger.d(TAG, "直播结束……")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
@@ -193,6 +221,13 @@ class CarcorderPreviewView private constructor(
|
||||
if (mCameraHelper != null) {
|
||||
mCameraHelper!!.unregisterUSB()
|
||||
}
|
||||
|
||||
if (liveStreamManager != null) {
|
||||
// 停止
|
||||
liveStreamManager!!.stopLiveStream()
|
||||
// 释放资源
|
||||
liveStreamManager!!.release()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSurfaceCreated(view: CameraViewInterface?, surface: Surface?) {
|
||||
|
||||
@@ -68,7 +68,6 @@ abstract class AbsLogView : ILogView, TouchProxy.OnTouchEventListener {
|
||||
|
||||
fun show(context: Context) {
|
||||
if (isShow) {
|
||||
Log.d("EmArrow", "isShow : $isShow")
|
||||
return
|
||||
}
|
||||
performCreate(context)
|
||||
|
||||
@@ -244,7 +244,6 @@ class LogInfoView : AbsLogView() {
|
||||
mLogHint!!.visibility = View.VISIBLE
|
||||
mLogRvWrap!!.visibility = View.GONE
|
||||
val layoutParams = systemLayoutParams ?: return
|
||||
Log.d("EmArrow", "minimize , layoutParams is not null")
|
||||
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
import com.mogo.eagle.core.data.app.AppConfigInfo
|
||||
import com.mogo.eagle.core.data.autopilot.*
|
||||
import com.mogo.eagle.core.data.chain.ChainConstant
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.data.constants.MoGoConfig
|
||||
import com.mogo.eagle.core.data.map.MogoLocation
|
||||
@@ -35,11 +36,20 @@ import com.mogo.eagle.core.function.call.obu.CallerObuListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.function.hmi.ui.logcatch.ILogViewListener
|
||||
import com.mogo.eagle.core.function.hmi.ui.logcatch.LogInfoView
|
||||
import com.mogo.eagle.core.utilcode.kotlin.onClick
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.LogLevel
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.util.*
|
||||
import com.mogo.map.MogoMap
|
||||
import com.mogo.map.uicontroller.VisualAngleMode
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_300
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MODE_CLOSE_SIGHT
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MODE_LONG_SIGHT
|
||||
import com.mogo.map.uicontroller.VisualAngleMode.MODE_MEDIUM_SIGHT
|
||||
import com.mogo.module.common.MogoApisHandler
|
||||
import kotlinx.android.synthetic.main.view_debug_setting.view.*
|
||||
import java.util.*
|
||||
|
||||
@@ -50,13 +60,13 @@ import java.util.*
|
||||
* 展示 本机、网络、工控机、OBU等状态信息,支持设置IP,等参数进行调试
|
||||
*/
|
||||
class DebugSettingView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), IMoGoObuStatusListener,
|
||||
IMoGoAutopilotStatusListener, IMoGoAutopilotCarStateListener,
|
||||
IMoGoMapLocationListener, IMoGoAutopilotIdentifyListener,
|
||||
IMoGoAutopilotPlanningListener {
|
||||
IMoGoAutopilotStatusListener, IMoGoAutopilotCarStateListener,
|
||||
IMoGoMapLocationListener, IMoGoAutopilotIdentifyListener,
|
||||
IMoGoAutopilotPlanningListener {
|
||||
|
||||
private val TAG = "DebugSettingView"
|
||||
|
||||
@@ -75,6 +85,12 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
// 全局路径规划点个数
|
||||
private var mRouteInfoSize = 0
|
||||
|
||||
private val mapUiController by lazy {
|
||||
MogoApisHandler.getInstance().apis?.mapServiceApi?.mapUIController
|
||||
}
|
||||
|
||||
private var lastVisualAngleMode: VisualAngleMode? = null
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.view_debug_setting, this, true)
|
||||
initView()
|
||||
@@ -204,21 +220,40 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
changesight_top_btn.setOnClickListener {
|
||||
CallerHDMapManager.setMapDAngle(0);
|
||||
lastVisualAngleMode = mapUiController?.currentMapVisualAngle
|
||||
|
||||
changesight_top_btn.onClick {
|
||||
mapUiController?.changeMapVisualAngle(MAP_STYLE_VR_ANGLE_TOP, null)
|
||||
}
|
||||
|
||||
changesight_back_btn?.onClick {
|
||||
mapUiController?.changeMapVisualAngle(MAP_STYLE_VR_ANGLE_300, null)
|
||||
}
|
||||
|
||||
changesight_cross_btn?.onClick {
|
||||
mapUiController?.changeMapVisualAngle(MAP_STYLE_VR_ANGLE_CROSS, null)
|
||||
}
|
||||
|
||||
changesight_far_btn?.onClick {
|
||||
mapUiController?.changeMapVisualAngle(MODE_LONG_SIGHT, null)
|
||||
}
|
||||
|
||||
reset_changesight?.onClick {
|
||||
lastVisualAngleMode?.let {
|
||||
mapUiController?.changeMapVisualAngle(it, null)
|
||||
}
|
||||
}
|
||||
|
||||
tvObuInfo.text = CallerObuListenerManager.getObuStatusInfoJsonString()
|
||||
tvAutopilotInfo.text =
|
||||
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfoJsonString()
|
||||
CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfoJsonString()
|
||||
|
||||
// 绘制应用基本信息
|
||||
drawAppInfo()
|
||||
|
||||
// 初始化OBU IP信息
|
||||
val ipAddress =
|
||||
SharedPrefsMgr.getInstance(context).getString(MoGoConfig.OBU_IP, "192.168.1.199")
|
||||
SharedPrefsMgr.getInstance(context).getString(MoGoConfig.OBU_IP, "192.168.1.199")
|
||||
|
||||
etObuIP.setText(ipAddress)
|
||||
etObuIP.text?.let { etObuIP.setSelection(it.length) }
|
||||
@@ -255,18 +290,18 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
|
||||
// 初始化 GSP数据源 数据
|
||||
rgGpsProvider.check(
|
||||
when (FunctionBuildConfig.gpsProvider) {
|
||||
0 -> {
|
||||
R.id.rbGpsProviderAndroid
|
||||
}
|
||||
1 -> {
|
||||
R.id.rbGpsProviderRTK
|
||||
}
|
||||
2 -> {
|
||||
R.id.rbGpsProviderOBU
|
||||
}
|
||||
else -> R.id.rbGpsProviderAndroid
|
||||
when (FunctionBuildConfig.gpsProvider) {
|
||||
0 -> {
|
||||
R.id.rbGpsProviderAndroid
|
||||
}
|
||||
1 -> {
|
||||
R.id.rbGpsProviderRTK
|
||||
}
|
||||
2 -> {
|
||||
R.id.rbGpsProviderOBU
|
||||
}
|
||||
else -> R.id.rbGpsProviderAndroid
|
||||
}
|
||||
)
|
||||
rgGpsProvider.setOnCheckedChangeListener { group, checkedId ->
|
||||
when (checkedId) {
|
||||
@@ -350,31 +385,29 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
tbLogCatch.isChecked =
|
||||
SharedPrefsMgr.getInstance(context).getBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
SharedPrefsMgr.getInstance(context).getBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
tbLogCatch.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
CallerDevaToolsManager.startCatchLog()
|
||||
SharedPrefsMgr.getInstance(context).putBoolean(MoGoConfig.CATCH_LOG, true)
|
||||
} else {
|
||||
CallerDevaToolsManager.stopCatchLog()
|
||||
SharedPrefsMgr.getInstance(context).putBoolean(MoGoConfig.CATCH_LOG, false)
|
||||
}
|
||||
}
|
||||
CallerDevaToolsListenerManager.registerDevaToolsLogCatchListener(TAG,
|
||||
object : IMoGoDevaToolsListener {
|
||||
override fun onLogCatchClose() {
|
||||
super.onLogCatchClose()
|
||||
tbLogCatch.isChecked = false
|
||||
}
|
||||
object : IMoGoDevaToolsListener {
|
||||
override fun onLogCatchClose() {
|
||||
super.onLogCatchClose()
|
||||
tbLogCatch.isChecked = false
|
||||
}
|
||||
|
||||
override fun onLogCatch(lineLog: String) {
|
||||
logInfoView?.let {
|
||||
if (logViewAttach) {
|
||||
it.onLogCatch(lineLog)
|
||||
}
|
||||
override fun onLogCatch(lineLog: String) {
|
||||
logInfoView?.let {
|
||||
if (logViewAttach) {
|
||||
it.onLogCatch(lineLog)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
tbLogDebugView.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
logInfoView = LogInfoView()
|
||||
@@ -394,6 +427,15 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
logViewDestroy()
|
||||
}
|
||||
}
|
||||
tbLogTraceView.setOnCheckedChangeListener { _, isChecked ->
|
||||
val traceInfoMap = CallerDevaToolsManager.getTraceInfo()
|
||||
val chainLogParam = traceInfoMap[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_DATA]
|
||||
chainLogParam?.let {
|
||||
it.record = isChecked
|
||||
traceInfoMap[ChainConstant.CHAIN_LINK_LOG_WEB_SOCKET_DATA] = chainLogParam
|
||||
CallerDevaToolsManager.refreshTraceInfo(traceInfoMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun logViewDestroy() {
|
||||
@@ -428,15 +470,15 @@ class DebugSettingView @JvmOverloads constructor(
|
||||
tvAutopilotInfo.text = GsonUtils.toJson(mAutoPilotStatusInfo)
|
||||
|
||||
tvCarInfo.text =
|
||||
"GPS时间:${mAutoPilotCarStateInfo?.values?.satelliteTime}\n" +
|
||||
"自车经纬度:\n${mAutoPilotCarStateInfo?.values?.lon}\n${mAutoPilotCarStateInfo?.values?.lat}\n"
|
||||
"GPS时间:${mAutoPilotCarStateInfo?.values?.satelliteTime}\n" +
|
||||
"自车经纬度:\n${mAutoPilotCarStateInfo?.values?.lon}\n${mAutoPilotCarStateInfo?.values?.lat}\n"
|
||||
|
||||
tvIdentifyInfo.text =
|
||||
"感知数据个数:${mIdentifyDataSize}"
|
||||
"感知数据个数:${mIdentifyDataSize}"
|
||||
tvTrajectoryInfoSize.text =
|
||||
"引导线点个数:${mTrajectoryInfoSize}"
|
||||
"引导线点个数:${mTrajectoryInfoSize}"
|
||||
tvRouteInfoSize.text =
|
||||
"全局路径规划点个数:${mRouteInfoSize}"
|
||||
"全局路径规划点个数:${mRouteInfoSize}"
|
||||
|
||||
// 用完之后重制为0,防止节点回掉突然没数据,导致页面显示还是之前的数据情况
|
||||
mIdentifyDataSize = 0
|
||||
|
||||
@@ -8,11 +8,13 @@ import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotGuardianStatusInfo
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.hmi.R
|
||||
import com.mogo.eagle.core.function.hmi.ui.utils.KeyBoardUtil
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import kotlinx.android.synthetic.main.view_auto_pilot_check.view.*
|
||||
import kotlinx.android.synthetic.main.view_check_system.view.*
|
||||
@@ -102,6 +104,7 @@ class AutoPilotAndCheckView @JvmOverloads constructor(
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
}
|
||||
updateSpeedSettingViews()
|
||||
// // 比如需要设置默认速度
|
||||
// val speed = "30"
|
||||
// etInputSpeed.setText(speed)
|
||||
@@ -112,6 +115,22 @@ class AutoPilotAndCheckView @JvmOverloads constructor(
|
||||
this.clickListener = clickListener
|
||||
}
|
||||
|
||||
/**
|
||||
* Bus不可设置自动驾驶速度,而Taxi可以
|
||||
*/
|
||||
private fun updateSpeedSettingViews() {
|
||||
when {
|
||||
AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode) -> {
|
||||
tvSpeedTitle.visibility = View.GONE
|
||||
llSpeedPosition.visibility = View.GONE
|
||||
}
|
||||
else -> {
|
||||
tvSpeedTitle.visibility = View.VISIBLE
|
||||
llSpeedPosition.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示工控机下载、升级状态信息
|
||||
* @param upgradeMode 升级模式(提示升级、静默升级)
|
||||
|
||||
@@ -71,6 +71,12 @@ class SystemVersionView @JvmOverloads constructor(
|
||||
if(AdUpgradeStateHelper.isDownloading(downloadStatus)){
|
||||
//点击Toast提示:下载剩余时间
|
||||
ToastUtils.showShort("预计"+AdUpgradeStateHelper.getRemainingTime(totalProgress,previousProgress,currentProgress)+"下载完成")
|
||||
}else if(AdUpgradeStateHelper.getUpgradeStatus()){
|
||||
//工控机状态为“升级中”
|
||||
ToastUtils.showShort("新版本升级中,预计5分钟升级完成")
|
||||
}else if(AdUpgradeStateHelper.isUpgradeFailed(upgradeStatus)){
|
||||
//如果升级失败,则Toast提示:升级失败,请联系运维人员
|
||||
ToastUtils.showShort("升级失败,请联系运维人员")
|
||||
}else if(AdUpgradeStateHelper.isHintUpgradeMode(upgradeMode) && AdUpgradeStateHelper.isDownloadFinish(downloadStatus,upgradeStatus)){
|
||||
//如果升级模式为“提示升级”,并且下载状态为已经下载完成,点击弹出升级确认弹窗
|
||||
if(adUpgradeDialog == null){
|
||||
@@ -86,6 +92,10 @@ class SystemVersionView @JvmOverloads constructor(
|
||||
//设置当前状态为“升级中”
|
||||
AdUpgradeStateHelper.setUpgradeStatus(true)
|
||||
CallerAutoPilotManager.setIPCUpgradeAffirm()
|
||||
//将角标设为升级中
|
||||
ivAdStatus?.setImageResource(R.drawable.icon_upgrading)
|
||||
adCircularProgressView?.visibility = View.GONE
|
||||
ivAdVersion?.setBackgroundResource(R.drawable.version_latest_background)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,12 +109,6 @@ class SystemVersionView @JvmOverloads constructor(
|
||||
})
|
||||
}
|
||||
adUpgradeDialog?.showUpgradeDialog()
|
||||
}else if(AdUpgradeStateHelper.getUpgradeStatus()){
|
||||
//工控机状态为“升级中”
|
||||
ToastUtils.showShort("新版本升级中,预计5分钟升级完成")
|
||||
}else if(AdUpgradeStateHelper.isUpgradeFailed(upgradeStatus)){
|
||||
//如果升级失败,则Toast提示:升级失败,请联系运维人员
|
||||
ToastUtils.showShort("升级失败,请联系运维人员")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
|
||||
<View
|
||||
android:id="@+id/viewUpgradeTips"
|
||||
android:layout_width="20px"
|
||||
android:layout_height="20px"
|
||||
android:layout_width="22px"
|
||||
android:layout_height="22px"
|
||||
app:layout_constraintCircle="@id/ivToolsIcon"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="60px"
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="@dimen/dp_768"
|
||||
android:layout_height="@dimen/dp_432"
|
||||
android:background="#FFFFFF">
|
||||
android:layout_height="@dimen/dp_432">
|
||||
|
||||
|
||||
<com.serenegiant.usb.widget.UVCCameraTextureView
|
||||
android:id="@+id/carcorderPreview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
||||
@@ -413,6 +413,16 @@
|
||||
android:textOn="关闭日志过滤面板"
|
||||
android:textSize="@dimen/dp_24" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/tbLogTraceView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:gravity="center"
|
||||
android:textOff="ADAS长链数据未写入"
|
||||
android:textOn="ADAS长链数据写入中..."
|
||||
android:textSize="@dimen/dp_24" />
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
</LinearLayout>
|
||||
<!--域控制器(工控机)配置信息-->
|
||||
|
||||
@@ -68,7 +68,6 @@ dependencies {
|
||||
api rootProject.ext.dependencies.mogocommons
|
||||
api rootProject.ext.dependencies.modulecommon
|
||||
api rootProject.ext.dependencies.mogoservice
|
||||
api rootProject.ext.dependencies.moduleshare
|
||||
api rootProject.ext.dependencies.moduleextensions
|
||||
api rootProject.ext.dependencies.callchat
|
||||
api rootProject.ext.dependencies.callchatprovider
|
||||
|
||||
@@ -61,7 +61,6 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
return;
|
||||
}
|
||||
start = System.currentTimeMillis();
|
||||
ChainTraceStarter.start("com.mogo.launcher.f", DeviceUtils.getMacAddress());
|
||||
// Crash 日志收集
|
||||
initCrashConfig();
|
||||
initLogConfig();
|
||||
@@ -153,7 +152,7 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
// 设置是否输出日志
|
||||
clientConfig.setShowDebugLog(true);
|
||||
// 设置是否是直播推流的主播
|
||||
clientConfig.setAnchor(false);
|
||||
clientConfig.setAnchor(true);
|
||||
// 设置从蘑菇AI开放平台获取的APPKey
|
||||
switch (DebugConfig.getCarMachineType()) {
|
||||
// 比亚迪
|
||||
@@ -178,8 +177,8 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
// 设置AI云平台分配给三方应用的签名密钥,需要从AI云平台申请
|
||||
// 设置车机设备的唯一标识(这些表识必须是通过后台录入的设备)
|
||||
clientConfig.setThirdPartyDeviceId(Utils.getDevicesId());
|
||||
// 设置循环检测间隔时间
|
||||
clientConfig.setLoopCheckDelay(60 * 60 * 24 * 1000);
|
||||
// 设置循环检测间隔时间(每隔2小时loop一次httpDnsConfig)
|
||||
clientConfig.setLoopCheckDelay(60 * 60 * 2 * 1000);
|
||||
//连接ami
|
||||
connectAmiIp();
|
||||
|
||||
@@ -249,7 +248,7 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
*/
|
||||
private void connectAmiIp() {
|
||||
String ipAddress = SharedPrefsMgr.getInstance(AbsMogoApplication.getApp().getBaseContext()).getString(MoGoConfig.OBU_IP, "192.168.1.199");
|
||||
Logger.d("OnAdasListenerAdapter", "application --ipAddress = " + ipAddress);
|
||||
//Logger.d("OnAdasListenerAdapter", "application --ipAddress = " + ipAddress);
|
||||
AmiClientManager.getInstance().setObuIp(ipAddress);
|
||||
}
|
||||
|
||||
@@ -302,7 +301,8 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
|
||||
private void initModules() {
|
||||
Logger.d(TAG, "initModules");
|
||||
|
||||
//mogo deva tools
|
||||
MogoModulePaths.addModuleFunctionServer(new MogoModule(MogoServicePaths.PATH_DEVA_TOOLS, "IMoGoDevaToolsProvider"));
|
||||
// 初始化 bugly 升级
|
||||
MogoModulePaths.addBaseModule(new MogoModule(UpgradeReportConstants.PATH, UpgradeReportConstants.NAME));
|
||||
// 初始化 apm 日志采集
|
||||
@@ -312,9 +312,8 @@ public abstract class MainMoGoApplication extends AbsMogoApplication {
|
||||
|
||||
MogoModulePaths.addBaseModule(new MogoModule(MapApiPath.PATH, "CustomMapApiBuilder"));
|
||||
MogoModulePaths.addBaseModule(new MogoModule(ServiceConst.PATH_REFRESH_STRATEGY, ServiceConst.PATH_REFRESH_STRATEGY));
|
||||
// MogoModulePaths.addBaseModule(new MogoModule(V2XConst.PATH_V2X_UI, V2XConst.MODULE_NAME));
|
||||
//mogo deva tools
|
||||
MogoModulePaths.addModuleFunctionServer(new MogoModule(MogoServicePaths.PATH_DEVA_TOOLS, "IMoGoDevaToolsProvider"));
|
||||
// MogoModulePaths.addBaseModule(new MogoModule(V2XConst.PATH_V2X_UI, V2XConst.MODULE_NAME));
|
||||
|
||||
// 域控制器模块(新)
|
||||
MogoModulePaths.addModuleFunctionServer(new MogoModule(MogoServicePaths.PATH_AUTO_PILOT, "IMoGoAutoPilotProvider"));
|
||||
// OBU 模块
|
||||
|
||||
@@ -50,7 +50,7 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.adasHigh
|
||||
//implementation rootProject.ext.dependencies.adasHigh
|
||||
implementation rootProject.ext.dependencies.mogocustommapoperational
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogoserviceapi
|
||||
@@ -74,6 +74,8 @@ dependencies {
|
||||
|
||||
implementation project(":libraries:mogo-map")
|
||||
implementation project(":libraries:mogo-map-api")
|
||||
|
||||
implementation project(':libraries:mogo-adas')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.flexbox
|
||||
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.adasHigh
|
||||
// implementation rootProject.ext.dependencies.adasHigh
|
||||
implementation rootProject.ext.dependencies.mogo_v2x
|
||||
implementation rootProject.ext.dependencies.mogoaicloudtrafficlive
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
@@ -75,6 +75,8 @@ dependencies {
|
||||
implementation project(':modules:mogo-module-carchattingprovider')
|
||||
implementation project(':core:mogo-core-res')
|
||||
|
||||
implementation project(':libraries:mogo-adas')
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.mogo.eagle.core.function.v2x.events.widgets;
|
||||
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.module.common.entity.MarkerExploreWay;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lixiaopeng
|
||||
* @description
|
||||
* @since 2020/7/29
|
||||
*/
|
||||
public interface SurroundingEventView extends IView {
|
||||
|
||||
void showSurroudingData(List<MarkerExploreWay> exploreWayList);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.mogo.eagle.core.function.v2x.events.widgets;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* @author lixiaopeng
|
||||
* @description
|
||||
* @since 2020/8/11
|
||||
*/
|
||||
public class SurroundingMarginDecoration extends RecyclerView.ItemDecoration {
|
||||
private int margin ;
|
||||
private int marginLeft ;
|
||||
|
||||
public SurroundingMarginDecoration(int space, int left) {
|
||||
margin = space;
|
||||
marginLeft = left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
outRect.bottom = margin;
|
||||
|
||||
//由于每行都只有2个,所以第一个都是2的倍数
|
||||
if (parent.getChildLayoutPosition(view) % 2 == 0) {
|
||||
outRect.left = marginLeft;
|
||||
outRect.right = margin / 2;
|
||||
} else {
|
||||
outRect.left = margin / 2;
|
||||
outRect.right = marginLeft;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,10 @@
|
||||
package com.mogo.eagle.core.function.v2x.trafficlight
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
|
||||
class TrafficLightConst {
|
||||
|
||||
companion object {
|
||||
const val MODULE_NAME = "MODULE_V2X_TRAFFIC_LIGHT"
|
||||
|
||||
private const val HOST_DEV = "http://dzt-test.zhidaozhixing.com"
|
||||
private const val HOST_TEST = "http://dzt-test.zhidaozhixing.com"
|
||||
private const val HOST_DEMO = "http://dzt-show.zhidaozhixing.com"
|
||||
private const val HOST_PRODUCT = "http://dzt.zhidaozhixing.com"
|
||||
|
||||
fun getNetHost(): String {
|
||||
return when (DebugConfig.getNetMode()) {
|
||||
DebugConfig.NET_MODE_DEV -> HOST_DEV
|
||||
DebugConfig.NET_MODE_QA -> HOST_TEST
|
||||
DebugConfig.NET_MODE_DEMO -> HOST_DEMO
|
||||
else -> HOST_PRODUCT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package com.mogo.eagle.core.data.autopilot
|
||||
|
||||
import android.util.Log
|
||||
import java.util.logging.Logger
|
||||
|
||||
/**
|
||||
* @author XuXinChao
|
||||
* @description 工控机升级状态实体类
|
||||
@@ -32,6 +29,7 @@ class AdUpgradeStateHelper {
|
||||
* @param downloadStatus 下载状态
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun showUpgradeTips(downloadStatus: Int,upgradeStatus: Int) : Boolean{
|
||||
return isDownloading(downloadStatus) || isDownloadFinish(downloadStatus,upgradeStatus) || getUpgradeStatus() || isUpgradeFailed(upgradeStatus)
|
||||
}
|
||||
@@ -41,6 +39,7 @@ class AdUpgradeStateHelper {
|
||||
* @param downloadStatus 下载状态
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun showCannotReboot(downloadStatus: Int,upgradeStatus: Int): Boolean{
|
||||
return isDownloading(downloadStatus)|| isDownloadFinish(downloadStatus,upgradeStatus) || getUpgradeStatus()
|
||||
}
|
||||
@@ -49,6 +48,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机是否处于“下载中”状态
|
||||
* @param downloadStatus 下载状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isDownloading(downloadStatus: Int) : Boolean{
|
||||
return downloadStatus == DOWNLOAD_START
|
||||
}
|
||||
@@ -58,6 +58,7 @@ class AdUpgradeStateHelper {
|
||||
* @param downloadStatus 下载状态
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isDownloadFinish(downloadStatus: Int,upgradeStatus: Int) : Boolean{
|
||||
return downloadStatus == DOWNLOAD_FINISH && upgradeStatus == USER_AFFIRM
|
||||
}
|
||||
@@ -66,6 +67,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机是否处于“下载失败”状态
|
||||
* @param downloadStatus 下载状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isDownloadFailed(downloadStatus: Int) : Boolean{
|
||||
return downloadStatus == DOWNLOAD_FAILED
|
||||
}
|
||||
@@ -74,6 +76,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机是否处于“升级成功”状态
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isUpgradeSuccess(upgradeStatus: Int) : Boolean{
|
||||
return upgradeStatus == UPGRADE_SUCCEED
|
||||
}
|
||||
@@ -82,6 +85,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机是否处于“升级失败”状态
|
||||
* @param upgradeStatus 升级状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isUpgradeFailed(upgradeStatus: Int) : Boolean{
|
||||
return upgradeStatus == UPGRADE_FAILED
|
||||
}
|
||||
@@ -91,6 +95,7 @@ class AdUpgradeStateHelper {
|
||||
* @param currentProgress 当前已下载包体大小
|
||||
* @param totalProgress 包体总大小
|
||||
*/
|
||||
@JvmStatic
|
||||
fun downloadProgress(currentProgress: Int,totalProgress: Int) : Int{
|
||||
return (currentProgress.toDouble()/totalProgress.toDouble()*100).toInt()
|
||||
}
|
||||
@@ -99,6 +104,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机升级模式是否是静默升级
|
||||
* @param upgradeMode 升级模式
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isQuietUpgradeMode(upgradeMode: Int) : Boolean{
|
||||
return upgradeMode == UPGRADE_QUIET
|
||||
}
|
||||
@@ -107,6 +113,7 @@ class AdUpgradeStateHelper {
|
||||
* 工控机升级模式是否是提示升级
|
||||
* @param upgradeMode 升级模式
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isHintUpgradeMode(upgradeMode: Int) : Boolean{
|
||||
return upgradeMode == UPGRADE_HINT
|
||||
}
|
||||
@@ -114,6 +121,7 @@ class AdUpgradeStateHelper {
|
||||
/**
|
||||
* 获取是否处于“升级中”状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getUpgradeStatus() : Boolean{
|
||||
return UPGRADING
|
||||
}
|
||||
@@ -122,6 +130,7 @@ class AdUpgradeStateHelper {
|
||||
* 设置是否处于“升级中”状态
|
||||
* @param upgrading 是否是升级中
|
||||
*/
|
||||
@JvmStatic
|
||||
fun setUpgradeStatus(upgrading: Boolean){
|
||||
UPGRADING = upgrading
|
||||
}
|
||||
@@ -129,6 +138,7 @@ class AdUpgradeStateHelper {
|
||||
/**
|
||||
* 获取工控机包体下载剩余时间
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getRemainingTime(totalProgress: Int,previousProgress: Int,currentProgress: Int) : String{
|
||||
//剩余包体大小
|
||||
val remainingSize = totalProgress - currentProgress
|
||||
@@ -139,14 +149,14 @@ class AdUpgradeStateHelper {
|
||||
//转换为分秒格式返回
|
||||
val minute = time/60
|
||||
val second = time%60
|
||||
if(minute>0 && second>0){
|
||||
return minute.toString()+"分钟"+second+"秒"
|
||||
return if(minute>0 && second>0){
|
||||
minute.toString()+"分钟"+second+"秒"
|
||||
}else if(minute>0){
|
||||
return minute.toString()+"分钟"
|
||||
minute.toString()+"分钟"
|
||||
}else if(second>0){
|
||||
return second.toString()+"秒"
|
||||
second.toString()+"秒"
|
||||
}else{
|
||||
return ""
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.mogo.eagle.core.data.chain
|
||||
|
||||
class ChainConstant {
|
||||
|
||||
companion object{
|
||||
|
||||
const val CHAIN_LINK_CLOUD_SHOW = 0
|
||||
const val CHAIN_LINK_ADAS = 1
|
||||
|
||||
const val CHAIN_LINK_LOG_CONNECT_STATUS = 0
|
||||
const val CHAIN_LINK_LOG_WEB_SOCKET_DATA = 1
|
||||
|
||||
const val CHAIN_LINK_LOG_ADAS_INIT = "-adasInitStatus"
|
||||
const val CHAIN_LINK_LOG_ADAS_MSG = "-adasWsMsg"
|
||||
|
||||
const val CHAIN_ALIAS_CODE_UDP_INIT = "PAD_ADAS_UDP_INIT"
|
||||
const val CHAIN_ALIAS_CODE_UDP_CONNECT_ADDRESS = "PAD_ADAS_UDP_CONNECT_ADDRESS"
|
||||
const val CHAIN_ALIAS_CODE_WEB_SOCKET_OPEN = "PAD_ADAS_WEB_SOCKET_OPEN"
|
||||
const val CHAIN_ALIAS_CODE_WEB_SOCKET_MESSAGE_JSON = "PAD_ADAS_WEB_SOCKET_MESSAGE_JSON"
|
||||
const val CHAIN_ALIAS_CODE_WEB_SOCKET_MESSAGE_BYTE = "PAD_ADAS_WEB_SOCKET_MESSAGE_BYTE"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_RECT_DATA = "PAD_ADAS_MESSAGE_AUTOPILOT_RECT_DATA"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_CAR_STATE = "PAD_ADAS_MESSAGE_AUTOPILOT_CAR_STATE"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_STATUS = "PAD_ADAS_MESSAGE_AUTOPILOT_STATUS"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ARRIVE = "PAD_ADAS_MESSAGE_AUTOPILOT_ARRIVE"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_ROUTE = "PAD_ADAS_MESSAGE_AUTOPILOT_ROUTE"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY = "PAD_ADAS_MESSAGE_AUTOPILOT_TRAJECTORY"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_GUARDIAN = "PAD_ADAS_MESSAGE_AUTOPILOT_GUARDIAN"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_RECORD = "PAD_ADAS_MESSAGE_AUTOPILOT_RECORD"
|
||||
const val CHAIN_ALIAS_CODE_ADAS_MESSAGE_AUTOPILOT_WARN = "PAD_ADAS_MESSAGE_AUTOPILOT_WARN"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.eagle.core.data.chain
|
||||
|
||||
class ChainLogParam {
|
||||
|
||||
var record: Boolean = false
|
||||
var des: String? = null
|
||||
|
||||
constructor(record: Boolean, des: String) {
|
||||
this.record = record
|
||||
this.des = des
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,12 @@ object HmiBuildConfig {
|
||||
@JvmField
|
||||
var isShowBadCaseView = true
|
||||
|
||||
/**
|
||||
* 是否展示工控机升级提示UI
|
||||
*/
|
||||
@JvmField
|
||||
var isShowUpgradeTipsView = true
|
||||
|
||||
/**
|
||||
* 是否展示转向灯ui
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,8 @@ object MoGoConfig {
|
||||
|
||||
// CMD全量日志抓取
|
||||
const val CATCH_LOG = "CATCH_LOG"
|
||||
// CMD全量日志抓取当时时间
|
||||
const val CATCH_LOG_TIME = "CATCH_LOG_TIME"
|
||||
|
||||
// 是否是演示(美化)模式,会存在SP中,方便做现场恢复
|
||||
const val IS_DEMO_MODE = "IS_DEMO_MODE"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.mogo.eagle.core.function.api.devatools
|
||||
|
||||
import com.mogo.eagle.core.data.chain.ChainLogParam
|
||||
import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider
|
||||
|
||||
/**
|
||||
@@ -9,5 +10,12 @@ interface IDevaToolsProvider : IMoGoFunctionServerProvider {
|
||||
|
||||
fun startLogCatch()
|
||||
|
||||
fun startLogCatch(duration: Int)
|
||||
|
||||
fun stopLogCatch()
|
||||
|
||||
fun getTraceInfo():HashMap<Int, ChainLogParam>
|
||||
|
||||
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>)
|
||||
|
||||
}
|
||||
@@ -193,6 +193,12 @@ interface IMoGoWaringProvider {
|
||||
*/
|
||||
fun registerBadCaseCallback(onShow:() -> View, onHide: (() -> Unit)?)
|
||||
|
||||
/**
|
||||
*注册工控机升级提示圆点View的回调
|
||||
* @param 提示圆点View
|
||||
*/
|
||||
fun registerUpgradeTipsCallback(tipsView:() -> View)
|
||||
|
||||
/**
|
||||
* 工控机重启返回结果
|
||||
* @param code
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.mogo.eagle.core.function.call.devatools
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.mogo.eagle.core.data.chain.ChainLogParam
|
||||
import com.mogo.eagle.core.data.constants.MogoServicePaths.PATH_DEVA_TOOLS
|
||||
import com.mogo.eagle.core.function.api.devatools.IDevaToolsProvider
|
||||
import com.mogo.eagle.core.utilcode.util.SnackbarUtils
|
||||
|
||||
object CallerDevaToolsManager {
|
||||
|
||||
@@ -17,10 +19,32 @@ object CallerDevaToolsManager {
|
||||
devaToolsProviderApi.startLogCatch()
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始抓取全量日志
|
||||
* duration 分钟数
|
||||
*/
|
||||
fun startCatchLog(duration: Int){
|
||||
devaToolsProviderApi.startLogCatch(duration)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止抓取全量日志
|
||||
*/
|
||||
fun stopCatchLog() {
|
||||
devaToolsProviderApi.stopLogCatch()
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新链路节点信息,是否写入
|
||||
*/
|
||||
fun refreshTraceInfo(map: HashMap<Int, ChainLogParam>) {
|
||||
devaToolsProviderApi.refreshTraceInfo(map)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取链路节点信息
|
||||
*/
|
||||
fun getTraceInfo():HashMap<Int, ChainLogParam>{
|
||||
return devaToolsProviderApi.getTraceInfo()
|
||||
}
|
||||
}
|
||||
@@ -273,6 +273,14 @@ object CallerHmiManager : CallerBase() {
|
||||
waringProviderApi?.registerBadCaseCallback(onShow, onHide)
|
||||
}
|
||||
|
||||
/**
|
||||
*注册工控机升级提示圆点View的回调
|
||||
* @param 提示圆点View
|
||||
*/
|
||||
fun registerUpgradeTipsCallback(tipsView:() -> View){
|
||||
waringProviderApi?.registerUpgradeTipsCallback(tipsView)
|
||||
}
|
||||
|
||||
/**
|
||||
* 工控机重启返回结果
|
||||
* @param code
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.eagle.core.utilcode.util">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
|
||||
<application>
|
||||
|
||||
<activity
|
||||
|
||||
@@ -17,6 +17,13 @@ import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleEventObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.eagle.core.utilcode.kotlin.ExtensionsKt;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||
|
||||
|
||||
@@ -34,7 +41,7 @@ public final class TipToast {
|
||||
private static ToastViewGenerator sGenerator;
|
||||
|
||||
public static void init( Context context, ToastViewGenerator generator ) {
|
||||
TipToast.sContext = context;
|
||||
TipToast.sContext = context.getApplicationContext();
|
||||
sHandler = new Handler( context.getMainLooper() );
|
||||
sGenerator = generator;
|
||||
}
|
||||
@@ -165,20 +172,21 @@ public final class TipToast {
|
||||
|
||||
sHandler.post(() -> {
|
||||
synchronized ( sSyncObject ) {
|
||||
|
||||
if ( context == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( sToast != null ) {
|
||||
sToast.cancel();
|
||||
if ( sToast != null) {
|
||||
View view = sToast.getView();
|
||||
if (view != null && ViewCompat.isAttachedToWindow(view)) {
|
||||
sToast.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
if ( sGenerator == null ) {
|
||||
sToast = Toast.makeText( context, msg, duration );
|
||||
} else {
|
||||
sToast = new Toast( context );
|
||||
final View view = sGenerator.make( context, msg, tipDrawable );
|
||||
|
||||
if ( view != null ) {
|
||||
sToast.setView( view );
|
||||
sToast.setGravity( sGenerator.gravity(), sGenerator.xOffset(), sGenerator.yOffset() );
|
||||
@@ -187,6 +195,15 @@ public final class TipToast {
|
||||
sToast = Toast.makeText( context, msg, duration );
|
||||
}
|
||||
}
|
||||
View view = sToast.getView();
|
||||
if (view != null) {
|
||||
LifecycleOwner lifecycleOwner = ExtensionsKt.getLifecycleOwner(view);
|
||||
lifecycleOwner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> {
|
||||
if (event == Lifecycle.Event.ON_DESTROY) {
|
||||
sToast = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
if ( sToast != null ) {
|
||||
sToast.show();
|
||||
}
|
||||
|
||||
@@ -3,38 +3,40 @@ package com.mogo.eagle.core.utilcode.util;
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.MediaDrm;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elegant.utils.storage.SharedPrefsMgr;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.elegant.utils.storage.SharedPrefsMgr;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class DeviceIdUtils {
|
||||
|
||||
public static final String KEY_DEVICE_ID = "deviceId";
|
||||
|
||||
private DeviceIdUtils() {}
|
||||
private DeviceIdUtils() {
|
||||
}
|
||||
|
||||
private static void saveDeviceId( Context context, String deviceId){
|
||||
private static void saveDeviceId(Context context, String deviceId) {
|
||||
SharedPrefsMgr.getInstance(context).putString(KEY_DEVICE_ID, deviceId);
|
||||
}
|
||||
|
||||
public static String getDeviceId( Context context) {
|
||||
if(context == null){
|
||||
public static String getDeviceId(Context context) {
|
||||
if (context == null) {
|
||||
throw new NullPointerException("context must not be null.");
|
||||
}
|
||||
|
||||
final Context appContext = context.getApplicationContext();
|
||||
String deviceId = SharedPrefsMgr.getInstance( context ).getString( KEY_DEVICE_ID );
|
||||
String deviceId = SharedPrefsMgr.getInstance(context).getString(KEY_DEVICE_ID);
|
||||
|
||||
if ( TextUtils.isEmpty( deviceId )) {
|
||||
if (TextUtils.isEmpty(deviceId)) {
|
||||
deviceId = getDeviceIdInternal(appContext);
|
||||
if (TextUtils.isEmpty(deviceId)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
@@ -54,35 +56,37 @@ public final class DeviceIdUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
saveDeviceId(appContext,deviceId);
|
||||
saveDeviceId(appContext, deviceId);
|
||||
}
|
||||
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
private static String getDeviceIdInternal( Context context) {
|
||||
private static String getDeviceIdInternal(Context context) {
|
||||
String id = "";
|
||||
|
||||
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
|
||||
if ( ContextCompat.checkSelfPermission( context, Manifest.permission.READ_PHONE_STATE ) != PackageManager.PERMISSION_GRANTED ) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
TelephonyManager telephonymanager = ( TelephonyManager ) context.getSystemService( Context.TELEPHONY_SERVICE);
|
||||
TelephonyManager telephonymanager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (telephonymanager != null) {
|
||||
id = telephonymanager.getDeviceId();
|
||||
if ( TextUtils.isEmpty(id))
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
id = "";
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private static String getAndroidId( Context context) {
|
||||
private static String getAndroidId(Context context) {
|
||||
String s = "";
|
||||
s = Settings.Secure.getString(context.getContentResolver(), "android_id");
|
||||
if ( TextUtils.isEmpty(s))
|
||||
if (TextUtils.isEmpty(s)) {
|
||||
s = "";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -95,16 +99,63 @@ public final class DeviceIdUtils {
|
||||
if (!method.isAccessible()) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
serial = ( String ) method.invoke(new Build(), "ro.serialno");
|
||||
} catch ( ClassNotFoundException e) {
|
||||
serial = (String) method.invoke(new Build(), "ro.serialno");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch ( NoSuchMethodException e) {
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch ( InvocationTargetException e) {
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch ( IllegalAccessException e) {
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return serial;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数字版权管理设备ID
|
||||
*
|
||||
* @return WidevineID,可能为空
|
||||
*/
|
||||
public static String getWidevineID(Context context) {
|
||||
try {
|
||||
//See https://stackoverflow.com/questions/16369818/how-to-get-crypto-scheme-uuid
|
||||
//You can find some UUIDs in the https://github.com/google/ExoPlayer source code
|
||||
final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
|
||||
MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID);
|
||||
byte[] widevineId = mediaDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
|
||||
if (widevineId == null) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte aByte : widevineId) {
|
||||
sb.append(String.format("%02x", aByte));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Exception | Error e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数字版权管理设备ID,进行MD5加密,获取32位的唯一标记,给后台生成SN
|
||||
*
|
||||
* @return WidevineID,可能为空
|
||||
*/
|
||||
public static String getWidevineIDWithMd5(Context context) {
|
||||
try {
|
||||
String widevineId = getWidevineID(context);
|
||||
if (!TextUtils.isEmpty(widevineId)) {
|
||||
widevineId = EncryptUtils.encryptHmacMD5ToString(widevineId, "MoGoAuto");
|
||||
return widevineId;
|
||||
} else {
|
||||
return getDeviceId(context);
|
||||
}
|
||||
} catch (Exception | Error e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return getDeviceId(context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,14 +55,6 @@ public final class TimeUtils {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
public static String formatYMD(long time){
|
||||
Date date = new Date(time);
|
||||
String strDateFormat = "yyyy-MM-dd";
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Milliseconds to the formatted time string.
|
||||
* <p>The pattern is {@code yyyy-MM-dd HH:mm:ss}.</p>
|
||||
@@ -1532,8 +1524,8 @@ public final class TimeUtils {
|
||||
return CHINESE_ZODIAC[year % 12];
|
||||
}
|
||||
|
||||
private static final int[] ZODIAC_FLAGS = {20, 19, 21, 21, 21, 22, 23, 23, 23, 24, 23, 22};
|
||||
private static final String[] ZODIAC = {
|
||||
private static final int[] ZODIAC_FLAGS = {20, 19, 21, 21, 21, 22, 23, 23, 23, 24, 23, 22};
|
||||
private static final String[] ZODIAC = {
|
||||
"水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座",
|
||||
"狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座"
|
||||
};
|
||||
|
||||
@@ -179,13 +179,12 @@ public abstract class AbsMogoApplication extends Application {
|
||||
*/
|
||||
protected void registerSocketHttpDnsTTL(String host) {
|
||||
sApis.addressChangedListener(map -> {
|
||||
Logger.d("TEST-SOCKET", "ttl callBack ,ready to getCache Dns IP");
|
||||
String dnsCacheIp = sApis.getCachedHttpDnsIps(host, HTTP_DNS_ADDRESS_TYPE_HTTP);
|
||||
if (dnsCacheIp == null) {
|
||||
return;
|
||||
}
|
||||
Logger.d("TEST-SOCKET", "获取缓存Dns IP : " + dnsCacheIp + " , 原缓存 IP : " + cacheIp);
|
||||
if (!dnsCacheIp.equals(cacheIp)) {
|
||||
Logger.d("TEST-SOCKET", "获取缓存Dns IP : " + dnsCacheIp + " , 原缓存 IP : " + cacheIp);
|
||||
socketTTL();
|
||||
this.cacheIp = dnsCacheIp;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ kapt.include.compile.classpath=false
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# Android operating system, and which are packaged with your app'protoc_platforms APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
android.jetifier.blacklist=module-service-2.1.16.8.aar
|
||||
android.jetifier.blacklist=module-service-2.1.16.10.aar
|
||||
## maven 配置
|
||||
RELEASE_REPOSITORY_URL=http://nexus.zhidaoauto.com/repository/maven-releases/
|
||||
SNAPSHOT_REPOSITORY_URL=http://nexus.zhidaoauto.com/repository/maven-snapshots/
|
||||
@@ -56,28 +56,30 @@ bytex.forbidUseLenientMutationDuringGetArtifact=true
|
||||
bytex.verifyProguardConfigurationChanged=false
|
||||
bytex.ASM_API=ASM7
|
||||
|
||||
HOOK_LOG_VERSION=1.4.109
|
||||
SERVICE_CHAIN_VERSION=1.0.43
|
||||
HOOK_LOG_VERSION=1.5.17
|
||||
SERVICE_CHAIN_VERSION=1.0.53
|
||||
################ 外部依赖引用 ################
|
||||
# loglib
|
||||
LOGLIB_VERSION=1.1.18
|
||||
LOGLIB_VERSION=1.2.8
|
||||
######## MogoAiCloudSDK Version ########
|
||||
# 网络请求
|
||||
MOGO_NETWORK_VERSION=1.3.18
|
||||
MOGO_NETWORK_VERSION=1.3.30
|
||||
# 鉴权
|
||||
MOGO_PASSPORT_VERSION=1.3.18
|
||||
MOGO_PASSPORT_VERSION=1.3.30
|
||||
# 常链接
|
||||
MOGO_SOCKET_VERSION=1.3.18
|
||||
MOGO_SOCKET_VERSION=1.3.30
|
||||
# 数据采集
|
||||
MOGO_REALTIME_VERSION=1.3.18
|
||||
MOGO_REALTIME_VERSION=1.3.30
|
||||
# 探路,道路事件发布,获取
|
||||
MOGO_TANLU_VERSION=1.3.18
|
||||
MOGO_TANLU_VERSION=1.3.30
|
||||
# 直播推流
|
||||
MOGO_LIVE_VERSION=1.3.18
|
||||
MOGO_LIVE_VERSION=1.3.30
|
||||
# 直播拉流
|
||||
MOGO_TRAFFICLIVE_VERSION=1.3.18
|
||||
MOGO_TRAFFICLIVE_VERSION=1.3.30
|
||||
# 定位服务
|
||||
MOGO_LOCATION_VERSION=1.3.18
|
||||
MOGO_LOCATION_VERSION=1.3.30
|
||||
# 远程通讯模块
|
||||
MOGO_TELEMATIC_VERSION=1.3.30
|
||||
######## MogoAiCloudSDK Version ########
|
||||
# 自研地图
|
||||
MAP_SDK_VERSION=2.0.5.1
|
||||
@@ -92,105 +94,107 @@ versionCode=80008
|
||||
versionName=2.5.1
|
||||
|
||||
################# 新架构模块Maven版本管理 #################
|
||||
MOGO_CORE_FUNCTION_AUTOPILOT_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_CHECK_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_HMI_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_MAIN_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_MAP_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_MONITORING_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_NOTICE_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_OBU_MOGO_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_SMP_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_V2X_VERSION=0.0.58.8
|
||||
MOGO_CORE_DATA_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_API_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_CALL_VERSION=0.0.58.8
|
||||
MOGO_CORE_RES_VERSION=0.0.58.8
|
||||
MOGO_CORE_UTILS_VERSION=0.0.58.8
|
||||
MOGO_CORE_NETWORK_VERSION=0.0.58.8
|
||||
MOGO_CORE_FUNCTION_AUTOPILOT_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_CHECK_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_HMI_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_MAIN_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_MAP_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_MONITORING_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_NOTICE_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_OBU_MOGO_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_SMP_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_V2X_VERSION=0.0.58.10
|
||||
MOGO_CORE_DATA_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_API_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_CALL_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_CARCORDER_VERSION=0.0.58.10
|
||||
MOGO_CORE_FUNCTION_DEVATOOLS_VERSION=0.0.58.10
|
||||
MOGO_CORE_RES_VERSION=0.0.58.10
|
||||
MOGO_CORE_UTILS_VERSION=0.0.58.10
|
||||
MOGO_CORE_NETWORK_VERSION=0.0.58.10
|
||||
################# 旧版本架构模块版本 #################
|
||||
## 工程内模块
|
||||
MOGO_COMMONS_VERSION=2.1.16.8
|
||||
MOGO_UTILS_VERSION=2.1.16.8
|
||||
MAP_AMAP_VERSION=2.1.16.8
|
||||
MAP_AUTONAVI_VERSION=2.1.16.8
|
||||
MOGO_MAP_VERSION=2.1.16.8
|
||||
MOGO_MAP_API_VERSION=2.1.16.8
|
||||
MOGO_SERVICE_VERSION=2.1.16.8
|
||||
MOGO_SERVICE_API_VERSION=2.1.16.8
|
||||
MOGO_CONNECTION_VERSION=2.1.16.8
|
||||
MOGO_MODULE_APPS_VERSION=2.1.16.8
|
||||
MOGO_MODULE_NAVI_VERSION=2.1.16.8
|
||||
MOGO_MODULE_SHARE_VERSION=2.1.16.8
|
||||
MOGO_MODULE_COMMON_VERSION=2.1.16.8
|
||||
MOGO_MODULE_MAIN_VERSION=2.1.16.8
|
||||
MOGO_MODULE_MAP_VERSION=2.1.16.8
|
||||
MOGO_MODULE_SERVICE_VERSION=2.1.16.8
|
||||
MOGO_MODULE_EXTENSIONS_VERSION=2.1.16.8
|
||||
MOGO_MODULE_SEARCH_VERSION=2.1.16.8
|
||||
MOGO_MODULE_BACK_VERSION=2.1.16.8
|
||||
MOGO_MODULE_V2X_VERSION=2.1.16.8
|
||||
MOGO_COMMONS_VERSION=2.1.16.10
|
||||
MOGO_UTILS_VERSION=2.1.16.10
|
||||
MAP_AMAP_VERSION=2.1.16.10
|
||||
MAP_AUTONAVI_VERSION=2.1.16.10
|
||||
MOGO_MAP_VERSION=2.1.16.10
|
||||
MOGO_MAP_API_VERSION=2.1.16.10
|
||||
MOGO_SERVICE_VERSION=2.1.16.10
|
||||
MOGO_SERVICE_API_VERSION=2.1.16.10
|
||||
MOGO_CONNECTION_VERSION=2.1.16.10
|
||||
MOGO_MODULE_APPS_VERSION=2.1.16.10
|
||||
MOGO_MODULE_NAVI_VERSION=2.1.16.10
|
||||
MOGO_MODULE_SHARE_VERSION=2.1.16.10
|
||||
MOGO_MODULE_COMMON_VERSION=2.1.16.10
|
||||
MOGO_MODULE_MAIN_VERSION=2.1.16.10
|
||||
MOGO_MODULE_MAP_VERSION=2.1.16.10
|
||||
MOGO_MODULE_SERVICE_VERSION=2.1.16.10
|
||||
MOGO_MODULE_EXTENSIONS_VERSION=2.1.16.10
|
||||
MOGO_MODULE_SEARCH_VERSION=2.1.16.10
|
||||
MOGO_MODULE_BACK_VERSION=2.1.16.10
|
||||
MOGO_MODULE_V2X_VERSION=2.1.16.10
|
||||
# 探路
|
||||
MOGO_MODULE_TANLU_VERSION=2.1.16.8
|
||||
MOGO_MODULE_TANLU_VERSION=2.1.16.10
|
||||
# 推送
|
||||
MOGO_MODULE_PUSH_VERSION=2.1.16.8
|
||||
MOGO_MODULE_PUSH_BASE_VERSION=2.1.16.8
|
||||
MOGO_MODULE_PUSH_NOOP_VERSION=2.1.16.8
|
||||
MOGO_MODULE_PUSH_VERSION=2.1.16.10
|
||||
MOGO_MODULE_PUSH_BASE_VERSION=2.1.16.10
|
||||
MOGO_MODULE_PUSH_NOOP_VERSION=2.1.16.10
|
||||
# 探路上报和分享模块
|
||||
TANLULIB_VERSION=2.1.16.8
|
||||
MOGO_TANLU_API_VERSION=2.1.16.8
|
||||
TANLULIB_VERSION=2.1.16.10
|
||||
MOGO_TANLU_API_VERSION=2.1.16.10
|
||||
#左侧面板模块
|
||||
MOGO_MODULE_LEFT_PANEL_VERSION=2.1.16.8
|
||||
MOGO_MODULE_LEFT_PANEL_NOOP_VERSION=2.1.16.8
|
||||
MOGO_MODULE_LEFT_PANEL_VERSION=2.1.16.10
|
||||
MOGO_MODULE_LEFT_PANEL_NOOP_VERSION=2.1.16.10
|
||||
# 小控件
|
||||
MOGO_MODULE_WIDGETS_VERSION=2.1.16.8
|
||||
MOGO_MODULE_WIDGETS_VERSION=2.1.16.10
|
||||
# obu
|
||||
MOGO_MODULE_OBU_VERSION=2.1.16.8
|
||||
MOGO_MODULE_OBU_MOGO_VERSION=2.1.16.8
|
||||
MOGO_MODULE_OBU_VERSION=2.1.16.10
|
||||
MOGO_MODULE_OBU_MOGO_VERSION=2.1.16.10
|
||||
# monitor
|
||||
MOGO_MODULE_MONITOR_VERSION=2.1.16.8
|
||||
MOGO_MODULE_MONITOR_VERSION=2.1.16.10
|
||||
# bugly
|
||||
CRASHREPORT_VERSION=2.1.16.8
|
||||
CRASHREPORT_BUGLY_VERSION=2.1.16.8
|
||||
CRASHREPORT_NOOP_VERSION=2.1.16.8
|
||||
CRASHREPORT_APMBYTE_VERSION=2.1.16.8
|
||||
CRASHREPORT_UPGRADE_VERSION=2.1.16.8
|
||||
CRASHREPORT_VERSION=2.1.16.10
|
||||
CRASHREPORT_BUGLY_VERSION=2.1.16.10
|
||||
CRASHREPORT_NOOP_VERSION=2.1.16.10
|
||||
CRASHREPORT_APMBYTE_VERSION=2.1.16.10
|
||||
CRASHREPORT_UPGRADE_VERSION=2.1.16.10
|
||||
## tts
|
||||
TTS_BASE_VERSION=2.1.16.8
|
||||
TTS_DI_VERSION=2.1.16.8
|
||||
TTS_ZHI_VERSION=2.1.16.8
|
||||
TTS_PAD_VERSION=2.1.16.8
|
||||
TTS_NOOP_VERSION=2.1.16.8
|
||||
TTS_BASE_VERSION=2.1.16.10
|
||||
TTS_DI_VERSION=2.1.16.10
|
||||
TTS_ZHI_VERSION=2.1.16.10
|
||||
TTS_PAD_VERSION=2.1.16.10
|
||||
TTS_NOOP_VERSION=2.1.16.10
|
||||
# 自研地图
|
||||
MAP_CUSTOM_VERSION=2.1.16.8
|
||||
MOGO_MODULE_ADAS_VERSION=2.1.16.8
|
||||
MAP_CUSTOM_VERSION=2.1.16.10
|
||||
MOGO_MODULE_ADAS_VERSION=2.1.16.10
|
||||
# 基础服务实现:passport、socket、location
|
||||
MOGO_BASE_WEBSOCKET_SDK_VERSION=2.1.16.8
|
||||
MOGO_BASE_SERVICES_APK_VERSION=2.1.16.8
|
||||
MOGO_BASE_SERVICES_SDK_VERSION=2.1.16.8
|
||||
MOGO_MODULE_CHAT_VERSION=2.1.16.8
|
||||
MOGO_BASE_WEBSOCKET_SDK_VERSION=2.1.16.10
|
||||
MOGO_BASE_SERVICES_APK_VERSION=2.1.16.10
|
||||
MOGO_BASE_SERVICES_SDK_VERSION=2.1.16.10
|
||||
MOGO_MODULE_CHAT_VERSION=2.1.16.10
|
||||
# 车聊聊
|
||||
MOGO_MODULE_CARCHATTING_VERSION=2.1.16.8
|
||||
MOGO_MODULE_CARCHATTING_VERSION=2.1.16.10
|
||||
# 车聊聊接口
|
||||
MOGO_MODULE_CARCHATTINGPROVIDER_VERSION=2.1.16.8
|
||||
MOGO_MODULE_CARCHATTINGPROVIDER_VERSION=2.1.16.10
|
||||
|
||||
# 皮肤
|
||||
MOGO_SKIN_SUPPORT_VERSION=2.1.16.8
|
||||
MOGO_SKIN_LIGHT_VERSION=2.1.16.8
|
||||
MOGO_SKIN_SUPPORT_IMPL_VERSION=2.1.16.8
|
||||
MOGO_SKIN_SUPPORT_NOOP_VERSION=2.1.16.8
|
||||
SKIN_SUPPORT_VERSION=2.1.16.8
|
||||
SKIN_SUPPORT_APPCOMPAT_VERSION=2.1.16.8
|
||||
SKIN_SUPPORT_CARDVIEW_VERSION=2.1.16.8
|
||||
SKIN_SUPPORT_CONSTRAINT_LAYOUT_VERSION=2.1.16.8
|
||||
SKIN_SUPPORT_DESIGN_VERSION=2.1.16.8
|
||||
MOGO_SKIN_SUPPORT_VERSION=2.1.16.10
|
||||
MOGO_SKIN_LIGHT_VERSION=2.1.16.10
|
||||
MOGO_SKIN_SUPPORT_IMPL_VERSION=2.1.16.10
|
||||
MOGO_SKIN_SUPPORT_NOOP_VERSION=2.1.16.10
|
||||
SKIN_SUPPORT_VERSION=2.1.16.10
|
||||
SKIN_SUPPORT_APPCOMPAT_VERSION=2.1.16.10
|
||||
SKIN_SUPPORT_CARDVIEW_VERSION=2.1.16.10
|
||||
SKIN_SUPPORT_CONSTRAINT_LAYOUT_VERSION=2.1.16.10
|
||||
SKIN_SUPPORT_DESIGN_VERSION=2.1.16.10
|
||||
# OCH
|
||||
MOGO_OCH_VERSION=2.1.16.8-test
|
||||
MOGO_OCH_VERSION=2.1.16.10-test
|
||||
MOGO_OCH_BUS_VERSION=2.0.66
|
||||
MOGO_OCH_NOOP_VERSION=2.0.66
|
||||
MOGO_OCH_TAXI_VERSION=2.0.66
|
||||
# mogoAiCloud sdk services
|
||||
MOGO_AICLOUD_SERVICES_SDK_VERSION=2.1.16.8
|
||||
MOGO_AICLOUD_SERVICES_SDK_VERSION=2.1.16.10
|
||||
# v2x-sdk
|
||||
MOGO_V2X_SDK_VERSION=1.0.1
|
||||
MOGO_V2X_SDK_VERSION=1.3.30
|
||||
################# 旧版本架构模块版本 #################
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.mogo.map.impl.custom;
|
||||
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_300;
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS;
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP;
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_CLOSE_SIGHT;
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_LONG_SIGHT;
|
||||
import static com.mogo.map.uicontroller.VisualAngleMode.MODE_MEDIUM_SIGHT;
|
||||
@@ -767,6 +770,12 @@ public class AMapViewWrapper implements IMogoMapView,
|
||||
return MODE_MEDIUM_SIGHT;
|
||||
case 2:
|
||||
return MODE_LONG_SIGHT;
|
||||
case 3:
|
||||
return MAP_STYLE_VR_ANGLE_300;
|
||||
case 4:
|
||||
return MAP_STYLE_VR_ANGLE_TOP;
|
||||
case 5:
|
||||
return MAP_STYLE_VR_ANGLE_CROSS;
|
||||
default:
|
||||
throw new IllegalStateException("mode is unCorrect");
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ dependencies {
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
kapt rootProject.ext.dependencies.aroutercompiler
|
||||
//implementation(name: 'common-4.1.1', ext: 'aar')
|
||||
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.mogo.usbcamera;
|
||||
|
||||
import com.serenegiant.usb.USBMonitor;
|
||||
|
||||
/**
|
||||
* @author donghongyu
|
||||
* USB摄像头方案,获取权限、获取YUV数据
|
||||
*/
|
||||
public class USBCameraHelper {
|
||||
private static USBCameraHelper mCameraHelper;
|
||||
/**
|
||||
* USB Manager
|
||||
*/
|
||||
private USBMonitor mUSBMonitor;
|
||||
|
||||
private USBCameraHelper() {
|
||||
}
|
||||
|
||||
public static USBCameraHelper getInstance() {
|
||||
if (mCameraHelper == null) {
|
||||
mCameraHelper = new USBCameraHelper();
|
||||
}
|
||||
return mCameraHelper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void registerUSB() {
|
||||
if (mUSBMonitor != null) {
|
||||
mUSBMonitor.register();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterUSB() {
|
||||
if (mUSBMonitor != null) {
|
||||
mUSBMonitor.unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* UVCCamera Helper class
|
||||
* <p>
|
||||
* Created by jiangdongguo on 2017/9/30.
|
||||
*/
|
||||
|
||||
public class UVCCameraHelper {
|
||||
public static final String ROOT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||
+ File.separator;
|
||||
@@ -77,6 +74,9 @@ public class UVCCameraHelper {
|
||||
void onConnectDev(UsbDevice device, boolean isConnected);
|
||||
|
||||
void onDisConnectDev(UsbDevice device);
|
||||
|
||||
void onCancelDev(UsbDevice device);
|
||||
|
||||
}
|
||||
|
||||
public void initUSBMonitor(Activity activity, CameraViewInterface cameraView, final OnMyDevConnectListener listener) {
|
||||
@@ -109,18 +109,15 @@ public class UVCCameraHelper {
|
||||
public void onConnect(final UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
|
||||
mCtrlBlock = ctrlBlock;
|
||||
openCamera(ctrlBlock);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// wait for camera created
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// start previewing
|
||||
startPreview(mCamView);
|
||||
new Thread(() -> {
|
||||
// wait for camera created
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// start previewing
|
||||
startPreview(mCamView);
|
||||
}).start();
|
||||
if (listener != null) {
|
||||
listener.onConnectDev(device, true);
|
||||
@@ -138,6 +135,9 @@ public class UVCCameraHelper {
|
||||
|
||||
@Override
|
||||
public void onCancel(UsbDevice device) {
|
||||
if (listener != null) {
|
||||
listener.onCancelDev(device);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -252,7 +252,6 @@ public class UVCCameraHelper {
|
||||
|
||||
public void capturePicture(String savePath, AbstractUVCCameraHandler.OnCaptureListener listener) {
|
||||
if (mCameraHandler != null && mCameraHandler.isOpened()) {
|
||||
|
||||
File file = new File(savePath);
|
||||
if (!Objects.requireNonNull(file.getParentFile()).exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.serenegiant.dialog;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
public abstract class DialogFragmentEx extends DialogFragment {
|
||||
protected static final String ARGS_KEY_REQUEST_CODE = "requestCode";
|
||||
protected static final String ARGS_KEY_ID_TITLE = "title";
|
||||
protected static final String ARGS_KEY_ID_MESSAGE = "message";
|
||||
protected static final String ARGS_KEY_TAG = "tag";
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
final Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
outState.putAll(args);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.serenegiant.dialog;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.serenegiant.utils.BuildCheck;
|
||||
|
||||
/**
|
||||
* パーミッション要求前に説明用のダイアログを表示するためのDialogFragment
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Deprecated
|
||||
public class MessageDialogFragment extends DialogFragment {
|
||||
// private static final boolean DEBUG = false; // FIXME 実働時はfalseにすること
|
||||
private static final String TAG = MessageDialogFragment.class.getSimpleName();
|
||||
|
||||
public static interface MessageDialogListener {
|
||||
public void onMessageDialogResult(final MessageDialogFragment dialog, final int requestCode, final String[] permissions, final boolean result);
|
||||
}
|
||||
|
||||
public static MessageDialogFragment showDialog(final Activity parent, final int requestCode, final int id_title, final int id_message, final String[] permissions) {
|
||||
final MessageDialogFragment dialog = newInstance(requestCode, id_title, id_message, permissions);
|
||||
dialog.show(parent.getFragmentManager(), TAG);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static MessageDialogFragment showDialog(final Fragment parent, final int requestCode, final int id_title, final int id_message, final String[] permissions) {
|
||||
final MessageDialogFragment dialog = newInstance(requestCode, id_title, id_message, permissions);
|
||||
dialog.setTargetFragment(parent, parent.getId());
|
||||
dialog.show(parent.getFragmentManager(), TAG);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static MessageDialogFragment newInstance(final int requestCode, final int id_title, final int id_message, final String[] permissions) {
|
||||
final MessageDialogFragment fragment = new MessageDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
// ここでパラメータをセットする
|
||||
args.putInt("requestCode", requestCode);
|
||||
args.putInt("title", id_title);
|
||||
args.putInt("message", id_message);
|
||||
args.putStringArray("permissions", permissions != null ? permissions : new String[]{});
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private MessageDialogListener mDialogListener;
|
||||
|
||||
public MessageDialogFragment() {
|
||||
super();
|
||||
// デフォルトコンストラクタが必要
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void onAttach(final Activity activity) {
|
||||
super.onAttach(activity);
|
||||
// コールバックインターフェースを取得
|
||||
if (activity instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)activity;
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
final Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)fragment;
|
||||
}
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
if (BuildCheck.isAndroid4_2()) {
|
||||
final Fragment target = getParentFragment();
|
||||
if (target instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)target;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
// Log.w(TAG, "caller activity/fragment must implement PermissionDetailDialogFragmentListener");
|
||||
throw new ClassCastException(activity.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onCreate(final Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// final Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
|
||||
final int requestCode = getArguments().getInt("requestCode");
|
||||
final int id_title = getArguments().getInt("title");
|
||||
final int id_message = getArguments().getInt("message");
|
||||
final String[] permissions = args.getStringArray("permissions");
|
||||
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(id_title)
|
||||
.setMessage(id_message)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int whichButton) {
|
||||
// 本当はここでパーミッション要求をしたいだけどこのダイアログがdismissしてしまって結果を受け取れないので
|
||||
// 呼び出し側へ返してそこでパーミッション要求する。なのでこのダイアログは単にメッセージを表示するだけ
|
||||
try {
|
||||
mDialogListener.onMessageDialogResult(MessageDialogFragment.this, requestCode, permissions, true);
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, int whichButton) {
|
||||
try {
|
||||
mDialogListener.onMessageDialogResult(MessageDialogFragment.this, requestCode, permissions, false);
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package com.serenegiant.dialog;
|
||||
/*
|
||||
* libcommon
|
||||
* utility/helper classes for myself
|
||||
*
|
||||
* Copyright (c) 2014-2018 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.serenegiant.utils.BuildCheck;
|
||||
|
||||
public class MessageDialogFragmentV4 extends DialogFragmentEx {
|
||||
// private static final boolean DEBUG = false; // FIXME 実働時はfalseにすること
|
||||
private static final String TAG = MessageDialogFragmentV4.class.getSimpleName();
|
||||
|
||||
private static final String ARGS_KEY_PERMISSIONS = "permissions";
|
||||
|
||||
/**
|
||||
* ダイアログの表示結果を受け取るためのコールバックリスナー
|
||||
*/
|
||||
public static interface MessageDialogListener {
|
||||
public void onMessageDialogResult(
|
||||
@NonNull final MessageDialogFragmentV4 dialog, final int requestCode,
|
||||
@NonNull final String[] permissions, final boolean result);
|
||||
}
|
||||
|
||||
/**
|
||||
* ダイアログ表示のためのヘルパーメソッド
|
||||
* @param parent
|
||||
* @param requestCode
|
||||
* @param id_title
|
||||
* @param id_message
|
||||
* @param permissions
|
||||
* @return
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public static MessageDialogFragmentV4 showDialog(
|
||||
@NonNull final FragmentActivity parent, final int requestCode,
|
||||
@StringRes final int id_title, @StringRes final int id_message,
|
||||
@NonNull final String[] permissions) throws IllegalStateException {
|
||||
|
||||
final MessageDialogFragmentV4 dialog
|
||||
= newInstance(requestCode, id_title, id_message, permissions);
|
||||
dialog.show(parent.getSupportFragmentManager(), TAG);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* ダイアログ表示のためのヘルパーメソッド
|
||||
* @param parent
|
||||
* @param requestCode
|
||||
* @param id_title
|
||||
* @param id_message
|
||||
* @param permissions
|
||||
* @return
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public static MessageDialogFragmentV4 showDialog(
|
||||
@NonNull final Fragment parent, final int requestCode,
|
||||
@StringRes final int id_title, @StringRes final int id_message,
|
||||
@NonNull final String[] permissions) throws IllegalStateException {
|
||||
|
||||
final MessageDialogFragmentV4 dialog
|
||||
= newInstance(requestCode, id_title, id_message, permissions);
|
||||
dialog.setTargetFragment(parent, parent.getId());
|
||||
dialog.show(parent.requireFragmentManager(), TAG);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* ダイアログ生成のためのヘルパーメソッド
|
||||
* ダイアログ自体を直接生成せずにこのメソッドを呼び出すこと
|
||||
* @param requestCode
|
||||
* @param id_title
|
||||
* @param id_message
|
||||
* @param permissions
|
||||
* @return
|
||||
*/
|
||||
public static MessageDialogFragmentV4 newInstance(
|
||||
final int requestCode,
|
||||
@StringRes final int id_title, @StringRes final int id_message,
|
||||
@NonNull final String[] permissions) {
|
||||
|
||||
final MessageDialogFragmentV4 fragment = new MessageDialogFragmentV4();
|
||||
final Bundle args = new Bundle();
|
||||
// ここでパラメータをセットする
|
||||
args.putInt(ARGS_KEY_REQUEST_CODE, requestCode);
|
||||
args.putInt(ARGS_KEY_ID_TITLE, id_title);
|
||||
args.putInt(ARGS_KEY_ID_MESSAGE, id_message);
|
||||
args.putStringArray(ARGS_KEY_PERMISSIONS, permissions);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private MessageDialogListener mDialogListener;
|
||||
|
||||
/**
|
||||
* コンストラクタ, 直接生成せずに#newInstanceを使うこと
|
||||
*/
|
||||
public MessageDialogFragmentV4() {
|
||||
super();
|
||||
// デフォルトコンストラクタが必要
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(final Context context) {
|
||||
super.onAttach(context);
|
||||
// コールバックインターフェースを取得
|
||||
if (context instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)context;
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
final Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)fragment;
|
||||
}
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
if (BuildCheck.isAndroid4_2()) {
|
||||
final Fragment target = getParentFragment();
|
||||
if (target instanceof MessageDialogListener) {
|
||||
mDialogListener = (MessageDialogListener)target;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDialogListener == null) {
|
||||
// Log.w(TAG, "caller activity/fragment must implement PermissionDetailDialogFragmentListener");
|
||||
throw new ClassCastException(context.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onCreate(final Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// final Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
|
||||
// }
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = savedInstanceState != null ? savedInstanceState : requireArguments();
|
||||
final int id_title = args.getInt(ARGS_KEY_ID_TITLE);
|
||||
final int id_message = args.getInt(ARGS_KEY_ID_MESSAGE);
|
||||
|
||||
final Activity activity = requireActivity();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(id_title)
|
||||
.setMessage(id_message)
|
||||
.setPositiveButton(android.R.string.ok, mOnClickListener)
|
||||
.setNegativeButton(android.R.string.cancel, mOnClickListener)
|
||||
.create();
|
||||
}
|
||||
|
||||
private final DialogInterface.OnClickListener mOnClickListener
|
||||
= new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
// 本当はここでパーミッション要求をしたいだけどこのダイアログがdismissしてしまって結果を受け取れないので
|
||||
// 呼び出し側へ返してそこでパーミッション要求する。なのでこのダイアログは単にメッセージを表示するだけ
|
||||
callOnMessageDialogResult(which == DialogInterface.BUTTON_POSITIVE);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
callOnMessageDialogResult(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* コールバックリスナー呼び出しのためのヘルパーメソッド
|
||||
* @param result
|
||||
*/
|
||||
private void callOnMessageDialogResult(final boolean result)
|
||||
throws IllegalStateException {
|
||||
|
||||
final Bundle args = requireArguments();
|
||||
final int requestCode = args.getInt(ARGS_KEY_REQUEST_CODE);
|
||||
final String[] permissions = args.getStringArray(ARGS_KEY_PERMISSIONS);
|
||||
try {
|
||||
mDialogListener.onMessageDialogResult(
|
||||
MessageDialogFragmentV4.this,
|
||||
requestCode, permissions, result);
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -24,199 +47,192 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CameraDialog extends DialogFragment {
|
||||
private static final String TAG = CameraDialog.class.getSimpleName();
|
||||
private static final String TAG = CameraDialog.class.getSimpleName();
|
||||
|
||||
public interface CameraDialogParent {
|
||||
public USBMonitor getUSBMonitor();
|
||||
public interface CameraDialogParent {
|
||||
public USBMonitor getUSBMonitor();
|
||||
public void onDialogResult(boolean canceled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method
|
||||
* @param parent FragmentActivity
|
||||
* @return
|
||||
*/
|
||||
public static CameraDialog showDialog(final Activity parent/* add parameters here if you need */) {
|
||||
CameraDialog dialog = newInstance(/* add parameters here if you need */);
|
||||
try {
|
||||
dialog.show(parent.getFragmentManager(), TAG);
|
||||
} catch (final IllegalStateException e) {
|
||||
dialog = null;
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public void onDialogResult(boolean canceled);
|
||||
}
|
||||
public static CameraDialog newInstance(/* add parameters here if you need */) {
|
||||
final CameraDialog dialog = new CameraDialog();
|
||||
final Bundle args = new Bundle();
|
||||
// add parameters here if you need
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method
|
||||
*
|
||||
* @param parent FragmentActivity
|
||||
* @return
|
||||
*/
|
||||
public static CameraDialog showDialog(final Activity parent/* add parameters here if you need */) {
|
||||
CameraDialog dialog = newInstance(/* add parameters here if you need */);
|
||||
protected USBMonitor mUSBMonitor;
|
||||
private Spinner mSpinner;
|
||||
private DeviceListAdapter mDeviceListAdapter;
|
||||
|
||||
public CameraDialog(/* no arguments */) {
|
||||
// Fragment need default constructor
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onAttach(final Activity activity) {
|
||||
super.onAttach(activity);
|
||||
if (mUSBMonitor == null)
|
||||
try {
|
||||
dialog.show(parent.getFragmentManager(), TAG);
|
||||
} catch (final IllegalStateException e) {
|
||||
dialog = null;
|
||||
mUSBMonitor = ((CameraDialogParent)activity).getUSBMonitor();
|
||||
} catch (final ClassCastException e) {
|
||||
} catch (final NullPointerException e) {
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
if (mUSBMonitor == null) {
|
||||
throw new ClassCastException(activity.toString() + " must implement CameraDialogParent#getUSBController");
|
||||
}
|
||||
}
|
||||
|
||||
public static CameraDialog newInstance(/* add parameters here if you need */) {
|
||||
final CameraDialog dialog = new CameraDialog();
|
||||
final Bundle args = new Bundle();
|
||||
// add parameters here if you need
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
protected USBMonitor mUSBMonitor;
|
||||
private Spinner mSpinner;
|
||||
private DeviceListAdapter mDeviceListAdapter;
|
||||
|
||||
public CameraDialog(/* no arguments */) {
|
||||
// Fragment need default constructor
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onAttach(final Activity activity) {
|
||||
super.onAttach(activity);
|
||||
if (mUSBMonitor == null) {
|
||||
try {
|
||||
mUSBMonitor = ((CameraDialogParent) activity).getUSBMonitor();
|
||||
} catch (final NullPointerException | ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (mUSBMonitor == null) {
|
||||
throw new ClassCastException(activity.toString() + " must implement CameraDialogParent#getUSBController");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState == null) {
|
||||
savedInstanceState = getArguments();
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState == null)
|
||||
savedInstanceState = getArguments();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle saveInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
saveInstanceState.putAll(args);
|
||||
}
|
||||
super.onSaveInstanceState(saveInstanceState);
|
||||
}
|
||||
@Override
|
||||
public void onSaveInstanceState(final Bundle saveInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
if (args != null)
|
||||
saveInstanceState.putAll(args);
|
||||
super.onSaveInstanceState(saveInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(initView());
|
||||
builder.setTitle(R.string.select);
|
||||
builder.setPositiveButton(android.R.string.ok, mOnDialogClickListener);
|
||||
builder.setNegativeButton(android.R.string.cancel, mOnDialogClickListener);
|
||||
builder.setNeutralButton(R.string.refresh, null);
|
||||
final Dialog dialog = builder.create();
|
||||
dialog.setCancelable(true);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setView(initView());
|
||||
builder.setTitle(R.string.select);
|
||||
builder.setPositiveButton(android.R.string.ok, mOnDialogClickListener);
|
||||
builder.setNegativeButton(android.R.string.cancel , mOnDialogClickListener);
|
||||
builder.setNeutralButton(R.string.refresh, null);
|
||||
final Dialog dialog = builder.create();
|
||||
dialog.setCancelable(true);
|
||||
dialog.setCanceledOnTouchOutside(true);
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create view that this fragment shows
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private final View initView() {
|
||||
final View rootView = getActivity().getLayoutInflater().inflate(R.layout.dialog_camera, null);
|
||||
mSpinner = (Spinner) rootView.findViewById(R.id.spinner1);
|
||||
final View empty = rootView.findViewById(android.R.id.empty);
|
||||
mSpinner.setEmptyView(empty);
|
||||
return rootView;
|
||||
}
|
||||
/**
|
||||
* create view that this fragment shows
|
||||
* @return
|
||||
*/
|
||||
private final View initView() {
|
||||
final View rootView = getActivity().getLayoutInflater().inflate(R.layout.dialog_camera, null);
|
||||
mSpinner = (Spinner)rootView.findViewById(R.id.spinner1);
|
||||
final View empty = rootView.findViewById(android.R.id.empty);
|
||||
mSpinner.setEmptyView(empty);
|
||||
return rootView;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateDevices();
|
||||
final Button button = (Button) getDialog().findViewById(android.R.id.button3);
|
||||
if (button != null) {
|
||||
button.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateDevices();
|
||||
final Button button = (Button)getDialog().findViewById(android.R.id.button3);
|
||||
if (button != null) {
|
||||
button.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
private final OnClickListener mOnClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
switch (v.getId()) {
|
||||
case android.R.id.button3:
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
private final OnClickListener mOnClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
switch (v.getId()) {
|
||||
case android.R.id.button3:
|
||||
updateDevices();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final DialogInterface.OnClickListener mOnDialogClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
final Object item = mSpinner.getSelectedItem();
|
||||
if (item instanceof UsbDevice) {
|
||||
mUSBMonitor.requestPermission((UsbDevice) item);
|
||||
((CameraDialogParent) getActivity()).onDialogResult(false);
|
||||
}
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
((CameraDialogParent) getActivity()).onDialogResult(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
private final DialogInterface.OnClickListener mOnDialogClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
final Object item = mSpinner.getSelectedItem();
|
||||
if (item instanceof UsbDevice) {
|
||||
mUSBMonitor.requestPermission((UsbDevice)item);
|
||||
((CameraDialogParent)getActivity()).onDialogResult(false);
|
||||
}
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
((CameraDialogParent)getActivity()).onDialogResult(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
((CameraDialogParent) getActivity()).onDialogResult(true);
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
((CameraDialogParent)getActivity()).onDialogResult(true);
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
|
||||
public void updateDevices() {
|
||||
public void updateDevices() {
|
||||
// mUSBMonitor.dumpDevices();
|
||||
final List<DeviceFilter> filter = DeviceFilter.getDeviceFilters(getActivity(), R.xml.device_filter);
|
||||
mDeviceListAdapter = new DeviceListAdapter(getActivity(), mUSBMonitor.getDeviceList(filter.get(0)));
|
||||
mSpinner.setAdapter(mDeviceListAdapter);
|
||||
}
|
||||
final List<DeviceFilter> filter = DeviceFilter.getDeviceFilters(getActivity(), R.xml.device_filter);
|
||||
mDeviceListAdapter = new DeviceListAdapter(getActivity(), mUSBMonitor.getDeviceList(filter.get(0)));
|
||||
mSpinner.setAdapter(mDeviceListAdapter);
|
||||
}
|
||||
|
||||
private static final class DeviceListAdapter extends BaseAdapter {
|
||||
private static final class DeviceListAdapter extends BaseAdapter {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
private final List<UsbDevice> mList;
|
||||
private final LayoutInflater mInflater;
|
||||
private final List<UsbDevice> mList;
|
||||
|
||||
public DeviceListAdapter(final Context context, final List<UsbDevice> list) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mList = list != null ? list : new ArrayList<UsbDevice>();
|
||||
}
|
||||
public DeviceListAdapter(final Context context, final List<UsbDevice>list) {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mList = list != null ? list : new ArrayList<UsbDevice>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mList.size();
|
||||
}
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsbDevice getItem(final int position) {
|
||||
if ((position >= 0) && (position < mList.size())) {
|
||||
return mList.get(position);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public UsbDevice getItem(final int position) {
|
||||
if ((position >= 0) && (position < mList.size()))
|
||||
return mList.get(position);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
@Override
|
||||
public long getItemId(final int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, View convertView, final ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.listitem_device, parent, false);
|
||||
}
|
||||
if (convertView instanceof CheckedTextView) {
|
||||
final UsbDevice device = getItem(position);
|
||||
((CheckedTextView) convertView).setText(
|
||||
String.format("UVC Camera:(%x:%x:%s)", device.getVendorId(), device.getProductId(), device.getDeviceName()));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public View getView(final int position, View convertView, final ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.listitem_device, parent, false);
|
||||
}
|
||||
if (convertView instanceof CheckedTextView) {
|
||||
final UsbDevice device = getItem(position);
|
||||
((CheckedTextView)convertView).setText(
|
||||
String.format("UVC Camera:(%x:%x:%s)", device.getVendorId(), device.getProductId(), device.getDeviceName()));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -97,20 +120,15 @@ public final class USBMonitor {
|
||||
}
|
||||
|
||||
public USBMonitor(final Context context, final OnDeviceConnectListener listener) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "USBMonitor:Constructor");
|
||||
}
|
||||
if (listener == null) {
|
||||
if (DEBUG) Log.v(TAG, "USBMonitor:Constructor");
|
||||
if (listener == null)
|
||||
throw new IllegalArgumentException("OnDeviceConnectListener should not null.");
|
||||
}
|
||||
mWeakContext = new WeakReference<Context>(context);
|
||||
mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
|
||||
mOnDeviceConnectListener = listener;
|
||||
mAsyncHandler = HandlerThreadHandler.createHandler(TAG);
|
||||
destroyed = false;
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "USBMonitor:mUsbManager=" + mUsbManager);
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "USBMonitor:mUsbManager=" + mUsbManager);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,9 +136,7 @@ public final class USBMonitor {
|
||||
* never reuse again
|
||||
*/
|
||||
public void destroy() {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "destroy:");
|
||||
}
|
||||
if (DEBUG) Log.i(TAG, "destroy:");
|
||||
unregister();
|
||||
if (!destroyed) {
|
||||
destroyed = true;
|
||||
@@ -153,13 +169,9 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public synchronized void register() throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
if (mPermissionIntent == null) {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "register:");
|
||||
}
|
||||
if (DEBUG) Log.i(TAG, "register:");
|
||||
final Context context = mWeakContext.get();
|
||||
if (context != null) {
|
||||
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
@@ -209,9 +221,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public void setDeviceFilter(final DeviceFilter filter) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.clear();
|
||||
mDeviceFilters.add(filter);
|
||||
}
|
||||
@@ -222,9 +232,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public void addDeviceFilter(final DeviceFilter filter) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.add(filter);
|
||||
}
|
||||
|
||||
@@ -234,9 +242,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public void removeDeviceFilter(final DeviceFilter filter) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.remove(filter);
|
||||
}
|
||||
|
||||
@@ -246,9 +252,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public void setDeviceFilter(final List<DeviceFilter> filters) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.clear();
|
||||
mDeviceFilters.addAll(filters);
|
||||
}
|
||||
@@ -259,9 +263,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public void addDeviceFilter(final List<DeviceFilter> filters) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.addAll(filters);
|
||||
}
|
||||
|
||||
@@ -270,9 +272,7 @@ public final class USBMonitor {
|
||||
* @param filters
|
||||
*/
|
||||
public void removeDeviceFilter(final List<DeviceFilter> filters) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
mDeviceFilters.removeAll(filters);
|
||||
}
|
||||
|
||||
@@ -282,9 +282,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public int getDeviceCount() throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
return getDeviceList().size();
|
||||
}
|
||||
|
||||
@@ -294,9 +292,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public List<UsbDevice> getDeviceList() throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
return getDeviceList(mDeviceFilters);
|
||||
}
|
||||
|
||||
@@ -307,9 +303,7 @@ public final class USBMonitor {
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
public List<UsbDevice> getDeviceList(final List<DeviceFilter> filters) throws IllegalStateException {
|
||||
if (destroyed) {
|
||||
throw new IllegalStateException("already destroyed");
|
||||
}
|
||||
if (destroyed) throw new IllegalStateException("already destroyed");
|
||||
// get detected devices
|
||||
final HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
|
||||
// store those devices info before matching filter xml file
|
||||
@@ -353,8 +347,8 @@ public final class USBMonitor {
|
||||
break;
|
||||
} else {
|
||||
// collection failed dev's class and subclass
|
||||
String devModel = android.os.Build.MODEL;
|
||||
String devSystemVersion = android.os.Build.VERSION.RELEASE;
|
||||
String devModel = Build.MODEL;
|
||||
String devSystemVersion = Build.VERSION.RELEASE;
|
||||
String devClass = String.valueOf(device.getDeviceClass());
|
||||
String subClass = String.valueOf(device.getDeviceSubclass());
|
||||
try{
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
|
||||
@@ -2,9 +2,7 @@ package com.serenegiant.usb.common;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
@@ -22,7 +20,6 @@ import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
import com.serenegiant.usb.IFrameCallback;
|
||||
import com.serenegiant.usb.ParentPreviewConstraintLayout;
|
||||
import com.serenegiant.usb.Size;
|
||||
import com.serenegiant.usb.USBMonitor;
|
||||
import com.serenegiant.usb.UVCCamera;
|
||||
@@ -52,7 +49,6 @@ import java.nio.ByteBuffer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
@@ -68,19 +64,19 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
|
||||
// 对外回调接口
|
||||
public interface CameraCallback {
|
||||
void onOpen();
|
||||
public void onOpen();
|
||||
|
||||
void onClose();
|
||||
public void onClose();
|
||||
|
||||
void onStartPreview();
|
||||
public void onStartPreview();
|
||||
|
||||
void onStopPreview();
|
||||
public void onStopPreview();
|
||||
|
||||
void onStartRecording();
|
||||
public void onStartRecording();
|
||||
|
||||
void onStopRecording();
|
||||
public void onStopRecording();
|
||||
|
||||
void onError(final Exception e);
|
||||
public void onError(final Exception e);
|
||||
}
|
||||
|
||||
public static OnEncodeResultListener mListener;
|
||||
@@ -180,16 +176,12 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "close:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "close:");
|
||||
if (isOpened()) {
|
||||
stopPreview();
|
||||
sendEmptyMessage(MSG_CLOSE);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "close:finished");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "close:finished");
|
||||
}
|
||||
|
||||
// 切换分辨率
|
||||
@@ -214,18 +206,14 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
|
||||
// 关闭Camera预览
|
||||
public void stopPreview() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "stopPreview:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "stopPreview:");
|
||||
removeMessages(MSG_PREVIEW_START);
|
||||
if (isRecording()) {
|
||||
stopRecording();
|
||||
}
|
||||
if (isPreviewing()) {
|
||||
final CameraThread thread = mWeakThread.get();
|
||||
if (thread == null) {
|
||||
return;
|
||||
}
|
||||
if (thread == null) return;
|
||||
synchronized (thread.mSync) {
|
||||
sendEmptyMessage(MSG_PREVIEW_STOP);
|
||||
if (!isCameraThread()) {
|
||||
@@ -239,12 +227,10 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "stopPreview:finished");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "stopPreview:finished");
|
||||
}
|
||||
|
||||
public void captureStill(final String path, AbstractUVCCameraHandler.OnCaptureListener listener) {
|
||||
public void captureStill(final String path, OnCaptureListener listener) {
|
||||
AbstractUVCCameraHandler.mCaptureListener = listener;
|
||||
checkReleased();
|
||||
sendMessage(obtainMessage(MSG_CAPTURE_STILL, path));
|
||||
@@ -366,9 +352,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(final Message msg) {
|
||||
final CameraThread thread = mWeakThread.get();
|
||||
if (thread == null) {
|
||||
return;
|
||||
}
|
||||
if (thread == null) return;
|
||||
switch (msg.what) {
|
||||
case MSG_OPEN:
|
||||
thread.handleOpen((USBMonitor.UsbControlBlock) msg.obj);
|
||||
@@ -472,17 +456,13 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public AbstractUVCCameraHandler getHandler() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "getHandler:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "getHandler:");
|
||||
synchronized (mSync) {
|
||||
if (mHandler == null) {
|
||||
if (mHandler == null)
|
||||
try {
|
||||
mSync.wait();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mHandler;
|
||||
}
|
||||
@@ -528,9 +508,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public void handleOpen(final USBMonitor.UsbControlBlock ctrlBlock) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleOpen:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleOpen:");
|
||||
handleClose();
|
||||
try {
|
||||
final UVCCamera camera = new UVCCamera();
|
||||
@@ -542,15 +520,12 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
} catch (final Exception e) {
|
||||
callOnError(e);
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "supportedSize:" + (mUVCCamera != null ? mUVCCamera.getSupportedSize() : null));
|
||||
}
|
||||
}
|
||||
|
||||
public void handleClose() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleClose:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleClose:");
|
||||
handleStopPusher();
|
||||
final UVCCamera camera;
|
||||
synchronized (mSync) {
|
||||
@@ -565,12 +540,8 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public void handleStartPreview(final Object surface) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleStartPreview:");
|
||||
}
|
||||
if ((mUVCCamera == null) || mIsPreviewing) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:");
|
||||
if ((mUVCCamera == null) || mIsPreviewing) return;
|
||||
try {
|
||||
mUVCCamera.setPreviewSize(mWidth, mHeight, 1, 31, mPreviewMode, mBandwidthFactor);
|
||||
// 获取USB Camera预览数据,使用NV21颜色会失真
|
||||
@@ -603,9 +574,7 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public void handleStopPreview() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleStopPreview:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:");
|
||||
if (mIsPreviewing) {
|
||||
if (mUVCCamera != null) {
|
||||
mUVCCamera.stopPreview();
|
||||
@@ -617,20 +586,14 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
callOnStopPreview();
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleStopPreview:finished");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleStopPreview:finished");
|
||||
}
|
||||
|
||||
// 捕获静态图片
|
||||
public void handleCaptureStill(final String path) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleCaptureStill:");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleCaptureStill:");
|
||||
final Activity parent = mWeakParent.get();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
if (parent == null) return;
|
||||
// mSoundPool.play(mSoundId, 0.2f, 0.2f, 0, 0, 1.0f); // play shutter sound
|
||||
try {
|
||||
final Bitmap bitmap = mWeakCameraView.get().captureStillImage(mWidth, mHeight);
|
||||
@@ -647,7 +610,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
os.flush();
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_MEDIA_UPDATE, outputFile.getPath()));
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
os.close();
|
||||
@@ -706,9 +668,8 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
private H264EncodeConsumer mH264Consumer;
|
||||
|
||||
public void handleStartPusher(RecordParams params) {
|
||||
if ((mUVCCamera == null) || (mH264Consumer != null)) {
|
||||
if ((mUVCCamera == null) || (mH264Consumer != null))
|
||||
return;
|
||||
}
|
||||
// // 获取USB Camera预览数据
|
||||
// mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21);
|
||||
|
||||
@@ -747,9 +708,8 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
// 停止音视频编码线程
|
||||
stopAudioRecord();
|
||||
stopVideoRecord();
|
||||
if(isSupportOverlay) {
|
||||
if(isSupportOverlay)
|
||||
TxtOverlay.getInstance().release();
|
||||
}
|
||||
// // 停止捕获视频数据
|
||||
// if (mUVCCamera != null) {
|
||||
// mUVCCamera.stopCapture();
|
||||
@@ -915,23 +875,18 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
public void handleUpdateMedia(final String path) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleUpdateMedia:path=" + path);
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleUpdateMedia:path=" + path);
|
||||
final Activity parent = mWeakParent.get();
|
||||
final boolean released = (mHandler == null) || mHandler.mReleased;
|
||||
if (parent != null && parent.getApplicationContext() != null) {
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.i(TAG, "MediaScannerConnection#scanFile");
|
||||
}
|
||||
if (DEBUG) Log.i(TAG, "MediaScannerConnection#scanFile");
|
||||
MediaScannerConnection.scanFile(parent.getApplicationContext(), new String[]{path}, null, null);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "handleUpdateMedia:", e);
|
||||
}
|
||||
if (released || parent.isDestroyed()) {
|
||||
if (released || parent.isDestroyed())
|
||||
handleRelease();
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "MainActivity already destroyed");
|
||||
// give up to add this movie to MediaStore now.
|
||||
@@ -941,71 +896,57 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
}
|
||||
|
||||
public void handleRelease() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleRelease:mIsRecording=" + mIsRecording);
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleRelease:mIsRecording=" + mIsRecording);
|
||||
handleClose();
|
||||
mCallbacks.clear();
|
||||
if (!mIsRecording) {
|
||||
mHandler.mReleased = true;
|
||||
Looper.myLooper().quit();
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleRelease:finished");
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleRelease:finished");
|
||||
}
|
||||
|
||||
// 自动对焦
|
||||
public void handleCameraFoucs() {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "handleStartPreview:");
|
||||
}
|
||||
if ((mUVCCamera == null) || !mIsPreviewing) {
|
||||
if (DEBUG) Log.v(TAG_THREAD, "handleStartPreview:");
|
||||
if ((mUVCCamera == null) || !mIsPreviewing)
|
||||
return;
|
||||
}
|
||||
mUVCCamera.setAutoFocus(true);
|
||||
}
|
||||
|
||||
// 获取支持的分辨率
|
||||
public List<Size> getSupportedSizes() {
|
||||
if ((mUVCCamera == null) || !mIsPreviewing) {
|
||||
if ((mUVCCamera == null) || !mIsPreviewing)
|
||||
return null;
|
||||
}
|
||||
return mUVCCamera.getSupportedSizeList();
|
||||
}
|
||||
|
||||
private final MediaEncoder.MediaEncoderListener mMediaEncoderListener = new MediaEncoder.MediaEncoderListener() {
|
||||
@Override
|
||||
public void onPrepared(final MediaEncoder encoder) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "onPrepared:encoder=" + encoder);
|
||||
}
|
||||
if (DEBUG) Log.v(TAG, "onPrepared:encoder=" + encoder);
|
||||
mIsRecording = true;
|
||||
if (encoder instanceof MediaVideoEncoder) {
|
||||
if (encoder instanceof MediaVideoEncoder)
|
||||
try {
|
||||
mWeakCameraView.get().setVideoEncoder((MediaVideoEncoder) encoder);
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "onPrepared:", e);
|
||||
}
|
||||
}
|
||||
if (encoder instanceof MediaSurfaceEncoder) {
|
||||
if (encoder instanceof MediaSurfaceEncoder)
|
||||
try {
|
||||
mWeakCameraView.get().setVideoEncoder((MediaSurfaceEncoder) encoder);
|
||||
mUVCCamera.startCapture(((MediaSurfaceEncoder) encoder).getInputSurface());
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "onPrepared:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void onStopped(final MediaEncoder encoder) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG_THREAD, "onStopped:encoder=" + encoder);
|
||||
}
|
||||
if (DEBUG) Log.v(TAG_THREAD, "onStopped:encoder=" + encoder);
|
||||
if ((encoder instanceof MediaVideoEncoder)
|
||||
|| (encoder instanceof MediaSurfaceEncoder)) {
|
||||
|| (encoder instanceof MediaSurfaceEncoder))
|
||||
try {
|
||||
mIsRecording = false;
|
||||
final Activity parent = mWeakParent.get();
|
||||
@@ -1027,7 +968,6 @@ public abstract class AbstractUVCCameraHandler extends Handler {
|
||||
} catch (final Exception e) {
|
||||
Log.e(TAG, "onPrepared:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
package com.serenegiant.usb.common;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.mogo.usbcamera.R;
|
||||
import com.serenegiant.dialog.MessageDialogFragmentV4;
|
||||
import com.serenegiant.utils.BuildCheck;
|
||||
import com.serenegiant.utils.HandlerThreadHandler;
|
||||
import com.serenegiant.utils.PermissionCheck;
|
||||
|
||||
/**
|
||||
* Created by saki on 2016/11/18.
|
||||
*
|
||||
*/
|
||||
public class BaseActivity extends AppCompatActivity
|
||||
implements MessageDialogFragmentV4.MessageDialogListener {
|
||||
|
||||
private static boolean DEBUG = false; // FIXME 実働時はfalseにセットすること
|
||||
private static final String TAG = BaseActivity.class.getSimpleName();
|
||||
|
||||
/** UI操作のためのHandler */
|
||||
private final Handler mUIHandler = new Handler(Looper.getMainLooper());
|
||||
private final Thread mUiThread = mUIHandler.getLooper().getThread();
|
||||
/** ワーカースレッド上で処理するためのHandler */
|
||||
private Handler mWorkerHandler;
|
||||
private long mWorkerThreadID = -1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// ワーカースレッドを生成
|
||||
if (mWorkerHandler == null) {
|
||||
mWorkerHandler = HandlerThreadHandler.createHandler(TAG);
|
||||
mWorkerThreadID = mWorkerHandler.getLooper().getThread().getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
clearToast();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void onDestroy() {
|
||||
// ワーカースレッドを破棄
|
||||
if (mWorkerHandler != null) {
|
||||
try {
|
||||
mWorkerHandler.getLooper().quit();
|
||||
} catch (final Exception e) {
|
||||
//
|
||||
}
|
||||
mWorkerHandler = null;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/**
|
||||
* UIスレッドでRunnableを実行するためのヘルパーメソッド
|
||||
* @param task
|
||||
* @param duration
|
||||
*/
|
||||
public final void runOnUiThread(final Runnable task, final long duration) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
mUIHandler.removeCallbacks(task);
|
||||
if ((duration > 0) || Thread.currentThread() != mUiThread) {
|
||||
mUIHandler.postDelayed(task, duration);
|
||||
} else {
|
||||
try {
|
||||
task.run();
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UIスレッド上で指定したRunnableが実行待ちしていれば実行待ちを解除する
|
||||
* @param task
|
||||
*/
|
||||
public final void removeFromUiThread(final Runnable task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
mUIHandler.removeCallbacks(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* ワーカースレッド上で指定したRunnableを実行する
|
||||
* 未実行の同じRunnableがあればキャンセルされる(後から指定した方のみ実行される)
|
||||
* @param task
|
||||
* @param delayMillis
|
||||
*/
|
||||
protected final synchronized void queueEvent(final Runnable task, final long delayMillis) {
|
||||
if ((task == null) || (mWorkerHandler == null)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
if (delayMillis > 0) {
|
||||
mWorkerHandler.postDelayed(task, delayMillis);
|
||||
} else if (mWorkerThreadID == Thread.currentThread().getId()) {
|
||||
task.run();
|
||||
} else {
|
||||
mWorkerHandler.post(task);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したRunnableをワーカースレッド上で実行予定であればキャンセルする
|
||||
* @param task
|
||||
*/
|
||||
protected final synchronized void removeEvent(final Runnable task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
private Toast mToast;
|
||||
/**
|
||||
* Toastでメッセージを表示
|
||||
* @param msg
|
||||
*/
|
||||
protected void showToast(@StringRes final int msg, final Object... args) {
|
||||
removeFromUiThread(mShowToastTask);
|
||||
mShowToastTask = new ShowToastTask(msg, args);
|
||||
runOnUiThread(mShowToastTask, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toastが表示されていればキャンセルする
|
||||
*/
|
||||
protected void clearToast() {
|
||||
removeFromUiThread(mShowToastTask);
|
||||
mShowToastTask = null;
|
||||
try {
|
||||
if (mToast != null) {
|
||||
mToast.cancel();
|
||||
mToast = null;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private ShowToastTask mShowToastTask;
|
||||
private final class ShowToastTask implements Runnable {
|
||||
final int msg;
|
||||
final Object args;
|
||||
private ShowToastTask(@StringRes final int msg, final Object... args) {
|
||||
this.msg = msg;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (mToast != null) {
|
||||
mToast.cancel();
|
||||
mToast = null;
|
||||
}
|
||||
final String _msg = (args != null) ? getString(msg, args) : getString(msg);
|
||||
mToast = Toast.makeText(BaseActivity.this, _msg, Toast.LENGTH_SHORT);
|
||||
mToast.show();
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/**
|
||||
* MessageDialogFragmentメッセージダイアログからのコールバックリスナー
|
||||
* @param dialog
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param result
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void onMessageDialogResult(final MessageDialogFragmentV4 dialog, final int requestCode, final String[] permissions, final boolean result) {
|
||||
if (result) {
|
||||
// メッセージダイアログでOKを押された時はパーミッション要求する
|
||||
if (BuildCheck.isMarshmallow()) {
|
||||
requestPermissions(permissions, requestCode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// メッセージダイアログでキャンセルされた時とAndroid6でない時は自前でチェックして#checkPermissionResultを呼び出す
|
||||
for (final String permission: permissions) {
|
||||
checkPermissionResult(requestCode, permission, PermissionCheck.hasPermission(this, permission));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パーミッション要求結果を受け取るためのメソッド
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
@Override
|
||||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults); // 何もしてないけど一応呼んどく
|
||||
final int n = Math.min(permissions.length, grantResults.length);
|
||||
for (int i = 0; i < n; i++) {
|
||||
checkPermissionResult(requestCode, permissions[i], grantResults[i] == PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パーミッション要求の結果をチェック
|
||||
* ここではパーミッションを取得できなかった時にToastでメッセージ表示するだけ
|
||||
* @param requestCode
|
||||
* @param permission
|
||||
* @param result
|
||||
*/
|
||||
protected void checkPermissionResult(final int requestCode, final String permission, final boolean result) {
|
||||
// パーミッションがないときにはメッセージを表示する
|
||||
if (!result && (permission != null)) {
|
||||
if (Manifest.permission.RECORD_AUDIO.equals(permission)) {
|
||||
showToast(R.string.permission_audio);
|
||||
}
|
||||
if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)) {
|
||||
showToast(R.string.permission_ext_storage);
|
||||
}
|
||||
if (Manifest.permission.INTERNET.equals(permission)) {
|
||||
showToast(R.string.permission_network);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 動的パーミッション要求時の要求コード
|
||||
protected static final int REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE = 0x12345;
|
||||
protected static final int REQUEST_PERMISSION_AUDIO_RECORDING = 0x234567;
|
||||
protected static final int REQUEST_PERMISSION_NETWORK = 0x345678;
|
||||
protected static final int REQUEST_PERMISSION_CAMERA = 0x537642;
|
||||
|
||||
/**
|
||||
* 外部ストレージへの書き込みパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
* @return true 外部ストレージへの書き込みパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionWriteExternalStorage() {
|
||||
if (!PermissionCheck.hasWriteExternalStorage(this)) {
|
||||
MessageDialogFragmentV4.showDialog(this, REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE,
|
||||
R.string.permission_title, R.string.permission_ext_storage_request,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 録音のパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
* @return true 録音のパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionAudio() {
|
||||
if (!PermissionCheck.hasAudio(this)) {
|
||||
MessageDialogFragmentV4.showDialog(this, REQUEST_PERMISSION_AUDIO_RECORDING,
|
||||
R.string.permission_title, R.string.permission_audio_recording_request,
|
||||
new String[]{Manifest.permission.RECORD_AUDIO});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ネットワークアクセスのパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
* @return true ネットワークアクセスのパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionNetwork() {
|
||||
if (!PermissionCheck.hasNetwork(this)) {
|
||||
MessageDialogFragmentV4.showDialog(this, REQUEST_PERMISSION_NETWORK,
|
||||
R.string.permission_title, R.string.permission_network_request,
|
||||
new String[]{Manifest.permission.INTERNET});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* カメラアクセスのパーミッションがあるかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
* @return true カメラアクセスのパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionCamera() {
|
||||
if (!PermissionCheck.hasCamera(this)) {
|
||||
MessageDialogFragmentV4.showDialog(this, REQUEST_PERMISSION_CAMERA,
|
||||
R.string.permission_title, R.string.permission_camera_request,
|
||||
new String[]{Manifest.permission.CAMERA});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
package com.serenegiant.usb.common;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Fragment;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.mogo.usbcamera.R;
|
||||
import com.serenegiant.dialog.MessageDialogFragment;
|
||||
import com.serenegiant.utils.BuildCheck;
|
||||
import com.serenegiant.utils.HandlerThreadHandler;
|
||||
import com.serenegiant.utils.PermissionCheck;
|
||||
|
||||
/**
|
||||
* Created by saki on 2016/11/19.
|
||||
*/
|
||||
public class BaseFragment extends Fragment
|
||||
implements MessageDialogFragment.MessageDialogListener {
|
||||
|
||||
private static boolean DEBUG = false; // FIXME 実働時はfalseにセットすること
|
||||
private static final String TAG = BaseFragment.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* UI操作のためのHandler
|
||||
*/
|
||||
private final Handler mUIHandler = new Handler(Looper.getMainLooper());
|
||||
private final Thread mUiThread = mUIHandler.getLooper().getThread();
|
||||
/**
|
||||
* ワーカースレッド上で処理するためのHandler
|
||||
*/
|
||||
private Handler mWorkerHandler;
|
||||
private long mWorkerThreadID = -1;
|
||||
|
||||
public BaseFragment() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// ワーカースレッドを生成
|
||||
if (mWorkerHandler == null) {
|
||||
mWorkerHandler = HandlerThreadHandler.createHandler(TAG);
|
||||
mWorkerThreadID = mWorkerHandler.getLooper().getThread().getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
clearToast();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDestroy() {
|
||||
// ワーカースレッドを破棄
|
||||
if (mWorkerHandler != null) {
|
||||
try {
|
||||
mWorkerHandler.getLooper().quit();
|
||||
} catch (final Exception e) {
|
||||
//
|
||||
}
|
||||
mWorkerHandler = null;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
|
||||
/**
|
||||
* UIスレッドでRunnableを実行するためのヘルパーメソッド
|
||||
*
|
||||
* @param task
|
||||
* @param duration
|
||||
*/
|
||||
public final void runOnUiThread(final Runnable task, final long duration) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
mUIHandler.removeCallbacks(task);
|
||||
if ((duration > 0) || Thread.currentThread() != mUiThread) {
|
||||
mUIHandler.postDelayed(task, duration);
|
||||
} else {
|
||||
try {
|
||||
task.run();
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UIスレッド上で指定したRunnableが実行待ちしていれば実行待ちを解除する
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
public final void removeFromUiThread(final Runnable task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
mUIHandler.removeCallbacks(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* ワーカースレッド上で指定したRunnableを実行する
|
||||
* 未実行の同じRunnableがあればキャンセルされる(後から指定した方のみ実行される)
|
||||
*
|
||||
* @param task
|
||||
* @param delayMillis
|
||||
*/
|
||||
protected final synchronized void queueEvent(final Runnable task, final long delayMillis) {
|
||||
if ((task == null) || (mWorkerHandler == null)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
if (delayMillis > 0) {
|
||||
mWorkerHandler.postDelayed(task, delayMillis);
|
||||
} else if (mWorkerThreadID == Thread.currentThread().getId()) {
|
||||
task.run();
|
||||
} else {
|
||||
mWorkerHandler.post(task);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したRunnableをワーカースレッド上で実行予定であればキャンセルする
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
protected final synchronized void removeEvent(final Runnable task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
private Toast mToast;
|
||||
|
||||
/**
|
||||
* Toastでメッセージを表示
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
protected void showToast(@StringRes final int msg, final Object... args) {
|
||||
removeFromUiThread(mShowToastTask);
|
||||
mShowToastTask = new ShowToastTask(msg, args);
|
||||
runOnUiThread(mShowToastTask, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toastが表示されていればキャンセルする
|
||||
*/
|
||||
protected void clearToast() {
|
||||
removeFromUiThread(mShowToastTask);
|
||||
mShowToastTask = null;
|
||||
try {
|
||||
if (mToast != null) {
|
||||
mToast.cancel();
|
||||
mToast = null;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private ShowToastTask mShowToastTask;
|
||||
|
||||
private final class ShowToastTask implements Runnable {
|
||||
final int msg;
|
||||
final Object args;
|
||||
|
||||
private ShowToastTask(@StringRes final int msg, final Object... args) {
|
||||
this.msg = msg;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (mToast != null) {
|
||||
mToast.cancel();
|
||||
mToast = null;
|
||||
}
|
||||
if (args != null) {
|
||||
final String _msg = getString(msg, args);
|
||||
mToast = Toast.makeText(getActivity(), _msg, Toast.LENGTH_SHORT);
|
||||
} else {
|
||||
mToast = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT);
|
||||
}
|
||||
mToast.show();
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
|
||||
/**
|
||||
* MessageDialogFragmentメッセージダイアログからのコールバックリスナー
|
||||
*
|
||||
* @param dialog
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param result
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void onMessageDialogResult(final MessageDialogFragment dialog, final int requestCode, final String[] permissions, final boolean result) {
|
||||
if (result) {
|
||||
// メッセージダイアログでOKを押された時はパーミッション要求する
|
||||
if (BuildCheck.isMarshmallow()) {
|
||||
requestPermissions(permissions, requestCode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// メッセージダイアログでキャンセルされた時とAndroid6でない時は自前でチェックして#checkPermissionResultを呼び出す
|
||||
for (final String permission : permissions) {
|
||||
checkPermissionResult(requestCode, permission, PermissionCheck.hasPermission(getActivity(), permission));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パーミッション要求結果を受け取るためのメソッド
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
@Override
|
||||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults); // 何もしてないけど一応呼んどく
|
||||
final int n = Math.min(permissions.length, grantResults.length);
|
||||
for (int i = 0; i < n; i++) {
|
||||
checkPermissionResult(requestCode, permissions[i], grantResults[i] == PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パーミッション要求の結果をチェック
|
||||
* ここではパーミッションを取得できなかった時にToastでメッセージ表示するだけ
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permission
|
||||
* @param result
|
||||
*/
|
||||
protected void checkPermissionResult(final int requestCode, final String permission, final boolean result) {
|
||||
// パーミッションがないときにはメッセージを表示する
|
||||
if (!result && (permission != null)) {
|
||||
if (Manifest.permission.RECORD_AUDIO.equals(permission)) {
|
||||
showToast(R.string.permission_audio);
|
||||
}
|
||||
if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)) {
|
||||
showToast(R.string.permission_ext_storage);
|
||||
}
|
||||
if (Manifest.permission.INTERNET.equals(permission)) {
|
||||
showToast(R.string.permission_network);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 動的パーミッション要求時の要求コード
|
||||
protected static final int REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE = 0x12345;
|
||||
protected static final int REQUEST_PERMISSION_AUDIO_RECORDING = 0x234567;
|
||||
protected static final int REQUEST_PERMISSION_NETWORK = 0x345678;
|
||||
protected static final int REQUEST_PERMISSION_CAMERA = 0x537642;
|
||||
|
||||
/**
|
||||
* 外部ストレージへの書き込みパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
*
|
||||
* @return true 外部ストレージへの書き込みパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionWriteExternalStorage() {
|
||||
if (!PermissionCheck.hasWriteExternalStorage(getActivity())) {
|
||||
MessageDialogFragment.showDialog(this, REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE,
|
||||
R.string.permission_title, R.string.permission_ext_storage_request,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 録音のパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
*
|
||||
* @return true 録音のパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionAudio() {
|
||||
if (!PermissionCheck.hasAudio(getActivity())) {
|
||||
MessageDialogFragment.showDialog(this, REQUEST_PERMISSION_AUDIO_RECORDING,
|
||||
R.string.permission_title, R.string.permission_audio_recording_request,
|
||||
new String[]{Manifest.permission.RECORD_AUDIO});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ネットワークアクセスのパーミッションが有るかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
*
|
||||
* @return true ネットワークアクセスのパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionNetwork() {
|
||||
if (!PermissionCheck.hasNetwork(getActivity())) {
|
||||
MessageDialogFragment.showDialog(this, REQUEST_PERMISSION_NETWORK,
|
||||
R.string.permission_title, R.string.permission_network_request,
|
||||
new String[]{Manifest.permission.INTERNET});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* カメラアクセスのパーミッションがあるかどうかをチェック
|
||||
* なければ説明ダイアログを表示する
|
||||
*
|
||||
* @return true カメラアクセスのパーミッションが有る
|
||||
*/
|
||||
protected boolean checkPermissionCamera() {
|
||||
if (!PermissionCheck.hasCamera(getActivity())) {
|
||||
MessageDialogFragment.showDialog(this, REQUEST_PERMISSION_CAMERA,
|
||||
R.string.permission_title, R.string.permission_camera_request,
|
||||
new String[]{Manifest.permission.CAMERA});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.serenegiant.usb.common;
|
||||
|
||||
import android.app.Service;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.serenegiant.utils.HandlerThreadHandler;
|
||||
|
||||
public abstract class BaseService extends Service {
|
||||
private static boolean DEBUG = false; // FIXME 実働時はfalseにセットすること
|
||||
private static final String TAG = BaseService.class.getSimpleName();
|
||||
|
||||
/** UI操作のためのHandler */
|
||||
private final Handler mUIHandler = new Handler(Looper.getMainLooper());
|
||||
private final Thread mUiThread = mUIHandler.getLooper().getThread();
|
||||
/** ワーカースレッド上で処理するためのHandler */
|
||||
private Handler mWorkerHandler;
|
||||
private long mWorkerThreadID = -1;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// ワーカースレッドを生成
|
||||
if (mWorkerHandler == null) {
|
||||
mWorkerHandler = HandlerThreadHandler.createHandler(TAG);
|
||||
mWorkerThreadID = mWorkerHandler.getLooper().getThread().getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDestroy() {
|
||||
// ワーカースレッドを破棄
|
||||
if (mWorkerHandler != null) {
|
||||
try {
|
||||
mWorkerHandler.getLooper().quit();
|
||||
} catch (final Exception e) {
|
||||
//
|
||||
}
|
||||
mWorkerHandler = null;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/**
|
||||
* UIスレッドでRunnableを実行するためのヘルパーメソッド
|
||||
* @param task
|
||||
* @param duration
|
||||
*/
|
||||
public final void runOnUiThread(final Runnable task, final long duration) {
|
||||
if (task == null) return;
|
||||
mUIHandler.removeCallbacks(task);
|
||||
if ((duration > 0) || Thread.currentThread() != mUiThread) {
|
||||
mUIHandler.postDelayed(task, duration);
|
||||
} else {
|
||||
try {
|
||||
task.run();
|
||||
} catch (final Exception e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UIスレッド上で指定したRunnableが実行待ちしていれば実行待ちを解除する
|
||||
* @param task
|
||||
*/
|
||||
public final void removeFromUiThread(final Runnable task) {
|
||||
if (task == null) return;
|
||||
mUIHandler.removeCallbacks(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* ワーカースレッド上で指定したRunnableを実行する
|
||||
* 未実行の同じRunnableがあればキャンセルされる(後から指定した方のみ実行される)
|
||||
* @param task
|
||||
* @param delayMillis
|
||||
*/
|
||||
protected final synchronized void queueEvent(final Runnable task, final long delayMillis) {
|
||||
if ((task == null) || (mWorkerHandler == null)) return;
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
if (delayMillis > 0) {
|
||||
mWorkerHandler.postDelayed(task, delayMillis);
|
||||
} else if (mWorkerThreadID == Thread.currentThread().getId()) {
|
||||
task.run();
|
||||
} else {
|
||||
mWorkerHandler.post(task);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したRunnableをワーカースレッド上で実行予定であればキャンセルする
|
||||
* @param task
|
||||
*/
|
||||
protected final synchronized void removeEvent(final Runnable task) {
|
||||
if (task == null) return;
|
||||
try {
|
||||
mWorkerHandler.removeCallbacks(task);
|
||||
} catch (final Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,30 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.common;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.serenegiant.usb.ParentPreviewConstraintLayout;
|
||||
import com.serenegiant.usb.UVCCamera;
|
||||
import com.serenegiant.usb.widget.CameraViewInterface;
|
||||
|
||||
|
||||
@@ -1,10 +1,32 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.common;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.serenegiant.glutils.RendererHolder;
|
||||
import com.serenegiant.usb.ParentPreviewConstraintLayout;
|
||||
import com.serenegiant.usb.UVCCamera;
|
||||
import com.serenegiant.usb.widget.CameraViewInterface;
|
||||
|
||||
@@ -101,7 +123,6 @@ public class UVCCameraHandlerMultiSurface extends AbstractUVCCameraHandler {
|
||||
mRendererHolder = new RendererHolder(thread.getWidth(), thread.getHeight(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void release() {
|
||||
if (mRendererHolder != null) {
|
||||
mRendererHolder.release();
|
||||
@@ -110,8 +131,7 @@ public class UVCCameraHandlerMultiSurface extends AbstractUVCCameraHandler {
|
||||
super.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void resize(final int width, final int height) {
|
||||
public synchronized void resize(final int width, final int height) {
|
||||
super.resize(width, height);
|
||||
if (mRendererHolder != null) {
|
||||
mRendererHolder.resize(width, height);
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
public interface IAudioEncoder {
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
public interface IVideoEncoder {
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
import android.media.AudioFormat;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* UVCCamera
|
||||
* library and sample to access to UVC web camera on non-rooted Android device
|
||||
*
|
||||
* Copyright (c) 2014-2017 saki t_saki@serenegiant.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All files in the folder are under this Apache License, Version 2.0.
|
||||
* Files in the libjpeg-turbo, libusb, libuvc, rapidjson folder
|
||||
* may have a different license, see the respective files.
|
||||
*/
|
||||
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.serenegiant.usb.encoder;
|
||||
|
||||
/**
|
||||
* 录制参数
|
||||
/** 录制参数
|
||||
*
|
||||
* Created by jiangdongguo on 2017/10/19.
|
||||
*/
|
||||
|
||||
public class RecordParams {
|
||||
private String recordPath;
|
||||
private int recordDuration;
|
||||
|
||||
@@ -19,10 +19,12 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
/**
|
||||
* 将PCM编码为AAC
|
||||
/**将PCM编码为AAC
|
||||
*
|
||||
* Created by jianddongguo on 2017/7/21.
|
||||
*/
|
||||
public class AACEncodeConsumer extends Thread {
|
||||
|
||||
public class AACEncodeConsumer extends Thread{
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "TMPU";
|
||||
private static final String MIME_TYPE = "audio/mp4a-latm";
|
||||
@@ -38,7 +40,7 @@ public class AACEncodeConsumer extends Thread {
|
||||
private AudioRecord mAudioRecord; // 音频采集
|
||||
private MediaCodec mAudioEncoder; // 音频编码
|
||||
private OnAACEncodeResultListener listener;
|
||||
private int mSamplingRateIndex = 0;//ADTS
|
||||
private int mSamplingRateIndex = 0;//ADTS
|
||||
private boolean isEncoderStart = false;
|
||||
private boolean isRecMp3 = false;
|
||||
private boolean isExit = false;
|
||||
@@ -46,7 +48,7 @@ public class AACEncodeConsumer extends Thread {
|
||||
private WeakReference<Mp4MediaMuxer> mMuxerRef;
|
||||
private MediaFormat newFormat;
|
||||
|
||||
private static final int[] AUDIO_SOURCES = new int[]{
|
||||
private static final int[] AUDIO_SOURCES = new int[] {
|
||||
MediaRecorder.AudioSource.DEFAULT,
|
||||
MediaRecorder.AudioSource.MIC,
|
||||
MediaRecorder.AudioSource.CAMCORDER,
|
||||
@@ -54,7 +56,7 @@ public class AACEncodeConsumer extends Thread {
|
||||
/**
|
||||
* There are 13 supported frequencies by ADTS.
|
||||
**/
|
||||
public static final int[] AUDIO_SAMPLING_RATES = {96000, // 0
|
||||
public static final int[] AUDIO_SAMPLING_RATES = { 96000, // 0
|
||||
88200, // 1
|
||||
64000, // 2
|
||||
48000, // 3
|
||||
@@ -75,13 +77,13 @@ public class AACEncodeConsumer extends Thread {
|
||||
private FileOutputStream fops;
|
||||
|
||||
// 编码流结果回调接口
|
||||
public interface OnAACEncodeResultListener {
|
||||
public interface OnAACEncodeResultListener{
|
||||
void onEncodeResult(byte[] data, int offset,
|
||||
int length, long timestamp);
|
||||
}
|
||||
|
||||
public AACEncodeConsumer() {
|
||||
for (int i = 0; i < AUDIO_SAMPLING_RATES.length; i++) {
|
||||
public AACEncodeConsumer(){
|
||||
for (int i=0;i < AUDIO_SAMPLING_RATES.length; i++) {
|
||||
if (AUDIO_SAMPLING_RATES[i] == SAMPLE_RATE) {
|
||||
mSamplingRateIndex = i;
|
||||
break;
|
||||
@@ -89,16 +91,16 @@ public class AACEncodeConsumer extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnAACEncodeResultListener(OnAACEncodeResultListener listener) {
|
||||
public void setOnAACEncodeResultListener(OnAACEncodeResultListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
public void exit(){
|
||||
isExit = true;
|
||||
}
|
||||
|
||||
public synchronized void setTmpuMuxer(Mp4MediaMuxer mMuxer) {
|
||||
this.mMuxerRef = new WeakReference<>(mMuxer);
|
||||
public synchronized void setTmpuMuxer(Mp4MediaMuxer mMuxer){
|
||||
this.mMuxerRef = new WeakReference<>(mMuxer);
|
||||
Mp4MediaMuxer muxer = mMuxerRef.get();
|
||||
if (muxer != null && newFormat != null) {
|
||||
muxer.addTrack(newFormat, false);
|
||||
@@ -108,7 +110,7 @@ public class AACEncodeConsumer extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
// 开启音频采集、编码
|
||||
if (!isEncoderStart) {
|
||||
if(! isEncoderStart){
|
||||
initAudioRecord();
|
||||
initMediaCodec();
|
||||
}
|
||||
@@ -116,16 +118,16 @@ public class AACEncodeConsumer extends Thread {
|
||||
byte[] mp3Buffer = new byte[1024];
|
||||
|
||||
// 这里有问题,当本地录制结束后,没有写入
|
||||
while (!isExit) {
|
||||
while(! isExit){
|
||||
byte[] audioBuffer = new byte[2048];
|
||||
// 采集音频
|
||||
int readBytes = mAudioRecord.read(audioBuffer, 0, BUFFER_SIZE);
|
||||
int readBytes = mAudioRecord.read(audioBuffer,0,BUFFER_SIZE);
|
||||
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "采集音频readBytes = " + readBytes);
|
||||
if(DEBUG)
|
||||
Log.i(TAG,"采集音频readBytes = "+readBytes);
|
||||
// 编码音频
|
||||
if (readBytes > 0) {
|
||||
encodeBytes(audioBuffer, readBytes);
|
||||
if(readBytes > 0){
|
||||
encodeBytes(audioBuffer,readBytes);
|
||||
}
|
||||
}
|
||||
// 停止音频采集、编码
|
||||
@@ -140,81 +142,81 @@ public class AACEncodeConsumer extends Thread {
|
||||
ByteBuffer[] outputBuffers = mAudioEncoder.getOutputBuffers();
|
||||
//返回编码器的一个输入缓存区句柄,-1表示当前没有可用的输入缓存区
|
||||
int inputBufferIndex = mAudioEncoder.dequeueInputBuffer(TIMES_OUT);
|
||||
if (inputBufferIndex >= 0) {
|
||||
if(inputBufferIndex >= 0){
|
||||
// 绑定一个被空的、可写的输入缓存区inputBuffer到客户端
|
||||
ByteBuffer inputBuffer = null;
|
||||
if (!isLollipop()) {
|
||||
ByteBuffer inputBuffer = null;
|
||||
if(!isLollipop()){
|
||||
inputBuffer = inputBuffers[inputBufferIndex];
|
||||
} else {
|
||||
}else{
|
||||
inputBuffer = mAudioEncoder.getInputBuffer(inputBufferIndex);
|
||||
}
|
||||
// 向输入缓存区写入有效原始数据,并提交到编码器中进行编码处理
|
||||
if (audioBuf == null || readBytes <= 0) {
|
||||
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, 0, getPTSUs(), MediaCodec.BUFFER_FLAG_END_OF_STREAM);
|
||||
} else {
|
||||
if(audioBuf==null || readBytes<=0){
|
||||
mAudioEncoder.queueInputBuffer(inputBufferIndex,0,0,getPTSUs(),MediaCodec.BUFFER_FLAG_END_OF_STREAM);
|
||||
}else{
|
||||
inputBuffer.clear();
|
||||
inputBuffer.put(audioBuf);
|
||||
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, readBytes, getPTSUs(), 0);
|
||||
mAudioEncoder.queueInputBuffer(inputBufferIndex,0,readBytes,getPTSUs(),0);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回一个输出缓存区句柄,当为-1时表示当前没有可用的输出缓存区
|
||||
// mBufferInfo参数包含被编码好的数据,timesOut参数为超时等待的时间
|
||||
MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
|
||||
MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
|
||||
int outputBufferIndex = -1;
|
||||
do {
|
||||
outputBufferIndex = mAudioEncoder.dequeueOutputBuffer(mBufferInfo, TIMES_OUT);
|
||||
if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "获得编码器输出缓存区超时");
|
||||
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
|
||||
do{
|
||||
outputBufferIndex = mAudioEncoder.dequeueOutputBuffer(mBufferInfo,TIMES_OUT);
|
||||
if(outputBufferIndex == MediaCodec. INFO_TRY_AGAIN_LATER){
|
||||
if(DEBUG)
|
||||
Log.i(TAG,"获得编码器输出缓存区超时");
|
||||
}else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED){
|
||||
// 如果API小于21,APP需要重新绑定编码器的输入缓存区;
|
||||
// 如果API大于21,则无需处理INFO_OUTPUT_BUFFERS_CHANGED
|
||||
if (!isLollipop()) {
|
||||
if(!isLollipop()){
|
||||
outputBuffers = mAudioEncoder.getOutputBuffers();
|
||||
}
|
||||
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||
}else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
|
||||
// 编码器输出缓存区格式改变,通常在存储数据之前且只会改变一次
|
||||
// 这里设置混合器视频轨道,如果音频已经添加则启动混合器(保证音视频同步)
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "编码器输出缓存区格式改变,添加视频轨道到混合器");
|
||||
if(DEBUG)
|
||||
Log.i(TAG,"编码器输出缓存区格式改变,添加视频轨道到混合器");
|
||||
synchronized (AACEncodeConsumer.this) {
|
||||
newFormat = mAudioEncoder.getOutputFormat();
|
||||
if (mMuxerRef != null) {
|
||||
if(mMuxerRef != null){
|
||||
Mp4MediaMuxer muxer = mMuxerRef.get();
|
||||
if (muxer != null) {
|
||||
muxer.addTrack(newFormat, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}else{
|
||||
// 当flag属性置为BUFFER_FLAG_CODEC_CONFIG后,说明输出缓存区的数据已经被消费了
|
||||
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "编码数据被消费,BufferInfo的size属性置0");
|
||||
if((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0){
|
||||
if(DEBUG)
|
||||
Log.i(TAG,"编码数据被消费,BufferInfo的size属性置0");
|
||||
mBufferInfo.size = 0;
|
||||
}
|
||||
// 数据流结束标志,结束本次循环
|
||||
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
|
||||
if (DEBUG)
|
||||
Log.i(TAG, "数据流结束,退出循环");
|
||||
if((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
|
||||
if(DEBUG)
|
||||
Log.i(TAG,"数据流结束,退出循环");
|
||||
break;
|
||||
}
|
||||
// 获取一个只读的输出缓存区inputBuffer ,它包含被编码好的数据
|
||||
ByteBuffer mBuffer = ByteBuffer.allocate(10240);
|
||||
ByteBuffer outputBuffer = null;
|
||||
if (!isLollipop()) {
|
||||
outputBuffer = outputBuffers[outputBufferIndex];
|
||||
} else {
|
||||
outputBuffer = mAudioEncoder.getOutputBuffer(outputBufferIndex);
|
||||
if(!isLollipop()){
|
||||
outputBuffer = outputBuffers[outputBufferIndex];
|
||||
}else{
|
||||
outputBuffer = mAudioEncoder.getOutputBuffer(outputBufferIndex);
|
||||
}
|
||||
if (mBufferInfo.size != 0) {
|
||||
if(mBufferInfo.size != 0){
|
||||
// 获取输出缓存区失败,抛出异常
|
||||
if (outputBuffer == null) {
|
||||
throw new RuntimeException("encodecOutputBuffer" + outputBufferIndex + "was null");
|
||||
if(outputBuffer == null){
|
||||
throw new RuntimeException("encodecOutputBuffer"+outputBufferIndex+"was null");
|
||||
}
|
||||
// 添加视频流到混合器
|
||||
if (mMuxerRef != null) {
|
||||
if(mMuxerRef != null){
|
||||
Mp4MediaMuxer muxer = mMuxerRef.get();
|
||||
if (muxer != null) {
|
||||
muxer.pumpStream(outputBuffer, mBufferInfo, false);
|
||||
@@ -228,25 +230,25 @@ public class AACEncodeConsumer extends Thread {
|
||||
addADTStoPacket(mBuffer.array(), mBufferInfo.size + 7);
|
||||
mBuffer.flip();
|
||||
// 将AAC回调给MainModelImpl进行push
|
||||
if (listener != null) {
|
||||
Log.i(TAG, "----->得到aac数据流<-----");
|
||||
listener.onEncodeResult(mBuffer.array(), 0, mBufferInfo.size + 7, mBufferInfo.presentationTimeUs / 1000);
|
||||
if(listener != null){
|
||||
Log.i(TAG,"----->得到aac数据流<-----");
|
||||
listener.onEncodeResult(mBuffer.array(),0, mBufferInfo.size + 7, mBufferInfo.presentationTimeUs / 1000);
|
||||
}
|
||||
}
|
||||
// 处理结束,释放输出缓存区资源
|
||||
mAudioEncoder.releaseOutputBuffer(outputBufferIndex, false);
|
||||
mAudioEncoder.releaseOutputBuffer(outputBufferIndex,false);
|
||||
}
|
||||
} while (outputBufferIndex >= 0);
|
||||
}while (outputBufferIndex >= 0);
|
||||
}
|
||||
|
||||
private void initAudioRecord() {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "AACEncodeConsumer-->开始采集音频");
|
||||
private void initAudioRecord(){
|
||||
if(DEBUG)
|
||||
Log.d(TAG,"AACEncodeConsumer-->开始采集音频");
|
||||
// 设置进程优先级
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
|
||||
int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
|
||||
AudioFormat.ENCODING_PCM_16BIT);
|
||||
for (final int src : AUDIO_SOURCES) {
|
||||
for (final int src: AUDIO_SOURCES) {
|
||||
try {
|
||||
mAudioRecord = new AudioRecord(src,
|
||||
SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
|
||||
@@ -266,18 +268,18 @@ public class AACEncodeConsumer extends Thread {
|
||||
mAudioRecord.startRecording();
|
||||
}
|
||||
|
||||
private void initMediaCodec() {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "AACEncodeConsumer-->开始编码音频");
|
||||
private void initMediaCodec(){
|
||||
if(DEBUG)
|
||||
Log.d(TAG,"AACEncodeConsumer-->开始编码音频");
|
||||
MediaCodecInfo mCodecInfo = selectSupportCodec(MIME_TYPE);
|
||||
if (mCodecInfo == null) {
|
||||
Log.e(TAG, "编码器不支持" + MIME_TYPE + "类型");
|
||||
if(mCodecInfo == null){
|
||||
Log.e(TAG,"编码器不支持"+MIME_TYPE+"类型");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
try{
|
||||
mAudioEncoder = MediaCodec.createByCodecName(mCodecInfo.getName());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "创建编码器失败" + e.getMessage());
|
||||
}catch(IOException e){
|
||||
Log.e(TAG,"创建编码器失败"+e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
MediaFormat format = new MediaFormat();
|
||||
@@ -293,9 +295,9 @@ public class AACEncodeConsumer extends Thread {
|
||||
}
|
||||
|
||||
private void stopAudioRecord() {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "AACEncodeConsumer-->停止采集音频");
|
||||
if (mAudioRecord != null) {
|
||||
if(DEBUG)
|
||||
Log.d(TAG,"AACEncodeConsumer-->停止采集音频");
|
||||
if(mAudioRecord != null){
|
||||
mAudioRecord.stop();
|
||||
mAudioRecord.release();
|
||||
mAudioRecord = null;
|
||||
@@ -303,9 +305,9 @@ public class AACEncodeConsumer extends Thread {
|
||||
}
|
||||
|
||||
private void stopMediaCodec() {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "AACEncodeConsumer-->停止编码音频");
|
||||
if (mAudioEncoder != null) {
|
||||
if(DEBUG)
|
||||
Log.d(TAG,"AACEncodeConsumer-->停止编码音频");
|
||||
if(mAudioEncoder != null){
|
||||
mAudioEncoder.stop();
|
||||
mAudioEncoder.release();
|
||||
mAudioEncoder = null;
|
||||
@@ -314,28 +316,28 @@ public class AACEncodeConsumer extends Thread {
|
||||
}
|
||||
|
||||
// API>=21
|
||||
private boolean isLollipop() {
|
||||
private boolean isLollipop(){
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
}
|
||||
|
||||
// API<=19
|
||||
private boolean isKITKAT() {
|
||||
private boolean isKITKAT(){
|
||||
return Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT;
|
||||
}
|
||||
|
||||
private long getPTSUs() {
|
||||
long result = System.nanoTime() / 1000;
|
||||
if (result < prevPresentationTimes) {
|
||||
result = (prevPresentationTimes - result) + result;
|
||||
private long getPTSUs(){
|
||||
long result = System.nanoTime()/1000;
|
||||
if(result < prevPresentationTimes){
|
||||
result = (prevPresentationTimes - result ) + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历所有编解码器,返回第一个与指定MIME类型匹配的编码器
|
||||
* 判断是否有支持指定mime类型的编码器
|
||||
*/
|
||||
private MediaCodecInfo selectSupportCodec(String mimeType) {
|
||||
* 判断是否有支持指定mime类型的编码器
|
||||
* */
|
||||
private MediaCodecInfo selectSupportCodec(String mimeType){
|
||||
int numCodecs = MediaCodecList.getCodecCount();
|
||||
for (int i = 0; i < numCodecs; i++) {
|
||||
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
||||
@@ -365,7 +367,7 @@ public class AACEncodeConsumer extends Thread {
|
||||
}
|
||||
|
||||
|
||||
private short[] transferByte2Short(byte[] data, int readBytes) {
|
||||
private short[] transferByte2Short(byte[] data,int readBytes){
|
||||
// byte[] 转 short[],数组长度缩减一半
|
||||
int shortLen = readBytes / 2;
|
||||
// 将byte[]数组装如ByteBuffer缓冲区
|
||||
|
||||
@@ -17,7 +17,9 @@ import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* 对YUV视频流进行编码
|
||||
* Created by jiangdongguo on 2017/5/6.
|
||||
*/
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class H264EncodeConsumer extends Thread {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@@ -10,9 +10,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Mp4封装混合器
|
||||
/**Mp4封装混合器
|
||||
*
|
||||
* Created by jianddongguo on 2017/7/28.
|
||||
*/
|
||||
|
||||
public class Mp4MediaMuxer {
|
||||
private static final boolean VERBOSE = false;
|
||||
private static final String TAG = Mp4MediaMuxer.class.getSimpleName();
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.serenegiant.utils;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PermissionGroupInfo;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public final class PermissionCheck {
|
||||
|
||||
public static final void dumpPermissions(@Nullable final Context context) {
|
||||
if (context == null) return;
|
||||
try {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final List<PermissionGroupInfo> list = pm.getAllPermissionGroups(PackageManager.GET_META_DATA);
|
||||
for (final PermissionGroupInfo info : list) {
|
||||
Log.d("PermissionCheck", info.name);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Log.w("", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パーミッションを確認
|
||||
* @param context
|
||||
* @param permissionName
|
||||
* @return 指定したパーミッションがあればtrue
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public static boolean hasPermission(@Nullable final Context context, final String permissionName) {
|
||||
if (context == null) return false;
|
||||
boolean result = false;
|
||||
try {
|
||||
final int check;
|
||||
if (BuildCheck.isMarshmallow()) {
|
||||
check = context.checkSelfPermission(permissionName);
|
||||
} else {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
check = pm.checkPermission(permissionName, context.getPackageName());
|
||||
}
|
||||
switch (check) {
|
||||
case PackageManager.PERMISSION_DENIED:
|
||||
break;
|
||||
case PackageManager.PERMISSION_GRANTED:
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
Log.w("", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 録音のミッションがあるかどうかを確認
|
||||
* @param context
|
||||
* @return 録音のパーミッションがあればtrue
|
||||
*/
|
||||
public static boolean hasAudio(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.RECORD_AUDIO);
|
||||
}
|
||||
|
||||
/**
|
||||
* ネットワークへのアクセスパーミッションがあるかどうかを確認
|
||||
* @param context
|
||||
* @return ネットワークへのアクセスパーミッションがあればtrue
|
||||
*/
|
||||
public static boolean hasNetwork(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.INTERNET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 外部ストレージへの書き込みパーミッションがあるかどうかを確認
|
||||
* @param context
|
||||
* @return 外部ストレージへの書き込みパーミッションがあればtrue
|
||||
*/
|
||||
public static boolean hasWriteExternalStorage(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.WRITE_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 外部ストレージからの読み込みパーミッションがあるかどうかを確認
|
||||
* @param context
|
||||
* @return 外部ストレージへの読み込みパーミッションがあればtrue
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
public static boolean hasReadExternalStorage(@Nullable final Context context) {
|
||||
if (BuildCheck.isAndroid4())
|
||||
return hasPermission(context, permission.READ_EXTERNAL_STORAGE);
|
||||
else
|
||||
return hasPermission(context, permission.WRITE_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 位置情報アクセスのパーミッションが有るかどうかを確認
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasAccessLocation(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.ACCESS_COARSE_LOCATION)
|
||||
&& hasPermission(context, permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 低精度位置情報アクセスのパーミッションが有るかどうかを確認
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasAccessCoarseLocation(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.ACCESS_COARSE_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度位置情報アクセスのパーミッションが有るかどうかを確認
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasAccessFineLocation(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* カメラへアクセス可能かどうか
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static boolean hasCamera(@Nullable final Context context) {
|
||||
return hasPermission(context, permission.CAMERA);
|
||||
}
|
||||
|
||||
/**
|
||||
* アプリの詳細設定へ遷移させる(パーミッションを取得できなかった時など)
|
||||
* @param context
|
||||
*/
|
||||
public static void openSettings(@NonNull final Context context) {
|
||||
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
final Uri uri = Uri.fromParts("package", context.getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* AndroidManifest.xmlに設定されているはずのパーミッションをチェックする
|
||||
* @param context
|
||||
* @param expectations
|
||||
* @return 空リストなら全てのパーミッションが入っていた,
|
||||
* @throws IllegalArgumentException
|
||||
* @throws PackageManager.NameNotFoundException
|
||||
*/
|
||||
public static List<String> missingPermissions(@NonNull final Context context, @NonNull final String[] expectations) throws IllegalArgumentException, PackageManager.NameNotFoundException {
|
||||
return missingPermissions(context, new ArrayList<String>(Arrays.asList(expectations)));
|
||||
}
|
||||
|
||||
/**
|
||||
* AndroidManifest.xmlに設定されているはずのパーミッションをチェックする
|
||||
* @param context
|
||||
* @param expectations
|
||||
* @return 空リストなら全てのパーミッションが入っていた,
|
||||
* @throws IllegalArgumentException
|
||||
* @throws PackageManager.NameNotFoundException
|
||||
*/
|
||||
public static List<String> missingPermissions(@NonNull final Context context, @NonNull final List<String> expectations) throws IllegalArgumentException, PackageManager.NameNotFoundException {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
|
||||
final String[] info = pi.requestedPermissions;
|
||||
if (info != null) {
|
||||
for (String i : info) {
|
||||
expectations.remove(i);
|
||||
}
|
||||
}
|
||||
return expectations;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user