반응형

이번 포스팅은 MoveEvent Value를 알아보도록 하겠습니다.

 

Android에서 onTouchListner를 상속받아 구현하게 되면 override 된 메서드를 구현해야 합니다.

 

오늘은 override 메소드에서 자주 쓰이는  MoveEvent Value를 나열해 보겠습니다.

 

1.  ACTION_DOWN = 0

 

2.  ACTION_UP = 1

 

3.  ACTION_MOVE = 2

 

4.  ACTION_CANCEL = 3

 

5.  ACTION_MASK = 255

 

6.  ACTION_POINTER_2_DOWN = 261

반응형
반응형

안녕하세요.

이번 포스팅은 Android OS 10을 TargetSDKVersion 으로 업그레이드 시 파일 조회하는 기능의 경우 발생할 수 있는 오류에 대하여 알아보도록 하겠습니다.


<Error>

TargetSDKVersion을 28에서 29로 업그레이드만 하였을 뿐인데 파일 조회하는 기능에서 아래와 같은 NullPointException이 발생하였습니다.

W/System.err: java.lang.NullPointerException: Attempt to get length of null array

W/System.err:     at com.eun.sample.core.Cert.a(Unknown Source:15)

W/System.err:     at com.eun.sample.core.Cert.<init>(Unknown Source:61)


<Solution>

Android OS 10이 출시되면서 보안이 많이 강화되었으며 이로 인해 파일 Access 제한이 되었습니다.

이를 해결하기 위해서는 Android Developer 외부저장소 Access 페이지를 참조하였으며, 해결방법을 찾을 수 있었습니다.


1. 가장 간단한 방법입니다.

   AndroidMenifest.xml 파일에 requestLagacyExternalStorage 속성을 true로 주어 기존 외부 저장소를 사용할 수 있도록 설정을 합니다.

이로 인해 앞서 발생하였던 Error 부분은 해결이 되었습니다.

    <manifest ... >
     
<!-- This attribute is "false" by default on apps targeting Android 10 or higher. -->
     
<application android:requestLegacyExternalStorage="true" ... >

        ...
     
</application>
   
</manifest>

또한 아래와 같은 설명을 되어 있으니 참고 하시면 좋을 것 같습니다.

 ★ 참고: 기존 외부 저장소를 사용 설정한 상태에서 앱을 설치하면 앱은 제거될 때까지 이 모드로 유지됩니다. 이 호환성 동작은 나중에 기기가 Android 10 이상을 실행하도록 업그레이드되든, 나중에 앱이 Android 10 이상을 타겟팅하도록 업데이트되든 관계없이 적용됩니다.


2. 좀 더 보완적으로 접근할 수 있는 방법입니다.

   저장소 Access Framework를 사용하여 파일을 조회하는 방법입니다.

   우선 아래에 있는 정보 미디어 컬렉션 중 하나를 선택해 조회할 수 있습니다.

   - 사진 : MediaStore.Image 

   - 동영상 : MediaStore.Video

   - 오디오 : MediaStore.Audio

  Download 디렉토리에 있는 파일을 비롯하여 다른 앱에서 만든 다른 파일에 Acccess 하려면 앱에서 사용자가 특정 파일을 선택하도록 허용하는 

저장소 Access Framework를 사용해야 합니다.


이번 포스팅에서 Android OS 10에서 파일 조회 시 NullPointException이 발생하였을 때 해결할 수 있는 방법에 대하여 알아보았습니다.

반응형
반응형

안녕하세요.

이번 포스팅은 Data-Scheme 설정할 시 앱 서랍에 앱 아이콘이 보이지 않는 현상에 대하여 원인과 해결방법에 대하여 알아보도록 하겠습니다.


<Error>

AndroidMenifest.xml에 Data-Scheme을 사용하는 앱을 빌드하거나 APK를 설치하였지만 앱 서랍에 앱 아이콘이 보이지 않는 현상  


<Solution>

android.intent.action.MAIN action 과 android.intent.action.VIEW action을 잘못 인식하여 발생하는 오류로서 두 action을 분리시켜주면 됩니다.

간혹 android.intent.action.MAIN android.intent.action.VIEW action을 붙여쓰여 빌드 시스템에서 VIEW로 잘못 인식하게 되는 겁니다.

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>

<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="sign"
android:host="eun" />
</intent-filter>


반응형
반응형

이번 포스팅은 제가 이미지 로딩 시 가장 많이 사용하는 라이브러리 대해 포스팅하도록 하겠습니다.

