2019년 3월 5일 화요일

Hex.decodeHex - 바이트문자열 변환

- Hex.decodeHex를 통한 byteString을 정수형으로 변환하는 샘플.



1. 기본 예제
String value = "ff";

try {
byte[] bytes = Hex.decodeHex(value);
long result = bytes[0] & 0xff;

System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}

> 결과 : 255
> 0xff 마스크를 적용하지 않으면 -1 결과가 나옴.
> 2의 보수 위키백과 :
https://ko.wikipedia.org/wiki/2%EC%9D%98_%EB%B3%B4%EC%88%98







2. 변환 응용
- long 데이터로 변환 예제
String value = "FF7FFFFFFF";

try {
byte[] bytes = Hex.decodeHex(value);
long result = 0;

for (int i = bytes.length - 1; i >= 0; i--) {
result += (long) (bytes[i] & 0xff) << 8 * i;

}

System.out.println(result);
} catch (DecoderException e) {
e.printStackTrace();
}

> 결과 : 1099511595007
> int형 양수 최대 길이는 7FFFFFFF

String.format 예제 - 자바

- 자바 기준 예제
- 자주 사용하는 예제



1. 기본
- int, long
long value = 123456789;
System.out.println(String.format("%d", value));

System.out.println(String.format("%20d", value));
> 길이지정 결과 출력


- float, double
double value = 12345.6789;
System.out.println(String.format("%f", value));


- 문자열
String value = "ABC";
String value2 = "가나다";
System.out.println(String.format("%s, %s", value, value2));

System.out.println(String.format("%5s, %5s", value, value2));
> 길이지정 결과 출력




- Object
List<Object> list = new ArrayList<>();
list.add("ABC"); list.add(123);
list.add(456.789);

System.out.println(String.format("%s", list));
> toString()이 구현된 형태로 출력


- 배열
Arrays.asList을 이용
System.out.println(String.format("%s", Arrays.asList(new String[] { "123", "가나다" })));


- byte
int value = 65535;
System.out.println(String.format("%x", value));
System.out.println(String.format("%X", value));
System.out.println(String.format("%02X", value));





2. 자리수
- 콤마
double value = 12345.6789;
System.out.println(String.format("%,f", value));
System.out.println(String.format("%,d", (int)value));
> 정수는 d, 소수는 f로 적용


- 소수점 자르기(소수점 표현 지정)
double value = 12345.6789;
System.out.println(String.format("%.6f", value));
> 비는 소수점 자리는 0으로 채움







2019년 3월 4일 월요일

유클리드 호제법 코드 예제 - 서로도 또는 최대공약수 구하기

- 유클리드 알고리즘 위키백과 :
https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95


- 기본 코드(Java)
public static int gcd(int a, int b) {
int tmp, n;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}

// 유클리드 알고리즘 부분
// b가 0이 될때까지(a%b), 반복문을 돌게되고, b가 0인 순간의 a를 GCD로 판단하고 리턴.
while (b != 0) {
n = a % b;
a = b;
b = n;
}
return a;
}


결과가 1인경우 서로소, 1이 아닌 경우는 최대공약수가 확인됩니다.
사용하는 방법에 따라 다양하게 사용할 수 있습니다.
개인적인 활용도는 디스플레이 화면비를 구할 때 사용합니다.


예) 화면비 구하기
public class RatioCheck {

public static void main(String[] args) {
int widht = 1024;
int height = 768;
int result = gcd(widht, height);
System.out.println("Ratio > " + (widht / result) + ":" + (height / result));

widht = 1920;
height = 1080;
result = gcd(widht, height);
System.out.println("Ratio > " + (widht / result) + ":" + (height / result));

}

public static int gcd(int a, int b) {
int tmp, n;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}

// 유클리드 알고리즘 부분
// b가 0이 될때까지(a%b), 반복문을 돌게되고, b가 0인 순간의 a를 GCD로 판단하고 리턴.
while (b != 0) {
n = a % b;
a = b;
b = n;
}
return a;
}

}


> 결과 :
Ratio > 4:3
Ratio > 16:9



ConstraintLayout 가이드

1. layout_constraint 속성

- app:layout_constraintTop_toTopOf="parent"
parent 속성으로 ConstraintLayout에 배치된 뷰는 최 상단을 기준으로 배치.

간단하게 자석처럼 최상단에 View을 붙는다.

예1 ) 모든 방향을 적용하면
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"


android:layout_width="wrap_content", android:layout_height="wrap_content"
크기로 배치된 View는 레이아웃 가운데 위치하게 된다.





android:layout_width="0dp", android:layout_height="0dp"
크기로 배치된 View는 레이아웃 모든 영역에서 레이아웃을 잡아 당겨지므로 전체화면으로 표시된다.





예2 ) 다른 레이아웃에 붙일 경우
app:layout_constraintTop_toBottomOf="@id/textView"




> 간단하게 Android 텍스트 뷰를 textView 아래 배치 하는 의미.


자주 사용하는 속성은
app:layout_constraintTop_toBottomOf="@id/textView"
app:layout_constraintLeft_toRightOf="@id/textView"
app:layout_constraintRight_toLeftOf="@id/textView"
app:layout_constraintBottom_toTopOf="@id/textView"



