먼저 설정창에 쓰일 layout 파일을 만든다.

option.xml
 

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
android:key="et_name"
android:title="이름"
/>
<CheckBoxPreference
android:key="cb_draw"
android:title="Drawing?"
android:summary="이미지 보기"
android:defaultValue="true"
/>
<PreferenceCategory
android:title="카테고리">
<PreferenceScreen
android:key="fluit"
android:title="과일">
<CheckBoxPreference
android:key="fluit_01"
android:title="사과"/>
<CheckBoxPreference
android:key="fluit_02"
android:title="배"/>
<CheckBoxPreference
android:key="fluit_03"
android:title="포도"/>
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>

레이아웃은 PrefenceScreen으로 해야하며 위 코드는 EditText, CheckBox, Category가 들어있다.
기본적으로 key, title, summary의 값을 지닌다. 



LiveWallPaPer_Canvas.java
package pe.berabue.livewallpaper;

import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.util.Log;

public class LiveWallPaPer_Canvas extends PreferenceActivity implements OnPreferenceClickListener, OnPreferenceChangeListener {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.layout.option);
        
        EditTextPreference editName = (EditTextPreference)findPreference("et_name");
        CheckBoxPreference checkDraw = (CheckBoxPreference)findPreference("cb_draw");
        editName.setOnPreferenceChangeListener(this);
        checkDraw.setOnPreferenceClickListener(this);
        
        // fluit category
        CheckBoxPreference checkFluit_01 = (CheckBoxPreference)findPreference("fluit_01");
        checkFluit_01.setOnPreferenceClickListener(this);
    }

	@Override
	public boolean onPreferenceClick(Preference preference) {
		if ( preference.getKey().equals("cb_draw")) {
			boolean isDraw = preference.getSharedPreferences().getBoolean("cb_draw", false);
			Log.v(null,"Click CheckPreference : "+isDraw);
			
			WallPaPer_Canvas.isDraw = isDraw;
		}
		if ( preference.getKey().equals("fluit_01") ) {
			Log.v(null,"Click fluit_01");
		}
		return false;
	}

	@Override
	public boolean onPreferenceChange(Preference preference, Object newValue) {
		if ( preference.getKey().equals("et_name") ) {
			preference.setSummary((CharSequence) newValue);
			Log.v(null,""+newValue);
		}
		return false;
	}
}
PreferenceActivity를 상속받는다.
addPreferencesFromResource(R.layout.option);
 먼저 작성해둔 option.xml 을 불러들인다.
xml파일에서 작성해둔 key값으로 리스너를 등록시킨다.

WallPaPer_Canvas.java 의 그림을 그려주는 부분에 isDraw를 추가시켜 놓았는데 Drawing?이 체크되면 이미지를 보이고 체크가 해제되면 이미지를 보여주지 않도록 바꾸어 놓았다.

WallPaPer_Canvas.jaca -> DrawFrame();
if (canvas != null) {
	if ( isDraw )
		canvas.drawBitmap(imgIcon, 0, 0, null);
}
 



ex.xml
 

<?xml version="1.0" encoding="UTF-8"?> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/icon" android:description="@string/test" android:settingsActivity="pe.berabue.livewallpaper.LiveWallPaPer_Canvas"/>

ex.xml 파일내의 settingsActivity 옵션에 "패키지명.액티비티명"을 입력 시키면 완성 ~



'Android > Live WallPaper' 카테고리의 다른 글

[ Live WallPaper - 02 ] 이미지 띄우기  (9) 2011.06.10
[ Live Wallpaper - 01 ] 기본 구조  (0) 2011.06.10



WallPePer_Canvas.java

package pe.berabue.livewallpaper;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class WallPaPer_Canvas extends WallpaperService {
    	
	private final Handler mHandler = new Handler();
	
	@Override
	public void onCreate() {
		super.onCreate();
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public Engine onCreateEngine() {
		return new CanvasEngine();
	}

	private class CanvasEngine extends Engine {  

		private Bitmap imgIcon;
		
		private final Runnable mRunnable = new Runnable() {
			public void run() {
				drawFrame();
			}
		};
		private boolean isVisible;
	        
		public CanvasEngine() {
			imgIcon = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.icon);
		}
		
		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);
			setTouchEventsEnabled(true);
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
			mHandler.removeCallbacks(mRunnable);
		}

		@Override
		public void onVisibilityChanged(boolean visible) {
			isVisible = visible;

			if (visible) {
				drawFrame();
			} else {
				mHandler.removeCallbacks(mRunnable);
			}
		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
		}
		
		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);
			Log.v(null," :::: onSurfaceChanged : "+format+" / "+width+", "+height);
			drawFrame();
		}

		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			super.onSurfaceDestroyed(holder);
			isVisible = false;
			mHandler.removeCallbacks(mRunnable);
		}

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) {
			Log.v(null," :::: onOffsetsChanged : "+xOffset+", "+yOffset+", "+xStep+", "+yStep+", "+xPixels+", "+yPixels);
			drawFrame();
		}

		@Override
		public void onTouchEvent(MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				Log.v(null," :::: onTouchEvent");
			}
			super.onTouchEvent(event);
		}

		public void drawFrame() {
			final SurfaceHolder holder = getSurfaceHolder();

			Canvas canvas = null;
			try {
				canvas = holder.lockCanvas();
				if (canvas != null) {
					canvas.drawBitmap(imgIcon, 0, 0, null);
				}
			} finally {
				if (canvas != null)
					holder.unlockCanvasAndPost(canvas);
			}

			mHandler.removeCallbacks(mRunnable);
			if (isVisible) {
				mHandler.postDelayed(mRunnable, 1000 / 25);
			}
		}
	}
}

