어댑터 패턴?

그래서 최근에 저는 사용자가 웹 앱과 브라우저 API를 사용하는 Android에서 카메라/마이크에 대한 권한을 부여할 수 있는 방법을 만들어야 하는 문제를 발견했습니다. Android용은 cordova 플러그인이었습니다. 안드로이드에서는 같은 개념으로 조금 다릅니다. 따라서 먼저 브라우저의 권한이 허용되는지 확인한 다음 권한을 요청해야 합니다. 논리는 샘입니다. 그래서 나 자신을 반복하는 대신에 만들어야 했기 때문에(어댑터 패턴을 사용하지 않고 어댑터를 사용하려는 파일에 반복 코드를 사용하는 경우) 어댑터 패턴에 대해 알게 되었습니다. 그 개념은 꽤 흥미로운 엔지니어링 패턴 중 하나입니다. 처음에는 머리를 이해하기가 약간 어렵지만 다음에 할 때 훨씬 더 쉬워지는 것이 얼마나 유익한지 알 수 있습니다.

나는 당신에게 최근 프로젝트에 대한 예를 제공할 것이며 당신이 당신의 작업에 그것을 사용하는 데 도움이 되기를 바랍니다. 나는 또한 마이크 확인을 위해 mic-check 패키지를 사용합니다. 어디선가 보고 멋지다고 생각했기 때문입니다. 아래 예제는 완전히 완료되지 않았지만 아이디어를 얻을 수 있습니다...

type AdapterType = {
  requestCameraPermission: () => void,
  requestMicrophonePermission: () => void,
  hasCameraPermission: () => Promise<boolean>,
  hasMicrophonePermission: () => Promise<boolean>,
};

export class PermissionsApiAdapter {
   hasCameraPermission = () =>
    navigator.permissions.query({ name: 'camera' }).then((permissionObj) => {
      console.log('permissionObj state:', permissionObj.state);

      return permissionObj.state === 'granted';
    });

  hasMicrophonePermission = () =>
    navigator.permissions
      .query({ name: 'microphone' })
      .then((permissionObj) => {
        console.log(permissionObj.state);

        return permissionObj.state === 'granted';
      });

  requestCameraPermission = () => {
    const cameraPermissions =
      navigator.mediaDevices &&
      navigator.mediaDevices.getUserMedia({
        video: true,
      });

    if (cameraPermissions) {
      return cameraPermissions
        .then(() => {
          alert('Accept permissions camera');
          console.log('request camera permissions enabled');

          return Promise.resolve(true);
        })
        .catch((err) =>
          Promise.reject(new Error(`${err.name} : ${err.message}`))
        );
    }

    return Promise.resolve(false);
  };

  requestMicrophonePermission = () => {
    const audioPermissions =
      navigator.mediaDevices &&
      navigator.mediaDevices.getUserMedia({
        audio: true,
      });

    if (audioPermissions) {
      return audioPermissions
        .then(() => {
          alert('Accept permissions microphone');
          console.log('request microphone permissions enabled');

          return Promise.resolve(true);
        })
        .catch((err: MediaPermissionsError) => {
          const { type } = err;

          if (type === MediaPermissionsErrorType.SystemPermissionDenied) {
            console.log(
              'browser does not have permission to access camera or microphone'
            );
          } else if (type === MediaPermissionsErrorType.UserPermissionDenied) {
            console.log('user didnt allow app to access camera or microphone');
          } else if (
            type === MediaPermissionsErrorType.CouldNotStartVideoSource
          ) {
            console.log(
              'camera is in use by another application (Zoom, Skype) or browser tab (Google Meet, Messenger Video'
            );
          }

          return Promise.reject(new Error(`${err.name} : ${err.message}`));
        });
    }

    return Promise.resolve(false);
  };
}

class WebAppsPermission {
  constructor(permissionAdapter: AdapterType) {
    this.permissionAdapter = permissionAdapter;
  }