- 레이아웃 샘플코드
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#d1c4e9"
        android:gravity="center"
        android:text="Hello World!"
        android:textSize="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#d1c4e9"
        android:gravity="center"
        android:text="Android"
        android:layout_marginTop="8dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>








2. layout_constraintDimensionRatio
레이아웃을 16:9, 1:1, 4:3 형태로 배치, 화면비.

예) 16:9 배치
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"

가로가 match_parent 크기 일 때 세로는 0dp 크기, Ratio 값의 영향으로 16:9로 배치.
가로가 160dp라면 세로는 90dp로 배치된다.




주의1 : 가로 세로 크기가 모두 고정된 값으로 지정된 경우 ratio는 적용되지 않는다.
주의2 : 1번의 layout_constraint을 적용하지 않으면 경고창이 표시된다.

This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints less... (Ctrl+F1)
Inspection info:The layout editor allows you to place widgets anywhere on the canvas, and it records the current position with designtime attributes (such as layout_editor_absoluteX). These attributes are not applied at runtime, so if you push your layout on a device, the widgets may appear in a different location than shown in the editor. To fix this, make sure a widget has both horizontal and vertical constraints by dragging from the edge connections.  Issue id: MissingConstraints


- 레이아웃 샘플코드
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="160dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="16:9"
        android:background="#d1c4e9"
        android:gravity="center"
        android:text="Hello World!"
        android:textSize="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>





3. 레이아웃 예제




- XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/topImage"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#d1c4e9"
        android:gravity="center"
        android:text="16:9"
        app:autoSizeTextType="uniform"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/userPanel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/topImage">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/userImage"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:background="@android:color/holo_blue_dark"
            android:gravity="center"
            android:text="1:1"
            app:autoSizeTextType="uniform"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="vertical"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@id/userImage"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:padding="12dp"
                android:text="UserId, autoSizeText"
                android:textColor="@android:color/black"
                app:autoSizeTextType="uniform" />

            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:padding="8dp"
                android:text="UserName, autoSizeText"
                app:autoSizeTextType="uniform" />
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@android:color/holo_green_dark"
        android:gravity="center"
        android:text="Text Field"
        android:textSize="30dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/userPanel" />

</androidx.constraintlayout.widget.ConstraintLayout>

2019년 3월 2일 토요일

안드로이드 앱 퍼미션 가이드

1. 퍼미션 확인
- AndroidManifest.xml 파일 내용 확인
- 붉은색 부분이 필요한 권한.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="simple.app.selfpermission">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


레퍼런스 : https://developer.android.com/guide/topics/permissions/overview?hl=ko




2. 권한 요청
- 권한 확인 : ContextCompat.checkSelfPermission
- 권한 요청 : ActivityCompat.requestPermissions

public void checkSelfPermission() {
String temp = "";
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
temp += Manifest.permission.WRITE_EXTERNAL_STORAGE + " ";
}

if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
temp += Manifest.permission.READ_PHONE_STATE + " ";
}

if (TextUtils.isEmpty(temp) == false) {
// 권한 요청
ActivityCompat.requestPermissions(this, temp.trim().split(" "), REQUEST_CODE_PERMISSIONS);
} else {
// 모두 허용 상태
}
}



3. 권한 요청 응답 확인
- onRequestPermissionsResult 오버라이드

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
// 권한 처리
case REQUEST_CODE_PERMISSIONS: {
int length = permissions.length;
for (int i = 0; i < length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
// 동의
Log.d(TAG, "PERMISSION_GRANTED : " + permissions[i]);
}
}
return;
}
default:
return;
}
}




4. 샘플코드
소스코드
APK



 

안드로이드9 HTTP Error - ERR_CLEARTEXT_NOT_PERMITTED

- 안드로이드 Pie 버전 부터 http 제한이 있습니다.
안드로이드 Pie : https://www.android.com/versions/pie-9-0/


1. ERR_CLEARTEXT_NOT_PERMITTED 오류
























WebView에서 http://www.google.com 으로 접속을 시도 하면 ERR_CLEARTEXT_NOT_PERMITTED 오류가 발생합니다.







2. 간단한 ERR_CLEARTEXT_NOT_PERMITTED 수정 방법
- AndroidManifest.xml 파일 수정.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="simple.app.httperror">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:usesCleartextTraffic="true"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

- 결과
























http://www.google.com 으로 접속을 시도하면 정상적으로 표시됩니다.
android:usesCleartextTraffic="true" 라인을 추가해서 처리하는 방법은 추천하지 않습니다.
3번 내용을 확인하고 올바른 방법으로 대응하는 것을 권장합니다.








3. 자세한 내용
https://android-developers.googleblog.com/2018/04/protecting-users-with-tls-by-default-in.html
https://developer.android.com/about/versions/pie/android-9.0-changes-28?hl=ko




ipTime 공유기 DNS 차단 풀기


- MTU 설정을 수동입력으로 600으로 수정 한 뒤 인터넷 연결 확인.






















일반적인 MTU 값은 1500 입니다. 600으로 수정 한 뒤 차단된 사이트에 접속하시면
차단을 풀 수 있습니다.
주의 : 500 이하로 설정할 경우 인터넷 연결이 안될 수 있습니다.

그리고 DNS 주소를
1.1.1.1 이나 8.8.8.8을 사용 하는 것을 권장합니다.

MTU 설정이 낮을 경우 스트리밍 동영상을 시청할 때 끊김 현상이 발생할 수 있습니다.