android setImage failed (사진을 못 가져올 때)

갤러리에서 사진을 선택할 때 사진을 못 가져오는 현상이 발생하면 아래 두 가지 경우를 생각 할 수 있습니다.

1. Permission Denial

java.lang.SecurityException: Permission Denial: reading 
com.android.providers.media.MediaProvider uri 
content://media/external/images/media/38498 from pid=27232, uid=10472 requires 
android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()

이 경우는 External storage에서 URI를 가져올 때 권한에 막혀 가져오지 못하는 경우입니다.
위와 같은 경우는 Manifest에 아래와 같이 권한 설정을 해주면 쉽게 가져올 수 있습니다.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


2. 이미지 용량 초과

 삼성 핸드폰의 경우 'Input agif image larger than 30MB.' 라는 로그 메세지를 보실 수 있
습니다. 일정 용량 이상의 사진파일은 불러오지 못하므로, setImageUri(uri)를 아래와 같이
BitmapFactory를 이용해 이미지의 size를 조정해주시면 불러 올 수 있습니다.

uri = data.getData();
try {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;
    Bitmap myBitmap = BitmapFactory.decodeStream(view.getContext().getContentResolver().openInputStream(uri), null, options);
    selectedImageView.setImageBitmap(myBitmap);
} catch(Exception e){
    e.getStackTrace();
}

Application windows are expected to have a root view controller at the end of application launch

에러 코드

Xcode 7 iOS9에서 발생
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException'reason : 'Application windows are expected to have a root view controller at the end of application launch'


원인

Xcode 7부터 앱 시작전에 root view controller를 설정해 주어야 합니다.


해결

-  ( BOOL ) application : ( UIApplication  * ) Application  didFinishLaunchingWithOptions : ( NSDictionary * ) launchOptions {
    // 윈도우 초기화
    self . window  =  [[ UIWindow  alloc ]  initWithFrame : [ UIScreen  MainScreen ]  bounds ]];
    self . window . rootViewController  =  [ UIViewController  new ];
    [ self . window  makeKeyAndVisible ];

    return  YES ;
}



python django 설치

django의 설치를 위해 아래 주소에서 tar.gz을 다운받습니다.

https://www.djangoproject.com/

다운받은 Django-1.8.4.tar.gz의 압축을 해제하면 아래와 같은 모습을 보실 수 있습니다.
























위 폴더의 setup.py를 아래와 같이 실행시켜줍니다.































setup.py install을 실행하면 아래와같이 설치가 진행, 완료됩니다.






























설치 완료된 django 프레임워크의 버전은 아래와 같이 django.get_version()을 통해 확인 할 수 있습니다.







App Transport Security

iOS9 혹은 OS X 10.11이상에서 유효한 기능이며, 어플이나 웹서비스 간의 안전한 연결을 위해 사용할 수 있습니다.

ATS가 활성화 되면 HTTP통신을 할 수 없습니다. 또한 Apple에서 권장하는 요구 사항을 충족하지 않는 연결은 강제로 연결 실패 처리 됩니다.



실제 에러 메시지

Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSErrorFailingURLStringKey=에러가 발생한 URL, NSErrorFailingURLKey=에러가 발생한 URL, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection., NSUnderlyingError=0x14eae740 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSErrorFailingURLKey=에러가 발생한 URL, NSErrorFailingURLStringKey=에러가 발생한 URL, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.}}}




필요조건

  • TLS버전 1.2 이상
  • 연결시 사용할수 있는 암호화스위트(암호화 알고리즘의 조합)는 다음 리스트로 제한
    • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • 서버인증서에 요구되는 조건
    • SHA256 이상의 지문
    • 2048 비트 이상의 RSA 키 또는 256 비트 이상의 Elliptic-Curve(ECC)키
  • 잘못된 인증서를 사용하면 강제로 실패되어, 연결할 수 없음



필요조건을 만족시킬 수 없는 경우

