원격 프로세스에서 Android 서비스 실행Running Android Services in Remote Processes

일반적으로 Android 응용 프로그램의 모든 구성 요소는 동일한 프로세스에서 실행 됩니다. Android 서비스는 다른 Android 개발자의 프로세스를 비롯 하 여 자체 프로세스에서 실행 되 고 다른 응용 프로그램과 공유 되도록 구성할 수 있다는 점에서 주목할 만한 예외입니다. 이 가이드에서는 Xamarin을 사용 하 여 Android 원격 서비스를 만들고 사용 하는 방법을 설명 합니다.Generally, all components in an Android application will run in the same process. Android services are a notable exception to this in that they can be configured to run in their own processes and shared with other applications, including those from other Android developers. This guide will discuss how to create and use an Android remote service using Xamarin.

Out-of-process 서비스 개요Out of Process Services Overview

응용 프로그램이 시작 되 면 Android는 응용 프로그램을 실행 하는 프로세스를 만듭니다.When an application starts up, Android creates a process in which to run the application. 일반적으로이 프로세스에서 응용 프로그램이 실행 되는 모든 구성 요소입니다.Typically, all the components the application will run in this one process. Android 서비스는 다른 Android 개발자의 프로세스를 비롯 하 여 자체 프로세스에서 실행 되 고 다른 응용 프로그램과 공유 되도록 구성할 수 있다는 점에서 주목할 만한 예외입니다.Android services are a notable exception to this in that they can be configured to run in their own processes and shared with other applications, including those from other Android developers. 이러한 유형의 서비스를 원격 서비스 또는 _out-of-process 서비스_라고 합니다.These types of services are referred to as remote services or out-of-process services. 이러한 서비스에 대 한 코드는 주 응용 프로그램과 동일한 APK에 포함 됩니다. 그러나 서비스를 시작 하면 Android에서 해당 서비스에 대해서만 새 프로세스를 만듭니다.The code for these services will be contained in the same APK as the main application; however, when the service is started Android will create a new process for just that service. 이와 달리 응용 프로그램의 나머지 부분과 동일한 프로세스에서 실행 되는 서비스는 _로컬 서비스_라고도 합니다.In contrast, a service that runs in the same process as the rest of the application is sometimes referred to as a local service.

일반적으로 응용 프로그램에서 원격 서비스를 구현할 필요는 없습니다.In general, it is not necessary for an application to implement a remote service. 대부분의 경우 로컬 서비스는 앱의 요구 사항에 따라 충분 하 고 바람직한 방법입니다.A local service is sufficient (and desirable) for an app's requirements in many cases. Out-of-process에는 Android에서 관리 해야 하는 자체 메모리 공간이 있습니다.An out-of-process has it's own memory space which must be managed by Android. 이 경우 전체 응용 프로그램에 더 많은 오버 헤드가 발생 하지만 서비스를 자체 프로세스에서 실행 하는 것이 유용할 수 있는 몇 가지 시나리오가 있습니다.Although this does introduce more overhead to the overall application, there are some scenarios where it can be advantageous to run a service in its own process:

  1. 공유 기능 – 일부 응용 프로그램 개발자에 게는 모든 응용 프로그램 간에 공유 되는 여러 앱 및 기능이 있을 수 있습니다.Sharing Functionality – Some application developers may have multiple apps and functionality that is shared between all the applications. 자체 프로세스에서 실행 되는 Android 서비스에서 해당 기능을 패키징하 면 응용 프로그램 유지 관리를 간소화할 수 있습니다.Packaging that functionality in an Android service which runs in its own process may simplify application maintenance. 또한 자체 독립 실행형 APK에서 서비스를 패키지 하 고 응용 프로그램의 나머지 부분과 별도로 배포할 수 있습니다.It is also possible to package the service in its own stand-alone APK and deploy it separately from the rest of the application.

  2. 사용자 환경 – 향상 된 두 가지 방법으로 out-of-process 서비스가 응용 프로그램의 사용자 환경을 향상 시킬 수 있습니다.Improving the User Experience – There are two possible ways that an out-of-process service can improve the user experience of the application. 첫 번째 방법은 메모리 관리를 처리 하는 것입니다.The first way deals with memory management. GC (가비지 수집) 순환이 발생 하면 Android는 GC가 완료 될 때까지 프로세스의 모든 작업을 일시 중지 합니다.When a garbage collection (GC) cycle occurs, Android will pause all activity in the process until the GC is complete. 사용자가이 일시 중지를 "끊길" 또는 "jank"로 인지할 수 있습니다.The user might perceive this pause as a "stutter" or "jank". 서비스가 자체 프로세스에서 실행 되는 경우 응용 프로그램 프로세스가 아닌 일시 중지 된 서비스 프로세스입니다.When a service is running in it's own process, it is the service process that is paused, not the application process. 이 일시 중지는 응용 프로그램 프로세스 (따라서 사용자 인터페이스)가 일시 중지 되지 않으므로 사용자에 게 훨씬 더 두드러집니다.This pause will be much less noticeable to the user as the application process (and therefore the user interface) is not paused.

    둘째, 프로세스의 메모리 요구 사항이 너무 커지면 Android에서 해당 프로세스를 종료 하 여 장치에 대 한 리소스를 확보할 수 있습니다.Secondly, if the memory requirements of a process becomes too large, Android may kill that process to free up resources for the device. 서비스의 메모리 공간이 크고 UI와 동일한 프로세스에서 실행 되는 경우 Android가 해당 리소스를 강제로 회수할 때 UI가 종료 되 고 사용자가 앱을 시작 하 게 됩니다.If a service does have a large memory footprint and it is running in the same process as the UI, then when Android forcibly reclaims those resources the UI will be shut down, forcing the user to start the app. 그러나 자체 프로세스에서 실행 되는 서비스가 Android에서 종료 되는 경우 UI 프로세스는 영향을 받지 않습니다.However, if a service, running in its own process is shut down by Android, the UI process remains unaffected. UI는 사용자에 게 투명 하 게 서비스를 바인딩하고 다시 시작 하 고 정상적인 기능을 다시 시작할 수 있습니다.The UI can bind (and restart) the service, transparent to the user, and resume normal functioning.

  3. 응용 프로그램 성능 향상 – UI 프로세스가 종료 되거나 서비스 프로세스와 별개로 종료 될 수 있습니다.Improving Application Performance – The UI process may be terminated or shut down independent of the service process. 시간이 오래 걸리는 시작 작업을 out-of-process 서비스로 이동 하면 UI 시작 시간이 향상 될 수 있습니다 (서비스 프로세스가 UI 시작 시간 사이에 활성 상태로 유지 되는 것으로 가정).By moving lengthy startup tasks to an out-of-process service, it is possible that the startup time of the UI maybe improved (assuming that the service process is kept alive in between the times that UI is launched).

