Loading..
🡩

[Kotlin] [Android] Global Application Context

2018.12.14 00:27

[Kotlin] [Android] Global Application Context

안드로이드 프로그래밍을 하다 보면 object 등에서 Context를 사용해야 할 경우가 있습니다.

하지만 Context를 매개변수로 받아 구현하면, Android Studio에서 메모리 누수가 발생한다고 경고를 해줍니다.

해당 사항을 해결하기 위해 Application을 상속 받아, App Class를 만들어 사용하도록 구현했습니다.

사용할 object, class에서 App.instance.context()를 통해 Context를 가져올 수 있습니다.


카카오프렌즈 무선 충전 마우스 패드 리뷰

2018.11.30 21:00

주문했던 카카오프렌즈 무선 충전 마우스 패드가 도착했습니다!

기존 마우스 패드를 쓴지가 오래되기도 했고, 보통 휴대폰을 책상위에 올려두면 충전을 못하는 상황이 많아서 구매했습니다!

저는 개인적으로 어피치를 좋아해서 어피치 디자인으로 구매했습니다.

라이언은 품절이더라구요 ㅠㅠ

제품의 기본 구성은 이렇습니다.

뜯으면 마우스 패드가 위치해있고, 그 밑에는 Micro USB 케이블과 사용 설명서가 있습니다.

사실 남는 케이블이 없어 하나 구매해야하나 걱정했는데 함께 들어있어서 다행이였습니다.

마우스 패드의 크기는 이렇습니다.

왼쪽에 올란 패드는 제가 기존 사용하던 마우스 패드입니다.

딱 마우스 패드 + 평범한 휴대폰 크기의 사이즈입니다.

사용하고 있는데, 상당히 편리하고 마우스 패드의 질감도 좋아 오래 사용하게 될 것 같습니다.

 

1e100.net이 뭐하는 도메인인가요?

2018.11.26 00:51


서버 네트워크 모니터링을 하다보면 자주 보이는 도메인, 1e100.net 입니다.

사실 처음 이 도메인을 보면 우리가 평소 보던 도메인도 아니고, 접속되는 사이트도 아니라서 혹시 공격 당하는 건 아닌지 많은 의심이 듭니다.

하지만 걱정하지 않으셔도 됩니다!

이 도메인은 구글에서 서버를 식별하기 위해 사용하는 도메인입니다.

구글에서 업로드한 FAQ 글에 따르면 구글에서 서버를 식별하고, 크로스 도메인 공격을 방지하기 위해 2009년부터 사용해왔다고 하네요.

참고로 1e100 이라는 이름은 1 * 10 ^ 100 구골을 뜻하는 이름입니다.

앞에 붙은 nrt, syd, kix등의 코드는 공항에서 사용하는 IATA 코드인 것 같습니다.

나리타 (도쿄), 시드니, 간사이와 같이 해당 서버의 지역을 나타내고 있는 것 같습니다.

워낙 기록이 많이 떠서 놀랐는데, 그렇게 큰 문제는 아니였네요!

CentOS 7 환경에서 avconv 설치하기

2018.11.25 18:12

CentOS 7 환경에서 avconv 설치

안녕하세요, kentakang 입니다.

서버에서 avconv가 필요해서 해당 패키지를 설치하는 과정을 업로드 해보려고 합니다.

생각보다 어렵지 않습니다.

우선 yasm을 설치해주세요.

sudo yum install yasm

그 다음 libav 페이지에 들어가서 최신 버전을 받아주세요.

글을 쓰는 11월 25일 기준 12.3 버전입니다.

wget https://libav.org/releases/libav-12.3.tar.gz
tar zxvf libav-12.3.tar.gz
cd libav-12.3
./configure
sudo make
sudo make install

해주시면 설치가 끝납니다.

CLion 컴파일 환경으로 WSL (Windows Subsystem for Linux) 사용하기

2018.11.21 21:32

안녕하세요, kentakang 입니다.

저는 평소 컴파일러로 gcc를 사용하는데, 아무래도 MinGW를 사용하는 경우에는 그 한계가 많습니다.