Info.plist에 특정 키와 값을 추가하면 ATS를 비활성화하거나 일부 동작을 변경할 수 있습니다.


ATS를 비활성화 (비추천)
<key> NSAppTransportSecurity </ key>
<dict>
    <key> NSAllowsArbitraryLoads </ key>
    <true />
</ dict>


기본적으로 ATS를 활성화 하고 ATS의 대상으로 하지 않는 도메일을 Info.plist에 기재
<key> NSAppTransportSecurity </ key>
<dict>
    <key> NSExceptionDomains </ key>
    <dict>
        <key> 예외처리할 도메인 </ key>
        <dict>
            <key> NSTemporaryExceptionAllowsInsecureHTTPLoads </ key>
            <true />
        </ dict>
    </ dict>
</ dict>


기본적으로 ATS를 무효로하고, ATS의 대상으로하는 도메인을 Info.plist에 기재
<key> NSAppTransportSecurity </ key>
<dict>
    <key> NSAllowsArbitraryLoads </ key>
    <true />
    <key> NSExceptionDomains </ key>
    <dict>
        <key> 예외처리할 도메인 </ key>
        <dict>
            <key> NSTemporaryExceptionAllowsInsecureHTTPLoads </ key>
            <false />
        </ dict>
    </ dict>
</ dict>


ATS의 요구사항을 낮출 설정을 Info.plist에 기재
<key> NSAppTransportSecurity </ key>
<dict>
    <key> NSExceptionDomains </ key>
    <dict>
        <key> 도메인 </ key>
        <dict>
            <key> NSTemporaryExceptionMinimumTLSVersion </ key>
            <string> TLSv1.1 </ string>
            <key> NSTemporaryExceptionRequiresForwardSecrecy </ key>
            <false />
        </ dict>
    </ dict>
</ dict>






Red-Hat 계열 Linux에서 Tomcat Service Setting

Install 및 Setting 전 확인 사항

  1. Root계정 권한 획득
  2. Tomcat 다운로드 후 압축 해제 상태


기본적으로 tomcat install은 패키지 설치가 아닌 apache tomcat을 다운받아서 압축을 푸는 개념으로 모든 설정파일과 service 시작 daemon파일이 tomcat 폴더에 들어있어 tomcat폴더의 bin 폴더에 들어가면 startup.sh와 shutdown.sh를 볼 수 있습니다. 이를 service 명령어로 올리고 내릴 수 있도록 설정하고 또한 리눅스 실행과 동시에 startup하도록 chkconfig에 등록 하도록 하겠습니다.

Where is Servie file


<Red-Hat/CentOS>

# pwd

위의 명령어를 통해 우선 startup파일과 shutdown파일의 위치를 확인 합니다.


Create Service shell script file

# vi /etc/rc.d/init.d/tomcat

위 커맨드를 실행 한 뒤 dhcp server를 configure해줍니다.


아래와 같이 Shell script를 작성 해 줍니다.




  1. 6~7번 line을 통해 chkconfig에 등록 할 수 있도록 해줍니다.
  2. 8번 line의 변수 TOMCAT_HOME에 tomcat폴더의 경로를 지정해줍니다.
  3. 11번 line 부터 case명령어를 통해 service {start|stop|restart}시의 기능을 부여합니다.
(start)시 startup.sh실행 (stop)시 shutdown.sh실행 (restart)시 stop, start 반복



add chkconfig

#chkconfig --add tomcat 을 설정합니다.
#chkconfig tomcat on 을 해 linux 시작 시 실행되도록 설정합니다.
#chkconfig --level 2345 tomcat on 커맨드를 통해 Run level별로 지정 해 줄 수 있습니다.
#chkconfig --list를 통해 확인합니다.




Service start

# /etc/init.d/tomcat start
# /etc/init.d/tomcat stop


# service tomcat start
# service tomcat stop


Android dynamic change image resource (안드로이드 동적 이미지 변경)

안드로이드 소스코드 내에서의 동적 이미지 변경 방법입니다.