mHandler를 등록하고 이미지를 준비시킨다.

onVisibilityChanged();  화면이 보여지고 있는지 가려졌는지를 알아내 isVisible에 넣는다.  화면이 보여지고 있다면 drawFrame();으로 들어간다. drawFrame();  실직적으로 이미지가 그려지는 곳.  이미지 처리를 완료하고 핸들러를 제거한다. 화면이 계속 보여지는 중이라면 원하는 딜레이로 핸들러를 다시 등록하여준다.
 

화면이 가려지거나(다른어플 실행, 화면꺼짐 등) 해당 Live Wallpaper를 종료시킬때 핸들러를 제거하여준다.
아래 화면과 같이 타이틀바 영역을 포함하여 좌표가 시작된다.


 



'Android > Live WallPaper' 카테고리의 다른 글

[ Live WallPaper - 03 ] 설정 화면 만들기  (0) 2011.07.15
[ Live Wallpaper - 01 ] 기본 구조  (0) 2011.06.10



AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="pe.berabue.livewallpaper"
      android:versionCode="1"
      android:versionName="1.0">

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".LiveWallPaPer_Canvas"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

  <service android:name=".WallPaPer_Canvas"  
        android:label="@string/app_name"  
        android:permission="android.permission.BIND_WALLPAPER">  
<intent-filter>  
<action android:name="android.service.wallpaper.WallpaperService"/>  
</intent-filter>  
<meta-data android:name="android.service.wallpaper" android:resource="@xml/ex"/>  
</service>  
    </application>
    
    <uses-sdk android:minSdkVersion="7" />
    <uses-feature android:name="android.software.live_wallpaper" />
</manifest>

xml파일을 syntaxhighlighter로 변환하면 이상하게 /> 문자열이 자동으로 바뀌어버리는......
아무튼, Activity는 필수가 아니다. 기본적으로 service부분과 uses-feature 부분만 넣어주면된다.



ex.xml

<?xml version="1.0" encoding="UTF-8"?>
<wallpaper 
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:thumbnail="@drawable/icon" 
    android:description="@string/test"
    android:settingsActivity="PreferenceActivity"/>

Live Wallpaper를 적용시킬때 나오는 아이콘과 설명 그리고 설정화면을 등록해준다.
android:settingsActivity부분을 넣지않으면 설정 버튼이 나오지 않는다.



WallPePer_Canvas.java

package pe.berabue.livewallpaper;

import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class WallPaPer_Canvas extends WallpaperService {
    	
	@Override
	public void onCreate() {
		super.onCreate();
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public Engine onCreateEngine() {
		return new CanvasEngine();
	}

	private class CanvasEngine extends Engine {  
        
		public CanvasEngine() {

		}
		
		@Override
		public void onCreate(SurfaceHolder surfaceHolder) {
			super.onCreate(surfaceHolder);
		}

		@Override
		public void onDestroy() {
			super.onDestroy();
		}

		@Override
		public void onVisibilityChanged(boolean visible) {

		}

		@Override
		public void onSurfaceCreated(SurfaceHolder holder) {
			super.onSurfaceCreated(holder);
		}
		
		@Override
		public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			super.onSurfaceChanged(holder, format, width, height);
			Log.v(null," :::: onSurfaceChanged : "+format+" / "+width+", "+height);
		}

		@Override
		public void onSurfaceDestroyed(SurfaceHolder holder) {
			super.onSurfaceDestroyed(holder);
		}

		@Override
		public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) {
			Log.v(null," :::: onOffsetsChanged : "+xOffset+", "+yOffset+", "+xStep+", "+yStep+", "+xPixels+", "+yPixels);
		}

		@Override
		public void onTouchEvent(MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				Log.v(null," :::: onTouchEvent");
			}
			super.onTouchEvent(event);
		}
	}
}

Activity대신 WallpaperService를 상속받는데 그러면 onCreateEngine() 메서드를 구현해 주어야 한다. Engine을 상속받은 CanvasEngine클래스가 중요한 부분. 클래스 이름에 Canvas를 붙인 이유는.. 목표가 OpenGL용 live wallpaper이기 때문에...(?)

onVisibilityChanged();  메서드는 화면이 보여질때와 가려질때를 알아낸다. onOffsetsChanged();  화면을 밀어 옆으로 이동할때 실행된다. 



+ Recent posts