728x90
반응형

앱을 설치하거나 로그를 찍을 때 케이블 연결이 끊기면 얼마나 힘들고 짜증이 날까요.


그래서 저는 wifi를 이용해서 무선으로 adb를 연결해서 사용하고 있습니다.


이번 포스팅에서는 무선으로 adb를 연결해서 사용하는지 이야기 해보려고합니다.


WIFI ADB ULTIMATE라는 Plugin입니다.


Preference(Command + ,) -> Plugins -> Browse Repositories... -> wifi 검색

검색 하시면 5개가 나오는데 저는 맨 아래에 있는 WIFI ADB ULTIMATE를 사용합니다.


Install을 하시고 Android Studio를 Restart를 해줍니다.


그리고 오른쪽에 WIFI ADB ULTIMATE를 누르면 아래와 같이 창이 나옵니다.



지금은 제 안드로이드폰을 연결 한 상태입니다.


이 기능을 사용하기 위해서 컴퓨터와 안드로이드폰이 같은 WIFI를 사용해야합니다.

(같은 네트워크를 사용하면 됩니다.)


그리고 초록색 재생 버튼을 누르면 연결이 완료됩니다.




그리고 Android Studio에서 Run을 하게 되면 아래와 같이 연결된 것을 볼 수 있습니다.



이 기능을 사용하기 위해서는 케이블로 연결하여 remote device로 연결해줘야합니다.

그러니 케이블을 이용해서 최초 한번은 연결해야 한다는 소리입니다.


이제 선 없이 앱 설치하고 로그 보세요!

728x90
반응형
728x90
반응형

이번에는 제가 Android Studio에서 정말 정말 많이 사용하는 기능인 "Add Selection for Next Occurrence"에 대해서 설명하려고 합니다.


아마 이 글을 다 읽으면서 혹은 읽고 난 후에 심쿵 하실 수도 있습니다.

저도 그랬습니다.



자 그럼 심쿵 하실 준비 되셨나요??


일단 예를 먼저 들어볼게요.

public class PoloniexTicker {
@SerializedName("USDT_BTC")
public Ticker usdtBtc;
@SerializedName("USDT_BCH")
public Ticker usdtBch;
@SerializedName("USDT_ETH")
public Ticker usdtEth;
@SerializedName("USDT_ETC")
public Ticker usdtEtc;
@SerializedName("USDT_XRP")
public Ticker usdtXrp;
@SerializedName("USDT_LTC")
public Ticker usdtLtc;
@SerializedName("USDT_DASH")
public Ticker usdtDash;
@SerializedName("BTC_BCH")
public Ticker btcBch;
@SerializedName("BTC_ETH")
public Ticker btcEth;
@SerializedName("BTC_ETC")
public Ticker btcEtc;
@SerializedName("BTC_XRP")
public Ticker btcXrp;
@SerializedName("BTC_LTC")
public Ticker btcLtc;
@SerializedName("BTC_DASH")
public Ticker btcDash;

public class Ticker {
@SerializedName("last")
public double last;
}
}

제가 폴로닉스에서 데이터를 가져오기 위해서 사용하는 모델 클래스입니다.


여러분들이 이 코드를 작성하려고 한다면 어떻게 하시겠나요?


코드를 보면 USDT_와 BTC_만 빼고 나머지는 같다고 볼 수 있습니다.


그래서 저는 USDT_쪽 코드를 작성하고 복사한 후에 BTC_로만 수정하려고 합니다.


아래에서 코드 작성하는 과정을 보겠습니다.


심쿵하셨나요??

안하셨으면...


이렇게 특정 문자열만 선택하여 수정, 삭제가 가능하게 합니다.



단축키는 맥용 기준으로 control + g 입니다.


이 기능을 사용하시면 위에 보여드렸던 예 말고도 많은 것을 할 수 있습니다.


저는 enum을 만들고 그에 대한 switch코드를 작성할 때도 사용합니다.


추가)

라고 의견을 주셨습니다.




728x90
반응형
728x90
반응형

이 글은 Realm을 사용하며 Java8을 사용하기 위해 jackOption을 설정한 개발자를 위한 글이다.