  permissionAdapter: AdapterType;

  requestCameraPermission = () =>
    this.permissionAdapter.requestCameraPermission();
  requestMicrophonePermission = () =>
    this.permissionAdapter.requestMicrophonePermission();
  hasCameraPermission = () => this.permissionAdapter.hasCameraPermission();
  hasMicrophonePermission = () =>
    this.permissionAdapter.hasMicrophonePermission();
}

export default WebAppsPermission;


이제 Android 앱의 경우 어댑터에는 기능이 약간 다른 동일한 논리가 있습니다.


type AndroidAdapterType = {
  requestCameraPermission: () => void,
  requestMicrophonePermission: () => void,
  hasCameraPermission: () => Promise<boolean>,
  hasMicrophonePermission: () => Promise<boolean>,
};

export class AndroidPermissionsApiAdapter {
   hasCameraPermission = (): Promise<boolean> =>
    new Promise((resolve, reject) => {
      window.cordova.plugins.diagnostic.isCameraAuthorized(
        (authorized) => {
          console.log(
            `App is ${
              authorized ? 'authorized' : 'denied'
            } access to the camera`
          );

          resolve(authorized);
        },
        (error) => {
          console.error(`The following error occurred: ${error}`);
          reject(error);
        },
        false
      );
    });

  hasMicrophonePermission = (): Promise<boolean> =>
    new Promise((resolve, reject) => {
      window.cordova.plugins.diagnostic.isMicrophoneAuthorized(
        (authorized) => {
          console.log(
            `App is ${
              authorized ? 'authorized' : 'denied'
            } access to the microphone`
          );
          resolve(authorized);
        },
        (error) => {
          console.error(`The following error occurred: ${error}`);
          reject(error);
        }
      );
    });

  requestCameraPermission = (): Promise<boolean> =>
    new Promise((resolve, reject) => {
      window.cordova.plugins.diagnostic.requestCameraAuthorization(
        (status) => {
          console.log(
            `Authorization request for camera use was ${
              status ===
              window.cordova.plugins.diagnostic.permissionStatus.GRANTED
                ? 'granted'
                : 'denied'
            }`
          );
          resolve(status);
        },
        (error) => {
          console.error(error);
          reject(error);
        },

        false
      );
    });

  requestMicrophonePermission = (): Promise<boolean> =>
    new Promise((resolve, reject) => {
      window.cordova.plugins.diagnostic.requestMicrophoneAuthorization(
        (status) => {
          if (
            status ===
            window.cordova.plugins.diagnostic.permissionStatus.GRANTED
          ) {
            console.log('Microphone use is authorized');
          }

          resolve(status);
        },
        (error) => {
          console.error(error);
          reject(error);
        }
      );
    });
}

class AndroidPermissions {
  constructor(permissionAdapter: CordovaAdapterType) {
    this.permissionAdapter = permissionAdapter;
  }

  permissionAdapter: AndroidAdapterType;

  requestCameraPermission = () =>
    this.permissionAdapter.requestCameraPermission();
  requestMicrophonePermission = () =>
    this.permissionAdapter.requestMicrophonePermission();
  hasCameraPermission = () => this.permissionAdapter.hasCameraPermission();
  hasMicrophonePermission = () =>
    this.permissionAdapter.hasMicrophonePermission();
}

export default AndroidPermissions;



그리고 제 경우에는 특정 폴더에서 사용하려고 했을 때 Context Provider
const adapter = new PermissionsApiAdapter();
    const cordovaAdapter = new AndroidPermissionsApiAdapter();
    const mediaPermission = new WebAppsPermission(
      window.cordova ? cordovaAdapter : adapter
    );


이제 공급자 또는 원하는 코드의 모든 위치에서 어댑터를 사용할 수 있습니다.

의미가 있기를 바랍니다 ☺️

좋은 웹페이지 즐겨찾기