管理中心
我的

开发步骤

  1. 初始化服务。

    应用在需要使用DV Engine能力时,首先需要进行初始化DV Engine服务,服务初始化,需要使用VirtualizationAdapter的静态方法initInstance,初始化结果通过onInitSuccess和onInitFail回调方法获取。

    DeviceInfo deviceInfo = new DeviceInfo(); 
    deviceInfo.setDeviceName(getDeviceName()); 
    deviceInfo.setDeviceType(DeviceInfo.DEVICE_TYPE_TV); 
    HwLog.d(TAG, "initMSDPService info:" + deviceInfo); 
    int initInstance = VirtualizationAdapter.initInstance(getApplicationContext(), deviceInfo, new IInitCallback() { 
        @Override 
        public void onInitSuccess(VirtualizationAdapter virtualizationAdapter) { 
            HwLog.i(TAG, "onInitSuccess"); 
            mVirtualizationAdapter = virtualizationAdapter; 
            AdapterUtil.getInstance().setVirtualizationAdapter(mVirtualizationAdapter); 
            int status = mVirtualizationAdapter.setVirtualizationCallback(mVirtualizationCallback); 
            HwLog.i(TAG, "setVirtualizationCallback status:" + status); 
            HwLog.i(TAG, "start listen"); 
            int result = mVirtualizationAdapter.startAdv(); 
            HwLog.i(TAG, "start listen result:" + result); 
        } 
        @Override 
        public void onInitFail(int code) { 
            HwLog.i(TAG, "onInitFail: " + code); 
            disconnect(); 
        } 
        @Override 
        public void onBinderDied() { 
            HwLog.e(TAG, "onBinderDied service died!"); 
            AdapterUtil.getInstance().setConnectedDevice(null); 
            mVirtualizationAdapter = null; 
            if (mDisplayService.get()) { 
                HwLog.i(TAG, "close surface"); 
                //发送广播,关闭SurfaceActivity 
                MainActivity.this.sendBroadcast(new Intent(ACTION_CLOSE_SURFACE_ACTIVITY)); 
                mDisplayService.set(false); 
            } 
        } 
    }); 
    HwLog.i(TAG, "initInstance result:" + initInstance);

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

    在初始化成功的回调接口onInitSuccess里面,使用回调参数VirtualizationAdapter实例对象的setVirtualizationCallback方法。可以通过onDeviceChange回调接口获取设备的连接事件和启动停止虚拟化事件。通过onPinCode获取显示pinCode,连接设备的时候鉴权使用。需要在writeSecureFile方法中,实现对鉴权文件的存储;需要在readSecureFile方法中,实现对鉴权文件的读取;需要在getSecureFileSize方法中,实现获取鉴权文件的大小。

    1. 设备的连接和虚拟化事件处理。
      @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(); 
          }
      }
    2. 显示设备连接码。

      当有手机进行首次连接时,应用会收到onPinCode事件通知进行连接码显示。

      @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(""); 
                  } 
              } 
          }); 
      }

      设备连接码需通过UI界面呈现给用户,用户在手机端输入该连接码进行认证,详细请参见《Huawei DV Engine三方安卓电视集成UX设计规范.pdf》。

    3. 鉴权文件管理。
    @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; 
    }

  3. 启动发现监听。

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

    mVirtualizationAdapter.startAdv();

  4. 停止发现监听。

    通过VirtualizationAdapter实例对象的stopAdv停止发现监听,监听停止成功后,手机不能发现该设备。

    mVirtualizationAdapter.stopAdv();

  5. 断开连接设备。

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

    mVirtualizationAdapter.disconnectDevice();

  6. 更新本地设备的名字。

    当前设备名称发生变化时需通过updateDeviceName通知DV Engine更新设备名称。

    mVirtualizationAdapter.updateDeviceName("new device name");

  7. 已认证过的设备管理。

    通过VirtualizationAdapter实例对象的getTrustDeviceList获取已经认证过的设备列表。

    mVirtualizationAdapter.getTrustDeviceList();

    通过VirtualizationAdapter实例对象的deleteTrustDevice删除制定的已认证设备信息。

    mVirtualizationAdapter.deleteTrustDevice (deviceId);

    设备管理需提供UI界面,详情请参见UX设计规范。

  8. 释放连接对象。

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

    VirtualizationAdapter.releaseInstance();

  9. 获取SDK版本号。

    通过VirtualizationAdapter静态方法getVersion可获取DV Engine的版本号,可以用来进行兼容性判断处理。

    VirtualizationAdapter.getVersion();

  10. Camera南向接口适配。

    DV Engine提供了Camera的南向适配接口,当厂商设备不支持Camera的Android标准接口或者Android标准接口性能较差时,可以使用Camera南向接口适配的方式。

    1. Camera南向接口使用C语言实现,请参照南向适配接口说明中的接口描述对相应接口进行实现。
    2. 接口实现后需编译成动态库,动态库名称必须为libdmsdpcamerahandler.so。
    3. 编译出来的64位和32位的动态库libdmsdpcamerahandler.so包分别放在HwDMSDPDevice.apk安装路径下的“lib/arm64/和lib/arm/”下。