8월, 2016의 게시물 표시

(안드로이드) 파일 저장하기

안드로이드는 다르 플랫폼의 디스크 기반 파일시스템과 유사한 파일 시스템을 사용한다. File객체는 건너띄는 것 없이 처음부터 끝까지 순서대로 많은 양의 데이터를 읽고 쓰는데 적합하다. 예를들어, 이미지 파일이나 네트워크를 통해 변경되어지는 것들을 저장흐넨ㄷ 좋다. 내부 또는 외부 저장장치 선택 모든 안드로이드 단말기들은 두개의 파일 저장 영역을 가지고 있다. "Internal" 과 "External" 저장장치 이 저장소의 이름들은 안드로이드 이전부터 만들어져 있던 것들입니다. 대부분의 단말기들은 내장되어 있는 비휘발성 메모리(내부 메모리)가 제공되어 있으며, 추가적으로 SD card(External Storage)와 같은 제거할 수 있는(removable) 저장장치를 가지고 있다.  내부 저장장치(Interanal Storage) 이 장치는 항상 사용할 수 있습니다. 이곳에 저장된 파일을 기본적으로는 오직 여러분의 앱에 의해서만 접속할 수 있다. 사용자가 여러분의 앱을 언인스톨할 때, 시스템은 내부저장소로부터 앱의 파일들을 모두 제거한다. 내부 저장소는 사용자든 다른 앱들이든 여러분의 파일에 접속할 수 없도록 하고 싶을때 사용하기 좋은 곳이다. 외부 저장장치(Interanal Storage) 이 장치는 항상 사용할 수는 없다. 왜냐하면 사용자가 USB저장장치처럼 외부저장소를마운트(mount) 할 수도있고, 어떤 경우에는 단말기에서 제거할 수도 있기 때문이다. 이 장치는 기본적으로 world-readable이다. 그래서 저장된 파일은 여러분의 제어밖에서(동의없이) 읽어질 수도 있다. 사용자가 여러분의 앱을 언인스톨할 때, 시스템은 여러분이 getExternalFilesDir()로 만든 디렉토리에 파일을 저장했을때만 자동으로 제거된다. 외부 저장소는 파일의 접속제한이 필요하지 않으며, 다른 앱들이나 사용자가 컴퓨터를 사용하여 접속하도록 공유하고 싶을 때 사용하기 좋은 곳이다.

(안드로이드) Bitmap 구현,관리하기

안드로이드에서 비트맵 관련 클래스는 android.graphics.Bitmap이다. 그래픽 관련 클래스들은 android.graphics패키지에 있으며 여기에 포함된 것이다. 그리고 객체 Factory관리를 위한 BitmapFactory클래스가 있다. BitmapFactory는 여러가지 이미지 포맷을 decode해서 bitmap으로 변환하는 함수들로 되어있는데, 그 이름들은decodeXXX로 되어있어서 쉽게 원하는 기능의 함수를 찾을수 있을 것이다. (1) BitmapFactory에서 주로 사용하고 있는함수와 옵션에 대한 설명 BitmapFactory.decodeFile() : 로컬에 존재하는 파일을 그대로 읽어올 때 쓴다. 파일 경로를 파라미터로 넘겨주면 FileInputStream을 만들어서 decodeStream을 한다.  ex) Bitmap orgImage=BitmapFactory.decodeFile("/sdcard/test.jpg"); BitmapFactory.decodeResource() : Resource폴더에 저장된 그림파일을 Bitmap으로 만들어 리턴해준다. ex) Bitmap orgImage=BitmapFactory.decodeResource(getResources(), R.drawable.test02); BitmapFactory.decodeStream() : InputStream으로부터 Bitmap을 만들어준다. BitmapFactory.Options : BitmapFactory가 사용하는 옵션클래스이다. Options객체를 생성하고 설정하고자 하는 옵션을 넣은 후 BitmapFactory의 함수 실행시 파라미터로 넘기면 된다. inSampleSize: decode시 얼마나 줄일지 설정하는 옵션인데 1보다 작을떄는 1이된다. 1보다 큰값일때 1/N만큼 이미지를 줄여서 decoding하게된다. 보통 2의 배수로 설정한다. ex) BitmapFac

(안드로이드) 이미지 로딩 처리(메모리캐시, 디스크캐시)

