글쓴이 보관물: mcsong

mcsong

mcsong에 대하여

Software Engineer, 카산드라 완벽 가이드(http://www.yes24.com/24/goods/5847220) 번역

TextView android:maxLines과 android:ellipsize 사용시 주의할 점

안드로이드 텍스트뷰는 가장 많이 사용하는 컴포넌트 중의 하나이고, 또 이 컴포넌트의 텍스트는 많은 경우 줄임(ellipse…)을 사용한다. 내 경우에는 가운데 줄임을 많이 사용하는 편이고, 아래와 같이 사용한 경우가 있었다.

<TextView
 android:id="@+id/action_detail_path"
 style="@style/SmallText"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_margin="4dp"
 android:ellipsize="middle"
 android:maxLines="2"
 android:text="@string/lbl_empty"
 />

위 XML 코드는 문제가 없어 보인다. 대부분의 경우에는 문제가 없이 잘 동작해 보였다.

그러나, 간혹 이 텍스트뷰로 인해서 크래시가 발생할 수도 있다. 발생할 수도 있다는 경우는 자주는 아니지만 가끔 발생한다는 것이다. 그래서 위 android:ellipse에 대응하는 TextView API는 setEllipsize 메서드이고, 아래와 같이 설명하고 있다.

void setEllipsize (TextUtils.TruncateAt where)

Causes words in the text that are longer than the view’s width to be ellipsized instead of broken in the middle. You may also want to setSingleLine() or setHorizontallyScrolling(boolean) to constrain the text to a single line. Use null to turn off ellipsizing. If setMaxLines(int) has been used to set two or more lines, only END and MARQUEE are supported (other ellipsizing types will not do anything).
Related XML Attributes:

– android:ellipsize

위 설명을 보면, setMaxLines() 메서드 인자가 2보다 크면, ellipse로 END, MARQUEE만 지원한다는 것이다. 결국 위 xml의 android:ellipsize=”middle”이 크래시를 유발할 수 있다.

앱에서 이 버그가 많이 발생하지 않아서 발견하기 어려(?)웠는데… 이게 다 API를 잘 읽어보지 않고 막 쓰는 제 불찰이었네요.. 괜히 애꿎은 제조사 탓만 했네요..ㅋㅋ

Robo 3T (Robomongo) 설치 on Ubuntu 16.04

Robo 3T는 Robomongo의 새로운 이름으로 아주 유용하게 사용할 수 있는 몽고디비 클라이언트 툴이다. 간단하게 설치하는 방법을 살펴보면 아래와 같다.

1. 다운로드
https://www.robomongo.org/download 에서 플랫폼 버전에 맞게 다운로드한다. 여기에서는 Linux를 선택한다.

2. 다운받은 파일을 필요한 위치에 이동시키고, 압축을 푼다.
mcsong@mcsong-ubuntu:~/Downloads$ mv robo3t-1.1.1-linux-x86_64-c93c6b0.tar.gz ../dev/
mcsong@mcsong-ubuntu:~/dev$ tar xvfz robo3t-1.1.1-linux-x86_64-c93c6b0.tar.gz

3. 링크파일을 패스가 잡혀있는 폴더에 생성한다.
mcsong@mcsong-ubuntu:~/dev/robo3t-1.1.1-linux-x86_64-c93c6b0/bin$ sudo ln -s /home/mcsong/dev/robo3t-1.1.1-linux-x86_64-c93c6b0/bin/robo3t /usr/local/bin/robo3t

4. 이제 실행해서 아래와 같이 연결을 추가하고 사용하면 된다. 

4.1 만약 아래와 같이 에러가 발생한다면..
mcsong@mcsong-ubuntu:~/dev/robo3t-1.1.1-linux-x86_64-c93c6b0/bin$ robo3t
This application failed to start because it could not find or load the Qt platform plugin "xcb"
in "".

Available platform plugins are: xcb.

Reinstalling the application may fix this problem.
Aborted (core dumped)

설치한 폴더의 lib 폴더에서 아래의 파일들을 삭제하면 된다.

libstdc++.so.6
libstdc++.so.6.0.22

안드로이드에서 비교적 안전하게 키 사용하기

많은 앱이 상품을 팔거나 각종 서비스에 연동하는 경우에 필요한 아이디나 키를 저장해서 사용한다. 이 키들을 안전하게 사용하려면 추가적인 처리가 필요하다. 짧은 지식으로 안전함의 순위를 나열하면 아래와 같다.

1. 안전한 방법 : 암호화해서 저장
2. 비교적 안전한 방법 : 네이티브 영역에 저장
3. 안전하지 않은 방법 : 리소스 파일에 저장

우선, 위 기준에 따른 사용방법을 살펴보자.

1. 안전한 방법
1.1 대칭키를 사용해서 키를 암호화한다.
1.2 안드로이드 리소스 파일에 암호화된 키를 저장한다.
1.3 암호화된 키를 사용하기 전에 서버에서 대칭키를 받아서 복호화한다.

2. 비교적 안전한 방법
2.1 네이티브 코드에 키를 리턴하는 메서드를 구현한다.
2.2 네이티브 메서드를 호출해서 키를 받는다.

3. 안전하지 않은 방법
3.1 키를 리소스 파일에 저장한다.
3.2 저장된 키를 사용한다.

이 글에서는 현실적으로 서버를 사용할 수 없는 경우에, 비교적 안전한 방법을 채택하는 형태를 살펴본다.

기존 프로젝트의 main 폴더에 jni 폴더를 만들고 아래와 같은 파일을 만든다.

위 파일의 내용은 아래와 같다.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := keys
LOCAL_SRC_FILES := keys.c

include $(BUILD_SHARED_LIBRARY)

Application.mk : 아래 코드로 모든 플랫폼에 해당하는 .so 를 만든다.

APP_ABI := all

Keys.c : 자바에서 호출할 메서드와 키를 정의한다.

#include 

JNIEXPORT jstring JNICALL
Java_net_sjava_keytest_MainActivity_getNativeKey1(JNIEnv *env, jobject instance) {
    return (*env)->  NewStringUTF(env, "First Key");
}

JNIEXPORT jstring JNICALL
Java_net_sjava_keytest_MainActivity_getNativeKey2(JNIEnv *env, jobject instance) {
    return (*env)->NewStringUTF(env, "Second Key");
}

이제 build.gradle에서 ndk를 포함시키는 코드를 추가한다.

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.0"
    defaultConfig {
        applicationId "net.sjava.keytest"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
}

그리고, MainActivity.java 에서 아래와 같이 키를 가져오는지 확인한다.

package net.sjava.keytest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("keys");
    }

    public native String getNativeKey1();
    public native String getNativeKey2();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String key1 = getNativeKey1();
        String key2 = getNativeKey2();

        ((TextView)findViewById(R.id.textview)).setText("Key1-->"+key1+"\nKey2-->"+key2);
    }
}

