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

반응형

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

기본폰트 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)

반응형

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/

반응형

댓글()

[에러] (43)Identifier removed: AH00144: couldn't grab the accept mutex

리눅스/APACHE|2021. 5. 24. 15:33
반응형

Apache 2.4.29 에서 mod_ssl 을 설정 후 아래와 같이 로그가 기록되며 apache2 데몬이 종료되는 현상이 발생되었습니다.

[Mon May 24 12:15:45.179136 2021] [mpm_prefork:emerg] [pid 21881] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179332 2021] [mpm_prefork:emerg] [pid 21539] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179353 2021] [mpm_prefork:emerg] [pid 21555] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179370 2021] [mpm_prefork:emerg] [pid 21534] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179394 2021] [mpm_prefork:emerg] [pid 21541] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179390 2021] [mpm_prefork:emerg] [pid 21537] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179414 2021] [mpm_prefork:emerg] [pid 22564] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.179437 2021] [mpm_prefork:emerg] [pid 21556] (43)Identifier removed: AH00144: couldn't grab the accept mutex
[Mon May 24 12:15:45.196963 2021] [core:alert] [pid 1325] AH00050: Child 21534 returned a Fatal error... Apache is exiting!
[Mon May 24 12:15:45.197000 2021] [:emerg] [pid 1325] AH02818: MPM run failed, exiting

 

이를 해결하기 위해 설정파일의 옵션을 아래의 값으로 활성화 해주면 됩니다.

/etc/apache2/apache2.conf

Mutex posixsem

 

아파치를 재시작하여 적용합니다.

# systemctl restart apache2

 

 

반응형

댓글()

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

프로그래밍/Android (Java)|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);

 

 

반응형

댓글()

WIFI ESP8266(ESP-01) + DHT11 을 이용해 온습도 측정하기 (DHT22 소스 추가)

관리자 자료실|2021. 5. 3. 14:34
반응형

ESP-01 과 DHT11 을 이용해 온도와 습도를 측정하고 데이터를 특정 서버로 전송하기 위한 방법 입니다.

제 PC 환경인 Ubuntu 18.04 에서 진행하였습니다.

 

[준비물]

USB serial adapter * 1개 (추후 납땜 필요, 아래 설명)

ESP-01 * 1개

DHT11 * 1개

 

 

1. 설치

 

# wget https://downloads.arduino.cc/arduino-1.8.12-linux64.tar.xz

# tar xvf arduino-1.8.12-linux64.tar.xz

# cd arduino-1.8.12

# ./install.sh

 

 

2. 실행

 

# arduino

 

* 한글이 깨져 보이는 경우 아래와 같이 영문으로 변경 가능합니다.
첫번째 메뉴 (File) > 아래에서 두번째 '환경설정' (Ctrl + Comma) > 두번째 항목인 'Editor language:' 를 'English(English)' 로 선택 후 아두이노를 재시작 하면 됩니다.

 

3. 환경 설정

 

File > Preferences 메뉴에서
Additional Boards Manager URLs: 에 아래 주소를 입력하고 [OK] 버튼을 누릅니다.

http://arduino.esp8266.com/stable/package_esp8266com_index.json

 

Tools > Board > Board Manager 메뉴에서 'ESP8266' 를 검색하고 설치합니다.

Tools > Board 에서 'Generic ESP8266 Module' 을 찾아 선택합니다.


Tools > Manage Libraries 를 실행하면 Library Manager 창이 뜹니다.
DHT sensor library 를 찾아 검색하면 Adafruit Unified Sensor 도 같이 설치하겠냐고 물어봅니다.
[Install all] 버튼을 눌러 모두 설치합니다.

 

 

4. 납땜

 

USB 시리얼 아답터 뒷면에 (DHT11 연결 부위) GND 와 IO0 (GPIO0) 부분을 전선으로 이어줍니다. (납땜 필요)
이렇게 해야 USB serial adapter 를 통해 펌웨어 쓰기가 가능해집니다.
* 동영상 참고

https://www.youtube.com/watch?v=QRnPRKbtEGU

 

준비 되었으면 ESP-01 을 연결 한 후 PC의 USB 포트에 꼽습니다.

 

5. 소스 다운로드 및 컴파일

 

