在此章节,我们需要将完成这篇Codelab学习,所需要的软硬件环境,及能力使用权限等信息。

硬件要求

软件要求

需要的知识点

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

具体操作,请按照《DeviceVirtualization Engine 接入准备》中详细说明来完成。

1. 集成DeviceVirtualization Engine。

在工程APP目录中的build.gradle中添加如下代码,将下载好的aar包添加至工程中

build.gradle

dependencies { implementation files('libs/devicevirtualization-device-android-1.0.0.300.aar') }

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

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

2. 在AndroidManifest.xml中配置应用为系统权限。

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.huawei.dmsdptest" android:sharedUserId="android.uid.system"> ......

3. 初始化服务。

使用VirtualizationAdapter的静态方法initInstance初始化,初始化时需要指定设备的名称与类型。初始化结果通过onInitSuccess和onInitFail回调方法获取。

4. 注册虚拟化服务回调接口

在初始化成功后,回调接口onInitSuccess将会返回一个VirtualizationAdapter实例对象。此时需要为该实例对象注册IVirtualizationCallback回调接口,该接口需要实现以下五个回调方法:

5. 启动发现监听

通过VirtualizationAdapter实例对象的startAdv方法启动发现监听,监听启动成功后,手机便可以发现该设备。完成此步骤后,设备虚拟化能力的基本功能就可以使用了。

MainActivity.java

mVirtualizationAdapter.startAdv();

6. 断开连接设备

设备可在需要的时候通过VirtualizationAdapter实例对象的disconnectDevice方法断开当前的连接设备。

MainActivity.java

mVirtualizationAdapter.disconnectDevice();

7. 释放连接对象

通过使用VirtualizationAdapter的静态方法releaseInstance释放连接对象

MainActivity.java

mVirtualizationCallback = new IVirtualizationCallback() { @Override public void onDeviceChange(String remoteDevice, int state) { if (state == CONNECT) { HwLog.i(TAG, "device has connected"); AdapterUtil.getInstance().setConnectedDevice(remoteDevice); } else if (state == DISCONNECT) { HwLog.i(TAG, "device has disconnected"); AdapterUtil.getInstance().setConnectedDevice(null); mDisplayService.set(false); //设备断开连接,需销毁显示投屏画面的Surface MainActivity.this.sendBroadcast(new Intent(ACTION_CLOSE_SURFACE_ACTIVITY)); } else if (state == START_PROJECTION) { HwLog.i(TAG, "service all ready,start project"); mDisplayService.set(true); //创建Surface,并通过startProjection接口传递给DV服务,用来显示投屏画面 Intent intent = new Intent(MainActivity.this, SurfaceActivity.class); MainActivity.this.startActivity(intent); } else if (state == STOP_PROJECTION) { HwLog.i(TAG, "stopProjection"); mDisplayService.set(false); //投屏能力停止,也需销毁显示投屏画面的Surface MainActivity.this.sendBroadcast(new Intent(ACTION_CLOSE_SURFACE_ACTIVITY)); } else if (state == REQUEST_CONNECTION) { //自定义弹窗布局文件 View dialogView = View.inflate(mContext, R.layout.dialog_permission, null); final AlertDialog dialog = new AlertDialog.Builder(mContext).setView(dialogView).create(); TextView titleTextView = dialogView.findViewById(R.id.title_id); TextView informationTextView = dialogView.findViewById(R.id.information_id); Button refuseButton = dialogView.findViewById(R.id.button_prohibition); Button permanentButton = dialogView.findViewById(R.id.button_permission_permanent); Button temporaryButton = dialogView.findViewById(R.id.button_permission_temporary); temporaryButton.requestFocus(); titleTextView.setText("是否允许"" + remoteDevice + ""访问本设备?"); informationTextView.setText("使用中可能会调用麦克风、摄像头用于音视频协同等服务。"); refuseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mVirtualizationAdapter != null) { int result = mVirtualizationAdapter.disconnectDevice(); HwLog.i(TAG, "disconnect device result:" + result); dialog.dismiss(); } } }); permanentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int result = mVirtualizationAdapter.acceptConnection(true); HwLog.i(TAG, "permanent permit result:" + result); dialog.dismiss(); } }); temporaryButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int result = mVirtualizationAdapter.acceptConnection(false); HwLog.i(TAG, "temporary permit result:" + result); dialog.dismiss(); } }); dialog.show(); } } @Override public void onPinCode(String deviceName, final String pinCode) { HwLog.i(TAG, "pinCode:" + pinCode); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { if (!TextUtils.isEmpty(pinCode)) { //显示pinCode mCode.setText(pinCode); } else { //如果pinCode是空串,不显示pinCode mCode.setText(""); } } }); } @Override public long getSecureFileSize(String fileName) { HwLog.i(TAG, "readSecureFile fileName:" + fileName); try (FileInputStream fileInputStream = openFileInput(fileName)) { FileChannel channel = fileInputStream.getChannel(); return channel.size(); } catch (IOException e) { HwLog.e(TAG, "getSecureFileSize failed"); } return 0; } @Override public byte[] readSecureFile(String fileName) { HwLog.i(TAG, "readSecureFile fileName:" + fileName); try (FileInputStream fileInputStream = openFileInput(fileName)) { int canRead = fileInputStream.available(); byte[] buffer = new byte[canRead]; int read = fileInputStream.read(buffer); if (read != canRead) { HwLog.e(TAG, "read file size failed"); } else { HwLog.i(TAG, "read file success"); return buffer; } } catch (IOException e) { HwLog.e(TAG, "read file failed"); } return new byte[0]; } @Override public boolean writeSecureFile(String fileName, byte[] bytes) { HwLog.i(TAG, "writeSecureFile fileName:" + fileName); try (FileOutputStream fileOutputStream = openFileOutput(fileName, MODE_PRIVATE)) { fileOutputStream.write(bytes); fileOutputStream.flush(); } catch (IOException e) { HwLog.e(TAG, "write file exception," + e); return false; } return true; } }; int status = mVirtualizationAdapter.setVirtualizationCallback(mVirtualizationCallback);

MainActivity.java

@Override protected void onDestroy() { HwLog.i(TAG, "onDestroy"); disconnect(); HwLog.i(TAG, "onDestroy end"); super.onDestroy(); } //全部释放干净 private void disconnect() { if (mVirtualizationAdapter != null) { //停止投屏 if (mDisplayService.get()) { int stopStatus = mVirtualizationAdapter.stopProjection(); HwLog.d(TAG, "disconnect stopProjection stopStatus:" + stopStatus); mDisplayService.set(false); } //停止连接监听 int disconnectDeviceStatus = mVirtualizationAdapter.disconnectDevice(); HwLog.i(TAG, "disconnect disconnectDevice status:" + disconnectDeviceStatus); //停止发现监听 int result = mVirtualizationAdapter.stopAdv(); HwLog.i(TAG, "disconnect stop listen result:" + result); } //释放adapter对象 VirtualizationAdapter.releaseInstance(); mVirtualizationAdapter = null; }

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

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

您可以点击下方按钮下载源码。

下载 source code

已复制代码