[Kotlin] val 프로퍼티에 대해서


Android App 개발시 Java를 사용할때에는 상수를 정의할때, final 을 사용했습니다.


처음 Kotlin을 접했을때에는 상수를 정의할때에는 어떤것을 써야하지? 라는 의문이 생겼고 지금까지는 val 프로퍼티가 상수로 불변값으로 생각했었습니다.


하지만 Kotlin 사이트내 설명 문구에서


"Classes in Kotlin can have properties. These can be declared as mutable, using the var keyword or read-only using the val keyword."


진하게 표시된 Read-Only 라는 글이 보이시나요?


네, 그렇습니다. immutable이 아닌 read-only 네요..;;


갑자기 궁금해져서 val 가 immutable이 아닌것을 확인해보고 싶었습니다.


테스트 코드 가동!!



class KotlinSpec {

    interface Counter {
        val count: Int
    }

    class SomeCounter: Counter {
        var _counter = 0

        override val count: Int
            get() = _counter++
    }

    @Test
    fun isValMutableTest() {
        val counter = SomeCounter()
        assertEquals(counter.count, 0)
        assertEquals(counter.count, 1)
    }
}


위와 같이 코드를 짜서 테스트를 돌리니 테스트가 정상으로 성공하네요.


따로 getter를 두지 않고 변수 선언과 동시에 초기화를 하게 되면 set을 할 수 없으니 immutable과 같다고 볼 수 있겠지만, 정확하게 알고 가는게 좋을것 같습니다.

(레퍼런스 사이트에서 영어라고 꼼꼼하게 읽어보지 않은 제 잘못이 크죠...)


간단한 내용이지만 읽어주셔서 감사합니다~

저작자 표시
신고
Posted by 냥아

[액티비티내 화면 캡처 방지하기]


오래간만에 블로그에 글을 남기네요^^;;


다시 작은글부터 시작해서 하나 둘씩 제가 성장해가는 내용들을 남겨보고 싶습니다..



[Java Source Code]

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);


[Kotlin Source Code]

window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)


코틀린이 안드로이드 공식언어로 채택된 만큼 최대한 코틀린을 사용해보려고 합니다 ㅎㅎ


화면캡처 방지 소스코드를 위의 한줄을 액티비티의 onCreate 호출시 설정해두면 적용이 됩니다.


만약 액티비티내 특정 영역에서 화면 캡처를 허용해야한다면, window.clearFlags를 사용하시면 됩니다.


여러 단말을 모두 테스트 해본것은 아니지만, 일부 단말에서는 "보안정책에 따라 화면을 캡처할 수 없습니다." 라는 토스트 메시지가 발생합니다.

저작자 표시
신고
Posted by 냥아

알파값이 0.0 의 경우는 0% 라고 생각하면 된다.

100%  FF

99% — FC

98% — FA

97% — F7

96% — F5

95% — F2

94% — F0

93% — ED

92% — EB

91% — E8

90% — E6

89% — E3

88% — E0

87% — DE

86% — DB

85% — D9

84% — D6

83% — D4

82% — D1

81% — CF

80% — CC

79% — C9

78% — C7

77% — C4

76% — C2

75% — BF

74% — BD

73% — BA

72% — B8

71% — B5

70% — B3

69% — B0

68% — AD

67% — AB

66% — A8

65% — A6

64% — A3

63% — A1

62% — 9E

61% — 9C

60% — 99

59% — 96

58% — 94

57% — 91

56% — 8F

55% — 8C

54% — 8A

53% — 87

52% — 85

51% — 82

50% — 80

49% — 7D

48% — 7A

47% — 78

46% — 75

45% — 73

44% — 70

43% — 6E

42% — 6B

41% — 69

40% — 66

39% — 63

38% — 61

37% — 5E

36% — 5C

35% — 59

34% — 57

33% — 54

32% — 52

31% — 4F

30% — 4D

29% — 4A

28% — 47

27% — 45

26% — 42

25% — 40

24% — 3D

23% — 3B

22% — 38

21% — 36

20% — 33

19% — 30

18% — 2E

17% — 2B

16% — 29

15% — 26

14% — 24

13% — 21

12% — 1F

11% — 1C

10% — 1A

9% — 17

8% — 14

7% — 12

6% — 0F

5% — 0D

4% — 0A

3% — 08

2% — 05

1% — 03

0% — 00


저작자 표시
신고
Posted by 냥아

1. 코틀린을 사용하기 위한 사전 작업


(1) 플러그인 설치


안드로이드 스튜디오에서 코틀린을 사용하기 위해서는 플러그인 설치를 우선적으로 진행해야합니다.