여러 가지 방법으로 다른 프로세스에서 실행 되는 서비스에 바인딩하는 것은 로컬 서비스에 바인딩하는 것과 같습니다.In many ways, binding to a service running in another process is the same as binding to a local service. 클라이언트는 BindService를 호출 하 여 서비스를 바인딩하고 필요한 경우 시작 합니다.The client will invoke BindService to bind (and start, if necessary) the service. 클라이언트와 서비스 간의 연결을 관리 하기 위해 Android.OS.IServiceConnection 개체가 생성 됩니다.An Android.OS.IServiceConnection object will be created to manage the connection between the client and the service. 클라이언트에서 서비스에 성공적으로 바인딩한 경우 Android는 서비스에서 메서드를 호출 하는 데 사용할 수 있는 IServiceConnection을 통해 개체를 반환 합니다.If the client successfully binds to the service, then Android will return an object via the IServiceConnection that can be used to invoke methods on the service. 그러면 클라이언트는이 개체를 사용 하 여 서비스와 상호 작용 합니다.The client then interacts with the service using this object. 검토 하려면 서비스에 바인딩하는 단계는 다음과 같습니다.To review, here are the steps to bind to a service:

  • 의도 – 만들려면 명시적 의도를 서비스에 바인딩하는 데 사용 해야 합니다.Create an Intent – An explicit intent must be used to binding to the service.
  • 클라이언트와 서비스 간의 중개자 역할을 하는 IServiceConnection 개체가 – IServiceConnection 개체를 구현 하 고 인스턴스화합니다 .Implement and Instantiate an IServiceConnection object – The IServiceConnection object acts as an intermediary between the client and the service. 클라이언트와 서버 간의 연결을 모니터링 하는 일을 담당 합니다.It is responsible for monitoring the connection between client and server.
  • BindService BindService – 메서드를 호출 하 여 이전 단계에서 만든 의도 및 서비스 연결을 Android로 디스패치합니다. 그러면 서비스를 시작 하 고 클라이언트와 서비스 간 통신을 설정 합니다. .Invoke the BindService method – Calling BindService will dispatch the intent and the service connection created in the previous steps to Android, which will take care of starting the service and establishing communication between client and service.

프로세스 경계를 교차 하지 않아도 되는 추가 복잡성이 도입 됩니다. 통신은 단방향 (클라이언트에서 서버로)이 고 클라이언트는 서비스 클래스에서 메서드를 직접 호출할 수 없습니다.The need to cross process boundaries does introduce extra complexity: the communication is one-way (client to server) and the client can't directly invoke methods on the service class. 서비스가 클라이언트와 동일한 프로세스를 실행 하는 경우 Android는 양방향 통신을 허용할 수 있는 IBinder 개체를 제공 합니다.Recall that when a service is running the same process as the client, Android provides an IBinder object which may allow for two-way communication. 이는 서비스가 자체 프로세스에서 실행 되는 경우에는 그렇지 않습니다.This is not the case with service running in its own process. 클라이언트는 Android.OS.Messenger 클래스의 도움을 사용 하 여 원격 서비스와 통신 합니다.A client communicates with a remote service with the help of the Android.OS.Messenger class.

클라이언트가 원격 서비스에 바인딩하기를 요청 하면 Android는 Service.OnBind 수명 주기 메서드를 호출 하며,이 메서드는 Messenger 캡슐화 된 내부 IBinder 개체를 반환 합니다.When a client requests to bind with the remote service, Android will invoke the Service.OnBind lifecycle method, which will return the internal IBinder object that is encapsulated by the Messenger. Messenger은 Android SDK에서 제공 하는 특수 한 IBinder 구현에 대 한 씬 래퍼입니다.The Messenger is a thin wrapper over a special IBinder implementation that is provided by the Android SDK. Messenger는 서로 다른 두 프로세스 간의 통신을 처리 합니다.The Messenger takes care of the communication between the two different processes. 개발자는 메시지를 직렬화 하 고 프로세스 경계를 넘어 메시지를 마샬링 한 다음 클라이언트에서 deserialize 하는 방법에 대해 걱정할 필요가 없습니다.The developer is unconcerned with the details of serializing a message, marshalling the message across the process boundary, and then deserializing it on the client. 이 작업은 Messenger 개체에 의해 처리 됩니다.This work is handled by the Messenger object. 이 다이어그램에서는 클라이언트가 out-of-process 서비스에 대 한 바인딩을 시작할 때 수반 되는 클라이언트 쪽 Android 구성 요소를 보여 줍니다.This diagram shows the client-side Android components that are involved when a client initiates binding to an out-of-process service:

클라이언트에서 서비스에 바인딩하는 단계 및 구성 요소를 보여 주는 다이어그램Diagram that shows the steps and components for a client binding to a service

원격 프로세스의 Service 클래스는 로컬 프로세스의 바인딩된 서비스에서 통과 하는 것과 관련 된 많은 Api가 동일한 수명 주기 콜백을 거칩니다.The Service class in the remote process will go through the same lifecycle callbacks that a bound service in a local process will go through, and many of the APIs involved are the same. Service.OnCreateHandler를 초기화 하 고 Messenger 개체에 삽입 하는 데 사용 됩니다.Service.OnCreate is used to initialize a Handler and inject that into Messenger object. 마찬가지로 OnBind 재정의 되지만 IBinder 개체를 반환 하는 대신 서비스에서 Messenger을 반환 합니다.Likewise, OnBind is overridden, but instead of returning an IBinder object, the service will return the Messenger. 이 다이어그램은 클라이언트가 바인딩하는 경우 서비스에서 발생 하는 상황을 보여 줍니다.This diagram illustrates what happens in the service when a client is binding to it:

원격 클라이언트에서 바인딩할 때 서비스가 거치는 단계 및 구성 요소를 보여 주는 다이어그램Diagram that shows the steps and components a service goes through when being bound to by a remote client

서비스가 Message 수신 되 면 Android.OS.Handler의 인스턴스에서를 통해 처리 됩니다.When a Message is received by a service, it is processed by in instance of Android.OS.Handler. 서비스는 HandleMessage 메서드를 재정의 해야 하는 자체 Handler 서브 클래스를 구현 합니다.The service will implement its own Handler subclass that must override the HandleMessage method. 이 메서드는 Messenger에서 호출 되며 Message를 매개 변수로 받습니다.This method is invoked by the Messenger and receives the Message as a parameter. HandlerMessage 메타 데이터를 검사 하 고이 정보를 사용 하 여 서비스에서 메서드를 호출 합니다.The Handler will inspect the Message meta-data and use that information to invoke methods on the service.

단방향 통신은 클라이언트가 Message 개체를 만들고 Messenger.Send 메서드를 사용 하 여 서비스에 디스패치할 때 발생 합니다.One-way communication occurs when a client creates a Message object and dispatches it to the service using the Messenger.Send method. Messenger.SendMessage를 직렬화 하 고 직렬화 된 데이터를 Android로 전달 하 여 프로세스 경계와 서비스 간에 메시지를 라우팅합니다.Messenger.Send will serialize the Message and hand that serialized data off to Android, which will route the message across the process boundary and to the service. 서비스에서 호스트 되는 Messenger는 들어오는 데이터에서 Message 개체를 만듭니다.The Messenger that is hosted by the service will create a Message object from the incoming data. Message는 큐에 배치 됩니다 .이 큐에는 메시지가 한 번에 하나씩 Handler 전송 됩니다.This Message is placed into a queue, where messages are submitted one at a time to the Handler. HandlerMessage에 포함 된 메타 데이터를 검사 하 고 Service에서 적절 한 메서드를 호출 합니다.The Handler will inspect the meta-data contained in the Message and invoke the appropriate methods on the Service. 다음 다이어그램은 이러한 다양 한 개념의 동작을 보여 줍니다.The following diagram illustrates these various concepts in action:

메시지를 프로세스 간에 전달 하는 방법을 보여 주는 다이어그램Diagram showing how messages are passed between processes

