코틀린은 다음과 같은 길이를 가지고 있다.

TypeWidth
Long64
Int32
Short16
Byte8
Double64
Float32

테스트를 해보자

val int = 123
val long = 123456L
val double = 12.34
val float = 12.34F
val hexadecimal = 0XAB
val binary = 0b01010101

println( "$int , $long , $double , $float , $hexadecimal , $binary")
==================
123 , 123456 , 12.34 , 12.34 , 171 , 85

String 멀티 라인

val rawString = """
안녕하세요
반갑습니다.
코틀린입니다
"""

print(rawString)

==============

    안녕하세요
    반갑습니다.
    코틀린입니다

Arrays

val array = arrayOf( 1 ,2 ,3)
var perfectSquares = Array(10 , { k -> k * k}) // 0(k)부터 시작해서 10개의 값을 가져온다.

println(Arrays.toString(array))
println(Arrays.toString(perfectSquares))

=====================

[1, 2, 3]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

String 템플릿

  • $변수 , ${변수} 가 가능하다..
var name = "Tommy"
var str = "Hello $name , Your name has ${name.length} characters"

println( name )
println( str )

===========
Tommy
Hello Tommy , Your name has 5 characters

Range

val aToZ = "a".."z";
val isTrue = "c" in aToZ
val oneToNine = 1..9
val isFalse = 11 in oneToNine

println( aToZ )
println( oneToNine )
println( " c is in aToZ = $isTrue , 11 is in oneToNine = $isFalse" )

==========

a..z
1..9
 c is in aToZ = true , 11 is in oneToNine = false

추가적으로 .downTo() .rangeTo()로 지정도 가능하다.

  • downTo()
  • rangeTo()
  • step (띄워넘기)
  • reversed
val counttingDown = 100.downTo(0)
val rangeTo = 10.rangeTo(20)

println( counttingDown )
println( rangeTo )

val oneToFifty = 1..50
val oddNumbers = oneToFifty.step(2)
val isIncludeNegativeNumber = 2 in oddNumbers
val isIncludePositiveNumber = 1 in oddNumbers

println( " 짝수 포함여부 : $isIncludeNegativeNumber , 홀수 여부 $isIncludePositiveNumber" )

val isIncludePositiveNumberReversed = 2 in (2..100).step(2).reversed()

println( " 뒤집었을 경우 짝수 포함여부 : $isIncludePositiveNumberReversed" )

==============

100 downTo 0 step 1
10..20
 짝수 포함여부 : false , 홀수 여부 true
 뒤집었을 경우 짝수 포함여부 : true

Loop

  • for in
  • array.indices -> index 가져올 수 있
val oneToTen = 1..2
for(k in oneToTen){
   for(j in 1..2){
       println(k * j)
   }
}

val array = arrayOf("A" , "B")
for(index in array.indices) { //인덱스를 가져올 수 있다.
   println("Element $index is ${array[index]}")
}
=============
1
2
2
4
Element 0 is A
Element 1 is B

Expression & Scope

  • @ 을 체크
fun testExpression() {
    Building("서울").Reception("02").printAddress()
}

class Building(val address : String) {
    inner class Reception(private val telephone : String) {
        fun printAddress() = println("${this@Building.address} , ${this.telephone} ")
    }
}

===========
서울 , 02

When

  • java 의 switch -> when 으로 사용가능하다.
fun testZeroFromWhen(){
    print(" ${testWhen( Int.MIN_VALUE )} , ${testWhen( Int.MAX_VALUE ) }" )
}

fun testWhen( x : Int) : Boolean{
    return when(x){
        Int.MIN_VALUE -> true
        Int.MAX_VALUE -> true
        else -> false
    }
}
//리스트안에 있는 체크
fun isInNumber(x : Int): Boolean {
    return when(x) {
        in listOf( 1, 2, 3, 4, 5) -> true //  리스트값 체크 가
        else -> false
    }
}
//when 에 인자가 없는 경
fun checkNoWhen( x : Int , y : Int) {
    when {
        x < y -> println("x is less then y")
        x > y -> println("x is greater than y")
        else -> println("x must equal y")
    }
}

라벨 정하기

fun printUntilStop(){
    val list = listOf( "a" , "b" , "stop" , "d")

    list.forEach stop@{
        if(it == "stop") return@stop
        else println(it)
    }

    list.forEach {
        if (it == "stop") return@forEach
        else println(it)
    }
}

========
a
b
d <-- 주의
a
b
d <-- 주의

클래스정의시 생성자 넣는 방법

  • require로 조건 체크 가능.. 오류시 -> java.lang.IllegalArgumentException 발생시킴
fun main(args : Array<String>){
    val person1 = Person( "" , "kim" , 20) // java.lang.IllegalArgumentException 발생
    val person2 = Person( "tommy" , "kim" , 20)
    print("person value = ${person1.firstName} , ${person2.lastName} , ${person1.age}")

}

class Person(val firstName : String , val lastName : String , val age : Int?){
    init{
        require( firstName.trim().length > 0 ) { "Invalid firstName argument."}
        require(lastName.trim().length > 0) { "Invalid lastName argument" }

        if(age != null) {
            require( age > 0 && age < 150) { "Invalid age argument" }
        }
    }
}

==============

코틀린에서 값을 가져올때

val person = Person( "tommy" , "kim" , 20)
print("person value = ${person.firstName} , ${person.lastName} , ${person.age}")
//위와 같이 접근이 가능하다.

그럼 자바에서는 코틀린의 Person 값을 어떻게 가져올까?

Person person = new Person("tommy" , "kim" , 26);
System.out.println(String.format("person firstName -> %s" , person.getFirstName()));
// 위와 같이 getter 로 접근 가능하다.

만약 생성자에서 nullSafe 가 있는 경우 어떻게 될까?

  • constructor : this 유