아래 보이는 이미지와 같이 Settings -> Plugins 로 이동한 뒤,


Install JetBrains plugin... 버튼을 클릭합니다.





그리고 나서 아래 그림과 같이 검색창에 kotlin 을 입력 한 뒤 코틀린 플러그인을 설치 후 안드로이드 스튜디오를 재시작 해줍니다.




(2) 빌드스크립트 (build.gradle)에 플로그인 추가


 - 프로젝트 빌드 스크립트 파일을 열고 난 후, 아래와 같이 추가 합니다.


[build.gradle]

buildscript {
repositories {
jcenter()
mavenCentral() // 코틀린을 사용하기 위한 추가
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.0' // 코틀린 플러그인 적용
}
}

allprojects {
repositories {
jcenter()
mavenCentral() // 코틀린을 사용하기 위한 추가
}
}


- 모듈 빌드 스크립트 파일을 열고 난 후, 추가 해야하는 부분은 아래와 같습니다.


[app/build.gradle]

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // 코틀린 플러그인을 적용합니다.

android {
compileSdkVersion
24
buildToolsVersion "24.0.2"

.....//중략
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

sourceSets {
main.
java.srcDirs += 'src/main/kotlin' // src/main/kotlin 디렉터리를 소스 디렉터리에 추가합니다.
}
}

repositories{
mavenCentral()
}

dependencies {
compile fileTree(
dir: 'libs', include: ['*.jar'])
compile
'com.android.support:appcompat-v7:24.+'
....'
compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.5' // 코틀린 라이브러리를 참조하도록 설정합니다.
}


코틀린을 사용하여 작성한 코드를 별도의 디렉토리로 분리하기 위해 sorceSets 부분을 정의했습니다.


src/main/kotlin 폴더를 생성하지 않았기 때문에 안드로이드 스튜디오의 Project 뷰를 Android -> Project로 변경하고 src/main 폴더에 kotlin 폴더를 생성합니다. 

(설정이 제대로 되었다면 java 폴더와 같이 kotlin 폴더의 색상 또한 파란색 폴더 [소스코드] 로 변경되는것을 확인할 수 있습니다)






저작자 표시
신고
Posted by 냥아

이클립스에서는 custom debug keystore 를 사용해서 한개의 프로젝트를 여러 PC에서 같은 컴파일을 할 수 있게 했는데

Android Studio에서는 해당기능이 안보이는것 같아 사용하지 않고 있다가 이제서야 방법을 찾게 되어 블로그에 올릴 수 있게 되었다.


- Eclipse 에서 Custom debug keystore 지정화면 -

