LG U+ MobileManager
회사 | 파인원커뮤니케이션즈 |
---|---|
진행 기간 | |
담당 Skills & 사용 Libraries | DataStoreFlowKotlinMVVMWebView |
팀구성 | Android 1명 JavaScript 개발자 5명 (react) |
U+모바일매니저 - Apps on Google Play
The beginning of a new communication life! U+ call convenience additional service settings/change/inquiry service app
📱 담당한 기능
- 전체 설계 및 개발
- 제네릭을 이용해 유연한 Web ↔ Native I/F 작성
- 연락처 저장및 전달( 듀얼넘버 기능 및 특수 문자 처리 )
- 생체인증 ( 구현 하였으나 Phase 2 개발로 변경 )
- 위젯 기능( 구현 하였으나 Phase 2 개발로 변경)
- Base64 , AES256 을 이용한 이용자 정보 암호화
- 함수형 프로그래밍 으로 코드 작성 하여 가독성 및 관리 용이
- Unit Test
🛠️ 상세 내용

- DI 및 MVVM 설계 및 추후 확장성 까지 고려 하여 앱을 작성 하였습니다.
data class BaseData<T>(
val header: Header,
val param : T
)
- Web 과의 브릿지 통신을 원활 하기 위한 제네릭 형식으로 처리 하였습니다.
internal inline fun <reified T> String.fromString(): T {
val type = object : TypeToken<T>(){}.type
return Gson().fromJson(this, type)
}
internal inline fun <reified T> JSONObject.fromJson(): T {
return this.toString().fromString()
}
/**
* result
*/
internal val JSONObject.result: JSONObject? get() {
return optJSONObject(RESULT)
}
internal val JSONObject.code: String get() {
return optString(ResultCode.CODE) ?: ResultCode.FAIL.code
}
- extension 형식으로 함수들을 정리하여 데이터 처리를 하였습니다.
suspend fun CustomTriple<JSONObject, (String) -> Unit, JSONObject?>.sendResult(resultCode : ResultCode, dispatcher: CoroutineDispatcher, result : Any? = null ) = withContext(dispatcher){
val header = [email protected]
val callback = [email protected]
val resultWrap = ResultWrapper(header.fromJson(),resultCode.code, result).toJsonString()
LogUtil.d(LogUtil.DEBUG_LEVEL_2,"post data : result = $resultWrap")
callback.invoke(resultWrap)
}
- 응답처리 ( 성공 ,실패 등등) 에 공통점이 있어 하나로 처리 할 수 있도록 작성 하였습니다.
open val coroutineExceptionHandler: CoroutineExceptionHandler
get() = CoroutineExceptionHandler { _, _ -> }
override suspend fun testProcess(triple: CustomTriple<JSONObject, (String) -> Unit, JSONObject?>) {
triple.params?.fromJson<UserInfo>()?.run {
triple.sendResultProcess(testRepository.testSetUser(this), ioDispatcher)
}?:triple.sendResult(ResultCode.NO_PARAMETER ,ioDispatcher)
}
private suspend fun CustomTriple<JSONObject, (String) -> Unit, JSONObject?>.requestProcess(type: HeaderType?) = withContext(ioDispatcher) {
LogUtil.i(LogUtil.DEBUG_LEVEL_2, "requestProcess : $type")
when (type) {
..생략..
HeaderType.LAUNCH_OEM_CONTACT -> { launchOEMContactProcess(this@requestProcess) }
HeaderType.GET_CONTACT_NAME_LIST -> { getContactNameListProcess(this@requestProcess) }
HeaderType.TYPE_ERROR -> { LogUtil.e(LogUtil.DEBUG_LEVEL_2, "requestProcess : ${HeaderType.TYPE_ERROR}") }
HeaderType.SEND_WEB_VERSION->{sendWebVersionProcess(this@requestProcess)}
else -> {
LogUtil.e(LogUtil.DEBUG_LEVEL_2, "requestProcess : ${HeaderType.TYPE_ERROR}")
}
}
}
suspend fun readData(data: DataStoreParam): CustomPair<ResultCode,Any?> {
var result: String? = null
val code = setRunCatching {
result = getDataStore(createKey(data.dataName))
}
result?.let { return CustomPair(ResultCode.SUCCESS, result) } ?: return CustomPair(code, null)
}
enum class ResultCode(val code: String) {
SUCCESS("200"), // 성공
..실패 사항 생략 ..
FAIL("9999"); //실패
val isSuccess : Boolean
get() = SUCCESS_STATES.contains(this)
companion object{
@JvmStatic
fun fromCode(code: String?): ResultCode = values().firstOrNull { it.code == code }?: FAIL
const val CODE = "code"
private val SUCCESS_STATES = setOf(SUCCESS)
@JvmStatic
suspend fun setRunCatching(dispatcher: CoroutineContext = Dispatchers.IO ,block : suspend ()->Unit ) : ResultCode = withContext(dispatcher){
return@withContext try {
block()
SUCCESS
}
..생략 ..
}catch (e : JsonSyntaxException){
LogUtil.e(LogUtil.DEBUG_LEVEL_2,"JsonSyntaxException : ${e.message}")
JSON_PARSE_ERROR
}catch (e : Exception){
LogUtil.e(LogUtil.DEBUG_LEVEL_2,"Exception : ${e.message}")
LogUtil.e(LogUtil.DEBUG_LEVEL_2,"Exception : ${e}")
FAIL
}
}
}
}
- 웹에서 오는 요청을 분류하여 처리 하도록 하였고 Exception을 한쪽에서 처리 할 수 있도록 하였습니다.

- 테스트도 작성 하였습니다.