그래서 CLion 설정을 뒤져보니, WSL 환경의 컴파일러를 가져다 사용할 수 있어서, 그렇게 프로그램을 컴파일 해보고 그 과정을 알려드리고자 글을 써봅니다.

우선 게시글을 보기 전 미리 설치해두셔야 할 것들입니다.

Requirements

WSL

CLion


우선 제 WSL 환경은 우분투여서, 우분투 기준으로 설명하겠습니다.

먼저 빌드에 필요한 패키지들을 설치해주세요.

sudo apt-get install cmake gcc clang gdb build-essential

그 다음, 아래 명령어를 실행시켜주시면 CLion과 연결을 위한 SSH 서버를 자동으로 설정합니다.

wget https://raw.githubusercontent.com/JetBrains/clion-wsl/master/ubuntu_setup_env.sh && bash ubuntu_setup_env.sh

해당 명령어로 설정하시면 기본 접속 포트가 2222번입니다.

한 번 접속 테스트 해보시고, 접속이 되신다면 CLion으로 넘어가겠습니다.

초기화면에서 Configure -> Settings -> Toolchains으로 가주세요.

그 다음 Toolchains을 하나 생성하겠습니다.

생성한 뒤, Environment 아래 체크박스에서 WSL을 선택해주시고,

Credentials 텍스트 박스의 디렉토리 아이콘을 눌러 아까 설정한 SSH 정보를 넣어주시면, 자동으로 컴파일러의 경로를 가져옵니다.

이대로 OK 버튼을 누르시면 설정이 끝납니다.

컴파일이 제대로 되는지 확인해보시고 사용하시면 됩니다.

블로그를 리뉴얼했습니다

2018.11.17 17:03

안녕하세요, kentakang 입니다.

이번 티스토리 업데이트에서 바뀐 점이 상당히 많아, 저도 블로그를 한 번 리뉴얼 해봤습니다.

블로그의 변경 사항들과 리뉴얼 하면서 느꼈던 것들을 적어보려 합니다.


디자인 변경

가장 큰 변경입니다.

블로그의 디자인을 전체적으로 변경했습니다.

사실 매번 스킨을 만들려고 다짐해도, 귀찮음 때문에 티스토리에서 제공하는 스킨을 사용했었는데,

이번에는 한 번 스킨을 직접 제작해봤습니다.

처음에는 기능 수정없이 순수 CSS로만 구현하려고 했는데, 디자인에 맞게 커스텀 하다 보니 사이트의 크기가 상당히 커졌네요.

메인 화면에는 무한 스크롤이 적용되어 있고, 카테고리 페이지와 검색 페이지도 자바스크립트를 통해 커스터마이징 했습니다.

이 부분은 추후 다른 글로 자세하게 다뤄보려고 합니다.


프로필 페이지 추가

프로필 페이지를 추가했습니다.

처음에는 티스토리의 페이지 기능을 사용해봤는데,

에디터에서 HTML 수정이 안되는 점 등등 많은 불편함이 있어, 자바스크립트를 통해 직접 구현했습니다.


카테고리 페이지 추가

카테고리 정리 페이지를 추가했습니다.

이 부분도 자바스크립트를 통해 구현했습니다.


SSL 적용

SSL 접속을 적용했습니다.

사실 이 부분은 티스토리가 SSL 지원을 시작했을때부터 적용해둔 잠수함 패치입니다.


댓글 시스템 변경

댓글에 utteranc.es를 적용했습니다.

댓글을 달 때는 Github 아이디가 필요하긴 한데,

블로그의 주제 상 대부분 Github 아이디가 있으실 거라고 판단해서, 적용했습니다.

utteranc.es 적용에 관련된 글도 나중에 자세히 작성해보도록 하겠습니다.


글을 마치며

11월 11일 부터 시작한 블로그 리뉴얼이 오늘 끝났습니다.

귀찮은 작업이긴 하지만, 하고 나니 뿌듯하네요.

읽어주셔서 감사드리고, 블로그에 방문해주셔서 감사합니다!

Python + Selenium을 통한 페이스북 동영상 다운로드

2018.11.05 01:05

Python + Selenium을 통한 페이스북 동영상 다운로드

