diff --git a/config.gradle b/config.gradle
index a9bb3a0e99..c1c27bc09f 100644
--- a/config.gradle
+++ b/config.gradle
@@ -238,6 +238,7 @@ 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}",
diff --git a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.java b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.java
index 6e1fbd06c9..dce789946c 100644
--- a/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.java
+++ b/core/function-impl/mogo-core-function-autopilot/src/main/java/com/mogo/eagle/core/function/autopilot/adapter/MoGoAdasListenerImpl.java
@@ -137,7 +137,7 @@ public class MoGoAdasListenerImpl implements OnAdasListener {
data.putOpt("lon", stateInfo.getValues().getLon());
data.putOpt("lat", stateInfo.getValues().getLat());
data.putOpt("alt", stateInfo.getValues().getAlt());
- data.putOpt("speed", stateInfo.getValues().getGnss_speed());
+ data.putOpt("speed", stateInfo.getValues().getVehicle_speed());
data.putOpt("heading", stateInfo.getValues().getHeading());
data.putOpt("acceleration", stateInfo.getValues().getAcceleration());
data.putOpt("yawRate", stateInfo.getValues().getYaw_rate());
diff --git a/core/function-impl/mogo-core-function-carcorder/build.gradle b/core/function-impl/mogo-core-function-carcorder/build.gradle
index f909f820b5..d612fd342f 100644
--- a/core/function-impl/mogo-core-function-carcorder/build.gradle
+++ b/core/function-impl/mogo-core-function-carcorder/build.gradle
@@ -52,6 +52,8 @@ dependencies {
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
@@ -61,6 +63,8 @@ dependencies {
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')
diff --git a/core/function-impl/mogo-core-function-carcorder/gradle.properties b/core/function-impl/mogo-core-function-carcorder/gradle.properties
index 3a7512bbca..ba1462e8ad 100644
--- a/core/function-impl/mogo-core-function-carcorder/gradle.properties
+++ b/core/function-impl/mogo-core-function-carcorder/gradle.properties
@@ -1,3 +1,3 @@
GROUP=com.mogo.eagle.core.function.impl
-POM_ARTIFACT_ID=devatools
+POM_ARTIFACT_ID=carcorder
VERSION_CODE=1
diff --git a/core/function-impl/mogo-core-function-carcorder/src/main/AndroidManifest.xml b/core/function-impl/mogo-core-function-carcorder/src/main/AndroidManifest.xml
index 3e174f9fb6..6c1ea8112e 100644
--- a/core/function-impl/mogo-core-function-carcorder/src/main/AndroidManifest.xml
+++ b/core/function-impl/mogo-core-function-carcorder/src/main/AndroidManifest.xml
@@ -1,4 +1,17 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-carcorder/src/main/java/com/mogo/eagle/core/function/carcorder/service/CarcorderService.kt b/core/function-impl/mogo-core-function-carcorder/src/main/java/com/mogo/eagle/core/function/carcorder/service/CarcorderService.kt
new file mode 100644
index 0000000000..c355159e07
--- /dev/null
+++ b/core/function-impl/mogo-core-function-carcorder/src/main/java/com/mogo/eagle/core/function/carcorder/service/CarcorderService.kt
@@ -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? = 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}")
+ }
+
+}
\ No newline at end of file
diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/carcorder/CarcorderPreviewView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/carcorder/CarcorderPreviewView.kt
index 52b9fb36a5..9ddb5dda02 100644
--- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/carcorder/CarcorderPreviewView.kt
+++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/carcorder/CarcorderPreviewView.kt
@@ -160,6 +160,10 @@ class CarcorderPreviewView private constructor(
Log.d(TAG, "onDisConnectDev")
showShortMsg("相机断开连接")
}
+
+ override fun onCancelDev(device: UsbDevice?) {
+ Log.d(TAG, "onCancelDev:" + device?.deviceName)
+ }
}
diff --git a/gradle.properties b/gradle.properties
index ba61ae3480..d6323c0ba7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -107,6 +107,7 @@ 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
diff --git a/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/USBCameraHelper.java b/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/USBCameraHelper.java
new file mode 100644
index 0000000000..e61d6478d0
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/USBCameraHelper.java
@@ -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();
+ }
+ }
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/UVCCameraHelper.java b/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/UVCCameraHelper.java
index 554cd199a9..4a14cd62f3 100644
--- a/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/UVCCameraHelper.java
+++ b/libraries/map-usbcamera/src/main/java/com/mogo/usbcamera/UVCCameraHelper.java
@@ -74,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) {
@@ -106,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);
@@ -135,6 +135,9 @@ public class UVCCameraHelper {
@Override
public void onCancel(UsbDevice device) {
+ if (listener != null) {
+ listener.onCancelDev(device);
+ }
}
});
@@ -249,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();
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/DialogFragmentEx.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/DialogFragmentEx.java
new file mode 100644
index 0000000000..d1a390497c
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/DialogFragmentEx.java
@@ -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);
+ }
+ }
+
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragment.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragment.java
new file mode 100644
index 0000000000..bfdf3595f1
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragment.java
@@ -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();
+ }
+
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragmentV4.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragmentV4.java
new file mode 100644
index 0000000000..b55b276159
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/dialog/MessageDialogFragmentV4.java
@@ -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);
+ }
+ }
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/CameraDialog.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/CameraDialog.java
index 53269a658f..dfad92686f 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/CameraDialog.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/CameraDialog.java
@@ -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 filter = DeviceFilter.getDeviceFilters(getActivity(), R.xml.device_filter);
- mDeviceListAdapter = new DeviceListAdapter(getActivity(), mUSBMonitor.getDeviceList(filter.get(0)));
- mSpinner.setAdapter(mDeviceListAdapter);
- }
+ final List 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 mList;
+ private final LayoutInflater mInflater;
+ private final List mList;
- public DeviceListAdapter(final Context context, final List list) {
- mInflater = LayoutInflater.from(context);
- mList = list != null ? list : new ArrayList();
- }
+ public DeviceListAdapter(final Context context, final Listlist) {
+ mInflater = LayoutInflater.from(context);
+ mList = list != null ? list : new ArrayList();
+ }
- @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;
+ }
+ }
}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/DeviceFilter.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/DeviceFilter.java
index 61b9c09d61..2e94263c92 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/DeviceFilter.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/DeviceFilter.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/IFrameCallback.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/IFrameCallback.java
index 3d00d77d29..f6aee755e0 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/IFrameCallback.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/IFrameCallback.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/Size.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/Size.java
index 55bf0b19b7..963a805398 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/Size.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/Size.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
index 1eea770006..b46ee9f4a6 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBMonitor.java
@@ -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);
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 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 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 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 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 getDeviceList(final List filters) throws IllegalStateException {
- if (destroyed) {
- throw new IllegalStateException("already destroyed");
- }
+ if (destroyed) throw new IllegalStateException("already destroyed");
// get detected devices
final HashMap 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{
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBVendorId.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBVendorId.java
index f2577935a6..d354b66ca7 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBVendorId.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/USBVendorId.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/UVCCamera.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/UVCCamera.java
index b73940d1b6..15a4180b75 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/UVCCamera.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/UVCCamera.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
index 00aa36d45a..992d1cf562 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/AbstractUVCCameraHandler.java
@@ -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 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
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseActivity.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseActivity.java
new file mode 100644
index 0000000000..8a446cd2a8
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseActivity.java
@@ -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;
+ }
+
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseFragment.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseFragment.java
new file mode 100644
index 0000000000..4e883ce185
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseFragment.java
@@ -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;
+ }
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseService.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseService.java
new file mode 100644
index 0000000000..78a2307af6
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/BaseService.java
@@ -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
+ }
+ }
+}
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java
index b102139d6d..2d01f1cd25 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandler.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java
index 7619d39df4..d8df6c26d1 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/common/UVCCameraHandlerMultiSurface.java
@@ -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);
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IAudioEncoder.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IAudioEncoder.java
index eef9858a73..9a0c0bdb7e 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IAudioEncoder.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IAudioEncoder.java
@@ -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 {
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IVideoEncoder.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IVideoEncoder.java
index 24370c80ff..7b8429d262 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IVideoEncoder.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/IVideoEncoder.java
@@ -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 {
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaAudioEncoder.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaAudioEncoder.java
index 761419aa50..3246364cff 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaAudioEncoder.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaAudioEncoder.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaSurfaceEncoder.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaSurfaceEncoder.java
index fc3e0a38ce..47eb607e08 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaSurfaceEncoder.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaSurfaceEncoder.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoBufferEncoder.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoBufferEncoder.java
index 30d3242bb9..40d26bfaa0 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoBufferEncoder.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/MediaVideoBufferEncoder.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/RecordParams.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/RecordParams.java
index 159218211a..0265cac1ea 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/RecordParams.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/RecordParams.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/AACEncodeConsumer.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/AACEncodeConsumer.java
index 0cbf441869..69319e9b7d 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/AACEncodeConsumer.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/AACEncodeConsumer.java
@@ -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 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缓冲区
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java
index 8ccd36026a..9310ce1ae4 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/H264EncodeConsumer.java
@@ -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;
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/Mp4MediaMuxer.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/Mp4MediaMuxer.java
index 1b2fc40c5b..64307af008 100644
--- a/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/Mp4MediaMuxer.java
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/usb/encoder/biz/Mp4MediaMuxer.java
@@ -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();
diff --git a/libraries/map-usbcamera/src/main/java/com/serenegiant/utils/PermissionCheck.java b/libraries/map-usbcamera/src/main/java/com/serenegiant/utils/PermissionCheck.java
new file mode 100644
index 0000000000..f3409fb84e
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/java/com/serenegiant/utils/PermissionCheck.java
@@ -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 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 missingPermissions(@NonNull final Context context, @NonNull final String[] expectations) throws IllegalArgumentException, PackageManager.NameNotFoundException {
+ return missingPermissions(context, new ArrayList(Arrays.asList(expectations)));
+ }
+
+ /**
+ * AndroidManifest.xmlに設定されているはずのパーミッションをチェックする
+ * @param context
+ * @param expectations
+ * @return 空リストなら全てのパーミッションが入っていた,
+ * @throws IllegalArgumentException
+ * @throws PackageManager.NameNotFoundException
+ */
+ public static List missingPermissions(@NonNull final Context context, @NonNull final List 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;
+ }
+}
diff --git a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libUVCCamera.so b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libUVCCamera.so
index 2c9b394b63..6b4d9fdfc4 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libUVCCamera.so and b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libUVCCamera.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libjpeg-turbo1500.so b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libjpeg-turbo1500.so
index 6e7e70e2e0..7965444d8e 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libjpeg-turbo1500.so and b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libjpeg-turbo1500.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libusb100.so b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libusb100.so
index 370d63d45a..c27d595219 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libusb100.so and b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libusb100.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libuvc.so b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libuvc.so
index 03830b267c..1f2486a5f6 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libuvc.so and b/libraries/map-usbcamera/src/main/jniLibs/arm64-v8a/libuvc.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libUVCCamera.so b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libUVCCamera.so
index a07bbbc70f..b6bf9769a5 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libUVCCamera.so and b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libUVCCamera.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libjpeg-turbo1500.so b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libjpeg-turbo1500.so
index d1e7b07021..97408c6d46 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libjpeg-turbo1500.so and b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libjpeg-turbo1500.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libusb100.so b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libusb100.so
index f0df5b052b..4f2603950e 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libusb100.so and b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libusb100.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libuvc.so b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libuvc.so
index 564d932313..ba68f84d05 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libuvc.so and b/libraries/map-usbcamera/src/main/jniLibs/armeabi-v7a/libuvc.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86/libUVCCamera.so b/libraries/map-usbcamera/src/main/jniLibs/x86/libUVCCamera.so
index 7cb48799f9..df770e4e3a 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86/libUVCCamera.so and b/libraries/map-usbcamera/src/main/jniLibs/x86/libUVCCamera.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86/libjpeg-turbo1500.so b/libraries/map-usbcamera/src/main/jniLibs/x86/libjpeg-turbo1500.so
index ce788243ba..d4b67c637c 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86/libjpeg-turbo1500.so and b/libraries/map-usbcamera/src/main/jniLibs/x86/libjpeg-turbo1500.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86/libusb100.so b/libraries/map-usbcamera/src/main/jniLibs/x86/libusb100.so
index 6b771d31ae..59d8f256cb 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86/libusb100.so and b/libraries/map-usbcamera/src/main/jniLibs/x86/libusb100.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86/libuvc.so b/libraries/map-usbcamera/src/main/jniLibs/x86/libuvc.so
index deba66615e..fdf4318185 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86/libuvc.so and b/libraries/map-usbcamera/src/main/jniLibs/x86/libuvc.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libUVCCamera.so b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libUVCCamera.so
index 33057578d1..4c1ea8ab15 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libUVCCamera.so and b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libUVCCamera.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libjpeg-turbo1500.so b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libjpeg-turbo1500.so
index 36b3f76a58..ee0ff7afe8 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libjpeg-turbo1500.so and b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libjpeg-turbo1500.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libusb100.so b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libusb100.so
index 05431ef82d..0c7cf3a9ae 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libusb100.so and b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libusb100.so differ
diff --git a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libuvc.so b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libuvc.so
index 0b37d34a94..1c4eb3ecb8 100644
Binary files a/libraries/map-usbcamera/src/main/jniLibs/x86_64/libuvc.so and b/libraries/map-usbcamera/src/main/jniLibs/x86_64/libuvc.so differ
diff --git a/libraries/map-usbcamera/src/main/res/values/strings_permissions.xml b/libraries/map-usbcamera/src/main/res/values/strings_permissions.xml
new file mode 100644
index 0000000000..9d7e54bfd7
--- /dev/null
+++ b/libraries/map-usbcamera/src/main/res/values/strings_permissions.xml
@@ -0,0 +1,32 @@
+
+
+ Regarding permission
+
+ No audio recording permission. \nAll audio function is disabled
+ Audio recording permission is necessary for movie capture with audio.
+ Audio recording permission is necessary for movie capture with audio.
+ Audio recording permission is necessary for streaming with audio.
+ Audio recording permission is necessary for streaming with audio.
+
+ No permission of writing external storage. \nMovie/still image capturing are disabled.
+ Permission of writing external storage is necessary for movie/still image capturing.
+ Permission of writing external storage is necessary for movie/still image capturing.
+ No writing external storage permission. \nApp will finish soon
+
+ No network access permission.
+ Network access permission is necessary for streaming.
+ Network access permission is necessary for streaming.
+ No network access permission. \nApp will finish soon
+
+ No location access permission
+ Location access permission is necessary for %s
+ Location access permission is necessary for %s
+ No location access permission. \nApp will finish soon
+
+ No camera access permission
+ No camera access permission. \nApp will finish soon
+ Camera access permission is necessary for fallback to built in camera.
+ Camera access permission is necessary for fallback to built in camera.
+
+ Permission to access phone state/hardware id necessary for calling.
+
\ No newline at end of file
diff --git a/modules/mogo-module-main/build.gradle b/modules/mogo-module-main/build.gradle
index 0e7680566d..b209b14507 100644
--- a/modules/mogo-module-main/build.gradle
+++ b/modules/mogo-module-main/build.gradle
@@ -62,6 +62,7 @@ dependencies {
implementation rootProject.ext.dependencies.mogo_core_utils
implementation rootProject.ext.dependencies.mogo_core_data
implementation rootProject.ext.dependencies.mogo_core_function_call
+ implementation rootProject.ext.dependencies.mogo_core_function_carcorder
} else {
api project(":foudations:mogo-commons")
api project(':modules:mogo-module-common')
@@ -72,6 +73,8 @@ dependencies {
implementation project(':core:mogo-core-utils')
implementation project(':core:mogo-core-data')
implementation project(':core:mogo-core-function-call')
+ implementation project(':core:function-impl:mogo-core-function-carcorder')
+
}
}
diff --git a/modules/mogo-module-main/src/main/java/com/mogo/module/main/MainActivity.java b/modules/mogo-module-main/src/main/java/com/mogo/module/main/MainActivity.java
index 670e5f7676..28b27876db 100644
--- a/modules/mogo-module-main/src/main/java/com/mogo/module/main/MainActivity.java
+++ b/modules/mogo-module-main/src/main/java/com/mogo/module/main/MainActivity.java
@@ -1,5 +1,7 @@
package com.mogo.module.main;
+import static com.mogo.module.main.MainPresenter.MOGO_PERMISSION_REQUEST_CODE;
+
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
@@ -22,6 +24,7 @@ import com.mogo.commons.mvp.MvpActivity;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.eagle.core.data.constants.MoGoFragmentPaths;
import com.mogo.eagle.core.data.map.MogoLocation;
+import com.mogo.eagle.core.function.carcorder.service.CarcorderService;
import com.mogo.eagle.core.utilcode.mogo.AppLaunchTimeUtils;
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
import com.mogo.eagle.core.utilcode.mogo.permissions.PermissionsDialogUtils;
@@ -50,8 +53,6 @@ import com.zhidao.autopilot.support.api.AutopilotServiceManage;
import java.util.HashMap;
import java.util.Map;
-import static com.mogo.module.main.MainPresenter.MOGO_PERMISSION_REQUEST_CODE;
-
/**
* @author congtaowang
* @since 2019-12-23
@@ -255,8 +256,12 @@ public class MainActivity extends MvpActivity implement
}
private void startBaseService() {
- Intent intent = new Intent(this, MogoMainService.class);
- startService(intent);
+ Intent intentMainServicee = new Intent(this, MogoMainService.class);
+ startService(intentMainServicee);
+
+ // USB 摄像头行车记录仪进程
+ Intent intentCarcorderService = new Intent(this, CarcorderService.class);
+ startService(intentCarcorderService);
}
protected void loadContainerModules() {
@@ -272,7 +277,7 @@ public class MainActivity extends MvpActivity implement
@Override
public void loadFunctionFragment() {
- Logger.d(TAG,"loadFunctionFragment……");
+ Logger.d(TAG, "loadFunctionFragment……");
// 加载 HMI 图层
BaseFragment fragmentHdMap = (BaseFragment) ARouter.getInstance().build(MoGoFragmentPaths.PATH_FRAGMENT_HMI).navigation();
addFragment(fragmentHdMap, fragmentHdMap.getTagName(), R.id.module_main_id_waring_fragment);
diff --git a/test/crashreport-apmbyte/src/main/java/com/mogo/test/crashreport/apm/ApmCrashReportProvider.java b/test/crashreport-apmbyte/src/main/java/com/mogo/test/crashreport/apm/ApmCrashReportProvider.java
index 8446c6d2e7..b2e9b3944a 100644
--- a/test/crashreport-apmbyte/src/main/java/com/mogo/test/crashreport/apm/ApmCrashReportProvider.java
+++ b/test/crashreport-apmbyte/src/main/java/com/mogo/test/crashreport/apm/ApmCrashReportProvider.java
@@ -66,17 +66,17 @@ public class ApmCrashReportProvider implements ITestCrashReportProvider {
//设置分配的appid
builder.aid(BYTEAMP_APPID);
//是否开启卡顿功能
- builder.blockDetect(true);
+ builder.blockDetect(false);
//是否开启严重卡顿功能
- builder.seriousBlockDetect(true);
+ builder.seriousBlockDetect(false);
//是否开启流畅性和丢帧
- builder.fpsMonitor(true);
+ builder.fpsMonitor(false);
//控制是否打开WebVeiw监控
- builder.enableWebViewMonitor(true);
+ builder.enableWebViewMonitor(false);
//控制是否打开内存监控
- builder.memoryMonitor(true);
+ builder.memoryMonitor(false);
//控制是否打开电量监控
- builder.batteryMonitor(true);
+ builder.batteryMonitor(false);
//是否打印日志,注:线上release版本要配置为false
builder.debugMode(true);
//支持用户自定义user_id把平台数据和自己用户关联起来,可以不配置