CaaS Engine是华为依托畅连业务通信能力,面向应用开发者和硬件开发者提供的开放接口,可以帮助开发者快速实现应用内视频通话服务。开发者通过华为设备虚拟化服务,可以使用任意视频数据作为视频通话的视频源。
CaaS Engine使华为智能手机、海量应用、合作伙伴的智能设备实现系统级音视频通话能力,构建庞大实时通信网络,致力为消费者打造更佳的通信体验。

您将建立什么

在这个Codelab中,你将创建Demo Project,并将CaaS Engine的SDK集成到Demo Project中,以及完成CaaS Engine服务的整体流程搭建。

您将会学到什么

硬件要求

软件要求

需要的知识点

集成CaaS Engine能力,需要完成以下准备工作:

具体操作,请按照《开发指南》中“应用开发”的详细说明来完成。

1. 集成SDK。

向项目中的build.gradle中配置仓库:

buildscript { repositories { google() jcenter() maven {url 'http://developer.huawei.com/repo/'} } } allprojects { repositories { maven {url 'http://developer.huawei.com/repo/'} google() jcenter() } }

在工程APP目录中的build.gradle中添加如下依赖:

repositories { flatDir { dirs 'libs' } } dependencies { implementation group: 'com.huawei.caaskit', name: 'caaskitlite', version: '1.0.1.400', ext: 'aar' }

点击同步工程按钮,进行工程同步,如下图所示:

同步成功后,如下图所示:

2. 添加appid信息。

在自身应用AndroidManifest.xml中添加开发者联盟创建应用时生成的appid信息,name为"com.huawei.hms.client.appid",value为"appid=*",*用自己注册的appid。权限申请,请依照《开发指南》中"开发准备"的详细说明来完成。

3. 在AndroidManifest.xml添加权限。

设备虚拟化服务权限:

<uses-permission android:name="com.huawei.dmsdp.permission.localappservice" />

4. 注册广播并进行初始化。

广播可以动态注册也可以静态注册,本例中以动态注册为例:
CaasKitHelper.java