이번 포스팅은 이미 비교한 자료 한 글이 있어서 해당 글로 갈음합니다.

 

Reference

1. https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

2. https://gun0912.tistory.com/19

반응형
반응형

이번 포스팅은 App Architecture 가이드 두 번째 포스팅입니다.

예제를 통해 좀 더 자세히 알아보도록 하겠습니다.


사용자 인터페이스 시작

UI는 fragment UserProfileFragment와 관련 레이아웃 파일 user_profile_layout.xml로 구성됩니다.

UI를 만들려면 데이터 모델에 다음 데이터 요소가 있어야 합니다.

▶ 사용자 ID: 사용자의 식별자입니다. fragment 인수를 사용하여 이 정보를 fragment에 전달하는 것이 좋습니다. Android OS에서 프로세스를 제거해도 이 정보가 유지되므로, 앱을 다시 시작할 때 ID를 사용할 수 있습니다.

▶ 사용자 개체: 사용자에 관한 세부정보를 보유하는 데이터 클래스입니다.

이 정보를 유지하기 위해 ViewModel 아키텍처 구성요소를 기반으로 하는 UserProfileViewModel을 사용합니다.

ViewModel 개체는 fragment나 activity 같은 특정 UI 구성요소에 대한 데이터를 제공하고 Model과 커뮤니케이션하기 위한 데이터 처리 비즈니스 로직을 포함합니다. 예를 들어 ViewModel은 데이터를 로드하기 위해 다른 구성요소를 호출하고 사용자 요청을 전달하여 데이터를 수정할 수 있습니다. ViewModel은 UI 구성요소에 관해 알지 못하므로 구성 변경(예: 기기 회전 시 activity 재생성)의 영향을 받지 않습니다.

지금까지 다음 파일을 정의했습니다.

▶ user_profile.xml: 화면의 UI 레이아웃 정의

▶ UserProfileFragment: 데이터를 표시하는 UI 컨트롤러

▶ UserProfileViewModelUserProfileFragment에서 볼 수 있도록 데이터를 준비하고 사용자 상호작용에 반응하는 클래스

다음 소스 코드는 이러한 파일의 시작 콘텐츠를 보여줍니다. 

편의를 위해 레이아웃 파일은 생략합니다.

UserProfileViewModel

class UserProfileViewModel:ViewModel(){

val userId :String= TODO() val user :User= TODO() }

UserProfileFragment

class UserProfileFragment:Fragment(){

override fun onCreateView(inflater:LayoutInflater, container:ViewGroup?, savedInstanceState:Bundle?):View{
return inflater.inflate(R.layout.main_fragment, container,false)
}
}

user를 가져오려면 ViewModel에서 Fragment 인수에 액세스해야 합니다. Fragment에서 인수를 전달할 수도 있고, 더 나은 방법으로 SavedState 모듈을 사용해 ViewModel에서 직접 인수를 읽을 수 있습니다.

참고: SavedStateHandle을 사용하면 ViewModel에서 관련 Fragment 또는 Activity의 저장된 상태와 인수에 액세스할 수 있습니다.


// UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle ):ViewModel(){
val userId :String= savedStateHandle["uid"]?: throwIllegalArgumentException("missing user id") val user :User= TODO()
}

// UserProfileFragment
privateval viewModel:UserProfileViewModel by viewModels(factoryProducer ={SavedStateVMFactory(this)}        ... )

이제 user 개체가 확보되면 Fragment에 알려야 합니다. 여기에서 LiveData 아키텍처 구성요소가 사용됩니다.

LiveData는 식별 가능한 데이터 홀더입니다. 앱의 다른 구성요소에서는 이 홀더를 사용하여 상호 간에 명시적이고 엄격한 종속성 경로를 만들지 않고도 개체 변경사항을 모니터링할 수 있습니다. 또한 LiveData 구성요소는 activity, fragment, 서비스와 같은 앱 구성요소의 수명 주기 상태를 고려하고, 개체 유출과 과도한 메모리 소비를 방지하기 위한 정리 로직을 포함합니다.

참고: RxJava와 같은 라이브러리를 이미 사용하고 있다면 LiveData 대신 계속 사용해도 됩니다. 그러나 이러한 라이브러리와 방법을 사용하는 경우 앱의 수명 주기를 올바르게 처리해야 합니다. 특히 관련 LifecycleOwner가 중지되면 데이터 스트림이 일시중지되고, 관련 LifecycleOwner가 제거되면 이러한 스트림이 제거되도록 해야 합니다. android.arch.lifecycle:reactivestreams 아티팩트를 추가하여 LiveData를 다른 반응형 스트림 라이브러리(예: RxJava2)와 함께 사용할 수도 있습니다.