setImageResource(getApplication().getResources().getIdentifier(String name, String defType, String defPackage));

위와같은 방식으로 가져오며, 아래는 소스코드의 예 입니다.

imageView image= (ImageView)findViewById(R.id.test_image);
image.setImageResource(getApplication().getResources().getIdentifier("ic_launcher", "mipmap", "com.testcode.testproject"));

이런 방식으로 소스코드 내에서 이미지를 변경 할 수 있습니다.

Android error: resource entry is already defined

안드로이드에서 error: resource entry name.png is already defined

라는 문구가 뜨면

이미 올라가있던 jpg파일이 등록된 후 png파일이 올라와서 리소스에 중복되어있는 경우입니다.

안드로이드 프로젝트 build -> rebuild project를 하시면 손쉽게 해결 할 수 있습니다.

Python socket programming #4 - multiprocessing #1

Python에서 thread는 GIL(Global Interpreter Lock)을 따르게 됩니다.
간단하게 설명하면 보통은 다수의 쓰레드가 작동할 때에 아래와 같은 모델을 상상하게 됩니다.

하지만 GIL에 의해서 python은 한 Thread씩 Lock이 걸리는게 아니라 전체에 걸리게 되면서 여러개의 Thread가 Single Processor에서 동작 하는 것 처럼 동작하게 됩니다.



프로그램을 통해 살펴보면

위는 한 개의 Thread를 동작시켜 총 작업 시간을 출력한 프로그램입니다.
100000000의 숫자를 하나씩 빼면서 while문을 돌리는 간단한 프로그램입니다.
출력 결과는 아래와 같습니다.

---------------------------------------------------
Starting Thread_1
Thread_1 의 작업 시간 8
Exiting Thread_1

Exiting Main Thread
총 작업 시간 8
---------------------------------------------------

또 다른 프로그램을 살펴보면

위는 두 개의 Thread를 동작시켜 총 작업 시간을 출력한 프로그램입니다.
기본적으로 생각했을 때엔 위에서 살펴본 하나의 Thread의 작업 시간인 8초와
동일한 시간을 생각 해 볼 수 있습니다. 하지만 결과는 아래와 같습니다.

---------------------------------------------------
Starting Thread_1
Starting Thread_2
Thread_2 의 작업 시간 15
Exiting Thread_2

Thread_1 의 작업 시간 16
Exiting Thread_1

Exiting Main Thread
총 작업 시간 16
---------------------------------------------------

생각했던 것과는 다르게 하나의 Thread의 작업 시간 8초의 두 배인 16초가 출력 되는 것을 보실 수 있습니다.

위와 같은 이유로 python에서는 thread보단 multiprocessing이 권장되어집니다.

1. Multiprocessing

python에서 사용하는 multiprocessing은 fork()와 같게 생각하시면 됩니다.
하나 이상의 자식 process를 생성하여 이를 병렬구조로 처리하는 것을 지칭합니다.

import multiprocessing
위와같이 모듈을 불러와 사용 할 수 있습니다.

2. Pool

p = Pool(n)
위의 Pool(n)을 통해 미리 process를 생성 할 수 있게 됩니다.

p.map(function, values)
위의 Pool.map을 통해 각 process들이 함수를 동작 시키게 할 수 있습니다.

multiprocessing의 pool을 이용한 예제를 통해 살펴보겠습니다.

위의 예제는 pool을 통해 3개의 process를 생성하고, f(x)함수를 불러와 1초씩 함수에서 대기하게 됩니다. 결론적으로 3개의 process가 10개의 값을 연산하려면 아래와 같이 총 4초가 걸리게 됩니다.

프로세서     값        연산시간      누적 연산시간
process 1 -> 0 -------- 1초  -------- 1초
process 2 -> 1 -------- 1초  -------- 1초
process 3 -> 2 -------- 1초  -------- 1초
------------------------------------------------------
process 1 -> 3 -------- 1초  -------- 2초
process 2 -> 4 -------- 1초  -------- 2초
process 3 -> 5 -------- 1초  -------- 2초
------------------------------------------------------
process 1 -> 6 -------- 1초  -------- 3초
process 2 -> 7 -------- 1초  -------- 3초
process 3 -> 8 -------- 1초  -------- 3초
------------------------------------------------------
process 1 -> 9 -------- 1초  -------- 4초


