所谓实时壁纸,就是指手机桌面不再是简单的图片,而是运行中的动画,这个动画是由程序实时绘制的,因此被称为实时壁纸。

为了开发实时壁纸,Android提供了WallpaperService基类,实时壁纸的实现类需要继承该基类,在Android应用中开发实时壁纸的步骤如下:

1、开发一个子类继承WallpaperService基类。

2、继承WallpaperService基类时必须重写onCreateEngine()方法,该方法返回WallpaperService.Engine子类对象。

3、开发者需要实现WallpaperService.Engine子类,并重写其中的public  void  onVisibilityChanged(boolean  visible)、public  void  onOffsetsChanged()方法。不仅如此,由于WallpaperService.Engine子类采用了与SurfaceView相同的绘图机制,因此还可选择性地重写在SurfaceHolder.Callback中的三个方法。重写这些方法时可通过SurfaceHolder动态地绘制图形。

下面的Service类就代表了实时壁纸服务,程序代码如下:

import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class LiveWallPaper extends WallpaperService{
  //实现WallpaperService必须实现的抽象方法
  @Override
  public Engine onCreateEngine() {
    // 返回自定义的Engine
    return new MyEngine();
  }
  class MyEngine extends Engine{
    //记录程序界面是否可见
    private boolean mVisible;
    //记录当前用户动作事件的发生位置
    private float mTouchX = -1;
    private float mTouchY = -1;
    //记录当前圆圈的绘制位置
    private float cx = 15;
    private float cy = 20;
    //定义画笔
    private Paint mPaint = new Paint();
    //定义一个Handler
    Handler mHandler = new Handler();
    //定义一个周期性执行的任务
    private final Runnable drawTarget = new Runnable() {

      @Override
      public void run() {
        drawFrame();
      }
    };
    public void onCreate(android.view.SurfaceHolder surfaceHolder) {
      super.onCreate(surfaceHolder);
      //初始化画笔
      mPaint.setColor(0xffffffff);
      mPaint.setAntiAlias(true);
      mPaint.setStrokeWidth(2);
      mPaint.setStrokeCap(Paint.Cap.ROUND);
      mPaint.setStyle(Paint.Style.STROKE);
      //设置处理触摸事件
      setTouchEventsEnabled(true);
    };
    @Override
    public void onDestroy() {
      super.onDestroy();
      //删除回调
      mHandler.removeCallbacks(drawTarget);
    }
    @Override
    public void onVisibilityChanged(boolean visible) {
      mVisible = visible;
      //当界面可见时,执行drawFrame()方法
      if(visible){
        //动态地绘制图形
        drawFrame();
      }else{
        //如果界面不可见,删除回调
        mHandler.removeCallbacks(drawTarget);
      }
    }
    @Override
    public void onOffsetsChanged(float xOffset, float yOffset,
            float xOffsetStep, float yOffsetStep, int xPixelOffset,
            int yPixelOffset) {
      drawFrame();
    }
    // //当屏幕大小改变时调用该方法
    // @Override
    // public void onSurfaceChanged(SurfaceHolder holder, int format,
    //              int width, int height) {
    //   super.onSurfaceChanged(holder, format, width, height);
    //    drawFrame();
    // }
    // @Override
    // public void onSurfaceCreated(SurfaceHolder holder) {
    //    super.onSurfaceCreated(holder);
    // }
    // @Override
    // public void onSurfaceDestroyed(SurfaceHolder holder) {
    //    super.onSurfaceDestroyed(holder);
    //     mVisible = false;
    //    mHandler.removeCallbacks(drawTarget);
    // }
    @Override
    public void onTouchEvent(MotionEvent event) {
      // 如果检测到滑动操作
      if(event.getAction() == MotionEvent.ACTION_MOVE){
        mTouchX = event.getX();
        mTouchY = event.getY();
      }else{
        mTouchX = -1;
        mTouchY = -1;
      }
      super.onTouchEvent(event);
    }
    //定义绘制图形的工具方法
    private void drawFrame(){
      //获取该壁纸的SurfaceHolder
      final SurfaceHolder holder = getSurfaceHolder();
      Canvas c = null;
      try {
        //获取该壁纸的SurfaceHolder
        c = holder.lockCanvas();
        if(c != null){
          c.save();
          //绘制背景色
          c.drawColor(0xff000000);
          //在触碰点绘制圆圈
          drawTouchPoint(c);
          //绘制圆圈
          c.drawCircle(cx, cy, 80, mPaint);
          c.restore();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }finally{
        if(c != null){
          holder.unlockCanvasAndPost(c);
        }
      }
      mHandler.removeCallbacks(drawTarget);
      //调度下一次重绘
      if(mVisible){
        cx += 15;
        cy += 20;
        //如果cx、cy移除屏幕,从左上角重新开始
        if(cx > 320){
          cx = 15;
        }
        if(cy > 400){
          cy = 20;
        }
        //指定0.1秒后重新执行mDrawCube一次
        mHandler.postDelayed(drawTarget, 100);
      }

    }
    //在屏幕触碰点绘制圆圈
    private void drawTouchPoint(Canvas c){
      if(mTouchX >= 0 && mTouchY >= 0){
        c.drawCircle(mTouchX, mTouchY, 40, mPaint);
      }
    }
  }

}

上面的程序中粗体字代码就是实现实时壁纸Service的关键代码,这两段粗体字代码重写了WallpaperService.Engine的onVisibilityChanged、onOffsetsChanged方法,并指定当桌面显示时调用drawFrame()方法进行绘制,drawFrame()方法绘制完成后通过Handler对象指定0.1秒后重绘。

上面的程序中被注释的代码是可有可无地,如果程序需要桌面的Surface改变事件提供响应,则可以考虑重写被注释代码。

定义了该Service类之后,接下来还需要在AndroidManifest.xml文件中配置该Service,配置实时壁纸Service与配置普通Service存在小小的区别。它需要指定如下两项:

1、指定运行实时壁纸需要android.permission.BIND_WALLPAPER权限。

2、为实时壁纸指定meta-data配置。

在AndroidManifest.xml文件中配置实时壁纸,也就是需要增加如下配置片段:

<!-- 配置实时壁纸Service -->
<service android:name=".LiveWallPaper"
  android:label="@string/app_name"
  android:permission="android.permission.BIND_WALLPAPER"
  >
  <!-- 为实时壁纸配置intent-filter -->

  <intent-filter >
    <action android:name="android.service.wallpaper.WallPapreService"/>
  </intent-filter>
  <!-- 为实时壁纸配置meta-filter -->

  <meta-data
    android:name="android.service.wallpaper"
    android:resource="@xml/livewallpaper"
  />
</service>

上面的配置文件中粗体字配置部分就是配置实时壁纸的关键代码,上面的配置文件中指定了实时壁纸的meta-data放在@xml/livewallpaper中定义,因此程序还需要zaires\xml\目录下增加一个livewallpaper.xml文件,该代码如下:

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmls:android="http://schemas.android.com/apk/res/android"/>

开发实时壁纸(Live Wallpapers)的更多相关文章

  1. Andoird开发手机壁纸

    Android 开发手机壁纸3种方法 首先使用WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(Cont ...

  2. 使用Node.js的socket.io模块开发实时web程序

    首发:个人博客,更新&纠错&回复 今天的思维漫游如下:从.net的windows程序开发,摸到nodejs的桌面程序开发,又熟悉了一下nodejs,对“异步”的理解有了上上周对操作系统 ...

  3. c# 利用AForge和百度AI开发实时人脸识别

    baiduAIFaceIdentify项目是C#语言,集成百度AI的SDK利用AForge开发的实时人脸识别的小demo,里边包含了人脸检测识别,人脸注册,人脸登录等功能 人脸实时检测识别功能 思路是 ...

  4. 基于flink快速开发实时TopN程序

    TopN 是统计报表和大屏非常常见的功能,主要用来实时计算排行榜.流式的TopN可以使业务方在内存中按照某个统计指标(如出现次数)计算排名并快速出发出更新后的排行榜. 我们以统计词频为例展示一下如何快 ...

  5. React开发实时聊天招聘工具 -第一章

    第一章 课程道学 6个页面 弱化css Antd-mobile作为组件库 Redux 状态管理 React-Router 路由 Axios异步请求 后端Express框架 Socket.io 数据库: ...

  6. 大众点评Java开发实时应用监控平台-CAT

    CAT介绍 CAT是基于Java开发的实时应用监控平台,包括实时应用监控,业务监控. CAT作为大众点评网基础监控组件,它已经在中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等)中得到广泛应 ...

  7. flex4+fms3.5+cs4开发实时音视频直播及点播详解

    开发工具及环境: 1)flash builder4 2)flash cs4 3)flash media server3.5 fms部分 fms是adobe的流媒体服务器,不过是收费的,价格大概是ora ...

  8. iOS开发——实时监控网速(仅作参考,发现一点问题)

    开发中用到获取网速的地方,应该就两种: 1.下载速度,这种可以直接在接受数据的地方统计计算.这个就不讲了. 2.获取手机网卡的数据,可以监控网卡的进出流量,下面就是. #import "Vi ...

  9. React开发实时聊天招聘工具 -第二章

    2-1 介绍React开发环境 npm install -g create-react-app xxx npm run eject   来配置webpack 2-2 ES6常用语法 其他 还有一些特性 ...

