태그 보관물: URI

안드로이드에서 인증이 필요한 콘텐츠 접근하기

안드로이드에서 인텐트(Intent)는 컴포넌트(액티비티, 콘텐트 프로바이더, 브로드캐스트 리시버, 서비스)를 호출하거나 메시지를 전달하는데 사용된다. 그리고 리소스에 접근해서 리소스를 사용할 수 있도록 제공한다. 이 리소스에 접근하는데 방법의 중심에는 URI라는 포맷을 사용한다. 이 URI 포맷은 Uniform Resource Identifier의 약자로 리소스를 표현하는 식별자이자 유일한 주소이다. 그리고 인텐트 를 보면, 안드로이드의 파일(content), 전화번호(tel) 등의 각종 정보를 가져올 수 있다는 것도 알 수 있다.

이제 안드로이드 앱에서 인터넷에 있는 mp3나 mp4같은 파일을 열어보고 싶은 경우를 살펴보자. 아래의 예처럼, url이 mp3 파일을 가리키고 있다면 mp3를 실행할 수 있는 앱이 뜨면서, 또 앱이 스트리밍을 지원한다면 다운로드 받지 않고도 바로 스트리밍이 되서 음악을 들을 수 있다. 실제로 대 부분의 오디오 앱들은 스트리밍을 지원한다.

String url = “http://www.example.com/abc.mp3”;

아래 코드는 인터넷에 있는 mp3/mp4/3gp 파일을 외부 앱을 통해서 스트리밍 받기 위해서 사용할 수 있는 코드이다.

String url = "http://www.example.com/abc.mp3";
if (url.endsWith(".mp3")) {
  Intent intent = new Intent(Intent.ACTION_VIEW);
  intent.setDataAndType(Uri.parse(url), "audio/*");
  startActivity(intent); 
  return true;
}
if (url.endsWith(".mp4") || url.endsWith(".3gp")) {
  Intent intent = new Intent(Intent.ACTION_VIEW); 
  intent.setDataAndType(Uri.parse(url), "video/*");
  startActivity(intent); 
  return true;
}

위 코드에서  “http://www.example.com/abc.mp3″가 로그인이 필요한 콘텐츠라고 가정해 보자. 위의 코드로 접근을 시도하면 5xx의 에러를 보게 될 것이다. 안드로이드는 인증이 필요한 콘텐츠를 쉽게 볼 수 있도록 URI 처리를 지원해서 인증처리를 지원한다.

위의 코드를 아래처럼 바꾸면 된다. 아래의 주황색 부분인 id, pw만 정해주면 인증이 처리되고, 아래의 mp3 데이터를 스트리밍으로 들을 수 있게 된다.

String url = "http://www.example.com/abc.mp3";

if (url.endsWith(".mp3")) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    URL url = new URL(url);
    String host = url.getProtocol() +"://"+id+":"+pw+"@" + url.getAuthority();
    String path = url.getPath();           

    Uri myUri = Uri.parse(host + path);
    intent.setDataAndType(Uri.parse(url), "audio/*");
    startActivity(intent);   
    return true;
}

if (url.endsWith(".mp4") || url.endsWith(".3gp")) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    URL url = new URL(url);
    String host = url.getProtocol() +"://"+id+":"+pw+"@" + url.getAuthority();
    String path = url.getPath();    

    intent.setDataAndType(Uri.parse(url), "video/*");
    startActivity(intent);   
    return true;
}

이렇게 내 콘텐츠를 확인할 수 있기에, 위 과정은 어찌 보면 매직같은 느낌이 날 수도 있다. 하지만 이 방식은 URI의 표준에 나와있고, HTTP 기본 인증으로 지원되는 내용이다. 아래의 이미지는 URI/URN/URL을 잘 설명해 주고 있다. 딱 보면, 서버가 서비스하는 프로토콜(http(s), ftp 등)에 맞춰서 로그인 정보를 넣을 수 있다는 것을 알 수 있다.

URI 표준에 대한 내용은 http://en.wikipedia.org/wiki/URI_scheme 에서 확인할 수 있다.

Android에서 content:/// 스키마의 Uri를 file:/// 스키마의 Uri로 변경하기..

안드로이드에서, 앱으로 파일을 공유하는 경우, 위치를 받아오는 포맷이 크게 2가지가 있다. 

하나는 content:/// 스키마의 포맷이고, 다른 하나는 file:/// 스키마의 포맷으로 Uri 객체나 리스트 Uri를 받을 수 있다. 그리고, 파일을 공유받기 위해서는 ACTION_SEND와 ACTION_SEND_MULTIPLE를 AndroidManifest.xml 파일에서 해당 Action을 처리하는 Activity안에 기술해 준다. 


	
    
	
        
        
        
        
        
        
        
    
    
        
        
       	
        
        
        
        
        
    

위의 과정을 통해서, 서비스하는 앱이 다른 앱에서 공유하는 파일의 위치를 받아서 업로드를 하거나, 파일을 전송할 수 있다. 위의 content:/// 스키마를 사용하는 기본 갤러리 앱등에서 받은 content:/// Uri를 file:/// 스키마의 Uri로 변경시켜 주는 코드이다. 

	/**
	 * Uri 스키마를 content:/// 에서 file:/// 로  변경한다.
	 * 
	 * @param ctx
	 * @param uri
	 * @return
	 * @throws Exception
	 */
	public static Uri convertContentToFileUri(Context ctx, Uri uri) throws Exception {
		Cursor cursor = null;
		try {
			cursor = ctx.getContentResolver().query(uri, null, null, null, null);
			cursor.moveToNext();
			return Uri.fromFile(new File(cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA))));
		} finally {
			if(cursor != null)
				cursor.close();
		}
	}	

자, 이제 변경된 Uri에서 파일의 위치를 가져와서 I/O 작업을 할 수 있겠다..