public class CaasKitHelper { private static final String TAG = "CaasKitHelper"; private static final String DMSDP_STARTDISCOVERY = "com.huawei.dmsdp.DMSDP_STARTDISCOVERY"; private static CaasKitHelper sCaasKitHelper; private DeviceDiscoverReceiver mDiscoverReceiver; private HwCaasServiceManager mHwCaasServiceManager; private HwCaasHandler mHwCaasHandler; private Context mContext; private boolean mIsSendShowFail; private boolean mIsCaasKitInit; private boolean mIsHasCaaSContacts; private HwCaasServiceCallBack mCallBack = new HwCaasServiceCallBack() { @Override public void initSuccess(HwCaasHandler handler) { ... } @Override public void initFail(int retCode) { ... } @Override public void releaseSuccess() { ... } }; private CaasKitHelper() { mContext = CaasKitApplication.getContext(); } public static CaasKitHelper getInstance() { if (sCaasKitHelper == null) { synchronized (CaasKitHelper.class) { if (sCaasKitHelper == null) { sCaasKitHelper = new CaasKitHelper(); } } } return sCaasKitHelper; } private void registerDiscoverReceiver() { Log.d(TAG, "registerDiscoverReceiver."); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(DMSDP_STARTDISCOVERY); if (mDiscoverReceiver == null) { Log.d(TAG, "mDiscoverReceiver."); mDiscoverReceiver = new DeviceDiscoverReceiver(); mContext.registerReceiver(mDiscoverReceiver, intentFilter); } } private void unregisterDiscoverReceiver() { Log.d(TAG, "unregisterDiscoverReceiver."); if (mDiscoverReceiver != null) { mContext.unregisterReceiver(mDiscoverReceiver); mDiscoverReceiver = null; } } /** * Initialization before using CaaSKitLite. */ public void caasKitInit() { Log.d(TAG, "caasKitInit." + mIsCaasKitInit); if (!mIsCaasKitInit) { registerDiscoverReceiver(); // Initialize mHwCaasServiceManager instance. mHwCaasServiceManager = HwCaasServiceManager.init(); // Initialize HwCaasHandler instance through handlerType. mHwCaasServiceManager.initHandler(mContext, HwCaasUtils.VIRTUAL_CAMERA_TYPE, mCallBack); mIsCaasKitInit = true; } } }

广播如下
DeviceDiscoverReceiver.java

public class DeviceDiscoverReceiver extends BroadcastReceiver { private static final String TAG = "DmsdpStartDiscoverReceiver"; private Context mApplicationContext; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive."); mApplicationContext = CaasKitApplication.getContext(); HwDmsdpService.init(mApplicationContext, new VirtualCameraListener()); } }

在合适的位置调用CaasKitHelper.getInstance().caasKitInit()进行广播的注册,和CaaS服务的初始化
CaasKitDemoActivity.java

public class CaasKitDemoActivity extends AppCompatActivity { ... @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_MEDIA_DATA) { if (resultCode == RESULT_OK && data != null && data.getData() != null) { setVideoFilePath(data); addVideoView(); CaasKitHelper.getInstance().caasKitInit(); } } } ... }

5. 虚拟Camera实现。

VirtualCameraListener.java

public class VirtualCameraListener extends CameraListener { // Use java.util.UUID.randomUUID().toString() to generate, please do not directly use the ID provided in the demo public static final String DEVICE_ID = "ff66bf58-6413-48e7-8dcd-c084254b199e"; // this ID is customized by the developer. public static final String VIRCAMERA_ID = "virtualcamera0"; private static final String TAG = "VirtualCameraListener"; private static final int VIDEO_BUFFER_MODE_YUV = 1; private static final int DEVICE_CAMERA = 5; private static final String DEVICE_NAME = "CaasKitCamera"; public VirtualCameraListener() { } @Override public List<DeviceInfo> getDeviceInfo() { Log.d(TAG, "getDeviceInfo."); List<DeviceInfo> listDeviceInfo = new ArrayList<>(); DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.setDeviceID(DEVICE_ID); deviceInfo.setDeviceName(DEVICE_NAME); deviceInfo.setDeviceType(DEVICE_CAMERA); deviceInfo.properties.put(CommonUtils.DEVICE_SUPPORTCAMERA_BOOLEAN, "true"); listDeviceInfo.add(deviceInfo); return listDeviceInfo; } @Override public HashMap<String, CameraInfo> getCameraInfo(String deviceId) { Log.d(TAG, "getCameraInfo."); HashMap<String, CameraInfo> mapCameraInfo = new HashMap<>(); CameraInfo cameraInfo = new CameraInfo(); cameraInfo.setCameraId(VIRCAMERA_ID); cameraInfo.setVideoType(VIDEO_BUFFER_MODE_YUV); cameraInfo.setSupportedFpsRange("25000,25000"); cameraInfo.setSupportedResolutionRange("1080,1920"); mapCameraInfo.put(VIRCAMERA_ID, cameraInfo); return mapCameraInfo; } @Override public CameraParameters getCameraParameters(String cameraId) { Log.d(TAG, "getCameraParameters."); CameraParameters cameraParams = new CameraParameters(); cameraParams.cameraId = VIRCAMERA_ID; cameraParams.properties.put(CommonUtils.CURRENT_RESOLUTION, "1080,1920"); cameraParams.properties.put(CommonUtils.CURRENT_FRAMERATES, "25000,30000"); cameraParams.properties.put(CommonUtils.CURRENT_IMAGEFORMAT, CommonUtils.IMAGE_FORMAT_NV21); cameraParams.properties.put(CommonUtils.CURRENT_DECODEFORMAT, CommonUtils.DECODE_FORMAT_RGBA); return cameraParams; } @Override public int startCaptureVideo(String cameraId, Surface surface) { Log.d(TAG, "startCaptureVideo." + cameraId); if (ExtSurfaceRender.getInstance().isEGLContextReady()) { Log.d(TAG, "startCaptureVideo."); ExtSurfaceRender.getInstance().startRendering(surface); } return 0; } @Override public int stopCaptureVideo(String cameraId) { Log.d(TAG, "stopCaptureVideo."); ExtSurfaceRender.getInstance().stopRendering(); return 0; } @Override public int notifyUnbindMSDPService() { Log.d(TAG, "notifyUnbindMSDPService."); HwDmsdpService.release(); return 0; } @Override public void checkPermissionOnCallback(int result) { Log.d(TAG, "checkPermissionOnCallback.result: " + result); } }

6. 配置悬浮通话界面。

CaasKitHelper.java

public class CaasKitHelper { private static final String TAG = "CaasKitHelper"; private static final String DMSDP_STARTDISCOVERY = "com.huawei.dmsdp.DMSDP_STARTDISCOVERY"; private static final int VIEWHEIGHT = 248; private static final int VIEWWIDTH = 256; private static final int LOCATION_X = 102; private static final int LOCATION_Y = 40; private static final int LOCATION_STARTY = 24; private static CaasKitHelper sCaasKitHelper; private DeviceDiscoverReceiver mDiscoverReceiver; private HwCaasServiceManager mHwCaasServiceManager; private HwCaasHandler mHwCaasHandler; private Context mContext; private boolean mIsSendShowFail; private boolean mIsCaasKitInit; private boolean mIsHasCaaSContacts; private HwCaasServiceCallBack mCallBack = new HwCaasServiceCallBack() { @Override public void initSuccess(HwCaasHandler handler) { // Callback after successful initialization of HwCaasHandler. mHwCaasHandler = handler; if (mHwCaasHandler != null) { boolean isSetSuccess = false; // query if there are contacts to call. mIsHasCaaSContacts = mHwCaasHandler.hasCaaSContacts(HwCaasUtils.ContactsType.NORMAL_CONTACTS); isSetSuccess = mHwCaasHandler.setContactViewSize(VIEWWIDTH, VIEWHEIGHT); Log.i(TAG, " isSetSuccess: " + isSetSuccess); isSetSuccess = mHwCaasHandler.setAppMode(HwCaasUtils.LANDSCAPE); Log.i(TAG, " isSetSuccess: " + isSetSuccess); isSetSuccess = mHwCaasHandler.setFloatViewLocation(HwCaasUtils.STARTVIEW, HwCaasUtils.POINT_RIGHTANDDOWN, LOCATION_X, LOCATION_STARTY); Log.i(TAG, "viewType: " + HwCaasUtils.STARTVIEW + " isSetSuccess: " + isSetSuccess); isSetSuccess = mHwCaasHandler.setFloatViewLocation(HwCaasUtils.CONTACTVIEW, HwCaasUtils.POINT_RIGHTANDUP, LOCATION_X, LOCATION_Y); Log.i(TAG, "viewType: " + HwCaasUtils.CONTACTVIEW + " isSetSuccess: " + isSetSuccess); isSetSuccess = mHwCaasHandler.setFloatViewLocation(HwCaasUtils.CALLVIEW, HwCaasUtils.POINT_RIGHTANDUP, LOCATION_X, LOCATION_Y); Log.i(TAG, "viewType: " + HwCaasUtils.CALLVIEW + " isSetSuccess: " + isSetSuccess); isSetSuccess = mHwCaasHandler.setFloatViewLocation(HwCaasUtils.VIDEOVIEW, HwCaasUtils.POINT_RIGHTANDUP, LOCATION_X, LOCATION_Y); Log.i(TAG, "viewType: " + HwCaasUtils.VIDEOVIEW + " isSetSuccess: " + isSetSuccess); if (mIsSendShowFail) { sendShow(); mIsSendShowFail = false; } } } @Override public void initFail(int retCode) { // Callback if init Handler fail. Log.i(TAG, "retCode: " + retCode); if (retCode == HwCaasUtils.SERVICE_EXCEPTION) { stopRendering(); } } @Override public void releaseSuccess() { // Callback after successful release of mHwCaasServiceManager. mHwCaasHandler = null; mIsSendShowFail = false; } }; }

7. 显示悬浮通话界面。

CaasKitHelper.java

public class CaasKitHelper { private static final String TAG = "CaasKitHelper"; private static CaasKitHelper sCaasKitHelper; private DeviceDiscoverReceiver mDiscoverReceiver; private HwCaasServiceManager mHwCaasServiceManager; private HwCaasHandler mHwCaasHandler; private Context mContext; private boolean mIsSendShowFail; private boolean mIsCaasKitInit; private boolean mIsHasCaaSContacts; /** * Virtualize Camera and show float ball. */ public void sendShow() { Log.d(TAG, "sendShow."); if (mHwCaasHandler != null && mIsHasCaaSContacts) { // show float ball. int ret = mHwCaasHandler.initVirtualCamera(VirtualCameraListener.DEVICE_ID, VirtualCameraListener.VIRCAMERA_ID); Log.d(TAG, "ret: " + ret); } else { // Prevent first call, mHwCaasHandler hasn't returned yet. mIsSendShowFail = true; Log.e(TAG, "sendShow fail."); } } /** * Called when the application is in the foreground and some scenes do not want to display the float ball. * * @return returns true if sent successfully. */ public boolean sendHide() { Log.d(TAG, "sendHide."); if (mHwCaasHandler != null) { // Send HIDE event to hide float ball. boolean isSendoK = mHwCaasHandler.sendEventToCaasService(HwCaasUtils.HIDE); Log.d(TAG, "isSendoK: " + isSendoK); return isSendoK; } Log.e(TAG, "sendHide fail."); return false; } }

8. 释放资源。

CaasKitHelper.java

public class CaasKitHelper { private static final String TAG = "CaasKitHelper"; private static CaasKitHelper sCaasKitHelper; private DeviceDiscoverReceiver mDiscoverReceiver; private HwCaasServiceManager mHwCaasServiceManager; private HwCaasHandler mHwCaasHandler; private Context mContext; private boolean mIsSendShowFail; private boolean mIsCaasKitInit; private boolean mIsHasCaaSContacts; /** * called when the app exits. */ public void caasKitRelease() { Log.d(TAG, "caasKitRelease." + mIsCaasKitInit); if (mIsCaasKitInit) { if (mHwCaasServiceManager != null) { // Source release. mHwCaasServiceManager.release(); mHwCaasServiceManager = null; } unregisterDiscoverReceiver(); mIsCaasKitInit = false; } } public void releaseVirtualCamera() { Log.d(TAG, "releaseVirtualCamera."); if (mHwCaasHandler != null) { // release virtual camera. int ret = mHwCaasHandler.releaseVirtualCamera(VirtualCameraListener.DEVICE_ID, VirtualCameraListener.VIRCAMERA_ID); Log.d(TAG, "ret: " + ret); } } }

干得好,你已经成功完成了Codelab并学到了:

您可以阅读下面链接,了解更多相关的信息。
相关文档

源码下载

Code copied