fun main(args : Array<String>){
    val person = Person( "tommy" , "kim" ) // 인자가 2개인걸 유의
    print("person value = ${person.firstName} , ${person.lastName} , ${person.age}")

}

class Person(val firstName : String , val lastName : String , val age : Int?){
    //생성자에서 null로 따로 치환해줘야 한다. ( this(...) )
    constructor( firstName: String , lastName: String) : this(firstName , lastName , null)
    init{
        require( firstName.trim().length > 0 ) { "Invalid firstName argument."}
        require(lastName.trim().length > 0) { "Invalid lastName argument" }

        if(age != null) {
            require( age > 0 && age < 150) { "Invalid age argument" }
        }
    }
}

내부 변수 초기화시 다른 방법으로도 가능하다.

fun main(args : Array<String>){
    val person2 = Person2( "tommy" , "kim" , null)
    print("person value = ${person2.getName()} , ${person2.getAge()}")
}

class Person2(firstName: String , lastName: String , howOld : Int?) {
    private val name : String
    private val age : Int?

    init {
        this.name = "$firstName,$lastName" //이렇게 초기화 가능
        this.age = howOld
    }

    fun getName() : String = this.name //함수 초기화가 이런식이 가능함

    fun getAge() : Int? = this.age
}

중첩 클래스

중첩시 내부 클래스가 가능하다. 내부 클래스에서 외부 클래스의 변수 접근을 위해선 inner를 붙여야 한다.

  • Inner
fun main(args : Array<String>){
    Line("ttt").InnerLine(2).draw()
}

class Line(graphName : String){
    private val name : String

    init{
        name = graphName
    }

    inner class InnerLine(val x : Int) {
        fun draw() : Unit {
            //$name 사용시 inner를 없는 경우 컴파일 오류
            print("Drawing Line from $x , name -> $name") 
        }
    }
}

중첩시 라벨을 통해서 같은 변수를 지정이 가능하다.

UI에서 뷰 변수를 지정시 많이 사용한다고 한다.

  • @A , @B 를 유의해서 보자.
fun main(args : Array<String>){
    A().B().foo("")
}

class A {
    private val somefield : Int = 1
    inner class B {
        private val somefield : Int = 2
        fun foo(s : String) {
            println("Field <somefield from B : " + this.somefield)
            println("Field <somefield from B : " + this@B.somefield)
            println("Field <somefield from A : " + this@A.somefield)
        }
    }
}
=============
Field <somefield from B : 2
Field <somefield from B : 2
Field <somefield from A : 1

Enum

Enum은 기본형태는 자바와 같다.

fun testEnum(){
    println(Day.valueOf("MONDAY"))
    println( Arrays.toString(Day.values()))
}

enum class Day(val weather : String) {
    MONDAY("good") , TUESDAY("rainy")
}
=============
MONDAY
[MONDAY, TUESDAY]

Interface로 확장도 가능하다.

fun testEnum(){
    val w = Word.HELLO
    w.print()
}

interface Printable {
    fun print()
}

enum class Word : Printable {
    HELLO {
        override fun print() {
            println("Word is HELLO")
        }
    },
    BYE {
        override fun print() {
            println("Word is BYE")
        }
    }
}
==========
Word is HELLO

Static 으로 접근

자세한 설명은 해당 링크로 가자.

fun main(args : Array<String>) {
    print(Student.create("tommy").name)
}

interface StudentFactory {
    fun create(name : String) : Student
}

class Student private constructor(val name : String) {
    companion object : StudentFactory{
        override fun create(name: String): Student {
            return Student(name)
        }
    }
}


Interface

fun main(args : Array<String>) {
    val pngImage = PNGImage()
    pngImage.save()
}

open class Image{
    open fun save() {
        println("Image save called")
    }
}

interface VendorImage{
    fun save() {
        println("VendorImage save called")
    }
}
class PNGImage : Image() , VendorImage {
    override fun save(){
        super<VendorImage>.save() //제너릭으로 해당 부모를 지정하는 것에 유의
        super<Image>.save() //제너릭으로 해당 부모를 지정하는 것에 유의
    }
}

확장함수

함수를 통해서 원하는 클래스에 추가적으로 붙일 수 있다.

우선 확장 안된 함수를 보자.

fun main(args : Array<String>){
    val items = listOf( 1 , 3,  7 , 9, 100)
    val newItems = drop( 2 , items)
    println( newItems )
}

fun <E> drop(k : Int , list : List<E>) : List<E> {
    val resultSize = list.size - k
    when {
        //resultSize 가 0보다 작으면 빈 리스트 변환
        resultSize <= 0 -> return emptyList<E>()
        //그렇지 않을 경우 k번째 아이템을 제거하고 새로운 리스트를 리턴받는다.
        else -> {
            val newList = ArrayList<E>(resultSize)
            for(index in k..list.size - 1) {
                newList.add(list[index])
            }
            return newList
        }
    }
}
==========
[7, 9, 100]

실행시 별도의 drop으로 함수를 호출해서 해야 한다.

그럼 이걸 이제 확장 함수로 바꿔보자.

fun main(args : Array<String>){
    val items = listOf( 1 , 3, 7 , 9, 100)
    val newItems = items.drop( 2 , items) // 컬렉션 변수뒤에 붙는 걸 유의해서 보자.
    println( newItems )
}

fun <E> List<E>.drop(k : Int , list : List<E>) : List<E> {
    val resultSize = list.size - k
    when {
        //resultSize 가 0보다 작으면 빈 리스트 변환
        resultSize <= 0 -> return emptyList<E>()
        //그렇지 않을 경우 k번째 아이템을 제거하고 새로운 리스트를 리턴받는다.
        else -> {
            val newList = ArrayList<E>(resultSize)
            for(index in k..size - 1) {
                newList.add(this[index]) //this를 주의
            }
            return newList
        }
    }
}
==========
[7, 9, 100]