process를 4개로 늘리거나, range를 (0,9)로 수정한다면 누적 연산시간이 3초가 걸리는 것을
확인 하실 수 있습니다.

아래는 출력 결과입니다.

값 0 에 대한 작업 Pid =  3712
값 1 에 대한 작업 Pid =  3740
값 2 에 대한 작업 Pid =  2568
값 3 에 대한 작업 Pid =  3712
값 4 에 대한 작업 Pid =  3740
값 5 에 대한 작업 Pid =  2568
값 6 에 대한 작업 Pid =  3712
값 7 에 대한 작업 Pid =  3740
값 8 에 대한 작업 Pid =  2568
값 9 에 대한 작업 Pid =  3712
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
총 작업 시간 4

Collection Framework(Java의 자료구조)

1.  Collection Framework
JDK 1.2이전 까지는 collection class인 Vector, Stack, Hashtable, Properties등을 사용 했으나, 이후 collection framework가 생기면서 재사용성이 높은 코드를 사용 할 수 있게 되었습니다. 

이후 collection class는 남아 있지만 


2. 대표 인터페이스
Collection Framework에는 크게 세 인터페이스로 나누어지며 특징은 다음과 같습니다.


  1. List - 중복이 가능한 순서를 기억하는 데이터 집합
  2. Set - 중복이 불가능하며 순서를 기억하지 않는 데이터 집합
  3. Map - 키와 값을 가지고 순서는 기억하지 않으며 키는 중복이 불가능하고 값은 중복이 가능한 데이터 집합







px, dp, dip, sp의 차이

dp (Density-independent Pixels)
160dpi화면을 기준으로 하며, 1dp1px과 거이 동일합니다.
고밀도 화면에서 실행할 경우 1dp를 그리는데 사용되는 픽셀의 수는 화면의 dpi 따라 적절히 조정되며, 마찬가지로 저밀도일 때 1dp의 화소 수는 축소됩니다.
px단위 대신에 dp단위를 사용하면 밀도가 다른 화면에서도 UI요소들의 일관성을 제공합니다. 

dip (Density-Independent Pixels)
dip는 초기버전에서 사용했지만 지금은 dp로 축약되었습니다.
 
sp (Scale-independent Pixels)
spdp단위와 같지만 사용자의 폰트사이즈 설정에 의해 조절됩니다.
sp는 글꼴크기를 지정 할 때 사용하는 것이 좋습니다.
 
pt (point)
1/72인치 에 해당됩니다.
 
px (pixels)
실제 화면의 픽셀에 해당합니다.
각 디바이스는 인치 당 픽셀수가 다르고 화면에서 사용 가능한 픽셀 수가 많거나 적을 수 있습니다. 
 
mm (Millimeters)
화면의 실제 크기를 기준으로 합니다.
 
in (Inches)
화면의 실제 크기를 기준으로 합니다.















Python socket programming #3 - MultiThreading (Threading module)

2. threading


두 번째로 threading 모듈은 thread 클래스를 상속받아 사용하는 모듈입니다.

클래스가 threading.Thread를 상속받아 사용하게 됩니다.

java와 마찬가지로 run 메소드를 오버라이드 하여 각 각 선언된 클래스를 통해

Class_name.start()를 작동시키면 run 메소드가 작동하게 됩니다.

위의 코드를 보면

class myThread (threading.thread):를 통해 클래스를 선언 한 뒤

생성자를 통해 thread의 name과 delay time을 인자로 받습니다.

이 후 thread1.start()를 통해 run 메소드를 작동시킵니다.

run 메소듣 내부에서는 print_count함수를 호출하여 5회 각 각 1초와 2초의 딜레이를 부여해 내용을 출력합니다.

