본문 바로가기

안드로이드 이야기/새소식

S펜 SDK 사용하기

갤럭시 노트가 공개됨과 동시에 갤럭시 노트 SDK(SPen SDK)도 발표되었습니다.
이번 글에서는 현재 공개된 갤럭시 노트 SDK를 사용하는 방법에 대해 간략히 알아보겠습니다.

갤럭시 노트 SDK는 다음 주소에서 다운로드할 수 있습니다.
http://innovator.samsungmobile.com/down/cnts/toolSDK.detail.view.do?platformId=1&cntsId=10211  

SDK를 다운로드했다면, 우선 새 프로젝트를 만듭니다. 이 글에서는 SPenExample이라는 이름으로 프로젝트 이름을 설정했습니다.

다음, 프로젝트 폴더에 다음과 같이 라이브러리 파일을 넣어줍니다.



라이브러리 파일을 추가한 후, 프로젝트 속성의 Java Build Path에 다음과 같이 S펜 라이브러리를 추가합니다.

 
S Pen 라이브러리가 정상적으로 빌드 패스에 추가되었다면 다음과 같에 Referenced Libraries에 표시됩니다. 이것으로 S Pen을 사용하기 위한 기본 준비는 끝났습니다.

 
이제 애플리케이션을 작성해 보겠습니다. 우선 아래와 같이 레이아웃을 작성합니다.
S Pen으로 그린 그림을 저장하는 CanvasView와 펜 설정 다이얼로그를 표시하는 SettingView를 다음과 같이 FrameLayout 내에 넣어 배치해야 합니다.

[main.xml]

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:gravity="center" >

        <RadioGroup
            android:id="@+id/penGroup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <RadioButton
                android:id="@+id/penRadio"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Pen" android:checked="true"/>

            <RadioButton
                android:id="@+id/eraserRadio"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Eraser" />
        </RadioGroup>

        <Button
            android:id="@+id/undo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:text="Undo" />

        <Button
            android:id="@+id/redo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:text="Redo" />
    </LinearLayout>

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" android:layout_below="@+id/header">

        <com.samsung.sdraw.CanvasView
            android:id="@+id/canvas"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <com.samsung.sdraw.SettingView
            android:id="@+id/setting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </FrameLayout>

</RelativeLayout>

이 글을 작성하는 날짜를 기준으로 작성된 S Pen 라이브러리 내의 가이드에는 CanvasView와 SettingView의 패키지가 각각 com.samsung.sdraw.canvas.CanvasView와 com.samsung.sdraw.setting.SettingView로 되어있던데, 실제 라이브러리를 뒤져보니 위의 코드와 같이 모두 com.samsung.sdraw 패키지 하위에 있었습니다.

공식 Documentation인데 틀린 부분이 있어서 좀 당황스러웠습니다. (이것 뿐만 아니라 따옴표 하나가 빠져있기도 했다는..)

이제 액티비티 코드를 작성할 차례입니다. 레이아웃에서 선언한 구성요소들의 인스턴스를 선언하고 초기화를 수행합니다. CanvasView.setSettingView()를 사용하여 CanvasView에 그려질 펜의 속성을 설정하는 SettingView를 연결하고, CanvasView의 히스토리를 추적하기 위해 HistoryChangeListener를 등록했습니다.

[SPenExampleActivity.java]
public class SPenExampleActivity extends Activity implements OnClickListener{
   
	private RadioButton penButton;
	private RadioButton eraserButton;
	private RadioGroup penGroup;
	private Button undoButton;
	private Button redoButton;
	
	private CanvasView canvas;
	private SettingView settings;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        penButton = (RadioButton)findViewById(R.id.penRadio);
        eraserButton = (RadioButton)findViewById(R.id.eraserRadio);
        penGroup = (RadioGroup)findViewById(R.id.penGroup);
        undoButton = (Button)findViewById(R.id.undo);
        redoButton = (Button)findViewById(R.id.redo);
        
        penGroup.setOnCheckedChangeListener(radioListener);
        penButton.setOnClickListener(this);
        eraserButton.setOnClickListener(this);
        undoButton.setOnClickListener(this);
        redoButton.setOnClickListener(this);
        
        canvas = (CanvasView)findViewById(R.id.canvas);
        settings = (SettingView)findViewById(R.id.setting);
        
        canvas.setSettingView(settings);
        canvas.setOnHistoryChangeListener(historyListener);
        
        if(!SDrawLibrary.isSupportedModel()){
        	Toast.makeText(getApplicationContext(), "Not supported model.", Toast.LENGTH_SHORT).show();
        	finish();
        }
    }