이미지
*안드로이드에서는 LruCache를 제공한다. LruCache는 LinkedHashMap을 사용하여 최근에 사용된 object의 strong reference를 보관하고 있다가 정해진 사이즈를 넘어가게 되면 가장 최근에 사용되지 않은 놈부터 쫒아내는 LRU알고리즘을 사용하는 메모리 캐시다. 예전에는 bitmapcache에 SoftReference나 WeakReference를 사용하는 방식을 썻으나 안드로이드 2.3부터 가비지 콜렉터가 공격적으로 이놈들의 메모리를 가비지 콜렉팅하면서 몹쓸 방법이 되었다. 게다가 이 방법은 3.0이전 버전에서 매모리 해제를 제대로 못해 크래쉬 문제도 있다. 그러나 LruCache를 사용해보겠다. LruCache의 캐시 사이즈를 정하기 위해서 고려할 사항 앱에서 앞으로 메모리를 얼마나 사용해야 하는가? 얼마나 많은 이미지들이 한 화면에 보여질 것인가? 얼마나 많은 이미지들이 다음에 보여주기 위해 준비되어야 하는가? 화면 해상도가 어떻게 되는가? 각 이미지마다 메모리를 얼마나 차지하는가? 이미지는 얼마나 자주 액세스 되는가? 질보다 양? 양보다 질? 어떤 경우에는 많은 양의 저해상도 이미지를 미리 보여주고 백그라운드로 고해상도 이미지를 로드하는 방법이 좋을 수도 있다. 너무 캐시사이즈를 작게하면 오버헤드만 발생하고, 사이즈를 너무 크게하면 OutOfMemoryException을 보게 된다. <아주 큰 비트맵을 효율적으로 로딩하기> 애플리케이션의 메모리 제한에 문제없이 비트맵을 로딩하는 방법. 이미지를 표시할 UI컴포넌트는 대체적으로 이미지보다 작게 표시된다. 이떄는 이미지의 원본사이즈가 아니라 표시될 컴포넌트의 크기에 맞게 로드하는것이 이득이다. BitmapFactory클래스가 비트맵을 디코딩하기 위한 여러 메소드(decodeByteArray(), decodeFile(), decodeResource())들을 제공한다. 이 메소드들은 비트맵을 디코딩할 때 메모리할당을 시도하

(안드로이드) 파일명으로 리소스 가져오기

리소스 접근하는 방법이 여러가지가 있지만, Bitmap testImg=BitmapFactory.decodeResource(res,R.drawable.testRes0); 이런식으로 파일 ID로 리소스를 읽어와 사용하는 방법이 보편적이다. 그러나 리소스가 많을 경우 testImg=new Bitmap[10]; for(int i=0;i<10;i++)   testImg[i]=BitmapFactory.decodeResource(res,R.drawable.tesrRes0+i); 이런식으로 ID로 연산을 하여 읽어오다보면 ID가 꼬이는 경우 문제가 발생할 여지가 있다. 파일명이 순차적으로 되어 있다고 하더라도 이런식의 접근은 좋지 않은 방법이다. 이럴경우, int tmpID; testImge=new Bitmap[10]; for(int i=0;i<10;i++) {       tmpID=res.getIdentifier("testRes"+i,"drawable","com.android.android.test");       testImg[i]=BitmapFactory.decodeResource(res,tmpID); } 이런식으로 리소스 파일명으로 ID를 알아와 접근하는 방식을 사용할 수 있다. "패키지명: 타입/ 리소스명",null,null getIdentifier("com.android.android.test:drawable/testRes",null,null); "리소스명","타입","패키지명" getIdentifier("testRes","drawable","com.android.android.test");

(안드로이드) 파일명으로 리소스 가져오기

