2017년 12월 20일 수요일

[Android] 안드로이드 gradle로 Release하기 : usage gradle apk release solution by productflavors : gradle v3.0.1

Android Studio v3 에서 gradle을 사용해서 한번에 다양한 release를 만들고 싶어졌다.
release apk파일들은 각기 다른 변수를 사용해서 다르게 만들어져야 했다.

1. 소스코드에서 gradle의 변수에 접근가능한 방법이 필요했다.
일반적으로 BuildConfig를 이용하면 Gradle의 변수에 접근 가능하다.
BuildConfig.DefinedName 
DefinedName을 하기 위해서는 gradle에서 buildConfigField를 이용하면 된다.
다음과 같이 boolean 타입의 변수를 정의해서 소스에서 접근할 수 있다.

android {
   defaultConfig{
      buildConfigField "boolean", "DefinedName", "false"
   }
}

2. Release할 때, 다양한 타입의 릴리즈파일을 생성하려면, productFlavors를 이용한다.
다음과 같이 flavorDimensions를 설정하고 productFlavors에서 release타입에 맞는
변수와 dimension을 설정하면 한번의 release동작으로 여러가지 apk를 생성할 수 있다.
BuildConfigField에서 정의된 DefinedName이 변하므로 빌드될 때, 소스코드가 변경되어 전혀다른 종류의 APK를 생성할 수 있다.
android {
   flavorDimensions "myOut"

   productFlavors {
        product1 {
            dimension "myOut"
            buildConfigField "boolean", "DefinedName", "true"
        }
        product2 {
            dimension "myOut"
            buildConfigField "boolean", "DefinedName", "false"
        }
   }
}

3. Release파일이름의 변경.
 release파일이름은 보통 app이름 + release인 app_release.apk 기본 형태로 생성된다.
 이 부분을 flavorName으로 바꾸고 싶은 경우 다음과 같이 사용해보자.
 myApp_product1.apk, myApp_product2.apk 형태로 release 파일을 생성할 수 있다.

android{
    release {
      applicationVariants.all { variant ->
         variant.outputs.all {
            def flavorName = variant.productFlavors[0].name;
            outputFileName = "myApp_${flavorName}.apk"
         }
      }
    }
}


2017년 8월 27일 일요일

[Android] NumberPicker : text blinking problem ( 선택된 문자 깜박임 방지 )

기본 NumberPicker를 사용하는 경우에, 선택된 문자를 터치하는 경우
깜박임이 발생한다.

깜박임을 방지하기 위해 다음과 같이 처리할 수 있다.


private void setNpbgFixxer( NumberPicker np ){
        try {
            Method method = np.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
            method.setAccessible(true);
            method.invoke(np, true);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        Field f = null;
        try {
            f =NumberPicker.class.getDeclaredField("mInputText");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        f.setAccessible(true);
        EditText inputText = null;
        try {
            inputText = (EditText)f.get(np);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        inputText.setFilters(new InputFilter[0]);
    }

2017년 6월 25일 일요일

[Android] ButterKnife : 안드로이드 리소스 라이브러리

퍼온곳 : https://lonelywolflee.blogspot.kr/2016/04/android-view-bind-butter-knife.html

공식 홈페이지

http://jakewharton.github.io/butterknife/


v 8.6.0 기준으로 소개 됩니다.

공식 페이지 : http://jakewharton.github.io/butterknife/
한줄 소개 : Field, Resource, Event Callback을 Android View 에 Bind 하기 위한 Annotation을 제공한다.
예제 코드 : http://github.com/LonelyWolfLee/lw-butterknife-example/
라이센스 : the Apache License, Version 2.0

Introduction

Simple example

TextView title에 R.id.title을 할당하기 위해서 기존에는 아래와 같이 하였다.
TextView title;
...
@Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    title = (TextView)activity.findViewById(R.id.title);
    // TODO Use fields...
}

하지만 Butter Knife를 사용하면 아래와 같이 사용이 가능 하다.
@BindView(R.id.title) TextView title;
...
@Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
    // TODO Use fields...
}

Advantage

  • control 객체를 가져오거나 resource 등을 가져오는 방식을 일관된 방식으로 사용 할 수 있다
  • 불필요한 boilerplate를 제거 할 수 있다
  • 로직과 정의 및 선언부를 분리 할 수 있어서 로직 구현 및 분석에 용이하다.


Installation

참고 : http://jakewharton.github.io/butterknife/#download

Android의 개발 환경은 IntelliJ 기반의 Android Studio에 gradle 기반의 프로젝트 설정 방식을 사용 한다. 원하는 프로젝트의 gradle 파일로 가서 다음과 같은 dependency 항목을 추가 한다. (실제 버전 확인)
dependencies {
    ...
    compile 'com.jakewharton:butterknife:8.6.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
}
정상적으로 동작 하지 않을 경우 다음 설정이 되어있는지 확인한다.
File > Other Settings > Default Settings > Build, Execution, Deployment > Compiler > Annotation Processors 에서 "Enable annotation processing"를 체크해준다.


Usages with example

Basic usage (예제 코드)

Controls, resources, event callback 을 annotation을 사용하여 정의 하고, onCreate()에서 ButterKnife.bind(this); 를 호출한다.
public class BasicWithButterKnifeActivity extends AppCompatActivity {

    @BindView(R.id.text_change_view)
    TextView changeView;

    @BindString(R.string.str_basic)
    String strChanged;

    @BindColor(R.color.colorBasicChanged)
    int colorChanged;

    @OnClick(R.id.button_change_text)
    void changeText() {
        changeView.setText(strChanged);
    }

    @OnClick(R.id.button_change_color)
    void changeColor() {
        changeView.setBackgroundColor(colorChanged);
    }

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

        ButterKnife.bind(this);
    }
}