위와 같이 내부적으로 this를 사용해서 해당 컬렉션을 가져오는 걸 볼수 있다.

순서와 매개변수에 따른 함수 호출

같은 이름과 같은 매개변수의 함수의 경우 ordering이 다를 수 있다. 다음의 예를 보자.

class Apple {
    fun eat() : Unit {
        println("Apple eat")
    }

    fun drop() : Unit {
        println("Apple drop")
    }
}

fun Apple.eat(): Unit {
    println("another Apple eat");
}

fun Apple.drop(where : String) : Unit {
    println("apple drop at $where")
}

실행시
val apple = Apple()
    apple.eat() //<- 처음 함수만 실행
    apple.drop()
    apple.drop("school")

===========
Apple eat
Apple drop 
apple drop at school

Null 오브젝트의 확장함수

null safe 오브젝트의 확장함수는 다음과 같다.

val test : String? = "222"
val test2 : String = "222"
var test3 : String? = null

val isEqual = test?.safeEquals(test2)
val isEqual2 = test3?.safeEquals(test2)
println(isEqual)
println(isEqual2)



//확장 함수
fun Any?.safeEquals(other : Any?) : Boolean {
    if (this == null && other == null) return true
    if (this == null) return false
    return this.equals(other)
}

===============
true
null

확장함수내에 맴버 변수 사용하기

확장함수를 사용시 클래스 내에 맴버변수를 같이 연동시 어떻게 하는 지 살펴보자.

  • 내부적으로 사용되는 hascode() 를 통해서 어떤 객체의 값을 가져오는지를 판별하자.
fun main(args : Array<String>){
    val mapping = Mappings()
    val inputStr = "Add one"
    println("hasCode #1-1 ${inputStr.hashCode()}")
    mapping.add(inputStr)
    mapping.add2("Add two")
    println("hasCode #2-1 ${mapping.hashCode()}")
    print(mapping.get(mapping.hashCode()))
}

class Mappings {
    private val map = hashMapOf<Int, String>()
    //확장 함수내부에 맴버변수를 사용가능하다.
    private fun String.stringAdd() : Unit {
        val hasCode = hashCode() //<- String 값에 대한 hascode
        println("hasCode #1-2 $hasCode")
        map.put( hasCode, this)
    }

    private fun String.stringAdd2() : Unit {
        val hasCode = this@Mappings.hashCode() //Mappings 클래스에 대한 hascode
        println("hasCode #2-2 $hasCode")
        map.put( hasCode , this)
    }

    fun add(str : String) : Unit = str.stringAdd()
    fun add2(str : String) : Unit = str.stringAdd2()
    fun get(key : Int) : String? = map.get(key)
}
=============
hasCode #1-1 514527815
hasCode #1-2 514527815 
hasCode #2-2 1360875712
hasCode #2-1 1360875712
Add two

다중 반환 값

  • Pair 에 대해서 알아보자
fun main(args : Array<String>) {
    val positiveRootVal = positivieRoot(4)
    val negativeRootVal = negativeRoot(4)
    print("$positiveRootVal , $negativeRootVal");
}

fun positivieRoot(k : Int) : Double {
    require( k >= 0)
    return Math.sqrt(k.toDouble())
}

fun negativeRoot(k : Int) : Double {
    require( k >= 0)
    return -Math.sqrt(k.toDouble())
}
=========================
// 2.0 , -2.0

위 내용을 보면 주어진 값의 제곱근을 양수와 음수로 보여준다.

중복된 내용이 많이 보인다. 이걸 다시 리펙토링 하면

fun main(args : Array<String>) {
    val roots = roots(5)
    print("positive -> ${roots[0]} , ${roots[1]}")
}

fun roots(k: Int) : Array<Double> {
    require( k >= 0 )
    val root = Math.sqrt( k.toDouble() )
    return arrayOf(root , -root)
}
================
//2.23606797749979 , -2.23606797749979

이렇게 배열로 하나 만들수 있다. 하지만 어느쪽이 양수인지를 알수가 없다.

그러면 Pair로 바꾸면 다음과 같다.

fun main(args : Array<String>) {
    val roots = roots(5)
    print("positive -> ${roots.first} , ${roots.second}")
}

fun roots(k: Int) : Pair<Double , Double> {
    require( k >= 0 )
    val root = Math.sqrt( k.toDouble() )
    return Pair(root , -root)
}

그럼 이걸 좀 더 줄이면

val (pos , neg) = roots(5) //!!
print("positive -> $pos , $neg")

이런식으로 줄일수 있다.

그리고 중위 함수(Infix) 로 바꿀수 있다


연산자

코틀린도 Swift 처럼 연산자를 오버로딩이 가능하다.

fun main(args : Array<String>) {
    val board = Chessboard()
    board[0 , 4] = Piece.Queen
    println(board[0,4])
}

enum class Piece {
    Empty , Pawn, Bishop , Queen
}

class Chessboard() {
    private val board = Array<Piece>(64 , {Piece.Empty})
    operator fun get(rank : Int, file : Int) : Piece = board[cal(rank , file)]

    operator fun set(rank : Int , file: Int , value : Piece) : Unit {
        println("set -> $rank , $file , $value , ${file * 8 + rank}")
        board[cal(rank , file)] = value
        println("check empty board -> ${board[cal( 0,2)]}") // 0, 2를 입력해서 빈값이 나오는지 확인
    }

    fun cal ( rank : Int , file : Int) : Int = file * 8 + rank
}

========
set -> 0 , 4 , Queen , 32
check empty board -> Empty
Queen

배열을 set , get을 하기위한 연산자를 오버로딩이 가능하다.

그리고 함수 호출 이름을 연산자로도 사용이 가능하다.

클래스를 함수처럼 사용도 가능하다.

