본문으로 바로가기
728x90
반응형

목차

     

    개요 

    지난번 글에서 Google API 없이 Youtube 데이터를 수집했던 에피소드를 포스팅했다. Google API 없이 Youtube Page를 분석해 자주 듣는 유투버의 커버 영상을 MP3 파일로 변환하여 다운로드하는 것이 주된 내용이었다.

     

    그러나 MP3 파일로 변환하여 다운로드하는 것까지는 자동화가 가능했지만 다운로드를 완료한 파일을 Android에 옮기는 부분을 자동화하지 못했다는 점이 아쉬웠던 부분으로써 언급했다.

     

    이 부분을 해결하려고 생각했던 Idea는 Python Kivy를 활용하는 것이었는데 이 포스팅을 쓰기 전 잠깐 다뤄보니 build를 통해 apk파일을 뽑아내는데 까지 시간이 너무 오래 걸려 다른 아이디어를 고민해 봤고 이 포스팅은 이에 대한 내용을 기록해보려고 한다.

     

    다운로드한 파일을 어떻게 옮길 수 있을까?

    통상적으로 개인 휴대폰으로 파일을 옮기는 방법으로는 다음 두 가지를 떠올렸다.

     

    1. 휴대폰과 USB 연결을 통해 다운로드하는 방법

    • 이는 지극히 통상적인 방법이다. 휴대폰과 PC를 케이블로 연결하여 직접 파일을 옮기는 것이다.

    2. 네트워크를 통해 다운로드하는 방법

    • 만약 개인 클라우드를 사용하고 있다면 개인 파일을 클라우드에 저장한 뒤 휴대폰에서 클라우드에 접속해 다운로드하는 방법이다.
    • 이외에도 FTP, HTTP와 같은 방법들?

    사실 최초의 목적은 파일이 다운로드가 완료되면 개인 클라우드와 연동해 자동으로 업로드가 되고 휴대폰에서 연결된 클라우드가 이를 감지해 동기화시키는 방법이었다. 이 방법은 배보다 배꼽이 더 클 것 같은 느낌이 들어 고려하지 않았다.

     

    즉 2번 방법은 고려의 대상이 아니며 조금은 불편하더라도 1번 방법을 고려했다. 여기서 불편한 점이라 하면 PC와 휴대폰을 케이블로 연결시키는 행위를 의미한다. 하지만 이 딱 이 정도 행위만 하고 특정 스크립트를 실행시키면 PC에 존재하는 File이 개인 휴대폰으로 옮겨주는 기능을 구현한다면 어느 정도 괜찮은 모양새인 듯싶다.

     

    휴대폰과 PC를 케이블로 연결하면 어떤 방법으로 전송이 가능한가?

    이 기능을 구현해 보기 위해 제일 처음 생각났던 건 adb이다.

     

    android debuger bridge라고도 불리는 이 도구는 안드로이드 개발 시 유용하게 쓰이는 도구이지만 기각이다. 휴대폰에서 “설정 > 휴대전화 정보 > 소프트웨어 정보 > 빌드번호”를 여러 번 터치해 “개발자 모드”를 활성화시켜야 하기 때문이다.

     

    나 스스로 이러한 과정을 통해 휴대폰으로 파일을 옮기는 것은 별 문제가 없지만 조금 더 일반적인 사용성에 목적을 두고 싶었다. 그렇게 추가적으로 조사를 하던 끝에 Mobile Transfer Protocol이라는 MTP 방식이 있단 걸 알게 되었다.

     

    MTP 사용하기

    Mac에서 테스트했기에 WIndows에서도 똑같은 과정이 일어나는지 확인은 못했지만 휴대폰을 PC에 연결하면 MTP 허용 여부에 대해 묻는다. 이는 다음과 같은 UI를 통해 일어난다.

     

    MTP는 WIndows Media Player에 내장된 기능 중 하나였지만 특정 안드로이드 버전(아이스크림 샌드위치)에서부터 알려지게 된 기능이라고 한다. MTP에 대한 여러 설명과 그에 대한 이해보다는 휴대폰에서 Android로 파일을 전송하기 위한 수단 중 하나라고 이해하자.

     

    필자는 Python을 자주 이용하기 때문에 Python에 MTP를 이용이 가능한지 조사했다.

     

    Python으로 MTP 사용하기

    PyPI에 검색해 보니 Python으로 MTP를 사용할 수 있게 개발된 라이브러리가 있었다.

     

    그러나 이 라이브러리를 사용하기 전 필요한 것이 있었는데 libmtp이다. libmtp는 MTP를 이용할 수 있게 만들어진 일종의 인터페이스와 같은 역할을 한다. PyMTP는 이를 python을 통해 다룰 수 있게 만들어진 라이브러리다.

     

    libmtp와 환경변수 설정

    Mac의 사용하고 있는 관계로 다음과 같이 libmtp가 설치가 가능했다.

    $ brew install libmtp
    

    hombrew로 설치해서 그런지 설치 경로가 다음과 같다.

    /System/Volumes/Data/opt/homebrew/Cellar/libmtp
    

    pymtp가 제대로 동작하려면 “libmtp.dylib”가 환경변수에 설정되어있어야 한다. libmtp.dylib는 다음의 경로에 존재한다.

    ╭─jako@prompt-pro /System/Volumes/Data/opt/homebrew/Cellar/libmtp/1.1.21/lib
    ╰─$ ls
    libmtp.9.dylib libmtp.a       libmtp.dylib   pkgconfig
    

    이제 환경변수에 다음과 같은 내용을 추가하자.

    export LIB_MTP=/System/Volumes/Data/opt/homebrew/Cellar/libmtp/1.1.21/lib
    export DYLD_LIBRARY_PATH=$LIB_MTP:$DYLD_LIBRARY_PATH
    

    PyMTP와 간단한 예제

    링크를 건 PyMTP PYPI를 보면 알겠지만 PyMTP는 다음과 같이 설치가 가능하다.

    pip install pymtp
    

    pymtp에 대한 간단한 예제 코드는 다음과 같다.

    from pymtp import MTP
    
    mtp = MTP()
    mtp.connect()
    
    device_name = mtp.get_devicename()
    print(device_name)
    
    mtp.disconnect()
    
    # OutPut
    b'\\xec\\xa7...\\xec\\x9d\\x98 S23'
    

    개인 휴대폰과 PC를 USB 케이블로 연결시킨 후 위 코드를 동작하면 휴대폰의 device name이 출력된다.

     

    PyMTP에 관련한 issue들

    pymtp를 계속 건드려보다가 특이사항을 알게 됐다. 이를 정리하면 다음과 같다.

    1. pymtp는 python2.x 버전을 기준으로 동작한다.
    2. pymtp를 통해 file을 전송하지 못한다.

     

    pymtp는 python2.x 버전을 기준으로 동작한다.

    이 이슈는 pymtp를 통해 휴대폰의 폴더 목록을 리스팅 하는 함수를 사용하다 알게 된 사실이다. pymtp에서는 get_folder_list를 통해 휴대폰에 존재하는 folder를 확인할 수 있는데 내부 구현을 살펴보면 다음과 같이 되어있다.

     

    어려운 문법은 아니지만 python3.x를 사용하고 있는 경우 라이브러리를 다음과 같이 변경하면 동작이 가능하다.

    if next.folder_id not in ret
    

    그러나 이와 같은 문법을 사용하는 부분은 get_folder_list 이외에도 더 존재한다.

     

    PyMTP를 통해 file을 전송하지 못한다.

    PyMTP를 사용한 예제들이 지극히 부족해 이 특이사항은 검증이 어렵다. 필자가 이 기능을 제대로 이용하지 못하는 것일 수도 있지만 파일 전송에 실패한 경우 -1이 리턴되며 어떤 이유로 실패되었는지 추적하기 어렵다 관련 함수는 다음과 같다.

     

    Python으로 Android에 어떻게 파일을 전송할 것인가?

    여러 차례 삽집을 시도했지만 PyMTP만으로 Android에 File을 전송하는 것은 무리라고 판단할 때쯤 “mtp-connect”라는 binary를 알게 되었다. 이는 homebrew를 통해 “libmtp”를 설치할 때 같이 설치된 binary이다.

     

    mtp-connect를 실행시키면 다음과 같은 옵션들이 나온다.

    ╭─jako@prompt-pro /System/Volumes/Data/opt/homebrew/Cellar/libmtp/1.1.21/lib ‹stable›
    ╰─$ mtp-connect                                                                                                                                   127 ↵
    libmtp version: 1.1.20
    
    Device 0 (VID=04e8 and PID=6860) is a Samsung Galaxy models (MTP).
    Usage: connect <command1> <command2>
    Commands: --delete [filename]
              --sendfile [source] [destination]
              --sendtrack [source] [destination]
              --getfile [source] [destination]
              --newfolder [foldername]
    

    mtp-connect의 “—sendfile” 옵션을 이용해 테스트해 본 결과 이 binary만으로 file 전송이 가능한 것을 확인했다. binary 자체를 이용하는 방법은 께름칙하지만 “Python으로 Android에 파일 전송하기”라는 목표만을 바라본다면 남은 선택지가 별로 없었기에 다음과 같이 subprocess를 이용하는 방식으로 Python을 이용해 Android에 파일을 전송할 수 있었다.

    import subprocess
    
    binary_path = "/System/Volumes/Data/opt/homebrew/Cellar/libmtp/1.1.21/bin/"
    mtp_connector = "mtp-connect"
    
    options = ['--sendfile', './test.text', "/DCIM"]
    
    subprocess.run([binary_path + mtp_connector] + options)
    

     

    마치며

    목표는 “Python으로 Android에 file 전송하기”였다. 이러한 목표를 PyMTP가 채워주진 못했지만 본문에서 소개한 이슈를 어느 정도 감안한다면 PyMTP를 통해 device의 정보를 분석하는 용도에서는 잘 만들어진 라이브러리라 생각된다.

     

    device의 정보를 읽어 들이는 것만을 전제로 상황이 얼마나 있을까 모르겠지만 일단은 뭔가 하나를 더 알게 되었다는 것에 만족하자.

     

     

     

    728x90
    반응형