안녕하세요, kentakang 입니다.

이번에 개인적인 용도로 페이스북 동영상을 다운로드 하는 프로그램을 만들었습니다.

제가 프로그램을 개발하면서 겪은 시행착오나, 여러가지 팁들을 공유하고자 게시글을 작성하게 되었습니다.

저는 Python을 통해 개발했고, 로그인 구현, 영상 다운로드를 위해 Selenium을 이용했습니다.

페이스북 동영상은 어떻게 다운받아요? (공개 동영상)

우선 공개 동영상을 다운로드 할 때 제가 이용한 방법을 적어보도록 하겠습니다.

우선 제가 다운로드 할 영상에 들어왔습니다.

여기서 소스 보기로 들어가시면 영상의 소스를 찾을 수 있습니다.

여기서 영상의 각 화질 별로 가져와야 할 주소가 달라집니다.

HD 지원 영상 : hd_src에서 HD 영상을 가져오거나, sd_src에서 SD 영상을 가져올 수 있습니다.

SD 지원 영상 : hd_src는 null입니다. sd_src에서 SD 영상을 가져올 수 있습니다.

이렇게 해서 src에 들어가 있는 주소를 빠짐없이 복사하면,

이렇게 원본 영상에 접근이 가능합니다.

저는 이렇게 영상을 다운 받는 로직을 아래 사진과 같이 작성했습니다.

# 영상 다운로드
def download(video_url):
driver.get(video_url)
page_source = driver.page_source
if check_isHD(page_source):
regex = "hd_src:\"[^\"\s()]+"
video_source = re.findall(regex, page_source)[0].replace('&', '&').replace('hd_src:"', '')
else:
regex = "sd_src:\"[^\"\s()]+"
video_source = re.findall(regex, page_source)[0].replace('&', '&').replace('sd_src:"', '')

urlretrieve(video_source, get_videoName(video_source))
print("다운로드 완료")

# HD 동영상인지 SD 동영상인지 확인
def check_isHD(page_source):
regex = "hd_src:[^\\s(),]+"
if re.findall(regex, page_source)[0] == 'hd_src:null':
return False
else:
return True

# URL에서 영상 파일 명 추출
def get_videoName(video_source):
regex = r"(\w+\.\w+)(?=\?|$)"
return re.findall(regex, video_source)[0]

여기까지 작성하면서 사용한 모듈은 Selenium, re, urllib.request.urlretrieve 입니다.

이렇게 하면 해당 디렉토리에 서버에 저장된 이름으로 비디오가 저장됩니다.

그럼 이제 비공개 그룹이나 친구 공개 동영상을 받아보도록 하겠습니다.

페이스북 동영상은 어떻게 받아요? (로그인이 필요한 영상)

사실 이 부분 때문에 Selenium을 사용한다고 봐도 될 정도입니다.

비공개 동영상의 경우 Selenium으로 접근하면

영상대신 이렇게 로그인 화면이 저를 반겨줍니다.

그래서 영상의 주소를 통해서 접근 했을 때, 이 영상이 비공개 영상인지 공개 영상인지 판단하는 로직이 필요합니다.

저는 판단의 기준을 2개로 잡았습니다.

우선 로그인 화면이 바로 뜨는 영상은 로그인 버튼이 있는지 찾고,

이렇게 그룹 메인 화면이 뜨는 비공개 그룹은, 그룹 가입 버튼을 찾도록 작성했습니다.

그리고 로그인을 했는지 확인하는 함수도 작성해줘야겠죠?

로그인을 했는지 확인하는 함수는

상단바에 있는 자신의 프로필로 가는 버튼을 찾도록 작성했습니다.

# 로그인 여부 확인
def check_login(video_url, login_driver):
try:
login_driver.find_element_by_class_name("_1k67")
except NoSuchElementException:
return False
return True

# 로그인이 필요한 영상인지 확인
def check_private(video_url):
try:
driver.find_element_by_class_name("login_page")
except NoSuchElementException:
if check_privategroup(video_url):
return True
return False
return True