리소스 접근시 여러가지 방법이 있겠지만 Bitmap testImg = BitmapFactory.decodeResource(res, R.drawable.testRes0); 이런식으로 파일 ID로 리소스를 읽어와 사용하고 있었습니다. 그런데 리소스가 많을 경우  testImg = new Bitmap[10]; for(int i = 0; i < 10; i++)         testImg[i] = BitmapFactory.decodeResource(res, R.drawable.testRes0+i); 이런식으로 ID로 연산을 하여 읽어오다보면 ID가 꼬이는 경우 문제가 발생할 여지가 많더군요. 파일명이 순차적으로 되어 있다고 하더라도 이런식의 접근은 안좋은 방법인것으로 알고 있습니다. 이럴경우 int tmpID; testImg = new Bitmap[10]; for(int i = 0; i < 10; i++) {        tmpID = res.getIdentifier( "testRes"+i, "drawable" , "com.androidpub.android.test");        testImg[i] = BitmapFactory.decodeResource(res, tmpID); } 이런식으로 리소스 파일명으로 ID를 알아와 접근하는 방식을 사용할 수 있습니다. "패키지명 : 타입 / 리소스명", null, null getIdentifier("com.androidpub.android.test:drawable/testRes", null, null); 또는 "리소스명", "타입", "패키지명" getIdentifier("testRes", "drawable", "com.androidpub.android.test"

(안드로이드) 스타트서비스와 바운드서비스 개요

*안드로이드 서비스 클래스는 애플리케이션이 백그라운드 작업을 시작시켜 수행할 수 있게 특별히 설계되었다. 작업을 빨리 수행하고 종료하는 브로드캐스트 수신자와 다르게, 서비스는 실행 시간이 길면서 사용자 인터페이스를 필요로하지 않는 작업을 수행하도록 설계되었다. <스타트 서비스> 스타트 서비스는 다른 애플리케이션 컴포넌트(예를들어, 액티비티나 브로드캐스트 수신자)에 의해 론칭된다. 그리고 서비스가 중단되거나 리소스 해제를 위해 안드로이드 런타임 시스템에 의해 소멸될 때까지 백그라운드로 무한정 실행된다. 이 서비스는 자신을 시작시킨 애플리케이션이 더 이상 포그라운드에 있지 않아도 계속 실행된다. 심지어는 실제로 서비스를 시작시킨 컴포넌트가 소멸될 경우에도 계속 실행된다. 기본적으로 이 서비스는 자신이 론칭되었던 애플리케이션 프로세스와 동일한 메인 스레드에서 실행된다. 이것을 로컬서비스 라고 한다. 따라서 CPU를 많이 사용하는 작업들은 그 서비스의 새로운 스레드에서 수행되도록 하는 것이 중요하다. 그리고 별도의 프로세스에서 서비스가 실행되는 것을 원격서비스 라고하며, 이때는 매니페스트 파일에 구성 변경을 해야 한다. 매니페스트 파일의 설정으로 서비스가 특별히 private(론칭된 프로세스 전용)으로 구성되지 않는다면 그 서비스는 같은 안드로이드 장치의 다른 컴포넌트에 의해 시작될 수 있다. 이때는 한 액티비티가 다른 액티비티를 론칭하는 방법과 똑같이 인텐트 매커니즘을 사용하면 된다. 스타트 서비스는 startService()메소드를 호출하여 론칭하며, 시작되는 서비스를 식별하는 인텐트 객체를 인자로 전달한다. 스타트 서비스는 작업을 완료한 후 stopSelf()를 호출하여 자신을 중단시켜야 한다. 또한, stopService()메소드를 호출하면 실행 중인 서비스를 다른 컴포넌트에서 중단시킬 수 있다. 이때는 중단될 서비스아 일치하는 인텐트를 인자로 전달한다. <인텐트 서비스> IntentService클

(안드로이드) Recycler뷰와 Toolbar 연동시키기

** CoordinatorLayout의 뷰 계층 구조에 속한 특정 뷰의 스크롤 액션을 기준으로 앱바의 요소들이 사라지거나 나타나게 하기 위해 CoorinatorLayout을 사용할 수 있다.  예를들어, RecyclerView의 리스트 항목을 스크롤할 때 그렇게 될 수 있다. 그리고 이렇게 하려면 스코롤이 생기는 요소와 그로 인해 연동되는 요소 모두의 속성을 설정해야 한다. 스크롤이 생기는 요소(여기서는 RecyclerView)의 경우에는 android:layout_behavior(또는 app:layout_bahavior)속성을 appbar_scrolling_view_behavior로 설정해야 한다. < android.support.v7.widget.RecyclerView android :id= "@+id/recycler_view" android :layout_width= "match_parent" android :layout_height= "match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> < android.support.design.widget.AppBarLayout android :layout_width= "match_parent" android :layout_height= "wrap_content" android :theme= "@style/AppTheme.AppBarOverlay" > < android.support.v7.widget.Toolbar android :id= "@+id/toolbar" android :layout_width= "

(안드로이드) 안드로이드 액티비티 생명주기 메소드

<동적상태 vs 영속적상태> 액티비티 생명주기를 관리하는 주 목적은 적시에 액티비티 상태를 저장하거나 복원하기 위함이다. 상태(state)는 액티비티가 현재 보존하고 있는 데이터와 현재 보이는 사용자 인터페이스 데이터( 화면에 나타난 뷰 객체의 데이터) 를 의미한다. 예를들어, 액티비티는 데이터베이스, 콘텐트 제공자, 파일 등에 저장될 필요가 있는 메모리의 데이터를 유지할 수 있다. 그런 상태정보를 영속적상태 라고한다. 화면에 보이는 사용자 인터페이스는 동적상태 라한다.(사용자인터페이스 상태 또는 인스턴스 상태) 예를들어,액티비티 A가 백그라운드에 있다가 포그라운드로 올 수 있다. 따라서 액티비티A가 포그라운드로 돌아오면 자신이 입력했던 텍스트가 그대로 남아있을 것이라 생각한다. 그러나 이 경우 액티비티A의 새로운 인스턴스가 생성되므로, 만일 동적 상태 데이터가 저장되어 복원되지 않았다면 사용자가 이전에 입력한 데이터는 유실된다. *안드로이드에서는 장치의 구성이 변경되면(장치를 세웠다 눕혔다)액티비티의 인스터스를 새로 생성한다는 것에 유의하자. 그러므로 동적상태를 저장하는 주 목적은 포그라운드와 백그라운드 액티비티들간이 매끄러운 전환을 제공하는 것이다. <액티비티의 생명주기 메소드> Activity클래스는 생명주기 메소드를 많이 갖으며, 액티비티의 상태가 변경될 때 이벤터처리기(Event Handler)처럼 동작한다. onCreate(Bundle savedInstanceState): 이 메소드는 액티비티 인스턴스가 최초 생성될 때 호출되며, 대부분의 초기화 작업을 하는데 이상적인 곳이다. 메소드 인자로 동적 상태 정보를 포함할 수 있는 Bundel객체를 인자로 전달한다. 그런 동적상태 정보는 직전에 생성되었다가 소멸된 동일 액티비티으 인스턴스로부터 전달되며, 일반적으로 사용자 인터페이스의 상태와 관련되는 데이터다. onRestart(): 액티비티 런타임 시스템에 의해 이전에 중지되었다

(안드로이드) 액티비티 생명주기

*안드로이드 시스템에서 메모리를 해제하기 위해 프로세스들을 중단시킨다. 메모리 해제를 위해 어떤 프로세스를 중단시킬지 결정할 때 시스템에서는 현재 실행 중인 모든 프로세스의 우선순위 와 상태 를 모두 고려한다. 그리고 이때 그런 요소들을 결합하여 구글에서 이야기하는 중요도 서열이라는 것을 생성한다. <안드로이드의 프로세스 상태> 1. 포그라운드 프로세스 가장높은 수준의 우선순위이다. 프로세스가 포그라운드 상태가 되려면 다음의 자격조건을 하나 이상 충족해야 한다. 사용자와 현재 상호작용중인 액티비티를 호스팅(포함해서 실행)한다. 사용자와 현재 상호작용 중인 액티비티에 연결된 서비스를 호스팅한다. 중단되면 사용자에게 해를 끼칠 수 있다는 거을 startForeground()메소드를 호출하여 알려준 서비스를 호스팅한다. 자신의 onCreate(), onResume(), onStart()콜백 메소드 중 하나를 실행하는 서비스를 호스팅한다. onReceive()메소드로 현재 실행중인 브로드캐스트 수신자를 호스팅한다. 2. 가시적프로세스 화면으로 볼 수는 있지만 사용자와 상호작용은 하지않는 액티비티를 포함하는 프로세스는 가시적 프로세스로 분류된다. 3. 서비스 프로세스 이미 시작되어 현재 실행 중인 서비스(service)를 포함하는 프로세스이다. 4. 백그라운드 프로세스 사용자가 화면으로 현재 볼 수 없는 하나 이상의 액티비티를 포함하는 프로세스다. 더 높은 우선순위의 프로세스에서 추가 메모리가 필요한 경우, 이 부류의 프로세스는 안드로이드 런타임에의해 중단될 가능성이 크다. 안드로이드는 백그라운드 프로세스내역을 동적ㅇ로 유지 관리하면서 실행 순서에 따라 프로세스를 중단시킨다. 5. 비어있는 프로세스 실행되는 애플리케이션을 포함하지 않으며, 새로 론칭되는 애플리케이션을 호스팅하기 위해 메모리에 남아있다. 문을 연 채로 엔진을 켜 놓고 탑승을 기다리는 버스와 유사하

(어플리케이션 개발) 중요사항 정리.

*이미지 메타데이터를 칼럼에 저장하기 위해서 Char, VARCHAR 의 선택시 고려한것 , 1. 가변길이인가? 2. 칼럼의 값이 자주변경되는가? --->CHAR은 고정길이 문자열로 일정한 바이트 크기를 미리 할당해 놓기 때문에 글자 길이가 비슷한 경우는, 글자만 업데이트 하게 된다. 하지만 VARCHAR은 가변길이 문자열로 길이가 다른 문자열로 업데이트 될 시, 레코드 자체를 다른공간으로 옮기거나 칼럼 값의 나머지 부분을 다른 공간에 저장해야 한다.

(안드로이드) ListView를 갱신하는 메소드

이미지
*ListView를 갱신하는 메소드는 1. notifyDataSetChanged() --->이 경우 ListView를 밑으로 쭉 내려 놓고 메소드를 호출하면 List가 갱신이 되면서 밑으로 내려놓은 자리에 그대로 위치하여 화면이 보이게 된다. 2. notifyDataSetInvalidated() --->이 메소드의 경우 ListView의 보이는 위치를 어디로 해놓아도 메소드를 호출하면 List가 갱신이되고, List의 맨 윗부분에(List의 첫번쨰 Index에) 화면이 보이게 된다.

(Tomcat) web.xml 설명

1. 웹 애플리케이션이 시작하는 즉시 서블릿을 시작하도록 웹 컨테이너에 지시하는 법 <servlet>   <servlet-name>appServlet</servlet-name>   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>   <load-on-startup>1</load-on-startup> </servlet> --->숫자 1이 우선순위가 가장 높고 값이 클수록 나중에 시작된다. 2. 서블릿과 URL매핑 서블릿이 어떤 URL요청에 반응해야 하는지 지정하는 것 <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> --> "/"는 모든 URL에 대해 appServlet가 처리하게 된다. 3. 컨텍스트 초기화 매개변수 사용 <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> 4. 서블릿 초기화 매개변수 사용 <servlet> <servlet-name>appServlet</servlet-name> <servletclass>org.springframework.web.servlet.DispatcherServlet</servlet

(어플리케이션 개발) 이미지서버를 분산시키는 것.

이미지
*이미지 호스팅 시스템에서는 고려해야 할 다른 측면이 있다. 저장될 이미지의 개수에 제한이 없다. 따라서 저장공간의 확장성에 대해서도 고려해야 한다. 이미지 보기나 다운로드를 요청할 때 응답시간이 빨라야 한다. 사용자가 이미지를 업로드하고 난 후, 해당 이미지는 항상 시스템에 저장되어 있어야 한다. (데이터에 대한 신뢰성) 시스템을 운용하기 쉬워야 한다.(관리성) 이미지 호스팅 서비스 자체의 이익율이 높지 않기 때문에, 시스템은 비용 효율적으로 운용될 필요가 있다. 다음은 이미지 호스팅 애플리케이션의 기능을 간단하게 도식화한 것이다.                                      그림 1 이미지 호스팅 애플리케이션의 아키텍처 다이어그램 이미지 호스팅 시스템에서는 고려해야 할 다른 측면이 있다.  서비스들(Services) 확장성있는 시스템을 설계할 때 각각의 명확한 인터페이스를 기반으로 나누어 생각하는 것은 좋은 방법이다. 이러한 방식으로 설계하는 시스템을 SOA(Service-Oriented Architecture)라고 부른다. 그리고 각각의 서비스는 다른 서비스와 상호작용을 위해 다른 서비스에서 공개하는 API형태인 추상화된 인터페이스를 사용한다. 시스템을 상호 보완적인 서비스로 분할한다는 것은 시스템을 기능단위로 분리시키는 것을 말한다. 이러한 추상화는 서비스와 서비스가 처한 환경 그리고 서비스와 서비스 사용자 사이의 명확한 관계를 수립하는데도 도움이 된다. 이러한 명확한 기술은 문제를 분리시키는데도 도움이 되지만, 각각을 독립적으로 확장시키는 것에도 효과적읻. 이런의미에서 시스템에서의 SOA는 객체 지향 프로그래밍과 아주 유사하다. 예제 애플리케이션에서 모든 이미지 업로드와 검색을 위한 요청은 같은 서버에서 처리되지만, 시스템을 확장시키기 위해서는 업로드와 검색 기능은 각각의 서비스로 분리되는 것이 합리적이다. 일반적으로 쓰기는 읽기보다 느리다.