아래는 출력 내용입니다.

Starting Thread_1
Exiting Main Thread
Starting Thread_2
Thread_1: 5
Thread_2: 5Thread_1: 4

Thread_1: 3
Thread_2: 4
Thread_1: 2
Thread_1: 1
Exiting Thread_1
Thread_2: 3
Thread_2: 2
Thread_2: 1
Exiting Thread_2

Android - 1. Activity(액티비티)

1. Application

글로벌 어플리케이션 상태를 유지하기 위한 기본 클래스 입니다.
AndroidManifest.xml의 application에서 name을 지정하여 사용 가능해집니다.


Activity class는 언제든지 스택에서 삭제되고 다시 불러오게 되지만 Application class는 한번 불리면 앱이 종료될 때 까지 유지됩니다.


2. Activity

Activity class를 사용하면 UI와  View를 배치 할 수 있는 창을 처리합니다. 모든 Activity들은 반드시 AndroidManifest.xml에 <activity>로 정의 되어야 합니다. Activity는 다른 Activity들의 method를 직접 호출할 수 없으며 데이터도 직접 액세스 할 수 없습니다.


3. Activity Lifecycle

Activity들은 activity stack으로 관리되며 새 Activity가 실행되면 stack의 상단의 배치됩니다.

Activity는 기본적으로 4가지 상태가 있습니다.

  1. Running - Activity가 화면의 foreground에 위치, 시스템 리소스가 부족해도 거이 중단되지 않는다.
  2. Paused - 화면에는 보이지만 다른 Activity가 일부분 가린 상태, 빠른 복귀를 위해 모든 상태정보를 유지하고 윈도우매니저에 연결을 유지하나 매우 낮은 메모리 상태에서 중지될 수 있다.
  3. Stopped - 완전히 다른 Activity에 의해 가려지는 경우, 상태정보와 윈도우매니저에 연결을 유지하나 중단될 가능성이 높다.
  4. Killed - 시스템 리소스가 부족할 때 메모리에서 중단되는 경우 해당 Activity들은 다시 시작되어야 한다.




4. Fragment

honeycomb부터 사용 가능한 Fragment는 Activity를 구현하는데 코드를 좀 더 모듈화 하고, 대형화면에 대해 정교한 사용자 인터페이스를 구축하고, 크고 작은 화면의 Application을 확장하는데 도움을 줍니다.







Python socket programming #2 - MultiThreading (Thread module)

파이썬에서의 멀티 쓰레딩은 두 가지의 모듈을 사용해 만들 수 있습니다.

각각의 모듈은 아래와 같습니다.


  • Thread
  • Threading


먼저 Thread는 C와 같이 함수를 이용해 Thread를 run 시키는 방식으로 MultiThreading을 구현합니다.

Threading은 흔히 자바에서 보던 방식처럼 Thread관련 클래스를 상속받아 run을 override 하여 사용합니다.

이 포스팅에선 먼저 Thread만 다루도록 하겠습니다.

1. Thread


기본적으로 Thread에서 thread를 run시키는 함수는 아래와 같습니다.

thread.start_new_thread( function, (argument))

아래 소스코드를 확인 해 보겠습니다.

위의 print_num함수에 threadName과 delay인자를 준 뒤

delay 시간만큼 텀을 두고 숫자를 1~5까지 출력하는 함수 입니다.

이 함수를 각 각 1초와 2초로 설정하여 두개의 쓰레드를 작동 시키는 프로그램입니다.

출력값은 synchronizing이 되어있지 않아 값이 겹쳐 나올 수 있게 됩니다.

마지막의 while은 Main Thread를 종료시키게 되면 생성된 2개의 쓰레드도 죽게 되므로

이를 막기위해 Main Thread에 무한루프를 걸어줍니다.

아래는 출력값 입니다.

Thread_1: 1
Thread_2: 1Thread_1: 2