펌웨어는 아래 URL 에서 가져옵니다. (asksensors.com 으로 데이터 전송)

https://github.com/asksensors/AskSensors-ESP8266-DHT/blob/master/dht11_https_get.ino

 

위 예제 파일 내용을 약간 수정하였습니다.

arduino_esp01_dht11.ino
0.00MB

 

소스 내에 ESP-01 이 접속할 wifi 접속 정보를 (ssid, password) 입력합니다.

변수 https_host, https_port, writeInterval, url 변수 등 수정할 곳을 수정합니다.

 

Tools > Board > Generic ESP8266 Module 를 선택합니다.

Tools > Ports 에서 /dev/ttyUSB0 을 선택합니다. (USB serial adapter 를 꼽으면 확인 가능)

업로드 버튼을 누릅니다. 상단 큰 아이콘 중에 하나 (두번째에 있음)

아두이노 하단부에 컴파일 로그중 아래 메세지가 뜨면 업로드 완료된 것입니다. 분리해도 됩니다.
Leaving...
Hard resetting via RTS pin...

* 펌웨어 업로드를 할 모듈이 여러개일 경우 USB 를 꼽은채로 여러번 되지 않으므로
한개 업로드 후 USB 를 뺐다 꼽고, 업로드 하고.. 반복하면 됩니다.

 

 

* 참고1

온습도 데이터 수집할때 만들었던 DB 테이블입니다.

 

mysql> create table records (id int(10) auto_increment primary key, rack int (5), temperature DECIMAL(5,2), humidity DECIMAL(5,2), time DATETIME);

+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int          | NO   | PRI | NULL    | auto_increment |
| rack        | int          | YES  |     | NULL    |                |
| temperature | decimal(5,2) | YES  |     | NULL    |                |
| humidity    | decimal(5,2) | YES  |     | NULL    |                |
| time        | datetime     | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

 

 

* 참고2

웹서버 라이브러리 및 소스

https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/

 

 

* 참고3

ESP8266 장치의 Mac Address 를 가져오고 싶을 경우 아래 소스코드를 참고 합니다. (출처 소스에서 Mac Address 마지막 : 문자 제거 코드 보완)

#include <ESP8266WiFi.h>
 
uint8_t MAC_array[6];
char MAC_char[18];
 
void setup() {
    Serial.begin(115200);
    Serial.println();
 
    WiFi.macAddress(MAC_array);
    for (int i = 0; i < sizeof(MAC_array); ++i){
      sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
    }
    int j = 0;
    while (MAC_char[j]) {
        j++;
    }
    MAC_char[j - 1] = '\0';

    Serial.println(MAC_char);
}
 
void loop() {
    // 여기에서 MAC_char 를 가져다 사용하면 됩니다.
    // 위 내용을 복사할 경우 arduino 에서 오류가 납니다.
    // 복사할때 공백이 제대로 복사되지 않아서인데, 직접 타이핑 하시거나 공백만 지우고 새로 입력하면 됩니다.
}

[출처] https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ssshin22&logNo=220883794542 

 

 

* 참고4

DHT22 소스 입니다.

arduino_esp01_dht22.ino
0.00MB

바로 위 첨부된 소스에 softAP 를 숨기는 코드를 넣었는데, 여러개의 온습도를 사용할 경우에는 혹시 모를 문제에 대비하기 위해 softAP 명칭을 다르게 줍니다. 아래 내용을 참고하세요.

 

const int pos = 170;
const char* charpos = pos+"0";

(생략)

WiFi.softAP(charpos, "ThisIsHiddenAp", 1, 1);

 

반응형

댓글()

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

반응형

댓글()

Windows C++ 로 시스템 메모리(MEM) 사용률 출력하기

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

 

MEMORYSTATUSEX memInfo;

memInfo.dwLength = sizeof(MEMORYSTATUSEX);

GlobalMemoryStatusEx(&memInfo);

DWORDLONG totalPhysMem = memInfo.ullTotalPhys; // 전체 메모리

DWORDLONG availPhysMem = memInfo.ullAvailPhys; // 남은 메모리

printf("MEM : %I64u %I64u\n", totalPhysMem / 1024, availPhysMem / 1024); // KB 로 출력

 

[참고] https://ospace.tistory.com/514

반응형

댓글()