Realm을 추가하고 앱을 실행하면 Application에서 Realm.init()부터 에러가 나는것을 볼 수 있다.


java.lang.ExceptionInInitializerError: RealmTransformer doesn't seem to be applied.

                                           Please update the project configuration to use the Realm Gradle plugin.

   See https://realm.io/news/android-installation-change/

at io.realm.RealmConfiguration.<clinit>(RealmConfiguration.java:78)

at io.realm.RealmConfiguration$Builder.initializeBuilder(RealmConfiguration.java:474)

at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:460)

at io.realm.Realm.init(Realm.java:201)


만약 저 링크에 있는 것처럼 Gradle 설정을 잘 따라 했다면 JackOption을 사용했는지 확인해봐야 한다.


만약 본인이 Lambda을 사용하기 위해 아래와 같이 JackOption을 사용했다면

Retrolambda를 사용해야 Realm을 사용 할 수 있다.


이 에러를 해결하기 위해서는 jackOptions을 제거하고 Retrolambda를 추가해야한다.


본인 프로젝트 build.gradle




Module build.gradle




출처

https://blog.realm.io/android-installation-change/

https://stackoverflow.com/questions/41153879/realm-android-realmtransformer-doesnt-seem-to-be-applied

https://github.com/evant/gradle-retrolambda

http://tiii.tistory.com/5

728x90
반응형
728x90
반응형

Realm은 Android에서 사용하던 SQLite와는 다른 C++ 코어 기반 DB입니다.