Thread_1: 3
Thread_2: 2
Thread_1: 4
Thread_1: 5
Thread_2: 3
Thread_2: 4
Thread_2: 5

Python socket programming #1 - basic server and client

python의 소켓은 C나 자바에 비해 비교적 단순한 모습을 취하고 있습니다.

Socket의 선언은 아래와 같습니다.

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

여기서 각각 PF(프로토콜 체계)와 AF(주소 체계)를 살펴보면

A. PF

  • PF_INET - IPv4 프로토콜
  • PF_INET6 - IPv6 프로토콜
  • PF_LOCAL - Local 통신 UNIX 프로토콜
B. AF
  • AF_INET - IPv4 프로토콜
  • AF_INET6 - IPv6 프로토콜
  • AF_LOCAL - Local 통신 UNIX 프로토콜
이를 통해 소켓을 만들 때에 사용하고자 하는 프로토콜을 사용할땐 PF를 주소 구조체 안에 주소 체계를 정의할 때엔 AF를 사용합니다.

기본적으로 C에서 socket을 생성 할 때 PF_INET을 사용하지만, Python에는 PF가 없습니다.

그리고 뒤에오는 SOCK_STREAM과 SOCK_DGRAM을 통해 각 각 TCP UDP를 결정하게 됩니다.


Socket에 대한 binding은 아래와 같이 선언합니다.

s.bind((host, port))

위와 같이 소켓 선언과 바인딩이 타 언어에 비해 아주 심플한 모습을 취하고 있습니다.

소켓을 통해 간단하게 값을 한 번만 주고 받는 에코서버를 작성해보도록 하겠습니다.

1. Server


서버에서 원격지의 소켓을 받기 위한 listen은 아래와 같이 선언합니다. 이 부분은 C의 서버 프로그래밍과 유사합니다.

s.listen(5)

listen을 통해 소켓이 개통이 되는데 뒤의 인자 backlog는 커널이 관리하는 대기 큐에서
연결 요청을 하고 기다리는 총 클라이언트의 수 입니다.

위 큐에 연결 요청한 소켓은 SYN_RCVD나 ESTABLISHED 상태로 대기합니다. 이 함수를 호

출하면 커널은 내부적으로 소켓의 상태를 CLOSED에서 LISTEN으로 바꿔줍니다.

Status

  • SYN_RCVD - 클라이언트가 connect 함수로 서버에 요청한 연결을 처리하기 위해 SYN 패킷을 통한 3-Way Handshaking을 진행하는 중입니다.
  • ESTABLISHED - 3-Way Handshaking이 모두 완료되면 이 상태가 됩니다.

마지막으로 클라이언트의 연결을 위한 accept 함수는 아래와 같습니다.

c = s.accept()

위를통해 클라이언트 소켓을 Accept 할 수 있습니다.

이제 send와 recv를 통해 값을 주고 받을 수 있습니다.

socket.send("connect success")

socket.recv(1024)

서버 소스는 아래와 같습니다.


먼저 socket.socket()를 통해 소켓을 생성 한 뒤

9999번 포트의 루프백 ip 127.0.0.1로 bind 해줍니다.

s.listen(5)와 s.accept()를 통해 클라이언트 소켓을 연결 한 뒤

send를 통해 'Connection success'를 전송 해 줍니다.

클라이언트가 들어오기 전 c, addr = s.accept()에서 대기중인 실행 모습은 아래와 같습니다.

listen ok


2. Client


Client 또한 마찬가지로 socket.socket()를 통해 소켓을 생성 해 줍니다.

그리고 아래와 같이 connect() 함수를 통해 해당 ip 127.0.0.1과 9999번 포트에 소켓을 연결 해 줍니다.

s.connect((host, port))

그리고 recv를 통해 상대방의 send를 기다립니다.

s.recv(1024)

서버와 클라이언트의 실행 결과는 아래와 같습니다.

-----------------------Server-----------------------
listen ok
connection ('127.0.0.1', 2617)
-----------------------Client------------------------
Connection success
-----------------------------------------------------