Android 시스템 에 서 비 스 를 추가 하 는 방법 강좌

머리말
최근 에 회사 의 플랫폼 이 안 드 로 이 드 4.4.4 에서 안 드 로 이 드 6.0 으로 전환 해 야 하기 때문에 문 제 는 우리 가 시스템 에 서 비 스 를 추 가 했 기 때문에 일부 시스템 급 서 비 스 를 이전 하고 일부 Framework 의 사용자 정의 패 키 지 를 이전 해 야 한 다 는 것 이다.
공교롭게도 Gerrit 에서 시스템 서 비 스 를 추가 하 는 패 치 를 보 았 습 니 다.마침 정 리 를 했 습 니 다.저 는 프레임 워 크 엔지니어 가 아니 지만 안 드 로 이 드 시스템 을 이해 하 는 것 이 좋 습 니 다.
시스템 서 비 스 를 어떻게 가 져 옵 니까?
Google 은 시스템 서 비 스 를 context 에서 가 져 왔 습 니 다.getSystemService 에서 가 져 왔 습 니 다.getSystemService 에서 어떤 일이 일 어 났 는 지 살 펴 보 겠 습 니 다.
getSystemService 의 실현 은 ContextImpl 입 니 다.ContextImpl 의 소스 코드 를 보면 알 수 있 습 니 다.
Android 4.4.4 (KitKat)
여 기 는 Android 4.4.4 의 소스 코드 입 니 다.6.0 의 소스 코드 는 잠시 후에 보 겠 습 니 다.

 //           
 @Override
 public Object getSystemService(String name) {
  //          HashMap     .
  ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
  return fetcher == null ? null : fetcher.getService(this);
 }

 private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
    new HashMap<String, ServiceFetcher>();
 //         ,        
 private static void registerService(String serviceName, ServiceFetcher fetcher) {
  if (!(fetcher instanceof StaticServiceFetcher)) {
   fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
  }
  SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
 } 
저 희 는 ContextImpl 에서 정적 코드 블록 을 많이 보 았 습 니 다.모두 등록 서비스 이 고 저희 가 자주 사용 하 는 시스템 서비스 입 니 다.

 static {
   registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
     public Object getService(ContextImpl ctx) {
      return AccessibilityManager.getInstance(ctx);
     }});

   registerService(CAPTIONING_SERVICE, new ServiceFetcher() {
     public Object getService(ContextImpl ctx) {
      return new CaptioningManager(ctx);
     }});
  ....
 }
그 러 고 보 니 이곳 이 우리 가 서 비 스 를 등록 하 는 곳 이 아 닙 니까?
소.우 리 는 시스템 서 비 스 를 등록 하 는 곳 을 찾 았 습 니 다.여기 서 우 리 는 우리 가 등록 하고 싶 은 서 비 스 를 추가 하고new ServiceFetcher() 의 추상 적 인 방법 을 완성 하면 됩 니 다.그러면 우 리 는 나중에 getSystemService 에 가입 할 때의 이름 을 입력 하면 우리 의 서비스 대상 을 얻 을 수 있 습 니 다.물론 이것 은 4.4 의 방법 입 니 다.
Android 6.0 (Marshmallow)
ContextImpl 코드 를 살 펴 보 겠 습 니 다.

 @Override
 public Object getSystemService(String name) {
  return SystemServiceRegistry.getSystemService(this, name);
 }
우 리 는 KitKat 와 크게 다르다 는 것 을 발견 했다.Marshmallow 는 System Service Registry 라 는 종류 에서 얻 은 것 이다.
자,그럼 우 리 는 그것 의 소스 코드 를 보 러 갑 니 다.원래 예전 과 같은 방식 이 었 습 니 다.단지 이러한 등록 서 비 스 를 관리 하기 위해 하나의 종 류 를 따로 포장 한 것 에 불과 합 니 다.이렇게 디자인 하 는 것 이 정말 좋 습 니 다.코드 상의 결합 도 는 훨씬 작 아 보이 고 ContextImpl 과 같은 종 류 는 점점 비대 해 지지 않 습 니 다.

final class SystemServiceRegistry {
 private final static String TAG = "SystemServiceRegistry";

 // Service registry information.
 // This information is never changed once static initialization has completed.
 private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
   new HashMap<Class<?>, String>();
 private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
   new HashMap<String, ServiceFetcher<?>>();
 private static int sServiceCacheSize;

 // Not instantiable.
 private SystemServiceRegistry() { }

 static {
  registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
    new CachedServiceFetcher<AccessibilityManager>() {
   @Override
   public AccessibilityManager createService(ContextImpl ctx) {
    return AccessibilityManager.getInstance(ctx);
   }});

  registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
    new CachedServiceFetcher<CaptioningManager>() {
   @Override
   public CaptioningManager createService(ContextImpl ctx) {
    return new CaptioningManager(ctx);
   }});
 ....
소.우리 Marshmallow 의 시스템 서 비 스 는 System 서비스 레 지 스 트 리 클래스 에 추가 해 야 합 니 다.같은 방식 입 니 다.그 다음 에 getSystem 서비스 에 가입 할 때의 이름 을 입력 하면 우리 의 서비스 대상 을 얻 을 수 있 습 니 다.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기