LiveData 구성요소를 앱에 통합하기 위해 UserProfileViewModel의 필드 유형을 LiveData<User>로 변경합니다. 이제 데이터가 업데이트되면 UserProfileFragment에 정보가 전달됩니다. 또한 이 LiveData 필드는 수명 주기를 인식하기 때문에 더 이상 필요하지 않은 참조를 자동으로 정리합니다.

UserProfileViewModel

class UserProfileViewModel( savedStateHandle:SavedStateHandle):ViewModel(){

val userId :String= savedStateHandle["uid"]?: throw IllegalArgumentException("missing user id") val user :LiveData<User>= TODO()
}

이제 데이터를 관찰하고 UI를 업데이트하도록 UserProfileFragment를 수정합니다.

UserProfileFragment

override fun onViewCreated(view:View, savedInstanceState:Bundle?){ super.onViewCreated(view, savedInstanceState)
viewModel
.user.observe(viewLifecycleOwner){ // update UI } }

사용자 프로필 데이터가 업데이트될 때마다 onChanged() 콜백이 호출되고 UI가 새로고침됩니다.

반응형
반응형

이번 포스팅은 App Architecture 가이드에 대하여 알아보도록 하겠습니다.


이 가이드에는 강력한 프로덕션 품질의 애플리케이션을 구축하기 위한 모범 사례와 권장 아키텍처가 포함되어 있습니다.

이 페이지는 Android 프레임워크 기본을 잘 아는 사용자를 대상으로 합니다. Android 앱 개발에 익숙하지 않으신 분들은 Developer 가이드를 참고하여 이 가이드에 언급된 개념에 대해 자세히 알아보세요.


1. 모바일 앱 사용자 환경


대부분의 경우 데스크톱 앱은 데스크톱 또는 프로그램 실행기에서 단일 시작 지점을 가진 다음 단일 프로세스로 실행됩니다. 반면에 Android 앱은 훨씬 더 복잡한 구조를 가지고 있습니다.  일반적인 Android 앱은 activityfragment서비스콘텐츠 제공업체broadcast receiver를 비롯하여 여러 앱 구성요소를 포함합니다.

개발자는 앱 매니페스트에서 이러한 앱 구성요소 대부분을 선언하게 되며, Android OS에서 이 파일을 사용하여 기기의 전반적인 사용자 환경에 앱을 통합하는 방법을 결정합니다. 올바르게 작성된 Android 앱에 여러 구성 요소가 포함되어 있고 사용자가 짧은 시간에 여러 앱과 상호 작용하는 경우가 많다는 점을 감안할 때, 앱은 다양한 종류의 사용자 중심 워크플로우 및 작업에 적응해야 합니다.

예를 들어 좋아하는 소셜 네트워킹 앱에서 사진을 공유하면 어떻게 되는지 생각해 보세요.

  1. 앱이 카메라 인텐트를 트리거합니다. 그런 다음 Android OS에서 카메라 앱을 실행하여 요청을 처리합니다. 이 시점에서 사용자는 소셜 네트워크 앱에서 나가지만 사용 환경은 끊김 없이 연결됩니다.
  2. 카메라 앱은 파일 선택기 실행처럼 다른 인텐트를 트리거하여 다른 앱을 실행할 수도 있습니다.
  3. 이후에 사용자가 다시 소셜 네트워크 앱으로 돌아와서 사진을 공유합니다.
이 과정에서 언제든지 전화나 알림에 의해 사용 환경이 중단될 수 있습니다. 사용자는 이 중단에 대응하고 난 후에 사진 공유 프로세스로 돌아가서 작업을 계속할 수 있기를 기대합니다. 휴대기기에서는 이렇게 앱을 바꾸는 동작이 일반적이므로, 앱에서 이러한 흐름을 올바르게 처리해야 합니다.

또한 휴대기기는 리소스가 제한되어 있으므로, 언제든지 운영체제에서 새로운 앱을 위한 공간을 확보하도록 언제든지 일부 앱 프로세스를 종료해야 할 수 있습니다.

이러한 환경 조건을 고려해 볼 때 앱 구성요소는 개별적이고 비순차적으로 실행될 수 있으며, 운영체제나 사용자가 언제든지 앱 구성요소를 제거할 수 있습니다. 이러한 이벤트는 직접 제어할 수 없기 때문에 앱 구성요소에 앱 데이터나 상태를 저장해서는 안 되며 앱 구성요소가 서로 종속되면 안 됩니다.


2. 일반 Architecture 원칙


앱 데이터와 상태를 저장하는 데 앱 구성요소를 사용할 수 없다면 앱을 어떻게 디자인해야 할까요?


관심사 분리

따라야 할 가장 중요한 원칙은 관심사 분리입니다. Activity 또는 Fragment에 모든 코드를 작성하는 실수는 흔히 일어납니다. 이러한 UI 기반의 클래스는 UI 및 운영체제 상호작용을 처리하는 로직만 포함해야 합니다. 이러한 클래스를 최대한 가볍게 유지하여 많은 수명 주기 관련 문제를 피할 수 있습니다.

Activity  Fragment 구현은 소유의 대상이 아니며, Android OS와 앱 사이의 계약을 나타내도록 이어주는 클래스에 불과합니다. 사용자 상호작용을 기반으로 또는 메모리 부족과 같은 시스템 조건으로 인해 언제든지 OS에서 클래스를 제거할 수 있습니다. 만족스러운 사용자 환경과 더욱더 수월한 앱 관리 환경을 제공하려면 이러한 클래스에 대한 의존성을 최소화하는 것이 좋습니다.


Model에서 UI 만들기

또 하나의 중요한 원칙은 Model에서 UI를 만들어야 한다는 것입니다. 가급적 지속적인 Model(a persistent model)을 권장합니다. Model은 앱의 데이터 처리를 담당하는 구성요소로, 앱의 View 개체 및 앱 구성요소와 독립되어 있으므로 앱의 수명주기와 관련 문제의 영향을 받지 않습니다.

지속적인 Model이 이상적인 이유는 다음과 같습니다.

▶ Android OS에서 리소스를 확보하기 위해 앱을 제거해도 사용자 데이터가 삭제되지 않습니다.

▶ 네트워크 연결이 취약하거나 연결되어 있지 않아도 앱이 계속 작동합니다.

데이터 관리 책임이 잘 정의된 Model 클래스를 기반으로 앱을 만들면 쉽게 테스트하고 일관성을 유지할 수 있습니다.


3. 권장하는 App Architecture



이 섹션에서는 종합적인 사용 사례(end-to-end use case)를 들어 아키텍처 구성요소를 사용하여 앱을 구성하는 방법을 보여줍니다.

참고: 모든 시나리오에서 잘 작동하는 앱을 작성하는 한 가지 방법은 없습니다. 하지만 이 권장 아키텍처는 대부분의 상황 및 워크플로에 유용한 출발점이 될 것입니다. 이미 일반 아키텍처 원칙을 준수하는 Android 앱 작성 방법을 사용하고 있다면 방법을 변경할 필요가 없습니다.

사용자 프로필을 표시하는 UI를 제작한다고 가정해 보겠습니다. 이 경우 비공개 백엔드 및 REST API를 사용하여 지정된 프로필의 데이터를 가져옵니다.

개요

먼저 다음 다이어그램을 살펴보세요. 앱을 설계한 이후 모든 모듈이 서로 어떻게 상호작용해야 하는지 보여줍니다.

각 구성요소가 한 수준 아래의 구성요소에만 종속됨을 볼 수 있습니다. 예를 들어 activity 및 fragment는 ViewModel에만 종속됩니다. Repository는 여러 개의 다른 클래스에 종속되는 유일한 클래스입니다. 이 예에서 Repository는 지속 데이터 Model과 원격 백엔드 데이터 소스(Remote Data Source)에 종속됩니다.

이 디자인은 일관되고 즐거운 사용자 환경을 만들어 줍니다. 사용자가 마지막으로 앱을 닫은 후 몇 분 후 또는 며칠 후에 앱으로 돌아오든 상관없이, 로컬에서 앱이 지속된다는 사용자의 정보를 즉시 볼 수 있습니다. 이 데이터가 오래된 경우 앱의 Repository 모듈이 백그라운드에서 데이터를 업데이트하기 시작합니다.

다음으로 이어지는 작업은 다음 포스팅을 통해 자세히 설명하도록 하겠습니다.



Reference

1. https://developer.android.com/jetpack/docs/guide


반응형

+ Recent posts