이제, 위 코드를 실행하면 아래의 실행 결과를 볼 수 있다.

현실적으로 앱 크래킹을 완벽하게 막기는 불가능한 것 같다. 그래서 프로가드(Proguard)로 난독화 처리와, 앱에서 사용하는 키를 비교적 안전하게 관리해서 크래킹을 어렵게 만드는 게 현실적인 방법인 것 같다.

* 레퍼런스 : https://medium.com/@abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad

안드로이드 지원(support) 라이브러리 구글 메이븐 리파지토리

구글이 지원(support) 라이브러리 다운로드를 위해서 자체 메이븐 리파지토리를 구축해서 25.4.0 버전부터는 구글의 메이븐 리파지토리에서 다운로드 받을 수 있다. 주소는 maven.google.com 이다. 그래서 안드로이드 프로젝트 build.xml 파일에 아래와 같이 구글의 리파지토리도 추가한다.

allprojects {
  repositories {
  jcenter()
  maven { url "https://jitpack.io" }
  maven { url "https://maven.google.com" }
  }
}

https://maven.google.com에 접속하면 https://dl.google.com/dl/android/maven2/ 로 리다이렉트 된다. 구글 메이븐 리파지토리는 서버에서 리스팅 기능을 제공하지 않아서 호스팅 하는 전체 라이브러리를 볼 수 가 없다.

그래서 지원 라이브러리 중에 appcompat-v7 에 대해서 약간의 정보를 살펴봤다.

메타 데이터 정보
https://dl.google.com/dl/android/maven2/com/android/support/appcompat-v7/maven-metadata.xml

라이브러리 파일
https://dl.google.com/dl/android/maven2/com/android/support/appcompat-v7/25.4.0/appcompat-v7-25.4.0.aar

그리고, 구글 지원 라이브러리 종류는 아래에서 확인할 수 있고, 위의 패턴으로 개별 라이브러리를 확인할 수 있다.
https://developer.android.com/topic/libraries/support-library/packages.html

안드로이드 페브릭(Fabric) 그래들(Gradle) 플러그인 버전 지정하기

페브릭(Fabric)은 아주 유용한 기능을 모바일 플랫폼에 쉽게 적용할 수 있게 도와주는 서비스이다. Crashlytics도 페브릭에서 제공하는 크래시 리포트 서비스이다. Crashlytics을 안드로이드에서 사용하는 방법은 fabric.io/kits/android/crashlytics/install 에서 확인할 수 있다. 여기에서 아래의 아래의 코드를 추가하라고 한다.

buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}

dependencies {
// These docs use an open ended version so that our plugin
// can be updated quickly in response to Android tooling updates

// We recommend changing it to the latest version from our changelog:
// https://docs.fabric.io/android/changelog.html#fabric-gradle-plugin
classpath 'io.fabric.tools:gradle:1.+'
}
}

위 코드를 보면 알겠지만, 페브릭의 그래들 플러그인 버전이 ‘io.fabric.tools:gradle:1.+’로 선언되어 있다. 주석을 읽어보면 알겠지만, docs.fabric.io/android/changelog.html#fabric-gradle-plugin 에서 최신 버전으로 수정하라고 한다. 이 문서를 보면, 아래와 같이 최신 버전을 확인할 수 있고, 변경 내용도 확인할 수 있다.

2017년 6월 14일에 확인해 본 결과로 1.22.2 버전이 최신버전이다.

위 과정에 더불어, 페브릭 그래들 플러그인에 대한 메타 정보는 아래 URL에서 확인할 수 있다.
fabric-artifacts.s3.amazonaws.com/public/io/fabric/tools/gradle/maven-metadata.xml

위 이미지에서 최신 버전 릴리즈 시점이 2017년 05월 31일 이라는 것도 알 수 있다.

결론으로 app 모듈에서 build.gradle 파일의 맨 처음은 아래와 같은 모습이 될 것이다.

buildscript {
    repositories {
        jcenter()
        maven { url 'https://maven.fabric.io/public' }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'

        classpath 'io.fabric.tools:gradle:1.22.2'
    }
}