




已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2D动态壁纸我之前已经详细分析过了,关于项目成果也放出来了,从这一篇文章开始我们自己动手写出这样的一个2D动态壁纸即项目演练二 开发2D动态壁纸DiceWallPaper。 之所以强调这是一个2D壁纸,这是区别于我接下来要介绍的一个3D动态壁纸开发项目。DiceWallPaper组织框架代码组织框架 界面用户配置页面 壁纸Service程序 该Service程序分析详见:Android动态壁纸分析DiceWallPaper主要包和类 包名:org.ourunix.android.dicewallpaper 主要类: DiceService.java 壁纸主要的服务程序; DiceSettings.java 壁纸用户配置页面; Constants.java及Utils.java是常量及工具类。开发难点及重点 1、壁纸程序动态改变 壁纸程序需要动态改变,使用线程来主动更新前台界面。 2、用户配置界面 壁纸程序可以提供用户自选配置,壁纸程序需要监听配置改变并做响应的显示。 3、多功能 多功能是指DiceWallPaper程序将会融合声音、震动等Android特色开发。壁纸的Service框架在Android动态壁纸分析已经详细的介绍过了,DiceWallPaper就来示例这个WallpaperService框架,真正做到学以致用,理论与实践结合。WallpaperService框架 DiceWallPaper继承自WallpaperService,我们不必要去一一实现这个Service里面所有方法,但是至少要实现onCreateEngine方法,这个方法是支撑整个壁纸运转的核心,当然你也可以一一实现诸如onCreate、onDestroy等方法,可以做些初始化和销毁的代码。 DiceWallPaper只实现了onCreateEngine方法,代码如下:Java代码1. publicclassDiceServiceextendsWallpaperService2. 3. Override4. publicvoidonCreate()5. /TODOAuto-generatedmethodstub6. super.onCreate();7. 8. 9. Override10. publicEngineonCreateEngine()11. /TODOAuto-generatedmethodstub12. returnnewDiceEngine();13. 14. 15. Override16. publicvoidonDestroy()17. /TODOAuto-generatedmethodstub18. super.onDestroy();19. 20. 在onCreateEngine方法中,我们返回的是一个自己写的DiceEngine实例,所以我们看到了我们将来所有的代码都是围绕DiceEngine类。壁纸引擎DiceEngine 在DiceEngine中,我们需要像在Android动态壁纸分析分析的一样,重写一些重要的方法。 这些方法包括:onCreate、onSurfaceCreated、onSurfaceChanged、onVisibilityChanged、onOffsetsChanged、onSurfaceDestroyed、onDestroy,当然我们也不是完全有必须重写这么多方法,我们的DiceWallPaper程序只需重写onVisibilityChanged、onOffsetsChanged。所以我们就好好看看这个两个方法的实现吧。 onVisibilityChanged方法是显示/不显示壁纸时调用的,所以如果不显示壁纸即壁纸被桌面上其他程序挡住时,我们可以在这个方法中做些让壁纸休息的程序,然后一旦其他程序移除了壁纸需要立即显示出来就用此方法再次工作。DiceWallPaper的onVisibilityChanged代码如下:Java代码1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 我在壁纸显示时调用一个线程去更新壁纸(其实是一个Canvas),壁纸不显示时移除这个线程并释放相关资源,需要注意的是我们一般不在线程中更新UI,但是壁纸程序不一样,我们是在某一个线程中直接更新界面的底层Canvas,这个要区分好。 我们接着上一次onVisibilityChanged方法来写更新壁纸的线程,其大致思路是这样的:在onVisibilityChanged方法中,判断壁纸是不是显式的,如果是则启动线程,隐式的则移除线程,这个我们还得接着是用Looper-Handler机制来控制。 首先定义一个Handler,代码如下:Java代码1. privateHandlermHandler=newHandler(getMainLooper(); 初始化时我们用的是主线程的Looper,当然你也可以直接new Handler不带参数的。接着再创建一个线程:Java代码1. privateThreaddiceThread=newThread()2. publicvoidrun()3. draw();4. 5. ; 如果让线程走就调用mHandler.postDelayed;移除就使用mHandler.removeCallbacks方法;所以onVisibilityChanged方法代码如下:Java代码1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 当然我在这个方法中,还做了一些初始化的代码即initOthers()和initBack(),另外在移除时还做了一些释放相关的代码,这个都不是特别重要的。需要说明的是我使用postDelayed方法主要是延迟线程工作的,因为桌面上的动态壁纸时刻都有变化,所以我要确保我的线程走完之后需要线程继续走下去并去作一些动作变化,所以线程结束之后得继续调用,代码我们看diceThread 这个线程中的draw方法:Java代码1. /*2. *所有在屏幕上画图的操作都是在这个方法中完成3. */4. publicvoiddraw()5. SurfaceHolderholder=getSurfaceHolder();6. Canvascanvas=holder.lockCanvas();7. canvas.drawBitmap(backBmp,xoffset,0,null);8. if(!sensorUsed)9. canvas.drawBitmap(diceStopLeftBmps,0,210,null);10. canvas.drawBitmap(diceStopRightBmps,0,210,null);11. else12. drawDiceAnim(canvas);13. 14. holder.unlockCanvasAndPost(canvas);15. mHandler.postDelayed(diceThread,50);16. 这个方法就是更新屏幕上的壁纸的,并在最后结束的时候再一次调用自己这个线程,确保实时刷新。下面我们就来接着讲解这个壁纸的描绘过程:首先通过getSurfaceHolder();获得Surface容器,并拿到底层的canvas画布,然后锁定这个画布就开始画画,最后释放这个画布。关于画布上画画的具体动作我都写在drawDiceAnim(canvas)方法,时间不早了,好了,本篇就来重点描述整个壁纸的绘画过程,在前面的壁纸更新线程中,我们已经知道DiceWallPaper壁纸的描述过程是通过一个线程来完成的,diceThread这个线程就是DiceWallPaper壁纸更新的线程。所以本篇的重点就是来讲解这个线程。初始化壁纸资源 在讲解线程之前,我们是否还记得我们的壁纸程序最核心的东东是那个壁纸程序引擎DiceEngine,我们在返回这个引擎的时候用initDiceRes()方法初始化了整个壁纸程序所需的资源,该方法如下:Java代码1. /*2. *初始化图片资源3. */4. publicvoidinitDiceRes()5. /back6. backPic=newintR.drawable.background1,R.drawable.background2;7. initBack();8. 9. /dice10. dicePics=newintR.drawable.dice_roll_01,R.drawable.dice_roll_02,11. R.drawable.dice_roll_03,R.drawable.dice_roll_04,12. R.drawable.dice_roll_05,R.drawable.dice_roll_06,13. R.drawable.dice_roll_07,R.drawable.dice_roll_08,14. R.drawable.dice_roll_09,R.drawable.dice_roll_10,15. R.drawable.dice_roll_11,R.drawable.dice_roll_12,16. R.drawable.dice_roll_13,R.drawable.dice_roll_14,17. R.drawable.dice_roll_15,R.drawable.dice_roll_16,;18. 19. diceBmps=newBitmapdicePics.length;20. 21. for(inti=0,j=dicePics.length;ij;i+)22. diceBmpsi=readBmp(dicePicsi);23. 24. 25. picCount=0;26. 27. 28. /dicestopleft29. diceStopLeftPics=newintR.drawable.dice_left_01,R.drawable.dice_left_02,30. R.drawable.dice_left_03,R.drawable.dice_left_04,31. R.drawable.dice_left_05,R.drawable.dice_left_06,;32. 33. /dicestopright34. diceStopRightPics=newintR.drawable.dice_right_01,R.drawable.dice_right_02,35. R.drawable.dice_right_03,R.drawable.dice_right_04,36. R.drawable.dice_right_05,R.drawable.dice_right_06,;37. 38. initStop();39. 40. SharedPreferenceslocalPrefs1=prefs;41. SharedPreferenceslocalPrefs2=localPrefs1;42. onSharedPreferenceChanged(localPrefs2,null);43. localPrefs2.registerOnSharedPreferenceChangeListener(this);44. 45. voiceSwith=true;46. vibraSwith=true;47. 我在该代码中主要做了下面几件事情:1、使用initBack()方法来初始化整个壁纸的大环境;2、初始化骰子图片资源,我把骰子图片分别用左右两类来归类其资源id号;3、使用initStop()来初始化骰子转停之后的图片,这是用来给用户看的最后一张图片;4、注册SharedPreferences ,监测用户对壁纸程序的改变设置;5、打开声音voiceSwith及骰子转动时震动的开关vibraSwith。初始化可设置资源 可设置资源是指用户可以通过配置文件来改变的资源,比如壁纸的大图片,壁纸是否有声音和骰子是否震动和作弊等等,因为这些配置是可变的,所以我们在在上述第4点注册SharedPreferences,需要说明的因为这些是随用户可变的,所以我就将这些可设置资源放在onVisibilityChanged显示壁纸中,当然有初始就有释放,所以onVisibilityChanged隐藏壁纸中。代码如下:Java代码1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 因为这是个演示程序,我对代码的优化不是很多,在这边可以看出代码执行效率并不是特别的高,所以读者可以通过设置全局静态变量的方法来做到提高优化执行效率,大体的方式是当检测到用户设置改变了就改写这个静态变量,当这个监测变量有改变时再去读取,这个读者可以试试,下面就看看initOthers()、initBack()、release()的代码吧。initOthers()方法:Java代码1. /*2. *初始化其他资源3. */4. publicvoidinitOthers()5. mSensorManager=(SensorManager)getSystemService(Service.SENSOR_SERVICE);6. mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);7. startSensor();8. if(voiceSwith)9. initMediaPlayer();10. 11. if(vibraSwith)12. initVibrator();13. 14. 可以看到initOthers()是判断用户是否晃动手机、管理播放声音、管理震动的一个方法。initBack()方法:Java代码1. /*2. *背景图片3. */4. publicvoidinitBack()5. if(backBmp!=null)6. if(!backBmp.isRecycled()7. backBmp.recycle();8. 9. 10. backBmp=readBmp(backPicbackNum);11. 这个方法就是直接更换程序壁纸的。release()方法是释放所有资源的:Java代码1. /*2. *释放3. */4. publicvoidrelease()5. stopSensor();6. mMediaPlayer.release();7. mVibrator.cancel();8. 该方法释放了sensor传感器、声音、震动等资源代码。壁纸的画布操作 现在还回到diceThread这个线程里面,线程代码很简单:Java代码1. /handler和线程,这个线程主要用来画图2. privateHandlermHandler=newHandler(getMainLooper();3. privateThreaddiceThread=newThread()4. publicvoidrun()5. draw();6. 7. ; 所有的壁纸更新配合操作都是在draw()方法中,我们看draw()方法:Java代码1. /*2. *所有在屏幕上画图的操作都是在这个方法中完成3. */4. publicvoiddraw()5. SurfaceHolderholder=getSurfaceHolder();6. Canvascanvas=holder.lockCanvas();7. canvas.drawBitmap(backBmp,xoffset,0,null);8. if(!sensorUsed)9. canvas.drawBitmap(diceStopLeftBmps,0,210,null);10. canvas.drawBitmap(diceStopRightBmps,0,210,null);11. else12. drawDiceAnim(canvas);13. 14. holder.unlockCanvasAndPost(canvas);15. mHandler.postDelayed(diceThread,50);16. 该方法主要做了下面几件事:1、获得SurfaceHolder,然后拿到底层的Canvas,然后开始我们的作品“绘画”;2、绘制底层的背景即大环境壁纸,这是使用canvas.drawBitmap(backBmp,xoffset,0,null); 方法,这个方法中第一个参数是我们的可供用户选择的壁纸背景,第二个参数是我们从onOffsetsChanged方法获取的,这个主要是壁纸移动的一个参数,界面用户滑动Launcher的时候就会调用这个方法,xoffset就是滑动变量。3、是骰子停止状态,这边主要是用来显示骰子最后呈现给玩家的一个数字画面;4、drawDiceAnim方法是绘制用户晃动手机,手机壁纸中骰子滚动的画面;5、释放canvas并继续调用这个绘制线程diceThread。这样整个画面就连在一起了,利用人眼的视觉停留就觉得骰子在一直转动一样。drawDiceAnim(canvas);代码如下:Java代码1. publicvoiddrawDiceAnim(Canvascanvas)2. if(sensorUsed)3. if(picCount+dicePics.length-1)4. canvas.drawBitmap(diceBmpspicCount,0,210,null);5. return;6. else7. canvas.drawBitmap(diceStopLeftBmps,0,210,null);8. canvas.drawBitmap(diceStopRightBmps,0,210,null);9. Log.i(Tag,iLeft:+iLeft+iRight:+iRight);10. picCount=0;11. sensorUsed=false;12. 13. 14. 这个绘制方式是和绘制大背景一样的,好了本骗文章代码比较多,下一篇文章预报:讲解壁纸程序的配置页面。 本篇主要介绍DiceWallPaper壁纸程序的配置页面,一个程序如果有用户自主配置页面会给用户觉得本程序更加专业的感觉,会给程序加分的,另外再从程序的多功能性来看也是有利的,所以我们为DiceWallPaper壁纸程序加上用户配置页面。 Android自带的很多应用程序都是具有配置页面的,一些大型的软件也都是具备用户可控可调性的,这些都是使用Android中自带的PreferenceActivity来完成的。关于PreferenceActivity的介绍,弯柚博客中有专门的介绍:用户配置界面PreferenceActivity的使用,所以这边不会再去介绍如何使用PreferenceActivity,而是介绍如何为DiceWallPaper壁纸程序设计配置页面。 效果图如下:配置选项的考虑 我们为DiceWallPaper壁纸程序的配置分为基本设置和高级设置两组,如下:开始码代码 现在开始使用PreferenceActivity,由于我们分了基本设置、高级设置,所以我们需要PreferenceCategory来归类,其中播放声音、震动交互、去除广告及推荐应用是使用的CheckBoxPreference,骰子的背景及骰子作弊是使用的ListPreference。 java代码方面,继承自PreferenceActivity的页面叫做DiceSettings,OnCreate方法代码如下:Java代码1. protectedvoidonCreate(BundlesavedInstanceState)2. /TODOAuto-generatedmethodstub3. super.onCreate(savedInstanceState);4. getPreferenceManager().setSharedPreferencesName(wallpaper_setting);5. addPreferencesFromResource(R.xml.preferences);6. prefs=getSharedPreferences(wallpaper_setting,0);7. initPref();8. 9. 其中initPref()方法代码如下:Java代码1. publicvoidinitPref()2. voiceCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_voice_key).toString();3. voiceCheck.setChecked(getVoiceSwitch();4. 5. vibraCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_vibrator_key).toString();6. vibraCheck.setChecked(getVibraSwitch();7. 8. backSelect=(ListPreference)findPreference(getString(R.string.preference_background_key);9. backSelect.setValueIndex(getBackSelect();10. 11. /*12. cheatSelect=(ListPreference)findPreference(getString(R.string.preference_cheat_key);13. cheatSelect.setValueIndex(getCheatSelect();14. 15. adCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_ad_key);16. adCheck.setChecked(getAdCheck();17. 18. adPref=(CheckBoxPreference)findPreference(getString(R.string.preference_setting_more_check_key).toString();19. adPref.setChecked(getAdSwitch();20. 21. adPref.setOnPreferenceClickListener(newOnPreferenceClickListener()22. 23. Override24. publicbooleanonPreferenceClick(Preferencepreference)25. /TODOAuto-generatedmethodstub26. AppConnect.getInstance(mContext).getPoints(newUpdatePointsNotifier()27. 28. Override29. publicvoidgetUpdatePointsFailed(Stringarg0)30. /TODOAuto-generatedmethodstub31. 32. 33. Override34. publicvoidgetUpdatePoints(Stringarg0,intarg1)35. /TODOAuto-generatedmethodstub36. Log.i(xxxxxxxxxxxxxx,arg0:+arg0+arg1:+arg1);37. money=arg1;38. 39. );40. adFlag=prefs.getBoolean(adflag,false);41. if(adFlag)42. startMoreSetting();43. else44. adPref.setChecked(false);45. showAdDialog(money);46. 47. /显示推荐应用列表(Offer).48. AppConnect.getInstance(mContext).showOffers(mContext);49. returntrue;50. 51. );52. 这里主要是初始化了整个配置界面的起始环境,这边初始化之后,我们在还回到壁纸主程序DiceService类中,在该类中的我们自己写的Engine中实现了OnSharedPreferenceChangeListener接口,该接口就是会监-听配置文件的改变情况:XML/HTML代码1. /*2. *配置文件改变时调用3. */4. 5. Override6. publicvoidonSharedPreferenceChanged(7. SharedPreferencessharedPreferences,Stringkey)8. /TODOAuto-generatedmethodstub9. voiceSwith=sharedPreferences.getBoolean(getString(R.string.preference_voice_key).toString(),true);10. vibraSwith=sharedPreferences.getBoolean(getString(R.string.preference_vibrator_key).toString(),true);11. 12. Stringtemp=prefs.getString(mContext.getString(R.string.preference_background_key).toString(),Constants.backgroud_select_01);13. if(temp.equals(Constants.backgroud_select_01)14. backNum=0;15. elseif(temp.equals(Constants.backgroud_select_02)16. backNum=1;17. 18. 19. StringtempCheat=prefs.getString(mContext.getString(R.string.preference_cheat_key).toString(),Constants.cheat_select_00);20. if(tempCheat.equals(Constants.cheat_select_00)21. cheatFlag=0;22. elseif(tempCheat.equals(Constants.cheat_select_01)23. cheatFlag=1;24. elseif(tempCheat.equals(Constants.cheat_select_02)25. cheatFlag=2;26. elseif(tempCheat.equals(Constants.cheat_select_03)27. cheatFlag=3;28. elseif(tempCheat.equals(Constants.cheat_select_04)29. cheatFlag=4;30. elseif(tempCheat.equals(Constants.cheat_select_05)31. cheatFlag=5;32. elseif(tempCheat.equals(Constants.cheat_select_06)33. cheatFlag=6;34. 35. 36. adSwitch=sharedPreferences.getBoolean(mContext.getString(R.string.preference_setting_more_check_key).toString(),false);37. 38. 监-听到变化之后,然后壁纸程序再做相应的处理,自此DiceWallPaper壁纸程序的配置页面就结束了。其他说明 壁纸程序中使用了广告推送和积分强调的代码,这是万普世纪提供的移动广告服务。上一篇开发2D动态壁纸五 DiceWallPaper壁纸程序的配置页面已经介绍
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 西安交通大学城市学院《工程项目前期》2023-2024学年第一学期期末试卷
- 智能教育质量监控体系-洞察及研究
- 2025年制造业绿色供应链与绿色供应链管理政策环境变化趋势分析与应对策略研究报告
- 2025年制药行业绿色节能技术改造与实施路径研究报告
- 小学国安活动方案
- 对外食堂活动方案
- 射阳安全活动方案
- 家具公共活动方案
- 家政活动早教活动方案
- 小学开展跳绳特活动方案
- 消防水鹤安装工程施工方案及主要技术措施
- 《高校教师师德修养》课件
- 2024年深圳市房屋租赁合同(3篇)
- 学校食品安全投诉举报制度及流程
- 人教部编版七年级语文上册《秋天的怀念》示范课教学课件
- 2024年保育员(初级)考试题及答案
- 广西壮族贺州市2024年小升初考试数学试卷含解析
- “非遗”之首-昆曲经典艺术欣赏智慧树知到期末考试答案章节答案2024年北京大学
- SMP-04-013-00 药品受托企业审计评估管理规程
- 店铺代运营合同范本
- 儿童乐园安全管理制度
评论
0/150
提交评论