Android

안드로이드 5기 2017년 강의 정리 6 (오준석의 생존코딩)

 

https://www.youtube.com/watch?v=InvEpfiD3P0&list=PLxTmPHxRH3VWSF7kMcsIaTglWUJZpWeQ9&index=125

https://github.com/suwonsmartapp/MyFirstAndroidApp5ki

MyFirstAndroidApp5ki-master.zip

 

43일차 Palette

43일차 Firebase

46일차 Gradle 이것저것

47일차 설정화면

48일차 소셜로그인

48일차 ChromeCustomTab, BottomNavigationView

48일차 TransitionDrawable, Animation

49일차 조도 센서

50일차 TedPermission 권한 체크

51일차 Firebase Functions

52일차 빌드 자동화 gradle

 


 

43일차 Palette

 

# 누구나 쉽게 이해할 수 있는 Git 에 입문 (backlog.com)
https://backlog.com/git-tutorial/kr/intro/intro1_1.html

# Selecting Colors with the Palette API (android developers)
https://developer.android.com/training/material/palette-colors

 

public class PaletteActivity extends AppCompatActivity {

    private ActivityPaletteBinding mBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBinding = DataBindingUtil.setContentView(this,
                R.layout.activity_palette);


        BitmapFactory.Options options = new BitmapFactory.Options();
        // 비트맵 샘플링 (용량줄이기) 2의 배수
        options.inSampleSize = 2;

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.girlfriend, options);
        createPaletteAsync(bitmap);
    }

    public void createPaletteAsync(Bitmap bitmap) {
        Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
            public void onGenerated(Palette p) {
                // Use generated instance

                Palette.Swatch vibrantSwatch = p.getVibrantSwatch();
                if (vibrantSwatch != null) {
                    mBinding.layout1.setBackgroundColor(vibrantSwatch.getRgb());
                    mBinding.title1.setTextColor(vibrantSwatch.getTitleTextColor());
                    mBinding.content1.setTextColor(vibrantSwatch.getBodyTextColor());
                }
                Palette.Swatch darkVibrantSwatch = p.getDarkVibrantSwatch();
                if (darkVibrantSwatch != null) {
                    mBinding.layout2.setBackgroundColor(darkVibrantSwatch.getRgb());
                    mBinding.title2.setTextColor(darkVibrantSwatch.getTitleTextColor());
                    mBinding.content2.setTextColor(darkVibrantSwatch.getBodyTextColor());
                }
                Palette.Swatch lightVibrantSwatch = p.getLightVibrantSwatch();
                if (lightVibrantSwatch != null) {
                    mBinding.layout3.setBackgroundColor(lightVibrantSwatch.getRgb());
                    mBinding.title3.setTextColor(lightVibrantSwatch.getTitleTextColor());
                    mBinding.content3.setTextColor(lightVibrantSwatch.getBodyTextColor());
                }
                Palette.Swatch mutedSwatch = p.getMutedSwatch();
                if (mutedSwatch != null) {
                    mBinding.layout4.setBackgroundColor(mutedSwatch.getRgb());
                    mBinding.title4.setTextColor(mutedSwatch.getTitleTextColor());
                    mBinding.content4.setTextColor(mutedSwatch.getBodyTextColor());
                }
                Palette.Swatch darkMutedSwatch = p.getDarkMutedSwatch();
                if (darkMutedSwatch != null) {
                    mBinding.layout5.setBackgroundColor(darkMutedSwatch.getRgb());
                    mBinding.title5.setTextColor(darkMutedSwatch.getTitleTextColor());
                    mBinding.content5.setTextColor(darkMutedSwatch.getBodyTextColor());
                }
                Palette.Swatch lightMutedSwatch = p.getLightMutedSwatch();
                if (lightMutedSwatch != null) {
                    mBinding.layout6.setBackgroundColor(lightMutedSwatch.getRgb());
                    mBinding.title6.setTextColor(lightMutedSwatch.getTitleTextColor());
                    mBinding.content6.setTextColor(lightMutedSwatch.getBodyTextColor());
                }
                Palette.Swatch dominantSwatch = p.getDominantSwatch();
                if (dominantSwatch != null) {
                    mBinding.layout7.setBackgroundColor(dominantSwatch.getRgb());
                    mBinding.title7.setTextColor(dominantSwatch.getTitleTextColor());
                    mBinding.content7.setTextColor(dominantSwatch.getBodyTextColor());
                }
            }
        });
    }
}

 