(출처: https://speakerdeck.com/realm/realm-introduction-seoul-meetup-10)



그리고 기존 RDB개념이 아닌 Object를 저장하는 개념입니다.


  

(출처: https://speakerdeck.com/realm/realm-introduction-seoul-meetup-10)



이렇게 사용함으로써 RDB개념에 대해 잘 모르는(저도 잘 모릅니다) 개발자에게 Realm은 그냥 객체를 사용하는데 알아서 DB에 쓰고 읽는 효과를 볼 수 있습니다.


하지만 제가 Realm을 쓰면서 놀란게 하나가 있습니다.


바로 모델 클래스를 상속 시킬수가 없다는 것입니다.


나닛?!


그래서 이번 블로그에서는 Realm을 사용하면서 발생하는 이슈중 하나인 RealmObject 상속으로 인한 모델 구조 변경에 대해서 이야기하려고합니다.


1. is-a관계 has-a관계로 만들기


예를 들어 Log클래스와 User클래스가 있고 User클래스는 Log클래스를 상속 받는 구조 입니다.

public class Log extends RealmObject {
public long createdTs;
public long updatedTs;
}

public class User extends Log {
public String name;
public int age;
public String email;
}

is-a관계로 모델을 구성 했을 때 Realm에서는 이런 오류가 발생합니다.

Valid model classes must either extend RealmObject or implement RealmModel.





출처: https://github.com/realm/realm-java/issues/2691

출처: https://github.com/realm/realm-java/issues/761


is-a관계가 언제 될지는 모르겠지만 아마 안될꺼같아요.


그래서 모델 클래스를 has-a관계로 바꿔야합니다.

public class User extends RealmObject {
public Log log;
public String name;
public int age;
public String email;
}


2. 상속구조 구현하기


is-a관계를 has-a관계로 바꾸면서 다형성(Polymorphism)과 유사한 형태를 만들어 보려고 합니다.


public interface ILog extends RealmModel {
Log getLog();
}
public interface IUser extends ILog {
User getUser();
}

ILog와 IUser를 만들고 IUser가 ILog를 상속받게 합니다.


public class Log extends RealmObject implements ILog{
public long createdTs;
public long updatedTs;

@Override
public Log getLog() {
return this;
}
}
public class User extends RealmObject implements IUser{
public Log log;
public String name;
public int age;
public String email;

@Override
public Log getLog() {
return log;
}

@Override
public User getUser() {
return this;
}
}

그리고 Log가 ILog를 실체화하고 User가 IUser를 실체화합니다.


이렇게 되면 Interface를 이용해서 다형성을 유지 할 수 있게 됩니다.


그리고 객체에 접근하기 위해서 getter를 선언해줍니다.


3. 동일한 primary key주기


Realm에서 객체를 update하기 위해서는 primary key가 선언되어 있어야 합니다.


이렇게 했을때 has-a관계에 있는 모델들이 동일한 primary key를 가지고 있어야만 is-a관계처럼 동일한 디비를 가질수 있게 됩니다.


public class Log extends RealmObject implements ILog {
public long createdTs;
public long updatedTs;
@PrimaryKey
private long logId;

public Log(long logId) {
this.logId = logId;
}

public Log() { }

public long getLogId() {
return logId;
}

@Override
public Log getLog() {
return this;
}
}
public class User extends RealmObject implements IUser {
public Log log;
public String name;
public int age;
public String email;
@PrimaryKey
private long logId;

public User(long logId) {
this.logId = logId;
log = new Log(logId);
}

public User() { }

public long getLogId() {
return logId;
}

@Override
public Log getLog() {
return log;
}

@Override
public User getUser() {
return this;
}
}

이렇게 하면 logId는 생성자를 통해서만 set할 수 있고 User와 Log가 동일한 logId를 가질 수 있습니다.


기본 생성자는 Realm에서 사용하기 떄문에 선언해줘야합니다.


4. auto increment 만들기


Realm realm = Realm.getDefaultInstance();
Number number = realm.where(Log.class).max("logId");
long logId = number == null ? 0 : number.longValue() + 1;
User user = new User(logId);

이렇게 하게 되면 Log의 마지막 logId값 보다 1큰 수를 logId로 가질 수 있게 됩니다.


5. 끝으로


이런식으로 기존 is-a관계를 has-a관계로 바꾸면서 primary key도 unique하게 가질 수 있는 구조를 만들었습니다.


하지만 이 방법이 정말 옳은지는 잘 모르겠습니다.


만약 이 포스팅을 보고 이 구조로 구현을 한다고 하시면 한번 더 고민해주셨으면 좋겠습니다.


여러분들의 많은 의견과 태클 감사하겠습니다.

728x90
반응형
728x90
반응형

글 제목 짓기가 너무 어렵네요..


이번에는 제가 Android Studio를 쓰면서 자주 사용하는 단축키중 하나를 소개하고자 합니다.


바로 Complete Current Statement입니다.



이게 뭐냐고요?


Android Studio가 자동으로 현재 코드를 완성시켜줍니다.


마법을 사용하자! 익스펙토 패트로눔!!


그럼 어떤 경우에 사용하는지 알아볼게요.





뭔가 실망하셨나요?


하지만 방향키와 ;를 누르는 작업이 많이 줄어듭니다.


저는 이기능을 사용하고나서 ;를 잘 안쓰는거 같아요.


이거 외에도 여기저기 많이 사용할 수 있는 것 같으니까 매번 눌러보세요!


728x90
반응형
728x90
반응형

코드를 작성할 때 주석을 작성하는 것은 매우 중요합니다.

필수라고 들었습니다.


다른사람이 작성한 코드에서 변수나 메소드가 어떻게 동작하는지 주석을 보면 알수가 있죠.

물론 제가 작성한 코드도 다른사람이 봐야하니까 꼭 달아야하죠.


하지만 저는 코드작성을 하다보면 깜빡하고 주석을 적지 않고 커밋을 날릴때가 있습니다.


그리고 돌아오는 선배의 말은


주석을 달아라!!!


네...


그래서 이번에는 Android Studio에서 메소드에 주석포멧 쉽게 생성하는 법에 대해서 알아 볼꺼에요.



네 이게 끝이에요...


/**하고 Enter를 하면 매개변수들과 리턴에 대해 자동으로 생성해줍니다.


참쉽죠?


그러니 여러분 주석 꼭 달아요!

(저도 열심히 주석 쓸게요)

728x90
반응형
728x90
반응형

코드를 작성하다보면 정렬도 삐뚤삐뚤하고 사용하지 않는 import를 펀하게 제거하기 위해 IDE의 도움을 받아야한다.


하지만 각 파일마다, 매번 아래와 같은 단축키 두개를 눌러서 작업하는거는 귀찮은 일이다.




하지만 우리 Android Studio에서는 정말 친절한 기능인 Reformat Code라는 기능이 있다.

(두둥)


하지만 이 기능을 사용하기 전에 한가지 설정을 해야한다.



여기서 Optimize imports와 Rearragnge code를 체크해주면 라인정렬과 import 정리가 한번에 해결된다.


그리고 왼쪽 Project View에서 패키지나 layout같은 폴더를 클릭하고 Reformat Code를 실행하면 폴더안에 있는 파일들이 전부 정리가 된다.

728x90
반응형
728x90
반응형

기존에 Android에서 제공하는 DrawerLayout은 아래와 같이 기존 화면 위에 올라오는 방식이다.


  


(출처: http://frogermcs.github.io/InstaMaterial-concept-part-7-navigation-drawer/)

(출처: http://www.journaldev.com/12648/navigationview-android)



하지만 오늘 소개하고자 하는 Library는 DrawerLayout과는 반대로 기존 화면이 움직이는 방식이다.


일단 말로만 들으면 무슨소리인지 모르니 아래 그림을 보자.

(출처: https://github.com/yarolegovich/SlidingRootNav)


어떤가요? 너무 신기하지 않나요?

저는 매우 신기해서 제 앱에도 넣었습니다.




자 이제 SlidingRootNav가 어떤건지 알았으니 사용해봅시다.


app Module build.gradle파일에 dependency를 추가해줍니다.

dependencies {
compile 'com.yarolegovich:sliding-root-nav:1.0.2'
}


샘플을 위헤 Activity에 들어갈 layout과 SlidingRootNav로 사용할 layout을 준비합니다.


main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:orientation="vertical"
tools:context="com.googry.googryslidingrootnav.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello World!"
android:textColor="@android:color/white"
android:textSize="30dp"/>

</FrameLayout>


sliding_root_nav.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="20dp"
android:gravity="center"
android:text="Sliding\nRoot\nNav"
android:textColor="@android:color/black"
android:textSize="30dp"/>

</FrameLayout>


MainActivity.java

public class MainActivity extends AppCompatActivity {

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

new SlidingRootNavBuilder(this)
.withMenuLayout(R.layout.sliding_root_nav)
.inject();
}
}

이렇게 하면 기본적인것은 끝이 납니다.


아주아주 기본예제인 것이죠.



하지만 지금은 햄버거 버튼도 없고 우리가 위에서 봤던 Toolbar가 같이 움직이는 그림은 아닙니다.

(뭐야 그럼 어떻게 해야하는거야?)


그럼 이제 툴바도 같이 움직이게 해봅시다.


일단 기본 테마에서 ActionBar를 제거하고 Title도 제거해줍시다.

parent를 Theme.AppCompat.Light.NoActionBar로 변경해도 상관없습니다.

(액션바만 없어져라!)


styles.xml

<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
</style>

</resources>

그 다음에는 main_activity.xml에 Toolbar를 추가해줍시다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:orientation="vertical"
tools:context="com.googry.googryslidingrootnav.MainActivity">


<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>


<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello World!"
android:textColor="@android:color/white"
android:textSize="30dp"/>

</FrameLayout>

</LinearLayout>

MainActivity.java에서 Toolbar를 연결해줍시다.

public class MainActivity extends AppCompatActivity {

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

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

new SlidingRootNavBuilder(this)
.withMenuLayout(R.layout.sliding_root_nav)
.inject();
}
}


이제는 Toolbar도 같이 움직입니다!


(아직 햄버거 버튼이 없잖아...)



이제 햄버거 버튼도 넣어봅시다.


햄버거 버튼은 SlidingRootNavBuilder에서 withToolbarMenuToggle()을 추가해주면 됩니다.

참 쉽죠?

public class MainActivity extends AppCompatActivity {

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

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(Color.WHITE);
setSupportActionBar(toolbar);

new SlidingRootNavBuilder(this)
.withMenuLayout(R.layout.sliding_root_nav)
.withToolbarMenuToggle(toolbar)
.inject();
}
}



Toolbar에 title과 햄버거 버튼 색깔은 아래코드를 추가하면 바꿀수 있습니다.


툴바 타이틀 색변경


toolbar.setTitleTextColor(Color.WHITE);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(Color.WHITE);
setSupportActionBar(toolbar);


툴바 햄버거 색 변경

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
<item name="colorButtonNormal">@android:color/white</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>

<style name="DrawerArrowStyle" parent="@style/Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">@android:color/white</item>
</style>


제가 만들고 있는 코인원헬퍼에는 이런식으로 적용했습니다.




위에서 작성한 코드들은 아래 깃허브에서 다운받아보실 수 있습니다.

https://github.com/sjjeong/GoogrySlidingRootNav



SlidingRootNav에 대한 더 많은 정보는 아래 깃허브 페이지에서 확인 할 수 있습니다.

https://github.com/yarolegovich/SlidingRootNav


스타도 꼭 눌러줍시다!


728x90
반응형

'Android > Library' 카테고리의 다른 글

(Android) 고품질 애니메이션을 위한 Lottie Library  (3) 2017.08.01
728x90
반응형

애니메이션 효과는 앱의 품질을 높여주는 역할을 하며 사용자에게 더 좋은 UI/UX를 제공합니다. 


(출처: https://github.com/airbnb/lottie-android)


그렇다면 이제 Lottie에 대해 알아보고 사용법에 대해 알아보자.


Lottie란?

Lottie는 Airbnb에서 만들었고 실시간으로 After Effect 애니메이션을 랜더링하고 iOS, Android, React Native에서 동작하는 고품질 애니메이션 라이브러리입니다.




그럼 After Effect에서 만든 파일은 .aep나 .aepx인데 이것을 안드로이드에서 바로 가져다가 쓸 수 있나?

아니요. 바로 가져다가 쓸 수 없습니다.


그래서 Bodymovin이라는 After Effect Plugin을 설치해서 안드로이드에서 사용할 수 있는 파일로 변환 해 줘야합니다.


Bodymovin을 사용하면 애니메이션을 JSON 데이터 포맷으로 추출 할 수 있고 이것을 가져다가 안드로이드에서 보여주면 됩니다.


그럼 이제 안드로이드에서 Lottie를 추가하고 사용하는 법에 대해 알아보자.


app Module build.gradle파일에 dependency을 추가해줍니다.

dependencies {
compile 'com.airbnb.android:lottie:2.1.0'
}

그리고 project sync를 하면 lottie 라이브러리가 추가 된 것을 확인 할 수 있습니다.



layout에 LottieAnimationView를 추가합니다.

<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_autoPlay="true"
app:lottie_fileName="data.json"
app:lottie_loop="true"/>


lottie_fileName은 After Effect에서 만든 애니메이션의 json파일 이름이 들어가야 합니다.

그리고 json파일은 assets폴더 안에 넣어줍니다.


lottie_autoPlay는 엑티비티가 실행되고 layout이 화면에 보여질때 자동으로 애니메이션을 시작하는 것이고

lottie_loop는 애니메이션이 끝나고 반복적으로 다시 실행 할지 결정하는 것입니다.


또한 autoPlay, fileName, loop와 같은 속성은 자바 코드로도 사용 할 수 있습니다.

LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);
animationView.setAnimation("data.json");
animationView.loop(true);
animationView.playAnimation();

그럼 결과는 아래와 같습니다.



LottieAnimationView에는 setProgress()를 사용해서 애니메이션의 offset을 바꾸거나 속도를 조절할 수 있습니다.







예제 샘플은 https://github.com/sjjeong/GoogryLottieSample 에서 확인 하실 수 있습니다.

예제에서 사용한 Lottie파일은 https://www.lottiefiles.com/ 에서 다운 받으실 수 있습니다.


추가로 애니메이션이 완료 된 후에 화면에서 사라지게 하고 싶으시다면 아래 코드를 확인해주세요.

final LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.lav_loading);
animationView.addAnimatorListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {

}

@Override
public void onAnimationEnd(Animator animation) {
animationView.setVisibility(View.GONE);
}

@Override
public void onAnimationCancel(Animator animation) {

}

@Override
public void onAnimationRepeat(Animator animation) {

}
});


728x90
반응형

'Android > Library' 카테고리의 다른 글

(Android) DrawerLayout을 반대로? SlidingRootNav로 하자!  (0) 2017.08.13

+ Recent posts