Usage on ViewHolder (예제 코드)

Controls, resources, event callback 을 annotation을 사용하여 정의 하고, constructor에서 ButterKnife.bind(Object, View); 를 호출한다.
예제에서 @OnClick 함수 내부에 item을 가져오기 위해 getItem을 사용하였다. clickButton()은 보기에는 method 정의로 보이지만 실제로는 R.id.btn_item 로 선언 된 Button view에 setOnClickListener 를 사용하여 달아준 리스너 객체와 연결되어 있다. 그렇기 떄문에 내부에서 getItem이 아닌 this.item 식으로 사용하게 되면 처음 class 가 생성 될 때에 ButterKnife.bind() 가 호출 될 시점의 값인 null 이 계속 호출 된다. 그래서 getItem() 같이 함수로 연결하여 나중에 들어온 값을 가져 올수 있도록 해야한다.
class RecyclerWithButterKnifeViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.txt_item)
    TextView text;
    String item;

    RecyclerWithButterKnifeViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    void bind(final String item) {
        this.item = item;
    }

    @OnClick(R.id.btn_item)
    void clickButton() {
        text.setText(getItem());
    }

    private String getItem() {
        return this.item;
    }
}

Usage on Fragment (예제 코드)

Controls, resources, event callback 을 annotation을 사용하여 정의 하고, constructor에서 ButterKnife.bind(Object, View); 를 호출한다.
Fragment는 실제로 사용되는 Activity와 lifecycle이 다르기 때문에 적절한 위치에서 bind 된 객체를 null로 만들어줄 필요가 있다. 이를 위해 bind 시점에 Unbinder 를 반환하여 handling 할수 있게 해준다. onCreateView 에서 bind 해고 onDestroyView에서 unbind 하는 것이 일반적이다.
public class FragmentB extends Fragment {

    @BindView(R.id.txt_description)
    TextView description;
    @BindView(R.id.img_view)
    ImageView image;
    @BindString(R.string.str_frag_b)
    String strDescription;
    @BindDrawable(android.R.drawable.star_big_on)
    Drawable drawable;

    private Unbinder unbinder;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_fragment, container, false);

        unbinder = ButterKnife.bind(this, view);
        description.setText(strDescription);
        image.setImageDrawable(drawable);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }
}

2017년 1월 17일 화요일

[Android] okHttp 사용하기

1. okHttp 사용하기


http://square.github.io/okhttp/

1-1. Get 방식.


OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();
  Response response = client.newCall(request).execute();
  return response.body().string();
}

1-2. Post 방식.

public static final MediaType JSON
    = MediaType.parse("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  Response response = client.newCall(request).execute();
  return response.body().string();
}



2. okHttp https 설정하기


http://stackoverflow.com/questions/33469218/okhttp-request-https-is-very-slow-on-android