티스토리 뷰

남자친구 100일 선물로 내가 줬던 것 중 하나가, 내가 직접 만든 안드로이드 앱이었다.


기능은 별 건 없고 매일 자정마다 바뀌는 내 사진이랑 응원 메시지를 볼 수 있는 앱이다.

(물론 비트윈 같은 상용 커플앱에 이미 사진 보는건 물론이고 훨씬 더 많은 기능이 있지만 선물은 정성인 법이... 지? <)


내부 구현은 Dropbox의 공유 기능을 이용해서 사진을 가져오는 것으로 되어 있다.

Dropbox에 파일을 올린 뒤 '공유' -> '링크 만들기' 버튼을 누르면 아래처럼 생긴 다운로드 링크가 생성된다. 


https://www.dropbox.com/s/(식별자)/(파일 이름)?dl=0


여기서 dl=0을 raw=1로 바꿔주면 다운로드가 아니라 직접 사진을 띄워주는 URL로 만들 수 있다.


저런 링크를 각 사진마다 생성한 다음, 배열에 직접 박아넣었다. 그 다음은 이런 식으로 동작한다.


(1) 오늘이 사귄지 며칠째 되는 날인지 계산한다.

(2) 0~(총 사진 수) 사이의 숫자를 하나 뽑아낸다. (1) 의 계산 결과를 초기값으로 사용하는 간단한 의사랜덤이다.

(3) 공유 링크들이 담겨있는 배열에서 링크 하나를 뽑아낸다. (2) 에서 나온 숫자가 인덱스다.

(4) HttpURLConnection 클래스를 이용하여 (3) 의 공유 링크에 접근한다.

(5) InputStream, BitmapFactory 등의 클래스를 이용하여 (4) 에서 받아온 데이터를 화면에 띄운다.


이렇게 구현하는 데만 해도 퍼미션이라던지 스레드라던지 여러가지 안드로이드 이슈 때문에 꽤 헤맸지만 이 얘기는 다음에 다시 정리해보자.



개발에 익숙치 않은 상태에서 급하게 만들다보니 많은 문제점들이 있지만, 그 중 하나는 새로운 사진을 추가할 때마다 Dropbox 공유 링크를 하나하나 복사해서 소스 코드에 직접 붙여줘야 한다는 것이다.


오늘은 Dropbox API를 이용해서, 링크를 하드코딩하지 않고 알아서 가져오도록 만들어보려고 한다.


(물론 내가 이 앱을 처음 만들 당시에도 "API를 쓰면 가져올 수 있겠구나" 라는 걸 모르는 사람은 아니었지만, 그 당시엔 아마 귀찮았을 것이다... 그땐 사진 양도 많지 않았고 API 문서 읽고 배우는 것보다 그냥 하드코딩하는게 빠를거라 판단했던 것 같다)



1) Dropbox API 사용 준비


https://www.dropbox.com/developers/apps


여느 플랫폼들이 그렇듯 개발자용 사이트가 따로 있다.

'My Apps' 탭을 누르고 'Create App' 버튼을 누르면 새 앱 (프로젝트 같은 의미다) 을 생성할 수 있다. 앱 생성 과정은 아주 간단한 편이다.

(얼마 전에 시도해봤던 트위터 앱 생성 과정은 쓸데없이 복잡했다...)


생성된 앱을 클릭하면 몇 가지 설정 화면이 뜨는데 위 사진과 같은 부분에서 '액세스 토큰' 을 생성하자.

Dropbox에서도 OAuth 2라는 인증 프로토콜을 사용하는데 이를 통해 인증을 받기 위한 수단이다.


---


2) SDK 설치 및 API 테스트


https://github.com/dropbox/dropbox-sdk-java#setup


안드로이드 앱에서 쓸 것이기 때문에 자바 API 문서를 보자.

먼저 Setup 부분을 보면 Maven을 쓰는지 Gradle을 쓰는지에 따라 방법이 나뉘어 있다.

안드로이드 스튜디오에서는 Gradle을 사용하므로 이쪽을 따라가자.

(사실 안드로이드 스튜디오에서 공식으로 사용하는 빌드 자동화 툴이라는 것 말고는 Gradle에 대해서 여전히 잘 모른다...)


dependencies {

    // ...

    compile 'com.dropbox.core:dropbox-core-sdk:3.0.10'

}


프로젝트 창에 보이는 파일들 중 'build.gradle' 을 열어보면 dependencies라는 항목이 있다. 그 안에 저 줄을 넣어준다.

넣어주고 나면 안드로이드 스튜디오 위쪽에 뭔가 변경 사항이 감지됐다는 식의 알림이 뜨는데, Sync를 눌러주면 저걸 알아서 설치한다. 설치가 끝나면 저 Dropbox SDK에서 지원하는 API들을 안드로이드 스튜디오가 인식할 수 있게 된다.


아래로 내려가서 튜토리얼을 살펴보자.


public class Main {

    private static final String ACCESS_TOKEN = "<ACCESS TOKEN>";