이 가이드에서는 out-of-process 서비스를 구현 하는 방법에 대해 자세히 설명 합니다.This guide will discuss the details of implementing an out-of-process service. 자체 프로세스에서 실행 되는 서비스를 구현 하는 방법 및 클라이언트가 Messenger 프레임 워크를 사용 하 여 해당 서비스와 통신할 수 있는 방법을 설명 합니다.It will discuss how to implement a service that is meant to run in its own process and how a client may communicate with that service using the Messenger framework. 또한 서비스에 메시지를 보내는 클라이언트와 메시지를 다시 클라이언트로 보내는 서비스에 메시지를 보내는 양방향 통신에 대해서도 간략하게 설명 합니다.It will also briefly discuss two-way communication: the client sending a message to a service and the service sending a message back to the client. 서비스는 서로 다른 응용 프로그램 간에 공유할 수 있기 때문에이 가이드에서는 Android 권한을 사용 하 여 서비스에 대 한 클라이언트 액세스를 제한 하는 한 가지 방법에 대해서도 설명 합니다.Because services can be shared between different applications, this guide will also discuss one technique for limiting client access to the service by using Android permissions.

중요

Bugzilla 51940/GitHub 1950-격리 된 프로세스 및 사용자 지정 응용 프로그램 클래스가 있는 서비스는 오버 로드를 올바르게 true IsolatedProcess 보고 하지 못합니다.Bugzilla 51940/GitHub 1950 - Services with isolated processes and custom Application class fail to resolve overloads properly reports that a Xamarin.Android service will not start up properly when the IsolatedProcess is set to true. 이 가이드는 참조용으로 제공 됩니다.This guide is provided for a reference. Xamarin Android 응용 프로그램은 여전히 Java로 작성 된 out-of-process 서비스와 통신할 수 있어야 합니다.A Xamarin.Android application should still be able to communicate with an out-of-process service that is written in Java.

요구 사항Requirements

이 가이드에서는 서비스 만들기에 대해 잘 알고 있는 것으로 가정 합니다.This guide assumes familiarity with creating services.

이전 Android Api를 대상으로 하는 앱에서 암시적 의도를 사용할 수 있지만이 가이드는 명시적 의도를 사용 하는 경우에만 중점적으로 설명 합니다.Although it is possible to use implicit intents with apps that target older Android APIs, this guide will focus exclusively on the use of explicit intents. Android 5.0 (API 레벨 21) 이상을 대상으로 하는 앱은 명시적 의도를 사용 하 여 서비스와 바인딩해야 합니다. 이는이 가이드에서 설명 하는 기술입니다.Apps targeting Android 5.0 (API level 21) or higher must use an explicit intent to bind with a service; this is the technique that will be demonstrated in this guide..

별도의 프로세스에서 실행 되는 서비스 만들기Create a Service that Runs in a Separate Process

위에서 설명한 것 처럼 서비스가 자체 프로세스에서 실행 되는 사실은 몇 가지 다른 Api가 포함 되어 있음을 의미 합니다.As described above, the fact that a service is running in its own process means that some different APIs are involved. 간단히 설명 하면 원격 서비스를 사용 하 고 사용 하는 단계는 다음과 같습니다.As a quick overview, here are the steps to bind with and consume a remote service:

  • Service 형식의 하위 클래스 – Service 서브 클래스를 만들고 바인딩된 서비스의 수명 주기 메서드를 구현 합니다.Create the Service subclass – Subclass the Service type and implement the lifecycle methods for a bound service. 또한 Android에서 서비스가 자체 프로세스에서 실행 되 고 있음을 알리는 메타 데이터를 설정 해야 합니다.It is also necessary to set meta-data that will inform Android that the service is to run in its own process.
  • 클라이언트 요청을 분석 하 고, 클라이언트에서 전달 된 매개 변수를 추출 하 고, 서비스에서 적절 한 메서드를 호출 하는 HandlerHandler을 구현 합니다.Implement a Handler – The Handler is responsible for analyzing the client requests, extracting any parameters that were passed from the client, and invoking the appropriate methods on the service.
  • 위에서 설명한 대로 Messenger –를 인스턴스화하면Service는 클라이언트 요청을 이전 단계에서 만든 Handler로 라우팅하는 Messenger 클래스의 인스턴스를 유지 해야 합니다.Instantiate a Messenger – As described above, each Service must maintain an instance of the Messenger class that will route client requests to the Handler that was created in the previous step.

자체 프로세스에서 실행 되는 서비스는 근본적으로 여전히 바인딩된 서비스입니다.A service that is meant to run in its own process is, fundamentally, still a bound service. Service 클래스는 기본 Service 클래스를 확장 하 고 android에서 android 매니페스트에 번들 해야 하는 메타 데이터를 포함 하는 ServiceAttribute로 데코 레이트 됩니다.The service class will extend the base Service class and is decorated with the ServiceAttribute containing the meta-data that Android needs to bundle in the Android manifest. 먼저 out-of-process 서비스에 중요 한 다음 ServiceAttribute 속성을 사용 합니다.To begin with, the following properties of the ServiceAttribute that are important to an out-of-process service:

  1. Exported – 다른 응용 프로그램에서 서비스와 상호 작용할 수 있도록이 속성을 true으로 설정 해야 합니다.Exported – This property must be set to true to allow other applications to interact with the service. 이 속성의 기본값은 false입니다.The default value of this property is false.
  2. Process –이 속성을 설정 해야 합니다.Process – This property must be set. 서비스가 실행 될 프로세스의 이름을 지정 하는 데 사용 됩니다.It is used to specify the name of the process that the service will run in.
  3. IsolatedProcess –이 속성을 사용 하면 추가 보안이 가능 하 고, Android에서 시스템의 나머지 부분과 상호 작용 하는 데 필요한 최소한의 권한을 가진 격리 된 샌드박스에서 서비스를 실행 하도록 지시 합니다.IsolatedProcess – This property will enable extra security, telling Android to run the service in an isolated sandbox with minimal permission to interact with the rest of the system. Bugzilla 51940-격리 된 프로세스의 서비스 및 사용자 지정 응용 프로그램 클래스가 오버 로드를 제대로 해결 하지 못했습니다 .를참조 하세요.See Bugzilla 51940 - Services with isolated processes and custom Application class fail to resolve overloads properly.
  4. Permission – 클라이언트에서 요청 하 고 부여 해야 하는 사용 권한을 지정 하 여 서비스에 대 한 클라이언트 액세스를 제어할 수 있습니다.Permission – It is possible to control client access to the service by specifying a permission that clients must request (and be granted).

서비스 자체 프로세스를 실행 하려면 ServiceAttributeProcess 속성을 서비스 이름으로 설정 해야 합니다.To run a service its own process, the Process property on the ServiceAttribute must be set to the name of the service. 외부 응용 프로그램과 상호 작용 하려면 Exported 속성을 true으로 설정 해야 합니다.To interact with outside applications, the Exported property should be set to true. Exported false되는 경우 동일한 APK (즉, 동일한 응용 프로그램)의 클라이언트만 서비스와 상호 작용할 수 있습니다.If Exported is false, then only clients in the same APK (i.e. the same application) and running in the same process will be able to interact with the service.