(참고 URL : http://stackoverflow.com/questions/17189076/what-is-the-equivalent-of-eclipse-custom-debug-keystore-in-android-studio)


Android Studio 에서는 gradle을 통해 빌드를 하기 때문에 gradle에 설정을 해야한다.


제가 알고 있는 방법은 2가지입니다.


(1) Project Structure 옵션을 통해 등록하기


1. File 메뉴 클릭 후 -> Project Structure 클릭 (Ctrl + Alt + Shift + S 혹은 아래 버튼 클릭해도 됨)



2. Modules 부분의 app 클릭, 우측의 Signing Tab 클릭



3. 아래와 같이 입력, 보통 debug key store 파일은

윈도우 : c:\User\사용자이름\.android\debug.keystore 이다.

리눅스 : /home/username/.android/debug.keystore

MAC : /Users/username/.android/debug.keystore



4. OK 버튼을 클릭하고 나면 build.gradle (app 폴더) 파일에 아래와 같이 생성된다.


signingConfigs {
debug {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('C:/Users/Donghyun Kim/.android/debug.keystore')
storePassword 'android'
}
}


여기에서 buildTypes 부분에 아래와 같이 추가한다.

debug {
signingConfig signingConfigs.debug
}


(2) gradle.properties 파일에 경로를 따로 빼놓기


(1) 방법의 4,5 번을 진행 후 signingConfigs에 들어가는 값을 gradle.properties로 뺀다. (서명키 보안 강화하기 방법이다)

gradle.properties 파일은 프로젝트를 생성할때 기본으로 생성되며, 만약에 생성이 안되어있으면 프로젝트 폴더내에 생성하면 된다.


properties 파일내에 keystore 파일에 대한 정보를 기입한다.

(debug_keystore 는 제가 따로 사용하기 위해 네이밍한것이기 때문에 변경가능합니다)


debug_keystore=경로
debug_keystore_pass=android
debug_key_alias=androiddebugkey
debug_key_pass=android


(2) signingConfigs 파일에 아래와 같이 기입한다.


signingConfigs {
def Properties props = new Properties()
def propFile = new File('gradle.properties')
if(propFile.canRead())
props.load(new FileInputStream(propFile))
debug {
storeFile file(props['debug_keystore'])
storePassword props['debug_keystore_pass']
keyAlias props['debug_key_alias']
keyPassword props['debug_key_pass']
}
}


저작자 표시
신고
Posted by 냥아

저는 안드로이드를 OS Ver 2.2 부터 지원하는 앱을 만들기 때문에 Notification 같은 경우에도


NotificationCompat 를 사용해서 알림을 표시합니다.


Ongoing 알림 같은 경우에는 계속 표시가 되어있어야하기 때문에 상단바나 잠금화면에서 알림이 표시되지 않았으면 하는 바램이 있었는데요.


해당 부분에 대해 이제야 찾았네요~!


해결방안

 NotificationCompat.Builder -> setPriority(NotificationCompat.PRIORITY_MIN);


위의 우선순위(Priority)를 Min(-2)로 사용하게 되면 알림영역에는 알림을 표시하고 있지만, 상단바나 잠금화면에서는 알림을 표시하지 않습니다.


레퍼런스 사이트에는 이렇게 적혀 있네요.


Set the relative priority for this notification. Priority is an indication of how much of the user's valuable attention should be consumed by this notification. Low-priority notifications may be hidden from the user in certain situations, while the user might be interrupted for a higher-priority notification. The system sets a notification's priority based on various factors including the setPriority value. The effect may differ slightly on different platforms.

저작자 표시
신고
Posted by 냥아

[Android]ExpandableListView 나에게 필요한 부분


ExpandableListView를 사용할때 Adapter를 어떻게 만들어야하는지는 다른 전문가 분들께서 정말 자세하고 친절하게 써주셨기 때문에

저는 따로 어떻게 생성해야하는지는 적지 않겠습니다.


대신 항상 헷갈리던 부분에 대해서만 간략히 적을건데요.


1. Group 뷰의 왼쪽에 나오는 Indicator 를 없애는 방법


<ExpandableListView

            android:id="@+id/test"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:groupIndicator="@null" >

</ExpandableListView>


저렇게 indicator 속성에 null을 넣어주거나


소스상에서


ExpandableListview epListView = (ExpandableListView)view.findViewById(R.id.testview);

epListView.setGroupIndicator(null);


로 해주시면 됩니다.



2. 리스트뷰 표시할때 Group이 표시되도록 하는 방법

그룹 인덱스만큼 expandGroup(Index) 해주면 됩니다.


for(int i = 0; i < m_GroupList.size(); i++)

{

epListView.expandGroup(i);

}


3. GroupView를 클릭 했을때에도 계속 펼쳐져있는 방법

GroupClick 이벤트를 잡아서 "return true" 해주면 끝~!!!!


epListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

@Override

public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id)

{

return true;

}

});

저작자 표시
신고
Posted by 냥아

[Android] Notification Icon Size


안드로이드 개발을 하면서 Notification을 많이 사용하게 되는데요.

간혹 테스트 하면서 노티를 띄울 시 상단바에 아이콘이 잘려서 표시되는 경우가 발생합니다.


원인은 앱 아이콘과 Notification 아이콘을 같은것을 사용해서 그런데요.


레퍼런스 사이트에서 설명해주는것을 보면


런처 아이콘 : 48 x 48 dp ( mdpi 기준)

Notification 아이콘 : 24 x 24 dp (mdpi 기준)


으로 사용해야한다고 적혀 있습니다.


dpi 에 대한 배율은 아래와 같이 적용됩니다.



- dpi 에 따른 이미지 배율


위의 이미지를 참고한다면


대략 Notification 아이콘은 아래와 같이 잡으면 되겠네요.


mdpi : 24 x 24

hdpi : 36 x 36

xhdpi : 48 x 48

xxhdpi : 72 x 72

xxxhdpi : 96 x 96


으로 사이즈를 잡으면 될것 같습니다.



***요약***


런처 아이콘 : 48 x 48

노티 아이콘 : 24 x 24


참고 사이트(이미지 출처) : http://developer.android.com/design/style/iconography.html


저작자 표시
신고
Posted by 냥아

[Android] error: Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?


안드로이드 개발을 하면서 언어 리소스 관리의 중요성을 느끼게 된 후, 모든 언어 리소스는 string.xml 에 기입하고 있는데 어느날 위와 같은 에러가 발생했다.


에러는 String.format을 사용할 때 흔히 String.format("테스트 1 값 : %d , 테스트 2 값 : %d", 1, 2); 를 사용하게 되는데 이 부분을 String.xml에서 그대로 사용하게 되면 발생하는 에러이다.