fun main(args : Array<String>) {
    val longs = RandomLongs(3)
    println("${longs()} , ${longs()} , ${longs()}")
}

class RandomLongs(seed : Long) {
    private val random = Random(seed)
    operator fun invoke() : Long = random.nextLong()
}
========
-4961115986754665064 , 1309571695633557482 , 1238145679872042884

또 다른 예제로는 다음과 같다.

여러개의 함수를(생성자가 아니다) 만들어서 그에 맞는 걸 실행도 가능하다.

fun main(args : Array<String>) {
    val Min1 = Min(1, 2, 3)
    val Min2 = Min(1L, 2L)
    print("$Min1 , $Min2")
}

object Min {
    operator fun invoke(a: Int, b: Int): Int = if (a <= b) a else b
    operator fun invoke(a: Int, b: Int, c: Int): Int = invoke(invoke(a, b), c)
    operator fun invoke(a: Int, b: Int, c: Int, d: Int): Int = invoke(invoke(a, b), invoke(c, d))

    operator fun invoke(a: Long, b: Long): Long = if (a <= b) a else b
    operator fun invoke(a: Long, b: Long, c: Long): Long = invoke(invoke(a, b), c)
    operator fun invoke(a: Long, b: Long, c: Long, d: Long): Long = invoke(invoke(a, b), invoke(c, d))
}

=========
1 , 1

비교 연산 할때도 자주 쓰인다.

fun main(args : Array<String>) {
    val tommy = BingoNumber(30)
    val kim = BingoNumber(24)
    println( tommy < kim )
    println( kim < tommy )
}

class BingoNumber(val age: Int) {
    operator fun compareTo(other : BingoNumber) : Int {
        return when {
            age < other.age -> -1 //age 가 other의 나이보다 적다면 -1
            age > other.age -> 1 //크다면 1
            else -> 0 //기타 0
        }
    }
}

=======
false 
true


요구사항

내 응용 프로그램에서는 최근에 다음과 같은 요구 사항이 있습니다. 항목의 반응적인 스트림에서 특정 항목이 하나 방출 될 때까지 기다린 다음 모든 항목을 관찰자에게 내 보냅니다. 해당 항목을 찾을 수 없으면 아무 것도 출력하지 말고 오류로 종료하십시오.


https://medium.com/@Cypressious/rxjava-kotlin-conditionally-delaying-the-first-item-in-a-stream-9d4e7a8d0071

'링크모음 > Android' 카테고리의 다른 글

인스턴트앱 팁  (0) 2017.12.04
room 연동 관련 팁  (0) 2017.12.01
fileexposeexception 발생시  (0) 2017.11.16
텐서플로로 안드로이드에서 실행하기  (0) 2017.11.15
Mockito 관련 팁 모음 링크  (0) 2017.11.06

출처 : http://blog.gaerae.com/2015/06/code-search-engines.html

Source graph

홈페이지: https://sourcegraph.com
깔끔한 화면과 다양한 검색을 지원해준다.

Search code

홈페이지: https://searchcode.com
GitHub, Bitbucket, Codeplex, Sourceforge, Fedora Project, Google Code에서 공유되고 있는 소스코드를 검색해준다.

Github

홈페이지: https://github.com
Github에서 관리되는 소스를 검색해준다.

Krugle

홈페이지: http://krugle.org
searchcode와 비슷하게 여러 오픈소스의 소스코드를 검색해준다.

Antepedia

홈페이지: http://www.antepedia.com
오픈소스 프로젝트의 내용을 검색해준다.

SymbolHound

홈페이지: http://symbolhound.com
여러 웹사이트에 있는 소스 코드를 검색해준다.

grepcode

홈페이지: http://grepcode.com
Java 프로젝트와 자바 언어에 대한 검색을 지원한다.

Omniref

홈페이지: https://www.omniref.com
Ruby를 사용하신다면 좋은 검색 사이트다.

Debian Code Search

홈페이지: http://codesearch.debian.net
리눅스 데비안 소스 코드를 검색해준다.

함께보기


마무리하며

구글링으로도 충분히 만족하겠지만 소스 코드를 직접 검색하는 서비스를 이용하면 가끔은 더 빨리 원하는 결과를 얻을때가 있다.
검색해서 얻은 코드는 잘 사용하면 득이지만 검색한 코드를 붙여넣기만 한다면 절대 좋은 코드가 작성되지 않는다.
타인의 코드 스타일을 보고 나와 비교해보면서 학습하는 자세가 중요하다고 생각한다.

'링크모음 > 코틀린' 카테고리의 다른 글

Sealed class + when 자세한 설명  (0) 2017.11.21
접근 제어자 관련 링크  (0) 2017.11.20
kotlin-let-apply-run-with-use 사용방법  (0) 2017.11.17
코틀린 1.1 한글번역 문서  (0) 2017.11.02
코틀린 Junit 사용하기  (0) 2017.09.02

Android things 디버깅시 현재 아이피를 처음에는 모른다. 물론 부팅화면에는 나오지만 앱으로 바로 실행되면 나오지는 않는다. 


그래서 할 수 있는 방법은 2가지 이다. 해당 아이피를 화면으로 출력해서 보여주는 것이다. 