서비스가 실행 되는 프로세스의 종류는 Process 속성 값에 따라 다릅니다.What kind of process the service will run in depends on the value of the Process property. Android는 다음과 같은 세 가지 유형의 프로세스를 식별 합니다.Android identifies three different types of processes:

  • 개인 프로세스 – 개인 프로세스는 해당 프로세스를 시작한 응용 프로그램에만 사용할 수 있는 프로세스입니다.Private Process – A private process is one that is only available to the application that started it. 프로세스를 개인으로 식별 하려면 해당 이름이 (세미콜론 )로 시작 해야 합니다.To identify a process as private, its name must start with a : (semi-colon). 이전 코드 조각과 스크린샷에 표시 된 서비스는 개인 프로세스입니다.The service depicted in the previous code snippet and screenshot is a private process. 다음 코드 조각은 ServiceAttribute의 예입니다.The following code snippet is an example of the ServiceAttribute:

    [Service(Name = "com.xamarin.TimestampService",
             Process=":timestampservice_process",
             Exported=true)]
    
  • 전역 프로세스 – 전역 프로세스에서 실행 되는 서비스는 장치에서 실행 되는 모든 응용 프로그램에 액세스할 수 있습니다.Global Process – A service that is run in a global process is accessible to all applications running on the device. 전역 프로세스는 소문자로 시작 하는 정규화 된 클래스 이름 이어야 합니다.A global process must be a fully qualified class name that starts with a lower case character. 서비스를 보호 하기 위해 단계를 수행 하지 않으면 다른 응용 프로그램에서 해당 서비스를 바인딩하고 상호 작용할 수 있습니다.(Unless steps are taken to secure the service, other applications may bind and interact with it. 무단 사용 으로부터 서비스를 보호 하는 방법에 대해서는이 가이드의 뒷부분에서 설명 합니다.Securing the service against unauthorized use will be discussed later in this guide.)

    [Service(Name = "com.xamarin.TimestampService",
             Process="com.xamarin.xample.messengerservice.timestampservice_process",
             Exported=true)]
    
  • 격리 된 프로세스 – 격리 된 프로세스는 자체 샌드박스에서 실행 되는 프로세스입니다 .이 프로세스는 시스템의 나머지 부분과 분리 된 별도의 권한을 갖지 않습니다.Isolated Process – An isolated process is a process that runs in its own sandbox, isolated from the rest of the system and with no special permissions of its own. 격리 된 프로세스에서 서비스를 실행 하기 위해 ServiceAttributeIsolatedProcess 속성은 다음 코드 조각과 같이 true로 설정 됩니다.To run a service in an isolated process, the IsolatedProcess property of the ServiceAttribute is set to true as shown in this code snippet:

    [Service(Name = "com.xamarin.TimestampService",
             IsolatedProcess= true,
             Process="com.xamarin.xample.messengerservice.timestampservice_process",
             Exported=true)]
    

격리 된 서비스는 신뢰할 수 없는 코드 로부터 응용 프로그램 및 장치를 보호 하는 간단한 방법입니다.An isolated service is a simple way to secure an application and the device against untrusted code. 예를 들어 앱은 웹 사이트에서 스크립트를 다운로드 하 여 실행할 수 있습니다.For example, an app may download and execute a script from a website. 이 경우 격리 된 프로세스에서이 작업을 수행 하면 신뢰할 수 없는 코드에 대 한 추가 보안 계층을 제공 하 여 Android 장치를 손상 시킬 수 있습니다.In this case, performing this in an isolated process provides an additional layer of security against untrusted code compromising the Android device.

중요

서비스를 내보낸 후에는 서비스의 이름을 변경 하면 안 됩니다.Once a service has been exported, the name of the service should not change. 서비스의 이름을 변경 하면 서비스를 사용 하는 다른 응용 프로그램이 중단 될 수 있습니다.Changing the name of the service may break other applications that are using the service.

Process 속성에 미치는 영향을 확인 하기 위해 다음 스크린샷에서는 자체 개인 프로세스에서 실행 되는 서비스를 보여 줍니다.To see the effect that the Process property has, the following screenshot shows a service running in its own private process:

개인 프로세스에서 실행 되는 서비스를 보여 주는 스크린샷Screenshot that shows a service running in a private process

다음 스크린샷에서는 글로벌 프로세스에서 실행 되는 Process="com.xamarin.xample.messengerservice.timestampservice_process" 및 서비스를 보여 줍니다.This next screenshot shows Process="com.xamarin.xample.messengerservice.timestampservice_process" and the service running in a global process:

전역 프로세스에서 실행 되는 서비스의 스크린샷Screenshot of a service running in a global process

ServiceAttribute 설정 되 면 서비스는 Handler를 구현 해야 합니다.Once the ServiceAttribute has been set, the service needs to implement a Handler.

처리기 구현Implementing a Handler

클라이언트 요청을 처리 하려면 서비스가 Handler를 구현 하 고 HandleMessage methodThis 해야 합니다 .이는 메서드가 클라이언트에서 메서드 호출을 캡슐화 하는 Message 인스턴스를 사용 하 고 해당 호출을 서비스에서 사용 하는 작업 또는 작업으로 변환 하는 것입니다. 따르십시오.To process client requests, the service must implement a Handler and override the HandleMessage methodThis is the method takes a Message instance which encapsulates the method call from the client and translates that call into some action or task that the service will perform. Message 개체는 정수 값인 What 라는 속성을 노출 하 고, 클라이언트와 서비스 간에 공유 되는의 의미를 제공 하며, 서비스에서 클라이언트에 대해 수행할 작업에 대 한 의미를 제공 합니다.The Message object exposes a property called What which is an integer value, the meaning of which is shared between the client and the service and relates to some task that the service is to perform for the client.

예제 응용 프로그램의 다음 코드 조각에서는 HandleMessage의 한 예를 보여 줍니다.The following code snippet from the sample application shows one example of HandleMessage. 이 예제에는 클라이언트가 서비스를 요청할 수 있는 두 가지 작업이 있습니다.In this example, there are two actions that a client can request of the service:

  • 첫 번째 작업은 Hello, 세계 메시지입니다. 클라이언트는 서비스에 간단한 메시지를 보냈습니다.The first action is a Hello, World message, the client has sent a simple message to the service.
  • 두 번째 작업은 서비스에서 메서드를 호출 하 고 문자열을 검색 합니다 .이 경우 문자열은 서비스가 시작 된 시간과 실행 시간을 반환 하는 메시지입니다.The second action will invoke a method on the service and retrieve a string, in this case the string is a message that returns what time the service started and how long it has been running:
public class TimestampRequestHandler : Android.OS.Handler
{
    // other code omitted for clarity

    public override void HandleMessage(Message msg)
    {
        int messageType = msg.What;
        Log.Debug(TAG, $"Message type: {messageType}.");

        switch (messageType)
        {
            case Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE:
                // The client as sent a simple Hello, say in the Android Log.
                break;

            case Constants.GET_UTC_TIMESTAMP:
                // Call methods on the service to retrieve a timestamp message.
                break;
            default:
                Log.Warn(TAG, $"Unknown messageType, ignoring the value {messageType}.");
                base.HandleMessage(msg);
                break;
        }
    }
}

또한 Message 서비스에 대 한 매개 변수를 패키지할 수 있습니다.It is also possible to package parameters for the service in the Message. 이에 대해서는이 가이드의 뒷부분에서 설명 합니다.This will be discussed later in this guide. 고려해 야 할 다음 항목은 들어오는 Messages를 처리 하는 Messenger 개체를 만드는 것입니다.The next topic to consider is creating the Messenger object to process the incoming Messages.

메신저 인스턴스화Instantiating the Messenger

앞에서 설명한 대로 Message 개체를 deserialize 하 고 Handler.HandleMessage를 호출 하는 것은 Messenger 개체의 책임입니다.As previously discussed, deserializing the Message object and invoking Handler.HandleMessage is the responsibility of the Messenger object. Messenger 클래스는 클라이언트에서 서비스에 메시지를 전송 하는 데 사용 하는 IBinder 개체도 제공 합니다.The Messenger class also provides an IBinder object that the client will use to send messages to the service.

