自从Android 2.1中加入了动态壁纸,一下子牛叉了很多啊,漂亮的壁纸层出不穷,看上去老土的Android手机总算也是可以炫一下了。
动态壁纸基础
制作方法,网上太多了,虽然基本都是抄的,其实都是从sample上发展出来的,我也把要点记一下,每次写新的都要把老的工程打开看,啥记性……
- res/xml中指定动态壁纸的xml文件:
1234<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android"android:settingsActivity="xxx.yyy.LiveWallpaperSettings"android:thumbnail="@drawable/icon" />
这里是说明自己图标和设定Activity。 - 还有一个设定Activity的xml文件,就是普通的PreferenceScreen,省略。
- 创建WallpaperService的子类,需要再onCreateEngine方法中返回一个Engine,Engine中画画儿,就像用SurfaceView一样。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091public class LiveWallpaper extends WallpaperService {public static final String SHARED_PREFS_NAME = "setting_file_name";@Overridepublic void onCreate() {super.onCreate();}@Overridepublic void onDestroy() {super.onDestroy();}@Overridepublic Engine onCreateEngine() {return new TestPatternEngine();}class TestPatternEngine extends Engine implementsSharedPreferences.OnSharedPreferenceChangeListener {private final Handler mHandler = new Handler();private final Runnable mDrawPattern = new Runnable() {public void run() {drawFrame();}};private boolean mVisible;private SharedPreferences mPreferences;TestPatternEngine() {mPreferences = LiveWallpaper.this.getSharedPreferences(SHARED_PREFS_NAME, 0);mPreferences.registerOnSharedPreferenceChangeListener(this);onSharedPreferenceChanged(mPreferences, null);}public void onSharedPreferenceChanged(SharedPreferences prefs,String key) {}@Overridepublic void onCreate(SurfaceHolder surfaceHolder) {super.onCreate(surfaceHolder);}@Overridepublic void onDestroy() {super.onDestroy();mHandler.removeCallbacks(mDrawPattern);}@Overridepublic void onVisibilityChanged(boolean visible) {mVisible = visible;if (visible) {drawFrame();} else {mHandler.removeCallbacks(mDrawPattern);}}@Overridepublic void onSurfaceChanged(SurfaceHolder holder, int format,int width, int height) {super.onSurfaceChanged(holder, format, width, height);drawFrame();}@Overridepublic void onSurfaceCreated(SurfaceHolder holder) {super.onSurfaceCreated(holder);}@Overridepublic void onSurfaceDestroyed(SurfaceHolder holder) {super.onSurfaceDestroyed(holder);mVisible = false;mHandler.removeCallbacks(mDrawPattern);}@Overridepublic void onOffsetsChanged(float xOffset, float yOffset, float xStep,float yStep, int xPixels, int yPixels) {drawFrame();}void drawFrame() {final SurfaceHolder holder = getSurfaceHolder();Canvas c = null;try {c = holder.lockCanvas();if (c != null) {// draw something}} finally {if (c != null)holder.unlockCanvasAndPost(c);}mHandler.removeCallbacks(mDrawPattern);if (mVisible) {mHandler.postDelayed(mDrawPattern, 1000 / 25);}}}} - 还有设定Activity的实现:
123456789101112131415161718192021222324252627public class LiveWallpaperSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {@Overrideprotected void onCreate(Bundle icicle) {super.onCreate(icicle);getPreferenceManager().setSharedPreferencesName(LiveWallpaper.SHARED_PREFS_NAME);addPreferencesFromResource(R.xml.livewallpaper_settings);getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);}@Overrideprotected void onResume() {super.onResume();}@Overrideprotected void onDestroy() {getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);super.onDestroy();}public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {}} - androidmanifest.xml中一定要加入的:
12345678910111213141516<service android:name=".LiveWallpaper" android:label="@string/app_name" android:icon="@drawable/icon"><intent-filter><action android:name="android.service.wallpaper.WallpaperService" /></intent-filter><meta-data android:name="android.service.wallpaper" android:resource="@xml/livewallpaper" /></service><activity android:label="@string/livewallpaper_settings"android:name=".LiveWallpaperSettings"android:theme="@android:style/Theme.Light.WallpaperSettings"android:exported="true"android:icon="@drawable/icon"></activity><uses-sdk android:minSdkVersion="7" /><uses-feature android:name="android.software.live_wallpaper" />
“uses-feature android:name=”android.software.live_wallpaper””这句话要慎用啊!Google的电子市场会认这句话,然后把有些可以用的机器过滤掉,比如俺的破机器,本来是不支持的,升级到2.1按说是可以用的。我看了市场上很多有名的动态壁纸,就没有加这句话~~
另外,如果想在动态壁纸中使用OpenGL ES,请参考这篇文章:Android中使用OpenGL ES的一二事。
加入AdMob广告
上面都是废话,我这次想说的主题是如何在壁纸设定界面里加入AdMob广告,好不容易做好的东西,总是要意思意思是吧,加个广告是没法的事情了。
不同于一般的Activity,直接加入AdMob是不行的,连个Layout都没有,而且直接加到壁纸上则非常糟糕,谁也不希望好好的背景上塞一个广告。所以一般动态壁纸的广告都加在设置界面里,这样还真有些不容易。
一般有两种方法,把Admob的adView当做一个Preference,直接加入xml就好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class AdmobPreference extends Preference { public AdmobPreference(Context context) { super(context, null); } public AdmobPreference(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected View onCreateView(ViewGroup parent) { //override here to return the admob ad instead of a regular preference display LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); return inflater.inflate(R.layout.admob_preference, null); } } |
相对的admob_preference的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ad_layout" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.google.ads.AdView xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads" android:id="@+id/ad" android:layout_width="fill_parent" android:layout_height="wrap_content" ads.adSize="BANNER" ads:adUnitId="a14e51ca560d266" ads:loadAdOnCreate="true" /> </LinearLayout> |
这里还是有些学问的,网上查一下会有无数的“AdView missing required XML attribute ‘adSize’”的问题,据说是4.1.0之后带来的问题,一定要这么写(将”http://schemas.android.com/apk/lib/com.google.ads”当做一个命名空间,而不是加入自己的程序中)才能不出错,至少大家是如此说的,可惜我不行,怎么写都有这个错,耗费了两个小时尝试了各种写法,还是不行啊!!最后还是写在代码里了:(
不过光这么写貌似还是不行,AdView周围还有留白,貌似是PreferenceActivity里的padding,去不掉,最后还是使用了Tab的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class SettingsTabActivity extends TabActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.table_layout); TabHost tabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; // Resusable TabSpec for each tab Intent intent; // Reusable Intent for each tab // Create an Intent for the regular live wallpaper preferences activity intent = new Intent().setClass(this, LivePaperSettings.class); // Initialize a TabSpec and set the intent spec = tabHost.newTabSpec("TabTitle").setContent(intent); spec.setIndicator("TabTitle"); tabHost.addTab(spec); tabHost.setCurrentTab(0); } |
对应的layout:
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 |
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:id="@+id/main_layout" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.google.ads.AdView android:id="@+id/ad" android:layout_width="fill_parent" android:layout_height="wrap_content" ads:backgroundColor="#000000" ads:primaryTextColor="#FFFFFF" ads:secondaryTextColor="#CCCCCC" ads.adSize="BANNER" ads:adUnitId="a14e51ca560d266" ads:loadAdOnCreate="true" /> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="1dp" android:visibility="invisible" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="1dp" /> </LinearLayout> </TabHost> |
大概就是如此了。
对了还有一个浪费了我两个多小时的问题,对于已经按照的live wallpaper,你修改了setting的Activity,直接覆盖安装是没效果的,点配置还是出现以前的Activity,发现这一点之前,我做了不知几百次修改上传,都快整挂了,Google怎么考虑的?!
出现AdView missing required XML attribute ‘adSize’是因为ads:adSize=”BANNER”打错成ads.adSize=”BANNER” , 但不了解, 已按了方法使用. 但广告都出不来.
@8888: 传上来写错了……这种弱智错误Eclipse会告诉我的。。
能把代码发给我吗?805858226@qq.com
谢谢!
如果博主通过tabactivity间接的启动preferenceActivity,但是在wallperpar中那个设置acitivity只能是一个preference的activity!这个问题怎么解决呢!
有可能在自己的activity中启动WallpaperService吗?
感谢楼主的分享。楼主你不妨尝试下keymob平台。keymob平台支持的开发平台多、丰富多样化的广告形式、还有丰富的广告资源。并且还能顺利通过市场审核,还不用担心被封号。这些都是keymob平台的优势支持。你想了解更多的信息请登入keymob平台官网进行了解。平台地址:www.keymob.com