쉘스크립트 수 비교하기

프로그래밍/BASH SHELL|2021. 6. 10. 11:34
반응형

기본 예제

#!/bin/bash

Boy="160"
Girl="158"

if [ "${Boy}" -gt "${Girl}" ]; then
        echo "소년이 더 큽니다. "
elif [ "${Boy}" -lt "${Girl}" ]; then
        echo "소녀가 더 큽니다. "
else

        echo "소년과 소녀가 같습니다."
fi

 

비교 연산자

A -lt B : A가 B보다 작습니다.
-le : 작거나 같습니다.

-gt : 큽니다.
-ge : 크거나 같습니다.
-eq : 같습니다.
-ne : 다릅니다.

 

반응형

댓글()

안드로이드 비정상 종료 감지 처리 (어플 재시작)

프로그래밍/ANDROID|2021. 6. 8. 10:18
반응형

아래 내용을 소스에 추가합니다.

(MainActivity 에서 감지시 초기 화면 SplashActivity 로 이동)

 

 

첫번재 방법

 

        // 비정상 종료시 어플 재시작
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
            Intent crashedIntent = new Intent(MainActivity.thisSplashActivity.class);

                Toast.makeText(MainActivity.this, "비정상 종료 되어 재시작 합니다.", Toast.LENGTH_SHORT).show();

                //crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(crashedIntent);
                System.exit(0);
            }
        });

 

 

두번째 방법

 

링크 참조

https://ssaurel.medium.com/how-to-auto-restart-an-android-application-after-a-crash-or-a-force-close-error-1a361677c0ce

 

반응형

댓글()

안드로이드 와이파이 SSID 가져오기

프로그래밍/ANDROID|2021. 6. 2. 08:52
반응형

Android 8 에서 동작하던 SSID 가져오기가 Android 11 에서 안되는 현상이 확인되었습니다.

구글링 해보니 runtime permission 적용하면 된다고 하여 아래소스를 찾아 적용하였습니다.

(기능 사용시 권한 부여)

 


public String SSID = null;


tryToReadSSID(); // 호출하여 아래 내용 실행


    // SSID 가져오기
    private void tryToReadSSID() {
        // If requested permission isn't Granted yet
        if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // Request permission from user
            ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 101);
        } else { // Permission already granted
            WifiManager wifiManager = (WifiManager) getActivity().getApplicationContext().getSystemService(WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            if(wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
                SSID = wifiInfo.getSSID().replaceAll("\"", ""); // SSID 앞뒤에 있는 따옴표 제거하고 SSID 변수에 입력
            }
        }
    }
 

 

반응형

댓글()

TextView 레이아웃 사이즈에 맞게 글자 크기 자동 조정하기

프로그래밍/ANDROID|2021. 6. 2. 07:58
반응형

레이아웃에서 아래와 같이 설정시

기본폰트 18sp 지만, 글자가 많아 레이아웃을 벗어날 경우 2sp 단위로 12sp 까지 줄일 수 있습니다.

 

<TextView
                android:id="@+id/tv_private"
                android:layout_width="0dp"
                android:layout_height="30dp"
                android:layout_weight="4"
                android:layout_marginLeft="20dp"
                android:text="0.0.0.0"
                android:textColor="@color/white"
                android:textSize="18sp" // 기본 크기
                android:textStyle="bold"
                android:gravity="center_vertical"

                android:autoSizeTextType="uniform"
                android:autoSizeMinTextSize="12sp" // 최소 크기
                android:autoSizeMaxTextSize="18sp" // 최대 크기
                android:autoSizeStepGranularity="2sp" /> // 조정 간격

 

반응형

댓글()

안드로이드에서 모바일 네트워크 구분하기 (2G, 3G, 4G, 5G)

프로그래밍/ANDROID|2021. 6. 2. 07:50
반응형

example.java

package com.example.mymobilenetworktype;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.TextView;

import static android.telephony.TelephonyManager.NETWORK_TYPE_1xRTT;
import static android.telephony.TelephonyManager.NETWORK_TYPE_CDMA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EVDO_0;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EVDO_A;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EVDO_B;
import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPAP;
import static android.telephony.TelephonyManager.NETWORK_TYPE_IDEN;
import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private TelephonyManager telephonyManager;

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

        textView = findViewById(R.id.textView);
        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_PHONE_STATE}, PackageManager.PERMISSION_GRANTED);
        telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }

        switch (telephonyManager.getDataNetworkType()) {
            case NETWORK_TYPE_EDGE:
            case NETWORK_TYPE_GPRS:
            case NETWORK_TYPE_CDMA:
            case NETWORK_TYPE_IDEN:
            case NETWORK_TYPE_1xRTT:
                textView.setText("2G");
                break;
            case NETWORK_TYPE_UMTS:
            case NETWORK_TYPE_HSDPA:
            case NETWORK_TYPE_HSPA:
            case NETWORK_TYPE_HSPAP:
            case NETWORK_TYPE_EVDO_0:
            case NETWORK_TYPE_EVDO_A:
            case NETWORK_TYPE_EVDO_B:
                textView.setText("3G");
                break;
            case NETWORK_TYPE_LTE:
                textView.setText("4G");
                break;
            case NETWORK_TYPE_NR:
                textView.setText("5G");
                break;
            default:
                textView.setText("Unknown");
        }
    }
}

 