서비스가 시작 되 면 Messenger을 인스턴스화하고 Handler를 삽입 합니다.When the service starts, it will instantiate the Messenger and inject the Handler. 이 초기화를 수행 하는 좋은 장소는 서비스의 OnCreate 메서드입니다.A good place to perform this initialization is on the OnCreate method of the service. 이 코드 조각은 자체 HandlerMessenger를 초기화 하는 서비스의 한 예입니다.This code snippet is one example of a service that initializes its own Handler and Messenger:

private Messenger messenger; // Instance variable for the Messenger

public override void OnCreate()
{
    base.OnCreate();
    messenger = new Messenger(new TimestampRequestHandler(this));
    Log.Info(TAG, $"TimestampService is running in process id {Android.OS.Process.MyPid()}.");
}

이 시점에서 마지막 단계는 Service OnBind를 재정의 하는 것입니다.At this point, the final step is for the Service to override OnBind.

서비스. OnBind 구현Implementing Service.OnBind

자체 프로세스에서 실행 되는지 여부에 관계 없이 모든 바인딩된 서비스는 OnBind 메서드를 구현 해야 합니다.All bound services, whether they run in their own process or not, must implement the OnBind method. 이 메서드의 반환 값은 클라이언트에서 서비스와 상호 작용 하는 데 사용할 수 있는 개체입니다.The return value of this method is some object that the client can use to interact with the service. 서비스가 로컬 서비스 인지 또는 원격 서비스 인지에 관계 없이 해당 개체는 정확히 달라 집니다.Exactly what that object is depends whether the service is a local service or a remote service. 로컬 서비스는 사용자 지정 IBinder 구현을 반환 하지만, 원격 서비스는 캡슐화 된 IBinder를 반환 하지만 이전 섹션에서 만든 Messenger를 반환 합니다.While a local service will return a custom IBinder implementation, a remote service will return the IBinder that is encapsulated but the Messenger that was created in the previous section:

public override IBinder OnBind(Intent intent)
{
    Log.Debug(TAG, "OnBind");
    return messenger.Binder;
}

이러한 세 단계가 완료 되 면 원격 서비스가 완료 된 것으로 간주 될 수 있습니다.Once these three steps are accomplished, the remote service can be considered complete.

서비스 사용Consuming the Service

모든 클라이언트는 원격 서비스를 바인딩하고 사용할 수 있도록 일부 코드를 구현 해야 합니다.All clients must implement some code to be able to bind and consume the remote service. 개념적으로 클라이언트의 관점에서 로컬 서비스 또는 원격 서비스에 바인딩하는 것 사이에는 약간의 차이가 있습니다.Conceptually, from the client's viewpoint, there are very few differences between binding to local service or a remote service. 클라이언트는 BindService 메서드를 호출 하 여 서비스 및 클라이언트와 서비스 간의 연결을 관리 하는 데 도움이 되는 IServiceConnection를 식별 하는 명시적 의도를 전달 합니다.The client invokes the BindService method, passing an explicit intent to identify the service and an IServiceConnection that helps manage the connection between the client and the service.

이 코드 조각은 원격 서비스에 바인딩하기 위한 명시적 의도 를 만드는 방법의 예입니다.This code snippet is an example of how to create an explicit intent for binding to a remote service. 의도는 서비스 및 서비스 이름을 포함 하는 패키지를 식별 해야 합니다.The intent must identify the package that contains the service and the name of the service. 이 정보를 설정 하는 한 가지 방법은 Android.Content.ComponentName 개체를 사용 하 고이를 의도에 제공 하는 것입니다.One way to set this information is to use an Android.Content.ComponentName object and to provide that to the intent. 이 코드 조각은 한 가지 예입니다.This code snippet is one example:

// This is the package name of the APK, set in the Android manifest
const string REMOTE_SERVICE_COMPONENT_NAME = "com.xamarin.TimestampService";
// This is the name of the service, according the value of ServiceAttribute.Name
const string REMOTE_SERVICE_PACKAGE_NAME   = "com.xamarin.xample.messengerservice";

// Provide the package name and the name of the service with a ComponentName object.
ComponentName cn = new ComponentName(REMOTE_SERVICE_PACKAGE_NAME, REMOTE_SERVICE_COMPONENT_NAME);
Intent serviceToStart = new Intent();
serviceToStart.SetComponent(cn);

서비스가 바인딩되면 IServiceConnection.OnServiceConnected 메서드가 호출 되 고 클라이언트에 IBinder를 제공 합니다.When the service is bound, the IServiceConnection.OnServiceConnected method is invoked and provides an IBinder to a client. 그러나 클라이언트는 IBinder를 직접 사용 하지 않습니다.However, the client will not directly use the IBinder. 대신 해당 IBinder에서 Messenger 개체를 인스턴스화합니다.Instead, it will instantiate a Messenger object from that IBinder. 이는 클라이언트가 원격 서비스와 상호 작용 하는 데 사용 하는 Messenger입니다.This is the Messenger that the client will use to interact with the remote service.

다음은 클라이언트에서 서비스 연결 및 연결 끊기를 처리 하는 방법을 보여 주는 매우 기본적인 IServiceConnection 구현의 예입니다.The following is an example of a very basic IServiceConnection implementation that demonstrates how a client would handle connecting to and disconnecting from a service. OnServiceConnected 메서드는 및 IBinder를 받고, 클라이언트는 해당 IBinder에서 Messenger을 만듭니다.Notice that the OnServiceConnected method receives and IBinder, and the client creates a Messenger from that IBinder:

public class TimestampServiceConnection : Java.Lang.Object, IServiceConnection
{
    static readonly string TAG = typeof(TimestampServiceConnection).FullName;

    MainActivity mainActivity;
    Messenger messenger;

    public TimestampServiceConnection(MainActivity activity)
    {
        IsConnected = false;
        mainActivity = activity;
    }

    public bool IsConnected { get; private set; }
    public Messenger Messenger { get; private set; }

    public void OnServiceConnected(ComponentName name, IBinder service)
    {
        Log.Debug(TAG, $"OnServiceConnected {name.ClassName}");

        IsConnected = service != null
        Messenger = new Messenger(service);

        if (IsConnected)
        {
            // things to do when the connection is successful. perhaps notify the client? enable UI features?
        }
        else
        {
            // things to do when the connection isn't successful.
        }
    }

    public void OnServiceDisconnected(ComponentName name)
    {
        Log.Debug(TAG, $"OnServiceDisconnected {name.ClassName}");
        IsConnected = false;
        Messenger = null;

        // Things to do when the service disconnects. perhaps notify the client? disable UI features?

    }
}

서비스 연결 및 의도가 만들어지면 클라이언트는 BindService를 호출 하 고 바인딩 프로세스를 시작할 수 있습니다.Once the service connection and the intent are created, it is possible for the client to call BindService and initiate the binding process:

IServiceConnection serviceConnection = new TimestampServiceConnection(this);
BindActivity(serviceToStart, serviceConnection, Bind.AutoCreate);

클라이언트가 서비스에 성공적으로 연결 되 고 Messenger를 사용할 수 있게 되 면 클라이언트가 서비스에 Messages를 보낼 수 있습니다.After the client has successfully bound to the service and the Messenger is available, it is possible for the client to send Messages to the service.

서비스에 메시지 보내기Sending Messages to the Service

클라이언트가 연결 되어 있고 Messenger 개체가 있는 경우 Messenger를 통해 Message 개체를 디스패치 하 여 서비스와 통신할 수 있습니다.Once the client is connected and has a Messenger object, it is possible to communicate with the service by dispatching Message objects via the Messenger. 이 통신은 단방향 이며 클라이언트는 메시지를 보내지만 서비스에서 클라이언트로의 반환 메시지는 없습니다.This communication is one-way, the client sends the message but there is no return message from the service to the client. 이와 관련 하 여 Message는 화재 및 잊은 메커니즘입니다.In this regard, the Message is a fire-and-forget mechanism.