随机推荐

  1. C++之路进阶——bzoj3876(支线剧情)

    F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在 ...

  2. MVC5关联表读取相关表数据

    SchoolName = db.Sys_Company.Find(gr.SchoolCode).FullName 只需Model中指定好SchoolCode是Sys_Company的主键就行了!

  3. generated clock

    内部时钟的定义: create_generated_clock,通过-source,-edges,-divide_by,-multiply_by来执行clock沿. create_generated_ ...

  4. winform插件机制学习

    这两天在看自定义控件,原来有太多知识没有掌握.今天看到插件机制,心里突然一亮,这个东西听了不少次,就是不知道是啥回事.这次有幸书里包含一个案例,我就跟着它一步步来.终于知道是什么回事了.这个应该在软件 ...

  5. mysql分区表的原理和优缺点

    1.分区表的原理 分区表是由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们也可以直接访问各个分区,存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分 ...

  6. 用CSS3实现文字描边

    CSS3作为新兴的前端技术可以实现很多复杂变化的效果,比如文字描边. 这里主要用到text-shadow属性,顾名思义就是为文字加上阴影效果.例: text-shadow:10px 5px 2px # ...

  7. CSS中的浮动问题

    有关于我们经常做的导航问题.我们如果想用ul>li来做导航的话,我是一般是用到浮动这个属性的. 也就是 float:left; 或者是 display:inline-block;  下边代码: ...

  8. Uva 11324 最大团

    题目链接:http://vjudge.net/contest/141990#problem/B 题意: 给一张有向图G,求一个结点集数最大的结点集,是的该结点集中任意两个结点 u 和 v,满足: 要么 ...

  9. sftp 设置仅能访问自己目录的用户

    1. 创建一个目录,owner为root,权限为750或755,此处为 /home/test01 添加一个用户test01,home目录设置为 /home/test01 再创建一个子目录用于用户上传: ...

  10. Double Buffering Windows Forms

    Double Buffering Windows Forms As much as we would like it not to be the case, graphics can be slow ...