[출처] https://programmerworld.co/android/how-to-detect-the-mobile-network-type-2g-3g-4g-5g-from-your-android-app-android-studio-complete-source-code/

반응형

댓글()

Ubuntu 18.04 에서 Android Studio 및 AVD 설치하기

프로그래밍/ANDROID|2021. 5. 21. 11:18
반응형

Ubuntu 18.04 에서 안드로이드 개발 환경 Android Studio 를 설치하고, AVD 를 이용하여 여러 단말기의 사이즈, OS 종류에서 테스트 할 수 있습니다.

 

1. 설치

# add-apt-repository ppa:maarten-fonville/android-studio

# apt -y update

# apt -y install android-studio

 

2. 실행

# /opt/android-studio/bin/studio.sh

설치 마법사에서 Next 이나 Custom 을 누르면 되고, 설치과정중 AVD 를 선택 후 Finish 를 눌러 설치를 진행합니다.

설치가 완료되어 Android Studio 가 실행되면 기본 프로젝트를 생성하거나 기존 프로젝트를 불러와 사용이 가능합니다.

 

3. AVD 사용

메뉴 Tools > AVD Manager 를 실행합니다.

하단의 [+Create Virtual Device] 버튼을 누르고 원하는 단말기 사이즈와 OS 버전을 선택 후 생성한 뒤,

우측의 아래 화살표 (▼) 를 눌러 Cold Boot Now 를 눌러 단말기 전원을 켜면 가동됩니다.

부팅이 완료되기 까지 시간이 조금 소요됩니다.

 

 

반응형

댓글()

C++ 프로그램 중복 실행 방지 (윈도우 기반)

프로그래밍/C, C++|2021. 5. 18. 13:16
반응형

HANDLE Mutex;
const char ProgMutex[] = "Sysdocu"; // 프로젝트명
if ((Mutex = OpenMutex(MUTEX_ALL_ACCESS, false, ProgMutex)) == NULL)
    Mutex = CreateMutex(NULL, true, ProgMutex);
else {
    MessageBox(NULL, "이미 실행중입니다.", "알림", MB_OK);
    return 0;
}

 

 

반응형

댓글()

PHP 와 JWT (JSON Web Tokens)를 이용한 예제

프로그래밍/PHP|2021. 5. 17. 16:04
반응형

해당 예제는 CentOS 7 또는 8 에서 사용이 가능합니다.

관련 패키지와 환경 설정을 진행합니다.

 

1. Composer 설치

 

# yum -y update

# yum -y install php-cli php-zip wget unzip

# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

# HASH="$(wget -q -O - https://composer.github.io/installer.sig)" 

# php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

 

# php composer-setup.php --install-dir=/usr/local/bin --filename=composer

 

여기에서 아래와 같은 에러 메세지가 출력될 경우 패키지를 추가로 설치하고 진행하면 됩니다.

php 를 소스 컴파일 하신 경우 해당 옵션 (--disable-json) 을 제거하고 재컴파일 해야 합니다.

 

(에러)

Some settings on your machine make Composer unable to work properly.
Make sure that you fix the issues listed below and run this script again:

The json extension is missing.
Install it or recompile php without --disable-json

 

(해결)
# yum install php-json

 

composer 가 잘 설치되었는지 명령어로 확인해봅니다.

사용할 수 있는 옵션이 출력 될경우 정상 설치된 것입니다.

 

# composer

 

확인이 되었으면 설치 프로그램을 삭제 합니다.

 

# php -r "unlink('composer-setup.php');"

 

 

2. PHP-JWT 설치

 

composer require firebase/php-jwt

 

 

3. 테스트

 

# vi first.php

<?php
require_once './vendor/autoload.php';
use Firebase\JWT\JWT;
$secret_key = "this-is-the-secret";

// 데이터 입력
$id = "sysdocu";
$email = "sysdocu@sysdocu.tistory.com";
$addr = "seoul";
$phone = "010-1111-2222";
 
$data = array(
    'id' => $id,
    'email' => $email,
    'addr' => $addr,
    'phone' => $phone
);
 
$jwt = JWT::encode($data, $secret_key);
echo "encoded jwt: " . $jwt . "<br>";
 
//$decoded = JWT::decode($jwt, $secret_key, array('HS256'));
//print_r($decoded);
?>


생성한 php 파일을 웹브라우저로 불러오면 출력되는 결과는 아래와 같습니다.

encoded jwt 값을 자세히 보시면 hearderpayloadsignature 값 모두 출력되는 것을 볼 수 있습니다. (점으로 구분) 

 

encoded jwt: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5c2RvY3UiLCJlbWFpbCI6InN5c2RvY3VAc3lzZG9jdS50aXN0b3J5LmNvbSIsImFkZHIiOiJzZW91bCIsInBob25lIjoiMDEwLTExMTEtMjIyMiJ9.xmYK1C0pnguCpC8qFUaJYYoLNnhkQ6kGiBxba_aM1gc

 

