반응형

 

 

지난 포스팅에서 ContentProvider의 개념, 사용법과 ContentProvider에서 사용하는 UriMatcher에 대해 기술하였다.

 

아직 포스팅을 접하지 못한 분은 아래 링크 클릭.

 

[Android] ContentProvider 누구보다 쉽게!

[Android] UriMatcher, 스마트하게 써보자!

 

ContentProvider에대해 기술한 포스팅에서 필자는 기존의 안드로이드 데이터베이스의 데이터 공유 방식이 아닌 메서드 콜을 통한 Bundle 반환 방식의 ContentProvider 샘플 코드를 기술하였다.

 

본 포스팅에서는 해당 방식에 대해 좀 더 자세하게 다루어보고자 한다.

 

 

메서드 콜 방식?

ContentProvider의 기본 방식은 이전 포스팅에서 언급하고, 아래 그림과 같이 CRUD에 해당하는 API를 ContentResolver를 통해 호출하는 방식을 취하며, 결과데이터는 Cursor, Uri, Int와 같이 다양한 데이터 타입으로 반환하는 구조였다.

 

ContentProvider 기본 동작 방식

 

하지만 본 포스팅에서는 기존의 방식이 아닌 좀 더 유연하게 외부 연동에 대응하며, 불필요한 데이터베이스 사용을 지양하기 위해 아래와 같이 메서드 콜 방식의 Bundle 객체를 제공해주는 방식으로 ContentProvider를 사용해보고자 한다.

 

메서드 call 방식의 ContentProvider 동작 구조

 

ContentProvider의 API 중 call API의 경우 상세 스팩은 아래와 같다.

 

스펙 상에서는 ContentProvider를 호출하는 authority 정보와 method 명을 바탕으로 호출하면, Bundle 객체를 반환한다고 명시되어 있다.

 

하지만 필자는 외부 연동과정에 있어 method 명을 제공하는 것 보다는 외부 연동 키를 제공해주고, 외부에서 접근하는 키에 따른 Bundle 객체를 제공해주는 방식을 취하고자 한다.

 

 

그래서 어떻게 해야하죠?

해당 내용은 지난 포스팅에서 샘플로 작성했던 코드를 참조하며 아래코드를 보면 된다.

/**
* 제공하는 데이터의 MIME 타입을 조사하는 메서드.
* 정보의 개수에 따라 MIME 타입의 형식이 다름.
* 강제 규칙은 아니지만 대체로 다음 형식에 작성
*
* 단수 : vnd.회사명.curosr.item/타입
* 복수 : vnd.회사명.cursor.dir/타입
*/
override fun getType(uri: Uri?): String? {
    val uriMatcher = RozeUriMatcher()
    return uri?.let {
    	uriMatcher.getExternalCallInfo(uri)
    } ?: return null
}

외부 앱에서는 ContentProvider의 getType을 통해 반환되는 메서드 키 값을 바탕으로 call 메서드에 입력만 해줌으로써 별도의 키 값을 하드코딩하지 않고 연동하여 데이터를 받아 올 수 있다.

/**
* 외부에서 메서드 호출 접근 시 처리한다.
*/
override fun call(method: String?, arg: String?, extras: Bundle?): Bundle {
  return when (method) {
    DabalExternal.SAMPLE.dabalExternalMethodKey -> isDabal()
    else -> Bundle()
  }
}

 

Bundle을 통해 데이터를 넘겨주기 때문에, 앱 연동시에 좀 더 유연하게 데이터를 넘겨줄 수 있다. 또한, 외부 앱 연동 개발자는 제공받은 Bundle 객체에서 필요한 데이터만 발췌하여 사용하면 되기 때문에 Cursor 객체에서 불필요한 코드를 통해 데이터를 확인하며 추출하는 일련의 작업을 생략할 수 있다.

 

/**
 * ContentResolver를 통해 외부 앱에서 데이터 추출 샘플
 */
private fun getData() {
  val testUri:Uri = Uri.parse("content://com.dabal.external/dabal_test_call")
  val method = this.contentResolver.getType(testUri)
  val bundle:Bundle? = this.contentResolver.call(testUri, method,null, null)
  val resultData: String? = bundle?.getString("result")
  resultString?.text = resultData
}

 

위의 방식으로 구현하게 되면, 외부 연동 개발자 입장에서는 호출 할 Uri 정보, Bundle로 넘겨받는 데이터 스펙에 대해서만 알고있다면, 내부에서 수정하는 키정보에 따른 영향도를 줄일 수 있다.

 

지금 하나의 케이스에 대해서만 기술했을 땐, 크게 와 닿지 않을 수 있다. 하지만 연동되는 외부 앱 정보가 많아지면서 리팩토링이 필요해지고 경우에 따라서 사전에 정의한 메서드 명, 키 정보등 ContentProvider 내부의 정보가 바껴야하는 상황에서는 위의 방식으로 구현하지 않으면 수정이 어렵게되어 스파게티 코드를 양산할 가능성이 높게된다.

 

 

마치며

본 포스팅에서는 ContentProvider를 call API를 이용해 사용하는 방법에 대해 기술하였다.

필자처럼 안드로이드 내부 데이터베이스를 사용하지 않고 외부 연동하는 방법에대해 고민하는 대다수의 개발자들이 많은 도움이 되었길 바라며 본 포스팅을 마치고자 한다.

반응형

+ Recent posts