    public static void main(String args[]) throws DbxException {

        // Create Dropbox client

        DbxRequestConfig config = DbxRequestConfig.newBuilder("dropbox/java-tutorial").build();

        DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);


FullAccount account = client.users().getCurrentAccount();

System.out.println(account.getName().getDisplayName());

    }

}


위에서 생성했던 '액세스 토큰' 을 ACCESS_TOKEN 상수로 넣어준다.

DbxRequestConfig.newBuilder() 에 들어가는 파라미터는 clientidentifier라고 써있는데 말 그대로 식별자라 별로 중요하지 않은 것 같다.


코드의 기본적인 뼈대는 같지만 저 예제는 그냥 자바고, 안드로이드라서 신경써줘야 하는게 더 있다.


- println을 그냥 쓰면 아무것도 안 뜰테니 TextView 같은걸로 띄워주자.

- 안드로이드에서 인터넷으로부터 뭔가 데이터를 받아올 때는 반드시 별도의 스레드를 만들어서 써야 한다. 안 그러면 android.os.NetworkOnMainThreadException이라는게 뜨면서 앱이 죽는다. 공유 링크에서 사진 가져올 때도 있었던 이슈인데 여기서도 마찬가지로 발생했다.


Dropbox에서 설정해 둔 내 사용자 이름이 뜬다면 성공이다.


---


3) 링크 받아오기


현재 내 사진들은 'Public' 폴더 안에 모두 저장되어 있는 상태이고, 각 사진들은 공유 링크를 가지고 있다.

이 공유 링크를 가져오는 것이 목적인데, 일단 공유 링크를 가져올 수 있는 방법은 아래와 같다.


ListSharedLinksResult resultLink = client.sharing().listSharedLinksBuilder().withPath(path).start();

List<SharedLinkMetadata> links = resultLink.getLinks();

String url = links.get(0).getUrl();


client 객체는 2) 의 튜토리얼에서 만들었던 그거다. 

여기다가 sharing() 메서드를 쓰면 DbxUserSharingRequests라는게 나오는데 얘가 공유 관련 기능을 담당하는 핵심 클래스인 것 같다.


중요한건 withPath() 안에 들어가는 'path' 인데, 폴더가 아니라 파일의 경로를 지정해줘야 한다.

뭔 소리냐면, 저기다가 "/public" 이라고 쓰면 public 폴더 안에 있는 모든 파일들의 공유 링크를 가져오는 게 아니라,

"/public/picture1.png" 라고 써줘야 picture1.png에 대한 공유 링크를 가져온다는 소리다.


그러면 폴더 안에 있는 각 파일들의 이름 (경로) 을 갖고오는 과정을 먼저 거쳐야 할 것 같다.


ListFolderResult result = client.files().listFolder("/public");

List<Metadata> files = result.getEntries();

String withpath = files.get(index).getPathLower();


비슷한데, client가 files() 메서드를 호출한다.

listFolder() 메서드는 폴더의 경로를 지정해 주면 그 폴더 안에 있는 파일들을 result에 쭉 넣어준다.


public 폴더에 100개의 사진이 들어있었다면 files 리스트의 크기는 100이 될 것이다.

files 리스트 안에서 공유 링크를 뽑고 싶은 파일의 경로를 알아내면 되는데, getPathLower() 메서드를 쓰면 된다.


---


아래는 전체 코드이다. 원래 저 자리에는 공유 링크들이 하드코딩된 배열에서 공유 링크를 가지고 오는 한 줄짜리 코드가 있었다.

todays_photo라는 변수는 몇 번째 사진을 가져올 것인지를 결정하는 변수로 위에서 이미 결정됐다.


뽑아온 공유 링크를 bottom_text (TextView) 에 넣어놨다가 빼 쓰는데 저건 스레드 안에서 쓴 변수를 바깥으로 어떻게 갖고와야할지 당장 생각이 안나서 쓴 임시 방편이다... 안그래도 스레드 프로그래밍은 해본 적이 거의 없는데 자바 자체도 오랜만이고 해서 영 기억이 안난다 (코드 보면 ArrayList도 나오는데 와 그런게 있었지 싶었다). 오늘은 피곤하니까 이건 다음에 해결하자.


                Thread dbxThread = new Thread(){

                    public void run(){

                        try{

                            DbxRequestConfig config = DbxRequestConfig.newBuilder("dropbox/gsmesie692").build();

                            DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);


                            ListFolderResult result = client.files().listFolder("/public");

                            List<Metadata> files = result.getEntries();

                            String path = files.get(todays_photo).getPathLower();


                            ListSharedLinksResult resultLink = client.sharing().listSharedLinksBuilder().withPath(path).start();

                            List<SharedLinkMetadata> links = resultLink.getLinks();

                            String url = links.get(0).getUrl().replace("?dl=0", "?raw=1");

                            bottom_text.setText(url);


                        } catch (DbxException e) {

                             e.printStackTrace();

                        }

                    }

                };


                dbxThread.start();


                try{

                    dbxThread.join();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }


                todays_URL = bottom_text.getText().toString();


이제 사진 개수만큼 코드에서 줄을 잡아먹던 공유 링크 배열은 없애도 괜찮게 되었다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함