우선 기본 wifi 와 이더넷 아이피 주소 획득 하는 방법이다. 안드로이드 띵쓰에서도 당연히 가능하다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
     * Returns MAC address of the given interface name.
     * @param interfaceName eth0, wlan0 or NULL=use first interface 
     * @return  mac address or empty string
     */
    public static String getMACAddress(String interfaceName) {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                if (interfaceName != null) {
                    if (!intf.getName().equalsIgnoreCase(interfaceName)) continue;
                }
                byte[] mac = intf.getHardwareAddress();
                if (mac==nullreturn "";
                StringBuilder buf = new StringBuilder();
                for (int idx=0; idx<mac.length; idx++)
                    buf.append(String.format("%02X:", mac[idx]));       
                if (buf.length()>0) buf.deleteCharAt(buf.length()-1);
                return buf.toString();
            }
        } catch (Exception ex) { } // for now eat exceptions
        return "";
        /*try {
            // this is so Linux hack
            return loadFileAsString("/sys/class/net/" +interfaceName + "/address").toUpperCase().trim();
        } catch (IOException ex) {
            return null;
        }*/
    }
 
    public static String getIPAddress(boolean useIPv4) {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
                for (InetAddress addr : addrs) {
                    if (!addr.isLoopbackAddress()) {
                        String sAddr = addr.getHostAddress();
                        //boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
                        boolean isIPv4 = sAddr.indexOf(':')<0;
 
                        if (useIPv4) {
                            if (isIPv4) 
                                return sAddr;
                        } else {
                            if (!isIPv4) {
                                int delim = sAddr.indexOf('%'); // drop ip6 zone suffix
                                return delim<0 ? sAddr.toUpperCase() : sAddr.substring(0, delim).toUpperCase();
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) { } // for now eat exceptions
        return "";
    }
cs

그리고 이걸 가져와서 화면에 뿌려서 체크를 하면 된다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
private fun checkIp(){
        // test functions
        Utils.getMACAddress("wlan0")
        Utils.getMACAddress("eth0")
        val ip4 = Utils.getIPAddress(true// IPv4
        val ip6 = Utils.getIPAddress(false// IPv6
 
        Logger.log("ip address $ip4 , $ip6 ")
 
        ipAddress.text = "current ipAddress : $ip4"
 
 
    }
cs


이게 처음 방법이고...아이피도 받는게 귀찮다.. 그러면 mDns 를 호출해서 하면된다. 

1
adb connect Android.local
cs

하지만 윈도우에서는 안된다. 그럼 이 프로그램을 우선 설치를 해보자. 


그리고 다른 명령어로 확인해보자. 

1
dns-sd -Q Android.local
cs

실행시 아래와 같이 나온다. 

Timestamp     A/R Flags if Name                             T   C Rdata
22:18:47.771  Add     2 13 Android.local.                   1   1 192.168.x.123
22:18:51.247  Add     2 13 Android.local.                   1   1 192.168.x.124


이중 맞는 걸 연결 해보자. 

adb connect 192.168.1.124 

그럼 성공되면 이젠 디버깅 고고씽

'링크모음 > Android Things' 카테고리의 다른 글

와이파이 연결  (0) 2017.11.23
Android – AudioRecord to WAV (오디오 녹음)  (0) 2017.11.15

http://developer88.tistory.com/m/137

'링크모음 > Android' 카테고리의 다른 글

room 연동 관련 팁  (0) 2017.12.01
2017 devfest 세션 및 후기 모음  (0) 2017.11.20
텐서플로로 안드로이드에서 실행하기  (0) 2017.11.15
Mockito 관련 팁 모음 링크  (0) 2017.11.06
android 매트리얼 ui builder  (0) 2017.11.06

http://icunow.co.kr/%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88%EB%9D%BC%EB%A9%B4-%EA%BC%AD-%ED%99%95%EC%9D%B8%ED%95%B4%EB%B4%90%EC%95%BC-%ED%95%A0-%ED%81%AC%EB%A1%AC-%ED%99%95%EC%9E%A5%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-4/

http://kugancity.tistory.com/m/entry/dialogflow%EB%A1%9C-chatbot-%EB%A7%8C%EB%93%A4%EA%B8%B0

https://m.blog.naver.com/chandong83/221140432948

'링크모음 > Android' 카테고리의 다른 글

2017 devfest 세션 및 후기 모음  (0) 2017.11.20
fileexposeexception 발생시  (0) 2017.11.16
Mockito 관련 팁 모음 링크  (0) 2017.11.06
android 매트리얼 ui builder  (0) 2017.11.06
android 저장소 전략  (0) 2017.11.04


Android – AudioRecord to WAV (오디오 녹음)


https://blog.uzuki.live/android-audiorecord-wav-%EC%98%A4%EB%94%94%EC%98%A4-%EB%85%B9%EC%9D%8C/


http://lucasmreis.github.io/blog/simple-react-patterns/

http://hellchosun.net/52

'자바 > 추천소스모음' 카테고리의 다른 글

자바 스노우크래프트 소스  (0) 2010.11.26
자바 스윙 화면 중간에 보이는 클래스  (0) 2010.10.25
자바메모장추천소스  (0) 2010.10.20

http://smartaedi.tistory.com/111

'링크모음 > etc' 카테고리의 다른 글

크롬 추천 확장기능 ~ 디자인편  (0) 2017.11.16
상업용 무료폰트 모음 링크  (0) 2017.11.09
익스퍼트 비기너2편  (0) 2017.11.06
mysql index 정리  (0) 2017.11.06
5일만에 기획부터 프로토타입까지  (0) 2017.11.05

http://www.popit.kr/%eb%82%98%eb%a7%8c-%eb%aa%a8%eb%a5%b4%ea%b3%a0-%ec%9e%88%eb%8d%98-java9-%eb%b9%a0%eb%a5%b4%ea%b2%8c-%eb%b3%b4%ea%b8%b0/

'링크모음 > java' 카테고리의 다른 글

java trim() 이 안먹힐때..  (0) 2017.09.28
대표적인 소프트웨어 아키텍쳐 10가지  (0) 2017.09.15
DTO와 VO 차이점..  (0) 2017.08.09

'링크모음 > etc' 카테고리의 다른 글

상업용 무료폰트 모음 링크  (0) 2017.11.09
라즈베리파이에서 할수있는 것 탑10  (0) 2017.11.07
mysql index 정리  (0) 2017.11.06
5일만에 기획부터 프로토타입까지  (0) 2017.11.05
기기별 목업  (0) 2017.11.05

'링크모음 > Android' 카테고리의 다른 글

fileexposeexception 발생시  (0) 2017.11.16
텐서플로로 안드로이드에서 실행하기  (0) 2017.11.15
android 매트리얼 ui builder  (0) 2017.11.06
android 저장소 전략  (0) 2017.11.04
오픈소스 정리  (0) 2017.11.02

http://jojoldu.tistory.com/243

'링크모음 > etc' 카테고리의 다른 글

라즈베리파이에서 할수있는 것 탑10  (0) 2017.11.07
익스퍼트 비기너2편  (0) 2017.11.06
5일만에 기획부터 프로토타입까지  (0) 2017.11.05
기기별 목업  (0) 2017.11.05
개발자 치트시트 추천  (0) 2017.10.30

https://www.slideshare.net/mobile/secret/6Bbyx0PnKcsDwe

'링크모음 > Swift' 카테고리의 다른 글

swift defer 예제  (0) 2017.10.22
swift4 tour  (0) 2017.10.22
노티피케이션 사용법  (0) 2017.10.20
swift 에서 self 값 체크  (0) 2017.10.18
pod update/install 시 라이버러리를 전부 강제 3.2로 세팅하기  (0) 2017.10.16

https://material.io/color/#!/?view.left=0&view.right=0&primary.color=9C27B0

'링크모음 > Android' 카테고리의 다른 글

텐서플로로 안드로이드에서 실행하기  (0) 2017.11.15
Mockito 관련 팁 모음 링크  (0) 2017.11.06
android 저장소 전략  (0) 2017.11.04
오픈소스 정리  (0) 2017.11.02
Android code style  (0) 2017.10.30

https://proandroiddev.com/animate-it-on-react-native-with-opengl-b470252166f4

RxKotlin

우선 dependencies을 추가를 하자.

 compile 'io.reactivex.rxjava2:rxjava:2.1.0'
 compile 'io.reactivex.rxjava2:rxkotlin:2.0.2'
io.reactivex.rxjava2:rxkotlin

의 경우 코틀린으로 확장해서 따로 유틸을 만든 것이다.

주소는 여기 클릭 해서 한번 보도록 하자.

그리고 소스셋을 지정해서 폴더를 구분해주자.

sourceSets {
     main.kotlin.srcDirs += 'src/main/kotlin'
}

그럼 코틀린 파일을 새로 만들어서 테스트 해보자.

1~10까지 돌면서 문자값으로 변경해주는 예제이다.

import io.reactivex.Observable

fun main(args : Array<String>) {
    Observable.range(1 , 10)
            .map { "Number : $it" }
            .subscribe(System.out::println)
}
=======================
Number : 1
Number : 2
Number : 3
Number : 4
Number : 5
Number : 6
Number : 7
Number : 8
Number : 9
Number : 10

또 다른 Scan 을 테스트 해보자.

fun testScan(){
    Observable.range(1 , 10)
            .scan(0) { total , next -> total + next} //람다를 이용한 축
            .subscribe(System.out::println)
}
=====================
0
1
3
6
10
15
21
28
36
45
55


Extension Operators

코틀린은 확장시 정말 편하게 가능하다.

스위프트도 더 편한것 같다.

RxJava 에서 확장 하는compose 나 life 을 대체할수 있다.

toSet으로 확장해서 사용하는 예제이다.

fun test_extenstion_toset(){
    val source = Observable.range(1, 10)

    val asSet = source.toSet()
    asSet.subscribe( { s -> System.out.println( s ) } )
}
//toSet 으로 확장하기.
fun <T> Observable<T>.toSet() = collect(
                                            { HashSet<T>() } , // HashSet으로 초기화
                                            { set , next -> set.add( next )} // set에 next를 추가
                                        )
                                .map { it as Set<T> } // 다시 Set으로 변경

==========================================
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Generic Type으로 말고 타겟을 직접 정의도 충분히 가능하다.

아래 예제는 주어진 값을 총합으로 구한다.

fun test_extenstion_sum(){
    val source = Observable.just( 100 , 50 , 250 , 150)

    val total = source.sum();
    total.subscribe( { s -> System.out.println( s ) } )
}

fun Observable<Int>.sum() =
        reduce(0) { total , next -> total + next}

==========================================================
550

RxKotlin

RxJava에서 Kotlin 으로 변경시 조금 다른 형태를 받을수 있습니다.

만약 리스트를 받아서 그 형태 그대로 리스트 형태의 옵저버를 만들고 싶을때 사용하면 편하다.

import io.reactivex.rxkotlin.toObservable

fun main(args: Array<String>) {

     val myList = listOf("Alpha", "Beta", "Gamma", "Delta", 
     "Epsilon")

     myList.toObservable() //일반 리스트를 Observable로 변경할 수 있는 확장 함수 가능
             .map(String::length)
             .subscribe(::println)
 }

그 외에도 여러가지 함수들이 있다. 한번 꼭 들어가서 확인 해보자.

https://github.com/ReactiveX/RxKotlin

Extensions

Target TypeMethodReturn TypeDescription
BooleanArraytoObservable()ObservableTurns a Boolean array into an Observable
ByteArraytoObservable()ObservableTurns a Byte array into an Observable
ShortArraytoObservable()ObservableTurns a Short array into an Observable
IntArraytoObservable()ObservableTurns an Int array into an Observable
LongArraytoObservable()ObservableTurns a Long array into an Observable
FloatArraytoObservable()ObservableTurns an Float array into an Observable
DoubleArraytoObservable()ObservableTurns an Double array into an Observable
ArraytoObservable()ObservableTurns aTarray into an Observable
IntProgressiontoObservable()ObservableTurns anIntProgressioninto an Observable
IterabletoObservable()ObservableTurns anIterable<T>into an Observable
IteratortoObservable()ObservableTurns anIterator<T>into an Observable
ObservableflatMapSequence()ObservableFlat maps eachTemission to aSequenece<R>
Observable<Pair<A,B>>toMap()CollectsPair<A,B>emissions into aMap<A,B>
Observable<Pair<A,B>>toMultimap()CollectsPair<A,B>emissions into aMap<A,List<B>>
Observable<Observable>mergeAll()ObservableMerges all Observables emitted from an Observable
Observable<Observable>concatAll()ObservableCocnatenates all Observables emitted from an Observable
Observable<Observable>switchLatest()ObservableEmits from the last emitted Observable
Observable<*>cast()ObservableCasts all emissions to the reified type
Observable<*>ofType()ObservableFilters all emissions to only the reified type
Iterable<Observable>merge()Merges an Iterable of Observables into a single Observable
Iterable<Observable>mergeDelayError()Merges an Iterable of Observables into a single Observable, but delays any error
BooleanArraytoFlowable()FlowableTurns a Boolean array into an Flowable
ByteArraytoFlowable()FlowableTurns a Byte array into an Flowable
ShortArraytoFlowable()FlowableTurns a Short array into an Flowable
IntArraytoFlowable()FlowableTurns an Int array into an Flowable
LongArraytoFlowable()FlowableTurns a Long array into an Flowable
FloatArraytoFlowable()FlowableTurns an Float array into an Flowable
DoubleArraytoFlowable()FlowableTurns an Double array into an Flowable
ArraytoFlowable()FlowableTurns aTarray into an Flowable
IntProgressiontoFlowable()FlowableTurns anIntProgressioninto an Flowable
IterabletoFlowable()FlowableTurns anIterable<T>into an Flowable
IteratortoFlowable()FlowableTurns anIterator<T>into an Flowable
FlowableflatMapSequence()FlowableFlat maps eachTemission to aSequenece<R>
Flowable<Pair<A,B>>toMap()CollectsPair<A,B>emissions into aMap<A,B>
Flowable<Pair<A,B>>toMultimap()CollectsPair<A,B>emissions into aMap<A,List<B>>
Flowable<Flowable>mergeAll()FlowableMerges all Flowables emitted from an Flowable
Flowable<Flowable>concatAll()FlowableCocnatenates all Flowables emitted from an Flowable
Flowable<Flowable>switchLatest()FlowableEmits from the last emitted Flowable
Flowablecast()FlowableCasts all emissions to the reified type
FlowableofType()FlowableFilters all emissions to only the reified type
Iterable<Flowable>merge()Merges an Iterable of Flowables into a single Flowable
Iterable<Flowable>mergeDelayError()Merges an Iterable of Flowables into a single Flowable, but delays any error
TtoSingle()SingleTurns anyTitem into aSingle<T>
FuturetoSingle()SingleTurns aFuture<T>into aSingle<T>
CallabletoSingle()SingleTurns aCallable<T>into aSingle<T>
() -> TtoSingle()SingleTurns a() -> Tinto aSingle<T>
Singlecast()SingleCasts all emissions to the reified type
Observable<Single>mergeAllSingles()ObservableMergaes all Singles emitted from an Observable
Flowable<Single>mergeAllSingles()FlowableMergaes all Singles emitted from a Flowable
T?.toMaybe()toMaybe()MaybeTurns a nullableTvalue into aMaybe<T>that will only emit if not null
FuturetoMaybe()MaybeTurns aFuture<T>into aMaybe<T>
CallabletoMaybe()MaybeTurns aCallable<T>into aMaybe<T>
() -> TtoMaybe()MaybeTurns a() -> Tinto aMaybe<T>
Maybecast()MaybeCasts any emissions to the reified type
MaybeofType()MaybeFilters any emission that is the reified type
Observable<Maybe>mergeAllMaybes()ObservableMerges all emitted Maybes
Flowable<Maybe>mergeAllMaybes()FlowableMerges all emitted Maybes
ActiontoCompletable()CompletableTurns anActioninto aCompletable
CallabletoCompletable()CompletableTurns aCallableinto aCompletable
FuturetoCompletable()CompletableTurns aFutureinto aCompletable
(() -> Any)toCompletable()CompletableTurns a(() -> Any)into aCompletable
ObservablemergeAllCompletables()Completable>Merges all emitted Completables
FlowablemergeAllCompletables()CompletableMerges all emitted Completables
ObservablesubscribeBy()DisposableAllows named arguments to construct an Observer
FlowablesubscribeBy()DisposableAllows named arguments to construct a Subscriber
SinglesubscribeBy()DisposableAllows named arguments to construct a SingleObserver
MaybesubscribeBy()DisposableAllows named arguments to construct a MaybeObserver
CompletablesubscribeBy()DisposableAllows named arguments to construct a CompletableObserver
ObservableblockingSubscribeBy()UnitAllows named arguments to construct a blocking Observer
FlowableblockingSubscribeBy()UnitAllows named arguments to construct a blocking Subscriber
DisposableaddTo()DisposableAdds aDisposableto the specifiedCompositeDisposable
CompositeDisposableplusAssign()DisposableOperator function to add aDisposableto thisCompositeDisposable


RxKotlin SAM(Single Abstract Methods) Ambiguity

아쉽게도 RxJava 만들시 코틀린을 염두에 두고 만들지는 못 했다. 그래서 RxKotlin 에서도 SAM 이슈는 발생하고 있다.

SAM 이슈 관련 문서 링크 ( 태환님 블로그 )

우선 문제가 생기는 코드를 보자. 자주 쓰는 Zip이므로 꼭 이해를 해야 한다.

fun test_sam1(){
    val source = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
    val numbers = Observable.range(1,4)

    val result = Observable.zip( source , numbers) { s , n -> "$s $n"} //오류 발생한다. 

    result.subscribe(::println)
}

위와 같이 BiFunction<String,Int,String>을 찾을 수 없다고 나온다.

그러면 수정을 다시 하면 정상적으로 나온다.

val source = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
val numbers = Observable.range(1,4)

val result = Observable.zip( source , numbers , 
                                BiFunction<String,Int,String>{ s , n -> "$s $n"} //이렇게 BiFunction을 따로 지정
                            )
result.subscribe(::println)
===================
Alpha 1
Beta 2
Gamma 3
Delta 4

그런데 소스가 콜백함수로 지저분해진다. 보기가 싫어진다.

그래서 앞서 소개한 RxKotlin 라이버러리를 이용하면 보기 좋게 만들수 있다.

  • io.reactivex.rxkotlin.Observables
val source = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
val numbers = Observable.range(1,4)

val result = io.reactivex.rxkotlin.Observables.zip( source , numbers) { s, n -> "$s $n"}

result.subscribe(::println)

그리고 zipWith을 확장해서 제공하고 있다.

val source = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
val numbers = Observable.range(1,4)

//    val result = io.reactivex.rxkotlin.Observables.zip( source , numbers) { s, n -> "$s $n"}
val result2 = source.zipWith( numbers ) { s, n -> "$s $n"} //zipWith는 따로 확장해서 사용중

result2.subscribe(::println)


let() 와 apply() 응용

Kotlin 에서 let 과 apply 는 아주 유용한 함수이다.

자세한 설명은 다음 링크 를 참조해서 보자.

val numbers = Observable.just( 180.0 , 160.0 , 140.0 , 100.0 , 120.0)

val average = numbers
        .map { it * 2 }
        .doOnNext({ println("doOnNExt => $it")} )
        .publish()
        .autoConnect(2)
        .let {
            val sum = it.doOnNext({ println("sum doOnNext => $it")}).reduce(0.0) { total , next -> total + next }
            val count = it.count()

            println("count -> "+ count)
            sum.doOnEvent( {d , e -> println("sum emmit -> $d")}).zipWith( count ) { s,c -> s/c }
        }
average.subscribeBy (::println )

============================

count -> io.reactivex.internal.operators.observable.ObservableCountSingle@7b1d7fff
doOnNExt => 360.0
sum doOnNext => 360.0
doOnNExt => 320.0
sum doOnNext => 320.0
doOnNExt => 280.0
sum doOnNext => 280.0
doOnNExt => 200.0
sum doOnNext => 200.0
doOnNExt => 240.0
sum doOnNext => 240.0
sum emmit -> 1400.0
280.0

Apply()

자체 함수를 실행할 수 있는 장점이 있다.

val statusObserver = PublishSubject.create<Long>()
statusObserver.subscribe{ println("Status Observer : $it")}

Observable.interval(1 , TimeUnit.SECONDS)
        .take(5)
        .publish()
        .autoConnect(2)
        .apply {
            subscribe(statusObserver) //Observable 클래스 내부에 있는 함수를 호출할 수 있다. 
        }
        .map{ it * 1000 }
        .subscribe{
            println("Main Observer : $it")
        }

Thread.sleep(7000);
============================================
Status Observer : 0
Main Observer : 0
Status Observer : 1
Main Observer : 1000
Status Observer : 2
Main Observer : 2000
Status Observer : 3
Main Observer : 3000
Status Observer : 4
Main Observer : 4000


Tuples and data classes

코틀린 함수로 Tuple 함수를 빨리 만드는 방법을 알아보자.

주어진 문자 , 숫자 를 뭉쳐서 Pair 로 만드는 예제이다.

val strings = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
val numbers = Observable.range(1,4)

Observables
.zip(strings , numbers) { s, n -> s to n} // Pair로 뭉쳐서 리턴
.subscribe{
println(it)
}
=================
(Alpha, 1)
(Beta, 2)
(Gamma, 3)
(Delta, 4)

위의 내용을 Data 클래스로 변경하면 더 보기가 편해진다.

val strings = Observable.just("Alpha" , "Beta" , "Gamma" , "Delta")
val numbers = Observable.range(1,4)

data class StringAndNumber(val myString : String , val myNumber : Int) //Data Class 생성 후 만들기

Observables
.zip(strings , numbers) { s, n -> StringAndNumber(s , n)} // Pair로 뭉쳐서 리턴
.subscribe{
println(it)
}

=====================
StringAndNumber(myString=Alpha, myNumber=1)
StringAndNumber(myString=Beta, myNumber=2)
StringAndNumber(myString=Gamma, myNumber=3)
StringAndNumber(myString=Delta, myNumber=4)



https://brunch.co.kr/@thinkaboutlove/87

'링크모음 > etc' 카테고리의 다른 글

익스퍼트 비기너2편  (0) 2017.11.06
mysql index 정리  (0) 2017.11.06
기기별 목업  (0) 2017.11.05
개발자 치트시트 추천  (0) 2017.10.30
파이썬 기초  (0) 2017.10.28

http://facebook.design/devices

'링크모음 > etc' 카테고리의 다른 글

mysql index 정리  (0) 2017.11.06
5일만에 기획부터 프로토타입까지  (0) 2017.11.05
개발자 치트시트 추천  (0) 2017.10.30
파이썬 기초  (0) 2017.10.28
아마존 직구방법 총정리  (0) 2017.10.21

http://www.mobiinside.com/kr/2017/11/03/buzzvil-tensorflow/

http://pluu.github.io/blog/android/droidkaigi/2017/11/01/droidkaigi-2017-android-storage/

'링크모음 > Android' 카테고리의 다른 글

Mockito 관련 팁 모음 링크  (0) 2017.11.06
android 매트리얼 ui builder  (0) 2017.11.06
오픈소스 정리  (0) 2017.11.02
Android code style  (0) 2017.10.30
Android RecyclerView 팁 모음  (0) 2017.10.30

+ Recent posts