# 비공개 그룹 여부 확인
def check_privategroup(video_url):
try:
driver.find_element_by_tag_name("video")
except NoSuchElementException:
regex = "joinButton_[0-9]+"
if bool(re.search(regex, driver.page_source)):
return True
return False

# 로그인이 필요한 영상 다운로드
def download_private(video_url):
print("로그인이 필요한 영상입니다.")
login_driver = webdriver.Chrome('chromedriver.exe')
login_driver.get(video_url)

while True:
if check_login(video_url, login_driver):
break
login_driver.get(video_url)
page_source = login_driver.page_source

if check_isHD(page_source):
regex = "hd_src:\"[^\"\s()]+"
video_source = re.findall(regex, page_source)[0].replace('&', '&').replace('hd_src:"', '')
else:
regex = "sd_src:\"[^\"\s()]+"
video_source = re.findall(regex, page_source)[0].replace('&', '&').replace('sd_src:"', '')

urlretrieve(video_source, get_videoName(video_source))
print("다운로드 완료")
login_driver.quit()


저는 이렇게 작성했습니다.

로그인 여부 확인 함수의 경우, 상단 프로필이 갖고 있는 클래스 네임 중 _1k67이 있어서 해당 클래스를 찾게 했습니다.

해당 Element가 존재하지 않을 경우, 로그인이 되지 않은걸로 판단 False를 리턴합니다.

비공개 영상 확인의 경우, 들어갔을때 로그인 페이지가 나오는지 확인하고

로그인 페이지가 나오지 않았더라도, joinButton_(임의 숫자)의 아이디를 가지고 있는 그룹 가입 버튼이 있는지 찾아

해당되는 경우 True를 리턴하도록 했습니다.

로그인은 유저가 직접 하도록 한 뒤 로그인 여부가 확인 될 경우 위에서 작성한 다운로드와 동일하게 다운로드를 진행합니다.


글을 마무리 하며

사실 처음에는, 어려운 작업이라 생각했는데 진행하다보니 그렇게 어려운 작업은 아니였습니다.

하지만 항상 크롤링 작업은 노가다입니다.

해당 페이지의 구조를 분석한 뒤, 모든 상황을 가정해보고 해당 상황에 맞게 프로그램을 작성해야합니다.

그렇게 해서 프로그램을 짜도, 페이지 구조가 바뀌면 갈아 엎어줘야 하구요.

크롤링, 파싱을 공부하기에는 난이도도 조금 있고 생각보다 재미있는 작업인 것 같습니다.

혹시 공부를 위해 소스가 필요하실 경우를 대비해 소스를 깃허브에 올려두셨으니,

소스를 확인하시려면 아래 Github를 확인하시고, 항상 궁금한 점은 댓글로 질문해주세요!

글 읽어주셔서 감사합니다.


facebook_video_downloader Github

React Native에서 블루투스 사용하기

2018.10.10 01:38

React Native에서 블루투스 사용하기


사실 React Native는 디바이스를 제어하는 기능을 하기에 효율적인 솔루션은 아닙니다.

기기의 디바이스적인 부분을 건드릴 때는 네이티브 코드로 작성하시는 것이 훨씬 간단하지만,

사정상 React Native를 통해 모두 구현하게 되어, React Native에서 블루투스를 사용하는 과정을 정리해 블로그에 올려봅니다.

우선 라이브러리가 필요합니다.

제가 사용할 라이브러리는 react-native-bluetooth-serial 라는 라이브러리 입니다.

NPM 또는 Yarn을 통해 설치 후, React-Native CLI를 통해 링크해주세요.

저는 Yarn을 이용해 설치하겠습니다.

yarn add react-native-bluetooth-serial
react-native link react-native-bluetooth-serial

그 다음, AndroidManifest.xml에 블루투스 관련 퍼미션을 추가해주세요.

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

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

...

</manifest>


이렇게 설치는 끝났습니다.

그 다음 안드로이드의 경우 사용 전 필요한 작업이 있습니다.

react-native-bluetooth-serial의 java -> RCTBluetoothSerialPackage 클래스에서

23번째 라인의 메소드를 아래와 같이 변경해주세요.

public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}

이렇게 해주시면 사용 가능합니다.

API의 기능은 위 깃에서 확인해주세요.