# activity_palette.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.myapplication.activities.PaletteActivity">

        <ImageView
            android:id="@+id/imageView3"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            app:srcCompat="@drawable/girlfriend" />

        <LinearLayout
            android:id="@+id/layout_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_6"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_7"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/title_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="24sp" />

            <TextView
                android:id="@+id/content_7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Selecting Colors with the Palette API"
                android:textSize="16sp" />
        </LinearLayout>
    </LinearLayout>
</layout>

 


 

43일차 Firebase

 

# Google Codelabs
https://codelabs.developers.google.com/

 

# Firebase Android Codelab – Build Friendly Chat
https://codelabs.developers.google.com/codelabs/firebase-android?hl=en

 

 


 

46일차 Gradle 이것저것

 

# 메소드 개수 제한 해제 하려면 multidex 적용할 것

 

# 앱을 출시할 때는 난독화를 할 것
minifyEnabled  true  // 잘되면 그냥 출시, 안되면 설정 수정

 

# proguard-rules.pro // 난독화 룰에 대한 파일

 

 


 

47일차 설정화면

 

# Settings (android developers)

https://developer.android.com/guide/topics/ui/settings#java

 

# Settings Activity 추가

 


 

48일차 소셜로그인

# Android용 Facebook 로그인 – 빠른 시작

https://developers.facebook.com/docs/facebook-login/android

 


 

48일차 ChromeCustomTab, BottomNavigationView

 

# Chrome Custom Tabs (chrome developer)
https://developer.chrome.com/multidevice/android/customtabs

 

# BottomNavigationView (android developer)
https://developer.android.com/reference/com/google/android/material/bottomnavigation/BottomNavigationView

 


 

48일차 TransitionDrawable, Animation

 

# Drawable resources (android developers)
https://developer.android.com/guide/topics/resources/drawable-resource

# Animation resources (android developers)
https://developer.android.com/guide/topics/resources/animation-resource

 

# Android scale animation on view
https://stackoverflow.com/questions/7414065/android-scale-animation-on-view

# AnimationActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/AnimationActivity.java

# activity_animation.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_animation.xml

# transition.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/drawable/transition.xml

# scale.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/anim/scale.xml

# shake.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/anim/shake.xml

translate.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/anim/translate.xml

 

 

public class AnimationActivity extends AppCompatActivity {

    ImageView mImageView;
    EditText mEditText;

    Animation mShakeAnimation;

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

        mShakeAnimation = AnimationUtils.loadAnimation(this, R.anim.shake);
        mShakeAnimation.setInterpolator(new CycleInterpolator(7));

        mImageView = (ImageView) findViewById(R.id.image_view);
        mEditText = (EditText) findViewById(R.id.edit_text);

        mEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                mEditText.startAnimation(mShakeAnimation);
            }
        });
    }

    public void transition(View view) {
        TransitionDrawable transitionDrawable = (TransitionDrawable) mImageView.getDrawable();
        transitionDrawable.startTransition(500);
    }

    public void animation1(View view) {
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
        mImageView.startAnimation(animation);
    }

    public void animation2(View view) {
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
        mImageView.startAnimation(animation);
    }
}

 

# activity_animation.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:onClick="transition"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Transition"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent" />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:srcCompat="@drawable/transition" />

    <Button
        android:id="@+id/button12"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:onClick="animation1"
        android:text="Animation1"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:onClick="animation2"
        android:text="Animation2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button1" />

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="name"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button13" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

# transition.xml

<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/girlfriend" />
    <item android:drawable="@drawable/blizzard" />
</transition>

 

# scale.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000">
    <scale
        android:fromXScale="5.0"
        android:fromYScale="5.0"
        android:pivotX="0"
        android:pivotY="0"
        android:toXScale="1.0"
        android:toYScale="1.0" />
</set>

 

# shake.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXDelta="0"
    android:interpolator="@android:anim/cycle_interpolator"
    android:toXDelta="10" />

 

 

# translate.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="700">
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1" />

    <translate
        android:fromXDelta="-100%"
        android:toXDelta="0" />
</set>

 

 


 

49일차 조도 센서

 

# SensorActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/SensorActivity.java

# activity_sensor.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_sensor.xml

 

 