내용을 받을 php 를 만듭니다.

 

# vi second.php

 

<?php
require_once './vendor/autoload.php';
use Firebase\JWT\JWT;
$secret_key = "this-is-the-secret";

// URL 에서 jwt 인자값을 가져온다.
$jwt = isset($_GET['jwt']) ? $_GET['jwt'] : null;
if (isset($jwt)) {

    // validate jwt 로그인된 상태 
    try {
        $decoded = JWT::decode($jwt, $secret_key, array('HS256'));
        $decoded_array = (array)$decoded;
        $result = array(
            'code' => 200,
            'status' => 'success',
            'jwt_payload' => $decoded_array
        );
    } catch (\Exception $e) {
        $result = array(
            'code' => 0,
            'status' => 'error',
            'message' => $e->getMessage().' Invalid JWT - Authentication failed!'
        );
    }

} else {
    $result = array(
        'code' => 0,
        'status' => 'error',
        'message' => 'JWT parameter missing!'
    );
}
echo json_encode($result);
?>

 

그리고 브라우저에서 first.php 의 결과 코드를 활용해 second.php 로 접속해 봅니다.

 

http://{도메인}/second.php?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6InN5c2RvY3UiLCJlbWFpbCI6InN5c2RvY3VAc3lzZG9jdS50aXN0b3J5LmNvbSIsImFkZHIiOiJzZW91bCIsInBob25lIjoiMDEwLTExMTEtMjIyMiJ9.xmYK1C0pnguCpC8qFUaJYYoLNnhkQ6kGiBxba_aM1gc

 

 

[결과]

{"code":200,"status":"success","jwt_payload":{"id":"sysdocu","email":"sysdocu@sysdocu.tistory.com","addr":"seoul","phone":"010-1111-2222"}}

 

 

데이터가 잘 확인되었습니다.

필요에 따라 이 샘플 코드를 이용해 세션 파일을 만드는 등 추가 작업을 진행하면 됩니다.

 

 

상세 설명은 아래 URL 에서 확인 가능합니다.

[출처1 - 환경 설치 부분] https://phoenixnap.com/kb/how-to-install-and-use-php-composer-on-centos-7

[출처2 - 테스트 부분] https://trytoso.tistory.com/1024

https://heartgamer.wordpress.com/2015/08/26/json-web-tokenjwt%EB%A5%BC-node-js%EC%99%80-php%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0/

 

 

 

반응형

댓글()

C++ 에서 구동 파일의 절대 경로 확인하기 (windows)

프로그래밍/C, C++|2021. 5. 17. 14:29
반응형

1. 구동 파일 절대 경로 출력 (파일)

 

char cCurrentPath[FILENAME_MAX];
GetModuleFileName(NULL, cCurrentPath, MAX_PATH);
cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';
printf("The current working file is %s\n", cCurrentPath);

 

 

2. 구동 파일 절대 경로 출력 (디렉토리)

- 위 소스에서 코드 한줄만 더 추가하면 파일명이 제외된 디렉토리만 출력됩니다.

PathRemoveFileSpec(cCurrentPath);

printf("The current working directory is %s\n", cCurrentPath);

 

반응형

댓글()

(에러) 인수 1을(를) 'ATL::CString'에서 'const char *'(으)로 변환할 수 없습니다.

프로그래밍/C, C++|2021. 5. 14. 14:15
반응형

코드나 환경에 따라 아래와 같은 에러가 출력될 수 있습니다.

저는 디렉토리 이동 함수를 사용할때 메세지가 출력 되었습니다.

 

(에러)

'int _chdir(const char *)': 인수 1을(를) 'ATL::CString'에서 'const char *'(으)로 변환할 수 없습니다.

 

(해결)

이경우 아래와 같이 해주세요.

_chdir((char*)(LPCTSTR)strFolderPath);

 

 

반응형

댓글()

Windows C++ 로 시스템 DISK 사용률 출력하기

프로그래밍/C, C++|2021. 4. 22. 09:33
반응형

BOOL  fResult;

unsigned __int64 i64FreeBytesToCaller,

    i64TotalBytes,

    i64FreeBytes;

fResult = GetDiskFreeSpaceEx(L"C:",

    (PULARGE_INTEGER)&i64FreeBytesToCaller,

    (PULARGE_INTEGER)&i64TotalBytes,

    (PULARGE_INTEGER)&i64FreeBytes);

if (fResult)

{

    printf("Available space to caller = %I64u MB\n",

        i64FreeBytesToCaller / (1024 * 1024));

    printf("Total space               = %I64u MB\n",

        i64TotalBytes / (1024 * 1024));

    printf("Free space on drive       = %I64u MB\n",

        i64FreeBytes / (1024 * 1024));

}

 

[출처] https://stackoverflow.com/questions/11917946/how-do-i-get-available-disk-space-from-windows-using-c

반응형

댓글()