에러 해결 방법은 2가지가 있는데,


1. <string name="test_format">테스트 1값 : %1$d, 테스트 2 값 : %2$d</string>

   위와같이 포맷 형식에 1$ , 2$ ... 의 순서를 붙여주는 방법


2. <string name="test_format" formatted="false">테스트 1 값 : %d, 테스트 2 값 : %d</string>

   속성에 formatted="false 를 추가하면 에러는 사라진다.

저작자 표시
신고
Posted by 냥아

[Android] 액티비티 화면 방향 설정


액티비티 화면은 크게 생각하면 "가로" , "세로" 두가지로 되어있고 폰을 360도 회전한다고 생각했을때 총 4가지의 방향이 있습니다.


보통 매니페스트에서 액티비티 내 속성에 아래와 같이 추가합니다.


<activity
android:name=".test"
android:screenOrientation="화면방향값">
</activity>


이번 포스팅에는 위의 screenOrientation 의 속성에 대해 정리해볼까 하는데요. 예전에 안드로이드 OS 2.2 (프로요) 개발당시에 봤었던 속성 보다 훨씬 많이 있어서 깜짝 놀랬습니다.



<ScreenOrientation 속성 종류>



속성

설명

unspecified

 기본값. 시스템에서 방향을 결정합니다. 선택된 디바이스마다 방향은 달라질 수 있습니다.

behind

 액티비티 스택에서 이전의 액티비티 방향과 같은 방향을 표시합니다.

landscape

 액티비티를 가로 방향으로 고정할때 사용됩니다.

portrait

 액티비티를 세로 방향으로 고정할때 사용됩니다.

reverseLandscape

 가로방향 고정, 일반적인 방향에서 역방향으로 표시합니다. (API 9 [OS ver 2.3] 추가)

reversePortrait

 세로방향 고정, 일반적인 방향에서 역방향으로 표시합니다. (API 9 [OS ver 2.3] 추가)

sensorLandscape

 가로방향 고정, 센서에 따라 정/역방향으로 표시합니다. (API 9 [OS ver 2.3] 추가)

sensorPortrait

 세로방향 고정, 센서에 따라 정/역방향으로 표시합니다. (API 9 [OS ver 2.3] 추가)

userLandscape

 가로방향 고정, 센서 장치 및 사용자 센서 기본설정에 따라 정/역방향으로 표시될 수 있습니다. 만약 센서 기반 회전 기능이 고정되어 있는 경우에는 landscape와 동일하게 동작하고 그렇지 않으면 sensorLandscape와 동일하게 동작합니다.(API 18 [OS ver 4.3] 추가)

userPortrait

 세로방향 고정, 센서 장치 및 사용자 센서 기본설정에 따라 정/역방향으로 표시될 수 있습니다. 만약 센서 기반 회전 기능이 고정되어 있는 경우에는 portrait와 동일하게 동작하고 그렇지 않으면 sensorPortrait와 동일하게 동작합니다.(API 18 [OS ver 4.3] 추가)

sensor

 방향은 기기 회전 센서에 의해 결정됩니다. 화면 방향은 사용자가 기기를 회전시킬때 변경되며 일부 장치에서는 4가지 방향으로 회전하지만 기본적으로 4가지 방향으로 회전하지 않습니다. 4방향을 모두 허용하려면 fullSensor 를 사용해야합니다.

fullSensor

 방향은 4 방향 중 하나의 기기 방향 센서에 의해 결정됩니다. (API 9 [OS ver 2.3] 추가)

nosensor

 방향은 물리적인 센서를 참조하지 않고 결정됩니다. 센서가 무시되므로 화면은 사용자가 움직이는 방법을 기반하지 하지 않습니다. 이 차이점을 제외하고 시스템은 unspecified 와 동일한 규정을 사용하여 방향을 선택합니다.

user

 사용자가 현재 선호하는 방향을 표시합니다.

fullUser

 센서 기반 회전 기능이 잠긴 경우에는 user 와 동일한 기능으로 동작하고, 그렇지 않을때에는 fullSensor와 동일하게 동작합니다.(API 18 [OS ver 4.3] 추가)

locked

 무엇이든지 현재의 회전으로 방향을 잠급니다.(API 18 [OS ver 4.3] 추가)


보통 ScreenOrientation 옵션은 화면을 고정할때 사용하는 옵션이므로 위의 표에서 landscape, portrait 속성을 가장 많이 사용합니다.


위의 설명글은 구글플레이 레퍼런스 사이트를 참고하여 해석한 부분인데요. 내용이 이상한 부분 있으시면 댓글로 말씀해주시면 감사하겠습니다.

저작자 표시
신고
Posted by 냥아