public class SensorActivity extends AppCompatActivity
        implements SensorEventListener {

    private static final String TAG = SensorActivity.class.getSimpleName();
    private SensorManager mSensorManager;
    private Sensor mLightSensor;
    private View mRoot;
    private float mCurrentLux = 0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor);
        mRoot = findViewById(R.id.root);

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

    }

    @Override
    protected void onResume() {
        super.onResume();
        // 센서 이벤트 등록
        mSensorManager.registerListener(this, mLightSensor, SensorManager.SENSOR_DELAY_UI);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 센서 이벤트 해제
        mSensorManager.unregisterListener(this);
    }

    private long mPrevTime = System.currentTimeMillis();

    @Override
    public void onSensorChanged(SensorEvent event) {
        // 1초에 한번씩
        long time = System.currentTimeMillis();
        if (time - mPrevTime < 1000) {
            return;
        }
        mPrevTime = time;

        // 조도
        float lux = event.values[0];

        getSupportActionBar().setTitle("조도 : " + lux + " lx");

        // 부드럽게 전환되는 Drawable
        ColorDrawable[] drawables = new ColorDrawable[]{
                new ColorDrawable(color(mCurrentLux)),
                new ColorDrawable(color(lux))
        };
        TransitionDrawable drawable = new TransitionDrawable(drawables);
        drawable.startTransition(1000);

        mRoot.setBackground(drawable);

        mCurrentLux = lux;
    }

    private int color(float lux) {
        if (lux < 255f / 7f) {
            return Color.MAGENTA;
        } else if (lux < 255f / 7f * 2f) {
            return Color.parseColor("#4b0082");
        } else if (lux < 255f / 7f * 3f) {
            return Color.BLUE;
        } else if (lux < 255f / 7f * 4f) {
            return Color.GREEN;
        } else if (lux < 255f / 7f * 5f) {
            return Color.YELLOW;
        } else if (lux < 255f / 7f * 6f) {
            return Color.parseColor("#ff8c00");
        }
        return Color.RED;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

 

 


 

50일차 TedPermission 권한 체크

 

# TedPermission
https://github.com/ParkSangGwon/TedPermission

 

# PermissionActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/PermissionActivity.java

# activity_permission.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_permission.xml

 

public class PermissionActivity extends AppCompatActivity {

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

    public void checkPermission(View view) {

        TedPermission.with(this)
                .setRationaleMessage("이 기능은 외부 저장소에 접근 권한이 필요합니다.")
                .setDeniedMessage("설정 메뉴에서 언제든지 권한을 변경할 수 있습니다")
                .setPermissions(Manifest.permission.READ_EXTERNAL_STORAGE)
                .setPermissionListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted() {
                        // 기능 수행
                        method();
                    }

                    @Override
                    public void onPermissionDenied(List<String> deniedPermissions) {

                    }
                }).check();
    }

    private void method() {

    }
}

 

 


 

51일차 Firebase Functions

 

# Cloud Functions for Firebase
https://firebase.google.com/docs/functions

 

 


 

52일차 빌드 자동화 gradle

 

# app/build.gradle
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/build.gradle

# gradle.properties
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/gradle.properties

 

# Sign APK without putting keystore info in build.gradle
https://stackoverflow.com/questions/20562189/sign-apk-without-putting-keystore-info-in-build-gradle/38046932

 

# gradle.properties (Global Properties)
모든 프로젝트에 적용한다. 검색할 것

 

# 오른쪽 윈도우 (Gradle 창) 에서 빌드하기
프로젝트명 – app – build – assembleRelease // 빌드하기
프로젝트명 – app – install – installRelease // ADB 명령으로 하지 않아도 자동으로 릴리스용으로 기기로 인스톨 됨

# 안드로이드 스튜디오 실행 없이 핸드폰으로 앱 설치
gradlew InstallRelease
gradlew InstallDebug
// 리눅스는 ./gradlew InstallRelease

 

android {
    signingConfigs {
        release {
            storeFile file('yourfile.keystore')
            storePassword ANDROID_STORE_PASSWORD
            keyAlias 'youralias'
            keyPassword ANDROID_KEY_PASSWORD
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

 

# app/build.gradle

signingConfigs {
    release {
        storeFile file("../keystore/test_key.jks")     // 키스토어 위치
        storePassword _storePassword
        keyAlias _keyAlias
        keyPassword _keyPassword
    }
}
buildTypes {
    // APK 생성 시 버전명 자동 기입하기
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk",
                            "-${variant.versionName}.apk")
            )
        }
    }
    release {
        signingConfig signingConfigs.release    // 여기
        minifyEnabled true      // 난독화
        zipAlignEnabled true    // zipAlign
        shrinkResources true    // 미사용 리소스 제거
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

 

# minifyEnabled true // 난독화를 켰을 때 오류가 나는 것을 무시

lintOptions {
    checkReleaseBuilds false
    // Or, if you prefer, you can continue to check for errors in release builds,
    // but continue the build even when errors are found:
    abortOnError false
}

 

# gradle.properties

org.gradle.parallel=true
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

_storePassword=1234
_keyAlias=key
_keyPassword=1234

android.enableBuildCache=true

 

 

 

 

Related posts

Leave a Comment