Message 개체를 만드는 기본 방법은 Message.Obtain factory 메서드를 사용 하는 것입니다.The preferred way to create a Message object is to use the Message.Obtain factory method. 이 메서드는 Android에서 유지 관리 되는 전역 풀에서 Message 개체를 가져옵니다.This method will pull a Message object from a global pool that is maintained by Android. 또한 Message.Obtain에는 서비스에 필요한 값 및 매개 변수를 사용 하 여 Message 개체를 초기화할 수 있도록 하는 오버 로드 된 메서드가 포함 되어 있습니다.Message.Obtain also has some overloaded methods that allow the Message object to be initialized with the values and parameters required by the service. Message 인스턴스화된 후에는 Messenger.Send를 호출 하 여 서비스로 발송 됩니다.Once the Message is instantiated, it dispatched to the service by calling Messenger.Send. 이 코드 조각은 서비스 프로세스에 대 한 Message를 만들고 발송 하는 한 가지 예입니다.This snippet is one example of creating and dispatching a Message to the service process:

Message msg = Message.Obtain(null, Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE);
try
{
    serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
    Log.Error(TAG, ex, "There was a error trying to send the message.");
}

Message.Obtain 메서드에는 여러 가지 형태가 있습니다.There are several different forms of the Message.Obtain method. 이전 예제에서는 Message.Obtain(Handler h, Int32 what)을 사용 합니다.The previous example uses the Message.Obtain(Handler h, Int32 what). 이는 out-of-process 서비스에 대 한 비동기 요청 이기 때문입니다. 서비스에서 응답이 없으므로 Handler null로 설정 됩니다.Because this is an asynchronous request to an out-of-process service; there will be no response from the service, so the Handler is set to null. 두 번째 매개 변수 Int32 whatMessage 개체의 .What 속성에 저장 됩니다.The second parameter, Int32 what, will be stored in the .What property of the Message object. .What 속성은 서비스 프로세스의 코드에서 서비스의 메서드를 호출 하는 데 사용 됩니다.The .What property is used by code in the service process to invoke methods on the service.