SDrawLibrary.isSupportedModel()을 사용하면 현재 단말기가 S Pen을 지원하는지 아닌지 알 수 있습니다. 예제에서는 S Pen을 지원하지 않는 단말기라면 애플리케이션을 종료하도록 구현했습니다.

다음, HistoryChangeListener와 버튼 리스너를 구현합니다. 라디오 버튼 상태에 따라 그리기 모드를 펜 모드와 지우개 모드 사이를 전환하도록 하였고, HistoryChangeListener를 통해 Undo, Redo 버튼의 활성화 여부를 설정했습니다.

펜과 지우개 모드 라디오 버튼을 클릭했을 때에는 설정 다이얼로그의 표시 여부에 따라 설정 다이얼로그를 표시하도록 구현했습니다. 

    private OnHistoryChangeListener historyListener = new OnHistoryChangeListener(){

		public void onHistoryChanged(boolean undoable, boolean redoable) {
			undoButton.setEnabled(undoable);
			redoButton.setEnabled(redoable);
		}
    	
    };
    
    private OnCheckedChangeListener radioListener = new OnCheckedChangeListener(){

		public void onCheckedChanged(RadioGroup group, int checkedId) {
			switch(checkedId){
			case R.id.penRadio:
				canvas.changeModeTo(CanvasView.PEN_MODE);
				break;
				
			case R.id.eraserRadio:
				canvas.changeModeTo(CanvasView.ERASER_MODE);
				break;
			}
		}
    	
    };

	public void onClick(View v) {
		switch(v.getId()){
		case R.id.penRadio:
			if(settings.isShown(SettingView.PEN_SETTING_VIEW)){
				settings.closeView();
			}else{
				settings.showView(SettingView.PEN_SETTING_VIEW);
			}
			break;
			
		case R.id.eraserRadio:
			if(settings.isShown(SettingView.ERASER_SETTING_VIEW)){
				settings.closeView();
			}else{
				settings.showView(SettingView.ERASER_SETTING_VIEW);
			}
			break;
		case R.id.undo:
			canvas.undo();
			break;
			
		case R.id.redo:
			canvas.redo();
			break;
		}
		
	}

이것으로 간단한 예제가 완성되었습니다. 예제를 실행하면 다음과 같은 화면이 표시됩니다.


Pen 라디오버튼을 누르면 펜 설정 다이얼로그가 표시됩니다.
언어 설정과는 상관없이 영어로 표시되는군요...


펜을 설정하고 낙서좀 해 보았습니다. :)
필기감이나 효과, 펜 종류는 S메모에 있는 것과 동일합니다. Undo/Redo 버튼도 사용 가능합니다.


예제에는 구현하지 않았지만, CanvasView.getData() 메서드를 사용하면 CanvasView의 비트맵 데이터를 byte[] 형태로 반환하므로, FileOutputStream을 사용하여 이미지로 저장할 수도 있습니다.

이것으로 S Pen SDK를 사용하는 방법에 대해 간단히 알아보았습니다.
S Pen SDK가 앞으로 얼마나 업데이트 될는지는 모르겠지만, 아직까지는 갤럭시 노트 이외의 애플리케이션에서 S Pen을 지원하는 용도로 이 라이브러리를 쓰기는 많이 제한적입니다.

첫째, CanvasView 자체는 상당히 사용하기 편리합니다. 하지만, CanvasView의 펜 속성이나 색상값을 설정하려면 꼭 SettingView를 사용해야 가능합니다. 즉, SettingView가 아닌 다른 방법으로는 설정을 변경할 수 없는 것이죠.

두번째, S Pen의 입력 감도를 별도로 얻어올 수 있는 방법이 없습니다. S Pen SDK에서 지원해주는 CanvasView가 아닌 다른 뷰를 사용하는 애플리케이션에서는 이 값을 알아야 굵기를 설정할 수 있을텐데, 이를 알아낼 수 있는 방법이 없어 기존의 애플리케이션에 S Pen의 압력을 감지하여 브러시의 굵기를 조절하는 기능을 추가하는 것은 불가능합니다.

위의 두 문제만 해결된다면 S Pen SDK의 활용 용도가 상당히 넓어지지 않을까 생각합니다.
그리고.. 가이드 문서 내의 오류도 조금만 더 신경 써 주었으면....ㅠㅠ


본 글에서 작성한 예제 첨부합니다.



- 리뷰에 사용된 갤럭시 노트는 삼성전자에서 무료로 제공받았습니다-