성태의 닷넷 이야기
작은 글씨
큰 글씨
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 한국어 로컬 모델 풀 파인튜닝 - LLM 바닥부터 만들기 (대형...
[정성태] 그러고 보니, 저도 노안이라서... 어느 순간부터 웹 브라우저 ...
[정성태] The case of the invalid handle erro...
[정성태] 해당 글을 잠시 읽어보니까, 그 글에 답이 잘 나오는군요. ^^...
[정성태] Stating the obvious about debugging...
[정성태] https://www.c-sharpcorner.com/artic...
[정성태] How can I detect if one of my helpe...
[정성태] 32비트 값을 64비트 레지스터에 넣을 때, 상위 32비트에 대...
[정성태] 본문에서 상위 8바이트의 16비트가 사용되지 않는 것을 볼 수 ...
[정성태] 한 번도 궁금한 적이 없었는데, If I mark my t...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Android - adb.exe를 이용한 파일 전송</h1> <p> adb.exe를 이용해 Android 기기에 파일을 전송하는 방법은 Visual Studio의 "Tools" / "Android" / "Android Adb Command Prompt..."를 선택해 대략 이런 식으로 진행하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>which adb.exe</span> /c/Program Files (x86)/Android/android-sdk/platform-tools/adb.exe C:\temp> <span style='color: blue; font-weight: bold'>adb push test.txt /storage/emulated/0/Download/test.txt</span> test.txt: 1 file pushed, 0 skipped. 0.0 MB/s (13 bytes in 0.000s) </pre> <br /> 위와 같이 전송했으면, 에뮬레이터에서 Files 앱을 실행해 "/Download" 디렉터리에 test.txt 파일이 복사된 것을 확인할 수 있습니다.<br /> <br /> 그런데, 2개 이상의 에뮬레이터, 또는 1개의 에뮬레이터와 1개의 실 기기가 연결돼 있다면 adb는 어디에 파일 업로드를 해야 하는지 판단할 수 없어 이런 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb push test.txt /storage/emulated/0/Download/test.txt</span> adb: error: failed to get feature set: more than one device/emulator </pre> <br /> 이런 경우 장치를 열거한 후,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb devices</span> List of devices attached <span style='color: blue; font-weight: bold'>T3AB101GPZY</span> device <span style='color: blue; font-weight: bold'>emulator-5554</span> device </pre> <br /> 대상 ID에 해당하는 장치를 선택하는 옵션을 곁들여 push를 하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb -s emulator-5554 push test.txt /storage/emulated/0/Download/test.txt</span> test.txt: 1 file pushed, 0 skipped. 0.0 MB/s (13 bytes in 0.000s) </pre> <br /> 참고로, 단순히 그 대상이 /Download 디렉터리에 복사하는 경우라면 더 편한 방법이 있는데요, 윈도우 탐색기에서 에뮬레이터 위로 드래그&드롭 동작을 하면 됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 위의 방법은 기기의 공용 저장소에 업로드하는 경우이고, (제한적으로) App 고유의 영역에 업로드하는 것도 가능합니다. 가령, MAUI로 만든 응용 프로그램의 경우,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > // ".\Platforms\Android\MainActivity.cs" namespace SimplePlayer; [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density )] public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle? savedInstanceState) { <span style='color: blue; font-weight: bold'>string appPath = this.FilesDir?.AbsolutePath ?? "";</span> // "/data/user/0/com.companyname.simpleplayer/files" } } </pre> <br /> FilesDir.AbsolutePath로 구한 경로, 즉 "/data/user/0/{package_name}/files"에 업로드하고 싶을 수도 있는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb push test.txt //data/user/0/com.companyname.simpleplayer/files/test.txt</span> adb: error: stat failed when trying to push to //data/user/0/com.companyname.simpleplayer/files/test.txt: Permission denied </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb shell</span> emu64xa:/ $ <span style='color: blue; font-weight: bold'>cd /data</span> emu64xa:/data $ <span style='color: blue; font-weight: bold'>cd /data</span> emu64xa:/data $ <span style='color: blue; font-weight: bold'>ls</span> ls: .: Permission denied </pre> <br /> 기본적으로는 저렇게 권한 오류가 떨어집니다. 왜냐하면, adb 명령어를 받아서 실행해 주는 Android 측, 예를 들어 Emulator에 설치된 adbd 데몬이 루트 권한이 없기 때문입니다.<br /> <br /> 검색해 보면, 루트 권한을 얻는 다양한 루팅 방법들이 나오는데 개인적인 의견으로는 해킹 등의 목적이 아닌, 단순히 우리처럼 ^^ MAUI 개발 용도라면 썩 권하고 싶지 않습니다. (게다가 이런 경우 아무리 github에 올려둔 repo가 있다고 해도 내부 바이너리 생성까지 빌드할 수 있도록 공개하지는 않았으므로 <a target='tab' href='https://www.sysnet.pe.kr/2/0/1638'>신뢰할 수 없는 수준</a>입니다.)<br /> <br /> 결국 물리 기기의 루팅 방법은 포기해야 합니다. 하지만, 테스트를 위해서라면 혹시 에뮬레이터는 그래도 안전하게 루트 권한을 얻는 방법을 허용하지 않았을까... 해서 검색했더니 아래의 글이 나옵니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #SQLite 사용시 root권한 획득 adbd cannot run as root in production builds Error ; <a target='tab' href='https://mrdevelop.tistory.com/entry/SQLite-사용시-root권한-획득-adbd-cannot-run-as-root-in-production-builds-Error'>https://mrdevelop.tistory.com/entry/SQLite-사용시-root권한-획득-adbd-cannot-run-as-root-in-production-builds-Error</a> </pre> <br /> 그러니까, Nexus 6 에뮬레이터를 "Goole Play Store"가 아닌 "Google APIs" 방식으로 생성하면 루트 권한을 얻을 수 있는 것입니다. 따라서 저렇게 생성한 에뮬레이터를 띄우면, 이후에는 개별 앱 공간에 파일 업로드가 자유롭게 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb push test.txt //data/user/0/com.companyname.simpleplayer/files/test.txt</span> test.txt: 1 file pushed, 0 skipped. 0.1 MB/s (13 bytes in 0.000s) </pre> <br /> 확인은 shell 접속으로 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp> <span style='color: blue; font-weight: bold'>adb shell</span> emu64xa:/ # <span style='color: blue; font-weight: bold'>ls /data/data/com.companyname.simpleplayer/files</span> profileInstalled test.txt </pre> <br /> <hr style='width: 50%' /><br /> <br /> 위의 방법을 알았으니 <a target='tab' href='https://www.sysnet.pe.kr/2/0/13626#source_by_code'>지난 MAUI 예제</a>에서 작성한 아래의 코드를 mp4 파일을 App 내에서 코드로 미리 복사하는 방법을 사용하지 않고도 실습할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > FileMediaSource? src = null; // docPath == "/data/user/0/com.companyname.simpleplayer/files/Documents" string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string filePath = Path.Combine(docPath, "file_example_MP4_1920_18MG.mp4"); src = MediaSource.FromFile(filePath) as FileMediaSource; </pre> <br /> 즉, 이렇게 복사해 준 후 테스트하면 되는 것입니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > adb push file_example_MP4_1920_18MG.mp4 //data/user/0/com.companyname.simpleplayer/files/Documents/file_example_MP4_1920_18MG.mp4 </pre> <br /> <hr style='width: 50%' /><br /> <a name='runas'></a> <br /> 그건 그렇고, 왜? Android Studio의 "Device Explorer"에서는 Nexus 에뮬레이터와 상관없이 개별 App 디렉터리로 파일 접근이 잘 되는 것일까요? <br /> <br /> 검색해 보니, 디버그 모드로 빌드한 패키지에 한해 접근할 수 있는 "run-as" 명령어가 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp> <span style='color: blue; font-weight: bold'>adb shell</span> emu64xa:/ $ <span style='color: blue; font-weight: bold'>run-as com.companyname.simpleplayer</span> emu64xa:/data/user/0/com.companyname.simpleplayer $ <span style='color: blue; font-weight: bold'>ls</span> cache code_cache files emu64xa:/data/user/0/com.companyname.simpleplayer $ <span style='color: blue; font-weight: bold'>cd files</span> emu64xa:/data/user/0/com.companyname.simpleplayer/files $ <span style='color: blue; font-weight: bold'>ls</span> profileInstalled emu64xa:/data/user/0/com.companyname.simpleplayer/files $ <span style='color: blue; font-weight: bold'>echo $USER</span> u0_a161 emu64xa:/data/user/0/com.companyname.simpleplayer/files $ <span style='color: blue; font-weight: bold'>exit</span> emu64xa:/ $ <span style='color: blue; font-weight: bold'>echo $USER</span> shell </pre> <br /> Android Studio도 다른 패키지들의 경우에는 "run-as: package not debuggable: com.breel.wallpapers18"라고 뜨는 것을 보니 아마도 저 명령어를 이용하는 듯합니다. ^^<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
3335
(왼쪽의 숫자를 입력해야 합니다.)