Message 클래스는 받는 사람에 사용 될 수 있는 두 가지 추가 속성 (Arg1Arg2도 노출 합니다.The Message class also exposes two additional properties that may be of use to the recipient: Arg1 and Arg2. 이러한 두 속성은 클라이언트와 서비스 간에 의미가 있는 값에 대 한 몇 가지 특별 한 합의를 가질 수 있는 정수 값입니다.These two properties are integer values that may have some special agreed upon values that have meaning between the client and the service. 예를 들어 고객 ID를 보유할 수 있으며 해당 고객에 대 한 구매 주문 번호를 포함할 수 Arg2 Arg1.For example, Arg1 may hold a customer ID and Arg2 may hold a purchase order number for that customer. Method.Obtain(Handler h, Int32 what, Int32 arg1, Int32 arg2)Message 만들어질 때 두 속성을 설정 하는 데 사용할 수 있습니다.The Method.Obtain(Handler h, Int32 what, Int32 arg1, Int32 arg2) can be used to set the two properties when the Message is created. 이러한 두 값을 채우는 또 다른 방법은 Message 개체를 만든 후에 .Arg.Arg2 속성을 직접 설정 하는 것입니다.Another way to populate these two values is to set the .Arg and .Arg2 properties directly on the Message object after it has been created.

서비스에 추가 값 전달Passing Additional Values to the Service

Bundle를 사용 하 여 더 복잡 한 데이터를 서비스에 전달할 수 있습니다.It is possible to pass more complex data to the service by using a Bundle. 이 경우 Bundle에 추가 값을 추가 하 고 보내기 전에 .Data 속성 속성을 설정 하 여 Message 함께 보낼 수 있습니다.In this case, extra values can be placed in a Bundle and sent along with the Message by setting the .Data property property before sending.

Bundle serviceParameters = new Bundle();
serviceParameters.

var msg = Message.Obtain(null, Constants.SERVICE_TASK_TO_PERFORM);
msg.Data = serviceParameters;

messenger.Send(msg);

참고

일반적으로 Message는 1MB 보다 큰 페이로드를 포함 하지 않아야 합니다.In general, a Message should not have a payload larger than 1MB. 크기 제한은 Android 버전에 따라 다르며, 공급 업체에서 장치와 함께 제공 되는 AOSP (Android 오픈 소스 프로젝트)의 구현에 대해 수행할 수 있는 모든 소유 변경 내용에 따라 달라질 수 있습니다.The size limit may vary according the version of Android and on any proprietary changes the vendor might have made to their implementation of the Android Open Source Project (AOSP) that is bundled with the device.

서비스에서 값 반환Returning Values from the Service

이 시점에 설명 된 메시징 아키텍처는 단방향 이며, 클라이언트는 서비스에 메시지를 보냅니다.The messaging architecture that has been discussed to this point is one-way, the client sends a message to the service. 서비스가 클라이언트에 값을 반환 해야 하는 경우이 지점에 대해 설명한 모든 것이 반대입니다.If it is necessary for the service to return a value to a client then everything that has been discussed to this point is reversed. 서비스는 Message를 만들고 모든 반환 값을 패키지 한 다음 Messenger를 통해 Message를 클라이언트에 디스패치합니다.The service must create a Message, packaged any return values, and dispatch the Message via a Messenger to the client. 그러나 서비스는 자체 Messenger을 만들지 않습니다. 대신, 초기 요청의 일부로 Messenger를 인스턴스화하고 패키지 하는 클라이언트에 의존 합니다.However, the service does not create its own Messenger; instead, it relies on the client instantiating and package a Messenger as part of the initial request. 서비스는이 클라이언트에서 제공한 Messenger를 사용 하 여 메시지를 Send 합니다.The service will Send the message using this client-provided Messenger.

양방향 통신에 대 한 이벤트 시퀀스는 다음과 같습니다.The sequence of events for two-way communication is this:

  1. 클라이언트는 서비스에 바인딩됩니다.The client binds to the service. 서비스와 클라이언트가 연결 되 면 클라이언트에서 유지 관리 하는 IServiceConnection 서비스에 Messages를 전송 하는 데 사용 되는 Messenger 개체에 대 한 참조를 갖게 됩니다.When the service and the client connect, the IServiceConnection that is maintained by the client will have a reference to a Messenger object that is used to transmit Messages to the service. 혼동을 피하기 위해이를 _서비스 Messenger_라고 합니다.To avoid confusion, this will be referred to as the Service Messenger.
  2. 클라이언트는 _클라이언트 처리기_라고 하는 Handler을 인스턴스화하고이를 사용 하 여 자체 Messenger ( 클라이언트 Messenger)를 초기화 합니다.Client instantiates a Handler (referred to as the Client Handler) and uses that to initialize its own Messenger (the Client Messenger). 서비스 Messenger와 클라이언트 Messenger는 서로 다른 두 방향으로 트래픽을 처리 하는 두 가지 다른 개체입니다.Note that the Service Messenger and the Client Messenger are two different objects that handle traffic in two different directions. 서비스 Messenger는 클라이언트에서 서비스로 메시지를 처리 하는 반면 클라이언트 Messenger는 서비스에서 클라이언트로 메시지를 처리 합니다.The Service Messenger handles messages from the client to the service, while the Client Messenger will handle messages from the service to the client.
  3. 클라이언트는 Message 개체를 만들고 클라이언트 Messenger를 사용 하 여 ReplyTo 속성을 설정 합니다.The client creates a Message object, and sets the ReplyTo property with the Client Messenger. 그런 다음 서비스 Messenger를 사용 하 여 서비스에 메시지를 보냅니다.The message is then sent to the service using the Service Messenger.
  4. 서비스는 클라이언트에서 메시지를 수신 하 고 요청 된 작업을 수행 합니다.The service receives the message from the client, and performs the requested work.
  5. 서비스가 클라이언트에 응답을 보낼 시간이 면 Message.Obtain를 사용 하 여 새 Message 개체를 만듭니다.When it is time for the service to send the response to the client, it will use Message.Obtain to create a new Message object.
  6. 클라이언트에이 메시지를 보내기 위해 서비스는 클라이언트 메시지의 .ReplyTo 속성에서 클라이언트 Messenger를 추출 하 고이를 사용 하 여 Message을 클라이언트에 다시 .Send 합니다.To send this message to the client, the service will extract the Client Messenger from the .ReplyTo property of the client message and use that to .Send the Message back to the client.
  7. 클라이언트에서 응답을 수신 하는 경우 .What 속성을 검사 하 여 Message를 처리 하는 자체 Handler 있습니다. 필요한 경우 Message에 포함 된 매개 변수를 추출 합니다.When the response is received by the client, it has its own Handler that will process the Message by inspecting the .What property (and if necessary, extracting any parameters contained by the Message).

이 샘플 코드는 클라이언트가 Message를 인스턴스화하고 서비스에서 응답을 위해 사용 해야 하는 Messenger를 패키징하는 방법을 보여 줍니다.This sample code demonstrates how the client will instantiate the Message and package a Messenger that the service should use for its response:

Handler clientHandler = new ActivityHandler();
Messenger clientMessenger = new Messenger(activityHandler);

Message msg = Message.Obtain(null, Constants.GET_UTC_TIMESTAMP);
msg.ReplyTo = clientMessenger;

try
{
    serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
    Log.Error(TAG, ex, "There was a problem sending the message.");
}

서비스는 Messenger를 추출 하 고이를 사용 하 여 클라이언트에 회신을 보내는 데 사용 되는 자체 Handler를 변경 해야 합니다.The service must make some changes to its own Handler to extract the Messenger and use that to send replies to the client. 이 코드 조각은 서비스의 Handler에서 Message를 만들고 클라이언트로 다시 보내는 방법의 예입니다.This code snippet is an example of how the service's Handler would create a Message and send it back to the client:

// This is the message that the service will send to the client.
Message responseMessage = Message.Obtain(null, Constants.RESPONSE_TO_SERVICE);
Bundle dataToReturn = new Bundle();
dataToReturn.PutString(Constants.RESPONSE_MESSAGE_KEY, "This is the result from the service.");
responseMessage.Data = dataToReturn;

// The msg object here is the message that was received by the service. The service will not instantiate a client,
// It will use the client that is encapsulated by the message from the client.
Messenger clientMessenger = msg.ReplyTo;
if (clientMessenger!= null)
{
    try
    {
        clientMessenger.Send(responseMessage);
    }
    catch (Exception ex)
    {
        Log.Error(TAG, ex, "There was a problem sending the message.");
    }
}

위의 코드 샘플에서 클라이언트에서 만든 Messenger 인스턴스는 서비스에서 받는 것과 동일한 개체가 아닙니다 .Note that in the code samples above, the Messenger instance that is created by the client is not the same object that is received by the service. 이러한 두 가지 Messenger 개체는 통신 채널을 나타내는 두 개의 개별 프로세스로 실행 됩니다.These are two different Messenger objects running in two separate processes that represent the communication channel.

Android 권한으로 서비스 보안 설정Securing the Service with Android Permissions

전역 프로세스에서 실행 되는 서비스는 해당 Android 장치에서 실행 되는 모든 응용 프로그램에서 액세스할 수 있습니다.A service that runs in a global process is accessible by all applications running on that Android device. 경우에 따라이 개방성 및 가용성은 바람직하지 않으며 권한이 없는 클라이언트의 액세스 로부터 서비스의 보안을 유지 해야 합니다.In some situations, this openness and availability is undesirable, and it is necessary to secure the service against access from unauthorized clients. 원격 서비스에 대 한 액세스를 제한 하는 한 가지 방법은 Android 권한을 사용 하는 것입니다.One way to limit access to the remote service is to use Android Permissions.

사용 권한은 Service 하위 클래스를 데코레이팅하는 ServiceAttributePermission 속성으로 식별할 수 있습니다.Permissions can be identified by the Permission property of the ServiceAttribute that decorates the Service sub-class. 이렇게 하면 서비스에 바인딩할 때 클라이언트에 부여 되어야 하는 사용 권한의 이름을 지정할 수 있습니다.This will name a permission that the client must be granted when binding to the service. 클라이언트에 적절 한 권한이 없으면 클라이언트에서 서비스에 바인딩하려 할 때 Android에서 Java.Lang.SecurityException을 throw 합니다.If the client does not have the appropriate permissions, then Android will throw a Java.Lang.SecurityException when the client tries to bind to the service.

Android에서 제공 하는 네 가지 권한 수준은 다음과 같습니다.There are four different permission levels that Android provides:

  • 일반 – 기본 사용 권한 수준입니다.normal – This is the default permission level. Android에서 요청 하는 클라이언트에 자동으로 부여할 수 있는 낮은 위험 권한을 식별 하는 데 사용 됩니다.It is used to identify low-risk permissions that can be automatically granted by Android to clients that request it. 사용자는 이러한 권한을 명시적으로 부여 하지 않아도 되지만 앱 설정에서 사용 권한을 볼 수 있습니다.The user does not have to explicitly grant these permissions, but the permissions can be viewed in the app settings.
  • 서명 –이는 Android에서 동일한 인증서로 서명 된 응용 프로그램에 자동으로 부여 되는 특별 한 범주의 권한입니다.signature – This is a special category of permission that will be granted automatically by Android to applications that are all signed with the same certificate. 이 사용 권한은 응용 프로그램 개발자가 사용자를 일정 하 게 승인 하기 위해 신경 하지 않고도 앱 간에 구성 요소나 데이터를 쉽게 공유할 수 있도록 설계 되었습니다.This permission is designed to make it easily for an application developer to share components or data between their apps without bothering the user for constant approvals.
  • 서명 Orsystem – 위에서 설명한 서명 권한과 매우 유사 합니다.signatureOrSystem – This is very similar to the signature permissions described above. 동일한 인증서로 서명 된 앱에 자동으로 부여 되는 것 외에도 Android 시스템 이미지를 사용 하 여 설치 된 앱에 서명 하는 데 사용 된 것과 동일한 인증서에 서명 된 앱에도이 권한이 부여 됩니다.In addition to being automatically granted to apps that are signed by the same certificate, this permission will also be granted to apps that are signed the same certificate that was used to sign the apps installed with the Android system image. 이 권한은 일반적으로 Android ROM 개발자가 응용 프로그램이 타사 앱에서 작동 하도록 허용 하는 데만 사용 됩니다.This permission is typically only used by Android ROM developers to allow their applications to work with third party apps. 일반적으로는 공용에 대 한 일반 배포를 위한 앱에서 일반적으로 사용 되지 않습니다.It is not commonly used by apps that are meant general distribution for the public at large.
  • 위험한 – 위험한 사용 권한은 사용자에 게 문제가 발생할 수 있는 권한입니다.dangerous – Dangerous permissions are those that could cause problems for the user. 따라서 위험한 사용 권한은 사용자가 명시적으로 승인 해야 합니다.For this reason, dangerous permissions must be explicitly approved by the user.

signaturenormal 권한은 Android에서 설치 된 시간에 자동으로 부여 되므로 클라이언트를 포함 하는 APK 전에 서비스를 호스트 하는 apk가 설치 되는 것이 중요 합니다.Because signature and normal permissions are automatically granted at installed time by Android, it is crucial that APK hosting the service be installed before the APK containing the client. 클라이언트를 먼저 설치한 경우 Android에서 사용 권한을 부여 하지 않습니다.If the client is installed first, Android will not grant the permissions. 이 경우 클라이언트 APK를 제거 하 고, 서비스 APK를 설치 하 고, 클라이언트 APK를 다시 설치 해야 합니다.In this case, it will be necessary to uninstall the client APK, install the service APK, and then re-install the client APK.

Android 권한으로 서비스를 보호 하는 일반적인 방법에는 다음 두 가지가 있습니다.There are two common ways to secure a service with Android permissions:

  1. 서명 수준 보안 – 구현 하면 서비스를 보유 하는 apk에 서명 하는 데 사용 된 것과 동일한 키로 서명 된 응용 프로그램에 권한이 자동으로 부여 됩니다.Implement signature level security – Signature level security means that permission is automatically granted to those applications that are signed with the same key that was used to sign the APK holding the service. 이 방법은 개발자가 자신의 응용 프로그램에서 액세스할 수 있는 서비스를 보호 하는 간단한 방법입니다.This is a simple way for developers to secure their service yet keep them accessible from their own applications. 서명 수준 권한은 ServiceAttributePermission 속성을 signature으로 설정 하 여 선언 됩니다.Signature level permissions are declared by setting the Permission property of the ServiceAttribute to signature:

    [Service(Name = "com.xamarin.TimestampService",
             Process="com.xamarin.TimestampService.timestampservice_process",
             Permission="signature")]
    public class TimestampService : Service
    {
    }
    
  2. 사용자 지정 권한 – 만들기 서비스 개발자가 서비스에 대 한 사용자 지정 권한을 만들 수 있습니다.Create a custom permission – It is possible for the developer of the service to create a custom permission for the service. 개발자가 다른 개발자의 응용 프로그램과 서비스를 공유 하려는 경우에 가장 적합 합니다.This is best for when a developer wants to share their service with applications from other developers. 사용자 지정 권한을 구현 하려면 약간의 노력이 필요 하며 아래에서 설명 합니다.A custom permission requires a bit more effort to implement and will be covered below.

사용자 지정 normal 권한 만들기에 대 한 간단한 예는 다음 섹션에 설명 되어 있습니다.A simplified example of creating a custom normal permission will be described in the next section. Android 사용 권한에 대 한 자세한 내용은 Google 설명서를 참조 하 여 보안 & 모범 사례를 참조 하세요.For more information about Android permissions, please consult Google's documentation for Best Practices & Security. Android 사용 권한에 대 한 자세한 내용은 android 사용 권한에 대 한 자세한 내용은 응용 프로그램 매니페스트에 대 한 Android 설명서의 사용 권한 섹션 을 참조 하세요.For more information about Android permissions, see the Permissions section of the Android documentation for the application manifest for more information about Android permissions.

참고

일반적으로 Google은 사용자의 혼동을 입증할 수 있으므로 사용자 지정 권한을 사용 하지 않습니다.In general, Google discourages the use of custom permissions as they may prove confusing to users.

사용자 지정 권한 만들기Creating a Custom Permission

사용자 지정 권한을 사용 하기 위해 클라이언트는 해당 권한을 명시적으로 요청 하는 동안 서비스에 의해 선언 됩니다.To use a custom permission, it is declared by the service while the client explicitly requests that permission.

서비스 APK에서 사용 권한을 만들려면 Androidmanifestmanifest 요소에 permission 요소가 추가 됩니다.To create a permission in the service APK, a permission element is added to the manifest element in AndroidManifest.xml. 이 사용 권한에는 name, protectionLevellabel 특성이 설정 되어 있어야 합니다.This permission must have the name, protectionLevel, and label attributes set. name 특성은 사용 권한을 고유 하 게 식별 하는 문자열로 설정 해야 합니다.The name attribute must be set to a string that uniquely identifies the permission. 이름은 다음 섹션과 같이 Android 설정앱 정보 보기에 표시 됩니다.The name will be displayed in the App Info view of the Android Settings (as shown in the next section).

protectionLevel 특성은 위에서 설명한 4 개의 문자열 값 중 하나로 설정 해야 합니다.The protectionLevel attribute must be set to one of the four string values that were described above. labeldescription는 문자열 리소스를 참조 해야 하며 사용자에 게 친숙 한 이름 및 설명을 제공 하는 데 사용 됩니다.The label and description must refer to string resources and are used to provide a user-friendly name and description to the user.

이 코드 조각은 서비스를 포함 하는 APK의 xml에서 사용자 지정 permission 특성을 선언 하는 예제입니다 .This snippet is an example of declaring a custom permission attribute in AndroidManifest.xml of the APK that contains the service:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"
          package="com.xamarin.xample.messengerservice">

    <uses-sdk android:minSdkVersion="21" />

    <permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP"
                android:protectionLevel="signature"
                android:label="@string/permission_label"
                android:description="@string/permission_description"
                />

    <application android:allowBackup="true"
            android:icon="@mipmap/icon"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">

    </application>
</manifest>

그런 다음 클라이언트 APK의 Androidmanifest 은이 새 사용 권한을 명시적으로 요청 해야 합니다.Then, the AndroidManifest.xml of the client APK must explicitly request this new permission. 이 작업은 Androidmanifestusers-permission 특성을 추가 하 여 수행 됩니다.This is done by adding the users-permission attribute to the AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"
          package="com.xamarin.xample.messengerclient">

    <uses-sdk android:minSdkVersion="21" />

    <uses-permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP" />

    <application
            android:allowBackup="true"
            android:icon="@mipmap/icon"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
    </application>
    </manifest>

앱에 부여 된 사용 권한 보기View the Permissions Granted to an App

응용 프로그램에 부여 된 사용 권한을 보려면 Android 설정 앱을 열고 을 선택 합니다.To view the permissions that an application has been granted, open the Android Settings app, and select Apps. 목록에서 응용 프로그램을 찾아 선택 합니다.Find and select the application in the list. 앱 정보 화면에서 앱에 부여 된 모든 사용 권한을 표시 하는 보기를 표시 하는 권한 을 탭 합니다.From the App Info screen, tap Permissions which will bring up a view that shows all the permissions granted to the app:

응용 프로그램에 부여 된 사용 권한을 찾는 방법을 보여주는 Android 장치에서 스크린샷Screenshots from an Android device showing how to find the permissions granted to an application

요약Summary

이 가이드는 원격 프로세스에서 Android 서비스를 실행 하는 방법에 대 한 고급 설명입니다.This guide was an advanced discussion about how to run an Android service in a remote process. 로컬 서비스와 원격 서비스 간의 차이점은 원격 서비스가 Android 앱의 안정성과 성능에 도움이 될 수 있는 몇 가지 이유를 설명 했습니다.The differences between a local and a remote service was explained, along with some reasons why a remote service can be helpful to stability and performance of an Android app. 원격 서비스를 구현 하는 방법 및 클라이언트가 서비스와 통신 하는 방법에 대해 설명 하 고 나면 인증 된 클라이언트만 서비스에 대 한 액세스를 제한 하는 한 가지 방법을 제공 합니다.After explaining how to implement a remote service and how a client can communicate with the service, the guide went on to provide one way to limit access to the service from only authorized clients.